
简介面向微信小程序开发入门者的在线点餐商城源码基于原生小程序框架与Java后端服务实现完整覆盖菜品浏览、购物车管理、订单确认等典型电商场景可帮助新手直观理解前后端数据交互、小程序API调用与整体项目结构。资源共60个文件主要包含wxml/wxss页面组件、js逻辑脚本、json配置文件、png/jpg界面素材以及md说明文档压缩包仅1.18MB轻量且便于对照学习。源码按功能模块组织前端涵盖菜品展示、购物车、订单等页面后端设计登录验证、菜品管理、订单处理与支付接口并接入微信支付和云开发能力。通过阅读和修改这套源码可以系统熟悉微信开发者工具、WXML/WXSS语法、RESTful接口设计、数据库操作及版本控制等关键知识点。目前已有1148人学习下载适合作为小程序电商项目从零到一的实战练手资料也便于后续扩展二次开发。1. 微信小程序点餐系统源码Java 版值不值得跑先看这三个卡点只要在代码平台搜微信小程序点餐系统源码 Java结果少说十几个。前端是小程序后端是 Spring Boot多数还带管理后台。但源码能不能落地关键不在代码量而在你照着说明第一次跑的时候会不会被环境、支付、域名三个坎拦住。这三个坎是后端起不来多半是 JDK 或数据库配置问题支付回调收不到多半是回调地址没配或金额单位错真机一打开图片全裂多半是图片路径还挂在本地磁盘。下面按已经跑通过的人的处理顺序把这类 Java 点餐系统的常见骨架、跑通步骤、核心链路改造和上线避坑串成一条可复现的路径。适合三类人接私活想快速交 Demo 的开发者、想用现成源码做社区或门店点餐项目的中级后端、想拿真实项目理解前后端协作的新手。读完你会知道改哪些点能换成商城逻辑也知道哪些钱不值得花。2. 拆解点餐系统源码的技术骨架Java 后端和小程序端各自管什么拿到源码先别急着启动。先扫一遍目录分清三部分小程序端、Java 后端、数据库脚本。很多老代码还带一个管理后台前端这部分和点餐业务解耦可以最后看。先弄清楚后端和小程序的职责边界后面改代码才不会到处找文件。2.1 后端为什么普遍是 Spring Boot MyBatis分层与模块划分这类源码选型高度一致Spring Boot MyBatis或 MyBatis-Plus MySQL Redis偶尔加一个 OkHttp 或 Hutool 做外部请求。Spring Boot 自带内置 Tomcat 和自动配置一条java -jar就能起服务对小程序这种以接口交付为主的场景最省事。MyBatis-Plus 把单表 CRUD 的样板代码省掉剩下自定义 SQL 只写在复杂查询里。点餐业务量没到微服务级别单体应用部署最简单别被过度设计带偏。代码分层基本都是四层Controller 暴露/api/**接口并做参数校验Service 放下单、支付回调这类事务性业务Mapper 管数据库操作Entity 直接映射表结构。业务模块一般拆成用户、分类、菜品、购物车、订单、支付、轮播图管理后台涉及的门店配置或 Banner 通常单独几张表。!-- pom.xml 核心依赖版本以你手里的源码为准 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId !-- 常见 2.x / 3.x2.x 用 JDK 1.83.x 需要 JDK 17 -- /parent dependencies !-- Web 能力内置 Tomcat提供 REST 接口 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- ORM 框架简化单表 CRUD -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.x/version /dependency !-- 请求微信登录和支付接口用的 HTTP 客户端 -- dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version3.x/version /dependency /dependencies第一眼看 pom 就能判断项目年代。spring-boot-starter-web 必有看到 mybatis-plus 说明单表操作以 BaseMapper 为主看到 okhttp 或 hutool 说明支付方式是直接拼 HTTP 请求而不是用官方 SDK这决定了后面你改支付时顺着谁的逻辑改。版本号不要盲目升级老代码配新依赖经常会踩编译或运行时兼容的坑。2.2 小程序端核心页面与请求约定小程序端绝大多数是原生框架少数用 uni-app。原生点餐小程序页面一般五个首页左侧分类、右侧菜品列表、购物车、订单确认、订单列表、我的。订单确认页和后端交互最密要同时拿购物车数据、算金额、提交订单很多逻辑不能只看某一个页面。// utils/request.js —— 全站统一的请求封装 const request (url, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: http://localhost:8080 url, // 开发环境地址上线换成 HTTPS 域名 method, data, header: { token: wx.getStorageSync(token) || }, success: (res) { // 后端统一返回 { code, data, msg }code 为 0 表示成功 if (res.data.code 0) { resolve(res.data.data) } else { wx.showToast({ title: res.data.msg, icon: none }) reject(res.data) } }, fail: reject }) }) }这里有两个约定要先确认返回结构是不是code/data/msgtoken 字段名是不是叫token。改别人的代码时最常翻车的点就是前端传token后端认Authorization字段对不上登录永远 401。先看后端有没有拦截器、拦截器读哪个 header再决定改前端还是改后端。2.3 数据库表设计跑通点餐闭环的最小表集合表结构决定业务边界。一份能跑通的点餐源码最少有七张表user 存放微信用户category 放菜品分类dish 放菜品cart 放购物车orders 和 order_detail 是订单主从表banner 是首页轮播。管理后台再补 admin 表和门店配置表。核心表要看订单主表和明细表的设计。CREATE TABLE orders ( id bigint NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL COMMENT 订单号唯一索引, user_id bigint NOT NULL COMMENT 下单用户ID, total_amount decimal(10,2) NOT NULL COMMENT 总金额单位元, status tinyint NOT NULL DEFAULT 0 COMMENT 状态0待支付 1已支付 2制作中 3已完成 -1已取消, remark varchar(255) DEFAULT NULL COMMENT 用户备注, create_time datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT点餐订单主表; CREATE TABLE order_detail ( id bigint NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL COMMENT 关联订单号, dish_id bigint NOT NULL COMMENT 菜品ID, dish_name varchar(100) NOT NULL COMMENT 冗余菜品名称防止菜品改名后历史订单出错, price decimal(10,2) NOT NULL COMMENT 下单时单价, quantity int NOT NULL DEFAULT 1 COMMENT 数量, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT订单明细表;订单主表放订单号和状态明细表冗余了菜品名称和下单价格。冗余是刻意为之菜品信息可以被管理员修改甚至删除但历史订单必须保持下单时的快照。金额一律用 decimal不要用 float/double。order_no 做唯一键而不是把自增 id 暴露给用户后面支付回调要靠 order_no 关联订单唯一索引能防重复回调。3. 从源码到本地跑通数据库初始化、后端启动、小程序端对接的完整步骤跑通这类源码顺序比能力重要。先环境、再数据、后联调别一上来就双击启动类。下面四步是我每次接手新源码都会走的标准流程半小时内能把前后端都拉起来。3.1 环境准备JDK、MySQL、Redis、微信开发者工具怎么搭配工具建议版本用途JDK1.8 或 11先看源码再装编译和运行 Spring BootMaven3.6 及以上拉依赖、打包MySQL5.7 或 8.0数据落地Redis3.x 及以上缓存、token 等微信开发者工具最新稳定版打开小程序端代码版本搭配是第一个坑。拿到源码先打开 pom.xml 看 java.version再决定装哪个 JDK。Spring Boot 2.x 用 JDK 1.8 最省事Spring Boot 3.x 必须 JDK 17 以上。见过有人拿 JDK 17 跑 2.x 老项目起来几分钟就报 Lombok 或 CGLIB 不兼容纯粹是白折腾。MySQL 和 Redis 本地装好即可点餐项目对版本不敏感优先保证端口没被占用。3.2 创建数据库并导入初始 SQL 的完整步骤源码的 sql 目录下通常有 init.sql。有的脚本自带 CREATE DATABASE有的要求你先建库。建议先连上 MySQL 手动建库再指定库名导入这样库名和后端配置能严格对齐。# 1. 建库字符集必须和脚本一致统一用 utf8mb4 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS order_system DEFAULT CHARACTER SET utf8mb4; # 2. 导入脚本注意指定字符集避免中文乱码 mysql -uroot -p --default-character-setutf8mb4 order_system sql/init.sql # 3. 确认表建出来了 mysql -uroot -p -e USE order_system; SHOW TABLES;-e是执行单条 SQL是文件重定向导入。第三步一定要做有的脚本建表语句里有外键依赖导入顺序不对会导致部分表缺失。如果 init.sql 里已经写了 CREATE DATABASE你直接mysql -uroot -p init.sql也行但导入后要去后端配置文件里核对库名、用户名、密码这一步错后面全连不上。3.3 配置 application.yml 并启动后端数据准备好了改配置文件。大多数源码把配置放在 src/main/resources/application.yml 里你实际要动的就三处数据库连接、Redis 地址、微信小程序 appid/secret。支付配置可以先不填等做到支付那一步再回来补。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/order_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 wx: appid: 你的小程序appid secret: 你的小程序secret参数说明server.port 如果 8080 被占用改成 8081小程序端 baseUrl 要同步改连接串里的 characterEncodingutf8 是后面中文乱码问题的关键前提Redis 密码如果有就加 password 字段没有就保持原样。appid 和 secret 可以先填测试号的值不影响登录流程调试。# 本地开发直接启动 mvn spring-boot:run # 或先打包再启动部署时更常用 mvn clean package -DskipTests java -jar target/order-system.jar第一条适合开发调试第二条适合验证打包产物。看到 Tomcat started on port 8080 和 Started Application 就算成功。如果启动后秒退看日志最底部的异常十有八九是数据库连不上、端口被占或 Redis 没启动。这些信息直接告诉你问题在哪别去瞎改业务代码。3.4 小程序端对接开发者工具里先做两个小设置后端起来了用微信开发者工具导入小程序端目录。这一步不要求你先有正式 AppID测试号也能跑通大部分功能。有两处必须先调详情-本地设置里勾选“不校验合法域名”以及 app.js 里的接口地址改成你本机的地址。// app.js —— 全站接口根地址 App({ globalData: { baseUrl: http://localhost:8080 // 开发期用本机地址上线换成 HTTPS 正式域名 } })逻辑说明模拟器里访问 localhost 是可以的前提是勾选不校验合法域名。真机预览时 localhost 指向手机自己你需要把地址换成电脑的局域网 IP例如http://192.168.1.5:8080手机和电脑连同一个 Wi-Fi 才能访问。这个环节最大的玄学是很多人前端报错不看 Console页面白屏就以为代码坏了实际上请求都发出来了打开调试器的 Network 面板逐条看很多问题一眼就能定位。4. 点餐核心链路怎么改从微信登录到下单支付的完整闭环跑通只是第一步。接私活或答辩真正要讲清楚的是核心链路。点餐系统最主干的一条业务线是微信登录 → 拉取分类和菜品 → 加入购物车 → 提交订单 → 微信支付 → 回调更新订单状态。按这条线逐段改出问题的概率最低。4.1 微信登录code2Session 换取 openid 的写法与测试小程序端调 wx.login 拿到临时 code后端拿 code 去微信接口换 openid再拿 openid 查用户表用户不存在就自动注册。这块逻辑每个源码都有区别只在 HTTP 客户端封装不同。// 参数code 是前端 wx.login() 回调里拿到的临时凭证一次性有效 public String wxLogin(String code) { String url https://api.weixin.qq.com/sns/jscode2session ?appid appid secret secret js_code code grant_typeauthorization_code; // 请求微信接口返回 JSON 里有 openid、session_key String resp httpUtil.get(url); JSONObject json JSON.parseObject(resp); String openid json.getString(openid); // 用 openid 查用户表不存在就自动注册然后生成业务系统的 token return createToken(openid); }逻辑说明openid 是用户在小程序生态里的唯一标识所有订单、购物车都挂在它对应的 user_id 下。secret 是敏感凭证只能放后端绝不能出现在小程序代码里。js_code 使用一次后就失效官方规定五分钟内有效重复使用会报错。开发期没有正式 AppID 时用微信公众平台的测试号也有 appid 和 secret流程完全一致。4.2 分类与菜品接口首页数据是怎么拼出来的首页一般是左边分类、右边菜品列表。后端提供两个接口一个拉全部分类一个按分类拉菜品。省事的项目会把分类和菜品拼成一个嵌套结构一次请求返回整个首页但这样不利于分页和缓存我一般倾向拆开。RestController RequestMapping(/api) public class DishController { // 菜品列表按分类筛选同时只返回上架状态的菜品 GetMapping(/dish/list) public Result list(RequestParam Long categoryId) { return Result.ok(dishService.listByCategory(categoryId)); } }逻辑说明service 里最常见的处理是只查 status1 的上架菜品下架的直接不返回。Result.ok 包装的 code/data/msg 结构和前端 request.js 的约定对应前端只看 code 是不是 0。参数说明categoryId 缺省或为 0 时一般表示查全部排序按 sort 字段你在数据库里改了分类排序小程序端不用动。4.3 购物车与下单事务、金额精度与订单状态机购物车有的源码放在小程序本地 storage有的放在后端 Redis点餐项目图省事常放本地。但下单逻辑一定在后端这是安全底线金额不能信前端算好的必须后端用数据库价格重新算。给一个下单核心逻辑的示意Transactional(rollbackFor Exception.class) public OrderVO submit(SubmitOrderReq req) { // 1. 校验菜品是否还在上架状态防止用户停留期间菜品被下架 ListDish dishes dishService.listByIds(req.getDishIds()); // 2. 以数据库价格为准重新计算总金额绝不信任前端传的总价 BigDecimal total BigDecimal.ZERO; for (Dish d : dishes) { total total.add(d.getPrice().multiply(req.getQuantity(d.getId()))); } // 3. 生成订单主表和明细表初始状态为“待支付” String orderNo generateOrderNo(); // 推荐时间戳 用户ID尾号 随机数 ordersMapper.insert(orderNo, req.getUserId(), total, 0); orderDetailMapper.batchInsert(orderNo, dishes, req.getQuantities()); return new OrderVO(orderNo, total); }这段注释要点有三Transactional 保证下单过程要么全成功要么全回滚防止主表写了明细没写总金额后端重算前端传的 total 只做展示状态从 0 待支付开始流转。状态机完整写法是0 待支付 → 1 已支付 → 2 制作中点餐场景→ 3 已完成超时未支付或用户取消 → -1。参数说明generateOrderNo 常见规则是 yyyyMMddHHmmss 用户 ID 尾号 四位随机数控制在 32 位以内避免超长影响索引性能。金额计算全部用 BigDecimal用 double 是点餐源码里翻车率最高的地方之一0.1 加 0.2 的浮点误差会让你对不上账。4.4 支付与回调统一下单的参数与验签习惯对接微信支付有 V2 和 V3 两代接口老源码多为 V2新源码 V3 居多。不管哪代你要改的核心配置都是商户号、API 密钥或证书、回调地址。给一个 V2 风格统一下单的参数组装示意V3 只是换成了 JSON 和证书签名业务参数是一样的// 统一下单参数以 V2 风格的 TreeMap 为例方便按字典序签名 SortedMapString, String params new TreeMap(); params.put(appid, appid); params.put(mch_id, mchId); // 商户号商户平台里查 params.put(out_trade_no, orderNo); // 订单号回调时靠它定位订单 params.put(total_fee, amountInFen); // 金额单位分1元 100 params.put(body, 在线点餐); params.put(notify_url, notifyUrl); // 回调地址必须公网可访问 params.put(trade_type, JSAPI); // 小程序支付固定用 JSAPI // 所有参数按字典序拼接后末尾加上 API 密钥再 MD5 生成签名 String sign genSign(params, apiKey); params.put(sign, sign);最容易踩坑的是 total_fee 单位。数据库存的是元decimal发给微信前必须转成 int 的分1 元就是 100漏乘 100 会出现金额差一百倍的神奇 bug。trade_type 小程序固定 JSAPI调用时还需要把用户的 openid 传给微信。notify_url 必须公网可访问本地联调时用内网穿透工具把 8080 端口映射到公网地址再把这个地址配到商户平台和代码里。回调处理顺序是先查订单是否存在、状态是否已支付验签通过后再更新状态最后向微信返回字符串 success不是 JSON搞反会导致微信一直重试回调。提示支付回调的方法第一行先写日志落库收到什么参数先记录下来再验签。这个习惯能省掉大半回调联调时间不然微信到底有没有发过来、参数对不对全是黑匣子。5. 上线避坑与常见问题排查域名、支付、图片、乱码四大高频坑把源码跑通和真正拿出去用是两回事。以下四个问题是我检查多份点餐商城源码时最常撞见的高频坑每条按现象、原因、解决三步写照着排查基本能定位到具体文件。5.1 真机请求必挂域名白名单与 HTTPS 校验现象模拟器里一切正常一用真机预览所有请求直接 fail页面全白。原因小程序正式环境要求所有请求域名必须配置在小程序后台的 request 合法域名列表里并且是备案过的 HTTPS。开发工具里勾选“不校验合法域名”只对开发工具生效真机上不认这个开关。解决开发期真机调试保持本地设置里“不校验合法域名”开着把接口地址从 localhost 换成电脑局域网 IP手机和电脑连同一 Wi-Fi。要上线去小程序管理后台的“开发管理-服务器域名”里配置 request 合法域名注意域名必须 HTTPS。这里有个常见误操作只给后端加跨域注解以为能解决实际上跨域解决的是浏览器限制小程序也有一套域名校验逻辑两者不是一回事。5.2 微信支付三连坑回调地址、证书、金额单位现象订单能生成但支付成功后订单状态永远停在待支付后台也看不到进账。原因最常见三个。一是 notify_url 填的是 localhost 或内网地址微信服务器根本访问不到二是 V3 支付需要商户证书序列号和私钥路径或配置错误导致回调验签失败三是 total_fee 直接传了元没有转成分微信拒单或金额错乱。解决开发期用内网穿透工具把本地 8080 映射到公网把映射出来的域名填进商户平台支付回调配置和代码里的 notify_url。回调方法第一行写日志把收到的全部参数记录到数据库或日志文件先确认微信是否真的回调了。状态更新要做幂等判断订单当前状态已经是已支付就不再重复入账防止微信超时重试导致金额重复累加。5.3 菜品图片裂开本地路径和访问 URL 不一致现象管理后台图片上传成功数据库里也存了路径但小程序端显示裂图电脑模拟器可能能看到真机一定不行。原因图片存的是本地磁盘绝对路径比如D:/upload/xxx.jpg或者存了相对路径但后端没做静态资源映射。模拟器能访问电脑本地路径真机访问的是手机自己当然找不到。解决两步。第一步后端加静态映射把磁盘上传目录映射成/images/**的 URL代码里统一拼出完整可访问的图片地址。第二步要真机可访问地址必须和接口域名一致或走对象存储数据库只存完整 URL。时间紧先用静态映射顶着长期上线建议直接换对象存储省得还得管磁盘扩容。5.4 中文乱码与数据库连接参数现象接口返回的菜品名、用户备注全是问号或者 SQL 查询带中文直接报错。原因三种诱因连接串没有加 characterEncodingutf8表或字段字符集是 latin1后端响应头没指定 UTF-8。老源码最常见的是第一种。解决统一改成 utf8mb4。连接串写成jdbc:mysql://localhost:3306/order_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai建表语句统一DEFAULT CHARSETutf8mb4接口返回前确认响应头里有Content-Type: application/json;charsetUTF-8。如果数据已经写成了乱码别转码直接把表和那批数据删掉重建比清洗快得多。6. 把点餐源码改造成商城源码三个可以下手的切入点如果你手里的项目是点餐但客户要的是商城也不用推翻重来。改三个点骨架就过来了。第一个是商品模型。给菜品表加库存字段再拆一张 SKU 表存规格、价格、库存。原来的“点什么菜”变成“下单时选规格”购物车明细从只存 dish_id 变成 dish_id sku_id。库存扣减的时机也要想清楚点餐通常不扣库存商城必须在下单时锁定库存、支付成功才真正扣减否则超卖是必然的。第二个是订单状态机。点餐看重“制作中”商城看重“发货”。把状态流改成待支付 → 已支付 → 待发货 → 已发货 → 已完成再补一个收货地址字段。支付回调之后进入待发货管理后台点发货再流转到下一状态。改状态机时要同步改小程序端的订单列表展示文案否则订单状态显示对不上。第三个是营销能力。优惠券、会员价、满减本质都是在下单计算金额时多加一步折扣计算放在 Service 层的同一个方法里。这一步适合用 Redis 缓存券模板和用户券包避免每次下单都查数据库。改完之后要重新验证 4.3 的总金额计算流程确保折扣后金额没有被四舍五入吃掉。我自己的教训是动手前先把状态机画出来再改表和代码。曾经有一次我直接改订单表字段改到一半发现订单明细里没有冗余商品规格历史订单全乱当天只能回滚重来。先把订单明细的冗余字段想全比什么都重要。希望帮到你。本文还有配套的精品资源点击获取