尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Java后端微信小程序点餐系统源码:从扫码到支付全链路拆解

发布时间:2026/9/26 4:23:53

资讯中心
01
ARTICLE

Java后端微信小程序点餐系统源码:从扫码到支付全链路拆解

Java后端微信小程序点餐系统源码:从扫码到支付全链路拆解
简介这份资源是面向微信小程序初学者与餐饮电商开发者的在线点餐系统源码基于微信小程序开发框架并结合Java后端服务提供了一套完整的餐饮点餐解决方案。资源包共60个文件以jpg、png图片素材和js逻辑脚本为主辅以json配置、wxss样式、wxml页面结构及一份md说明文档压缩包约1.18MB目录涵盖app.js、utils工具、imgs资源与page页面等模块结构清晰便于按需查阅。目前已有1148人学习下载适合想通过实战理解小程序开发流程的技术人员。源码覆盖菜品展示、购物车、订单确认等页面组件以及登录验证、菜品管理、订单处理、微信支付集成等后端接口设计还涉及数据库设计与云开发思路。读者可借此熟悉微信开发者工具的使用、WXML与WXSS语法、小程序API调用、RESTful接口设计及项目部署流程在分析修改中掌握在线点餐系统的运作机制是学习小程序开发与电商系统整合的实用参考。1. 一套 Java 后端的微信小程序点餐系统到底由哪些东西拼起来很多人第一次接触「微信小程序商城源码微信在线点餐源码,微信小程序点餐系统源码,Java」这个方向脑子里想的是一份压缩包解压就能跑。真上手才发现它其实是三块东西拼起来的一个跑在微信里的小程序前端、一个用 Java 写的后端服务、一套存菜品和订单的数据库。少了任何一块扫码点餐这条链路都断。我做过几个餐厅的点餐小程序最典型的场景是顾客扫桌角二维码进小程序看菜单、加购物车、下单后厨打印机出单前台收银台能看到订单状态。这套流程里小程序负责展示和交互Java 后端负责算价、扣库存、生成订单号、对接微信支付数据库负责把菜品、桌号、订单持久化。适合谁做想接私活的后端、想练手全栈的学生、以及餐厅自己养了技术想自建系统的老板。它不难但坑集中在登录态、支付回调和库存并发这三处后面会一条条拆。2. 从扫码到下单小程序前端与 Java 后端的职责怎么切2.1 为什么点餐系统一定要前后端分离先把架构定下来不然后面全是返工。微信小程序点餐系统源码里前端就是微信小程序原生或 uni-app 打包出来的那套页面它只干三件事渲染菜单、收集用户操作、调后端接口。真正的业务逻辑——比如「满 50 减 10」「第二份半价」「库存只剩 3 份」——全部放在 Java 后端。这么切的原因很实在小程序包体积有上限把算价逻辑写在前端改一次活动就要重新提审等审核那几天活动早黄了。放后端改完重启服务就生效。而且前端代码是能被反编译的价格计算放前端等于把底价告诉所有人。常见做法是前端只传「菜品 id 数量 桌号」后端拿着这些去数据库查真实价格再算总价前端传过来的价格一律不信。2.2 后端接口的最小集合一个能跑起来的点餐后端接口不用多下面这几个是刚需接口方法作用关键入参/api/loginPOST用 code 换登录态code、桌号/api/menu/listGET拉取分类和菜品分类 id/api/cart/calcPOST后端算价菜品 id 列表、数量/api/order/createPOST生成订单桌号、菜品明细、备注/api/order/payPOST发起微信支付订单号/api/order/notifyPOST支付回调微信回调报文这张表建议直接抄进你的接口文档。注意 /api/cart/calc 和 /api/order/create 是两个接口别合并。算价是高频操作用户每加一个菜就要调一次下单是低频且要落库的。分开之后算价接口可以走缓存下单接口才开事务。2.3 用 Java 写登录态换取的最小代码微信小程序的登录不是传统账号密码是前端 wx.login 拿到一个临时 code后端拿 code 去微信服务器换 openid。下面是最小实现// 用 code 换 openid这是微信小程序登录的第一步 PostMapping(/api/login) public Result login(RequestBody LoginDTO dto) { // 1. 拿 code 去微信接口换 openid 和 session_key String url https://api.weixin.qq.com/sns/jscode2session ?appid appId secret appSecret js_code dto.getCode() grant_typeauthorization_code; String resp restTemplate.getForObject(url, String.class); JSONObject json JSON.parseObject(resp); // 2. 微信返回错误码要判空别直接取 openid if (json.getInteger(errcode) ! null json.getInteger(errcode) ! 0) { return Result.fail(登录失败: json.getString(errmsg)); } String openid json.getString(openid); // 3. 生成自己的 token别把 session_key 传给前端 String token jwtUtil.sign(openid); return Result.ok(token); }逻辑说明第一步拼微信的 jscode2session 地址appid 和 secret 从配置中心读别硬编码在代码里。第二步一定要判 errcode微信在 code 过期或 appid 不匹配时会返回非 0直接取 openid 会拿到 null后面全崩。第三步自己签一个 JWT 返回给前端session_key 是敏感数据只留在服务端用来后面解密手机号或支付。参数说明appId 和 appSecret 在小程序后台「开发管理」里拿code 有效期只有 5 分钟且只能用一次前端拿到后要立刻发请求别缓存。token 过期时间我一般设 7 天配合前端静默续期。2.4 菜单和购物车的接口怎么写菜单接口按分类查返回结构建议是「分类数组每个分类里嵌菜品数组」前端一次渲染完别让前端循环调接口。购物车算价接口接收的是菜品 id 和数量后端去数据库查当前价格// 后端算价前端只传 id 和数量价格以后端为准 PostMapping(/api/cart/calc) public Result calc(RequestBody CartDTO dto) { BigDecimal total BigDecimal.ZERO; for (CartItem item : dto.getItems()) { // 1. 从数据库查真实菜品不信任前端传的价格 Dish dish dishMapper.selectById(item.getDishId()); if (dish null || dish.getStatus() 0) { return Result.fail(菜品已下架: item.getDishId()); } // 2. 用 BigDecimal 算钱别用 double BigDecimal price dish.getPrice(); total total.add(price.multiply(new BigDecimal(item.getCount()))); } return Result.ok(total); }逻辑说明循环里每次都查库菜品多的时候会有 N 次查询菜品超过 30 个建议改成 selectBatchIds 一次查完再在内存里匹配。金额一律用 BigDecimaldouble 在累加时会出现 0.10.20.30000000000000004 这种玄学问题对账时能让你查一晚上。参数说明CartDTO 里的 items 是菜品 id 和数量的列表count 要做上限校验比如单个菜品最多 99 份防止有人传个 999999 把库存算爆。3. 订单落库与微信支付Java 侧最容易翻车的两段3.1 订单表怎么设计才扛得住并发订单表是整个系统的核心设计不好后面改起来要命。我一般用两张表order_main 存订单主体order_item 存订单里的菜品明细。主表关键字段有order_no自己生成的业务单号不是自增 id、openid、table_no、total_amount、status、create_time、pay_time。order_no 的生成别用时间戳同一秒下单会撞。常见做法是「日期 桌号 随机数」或者用雪花算法。status 用数字枚举0 待支付、1 已支付、2 已出餐、3 已完成、4 已取消。库存扣减放在下单时还是支付时我建议下单时先「预扣」支付回调里确认超时未支付再回滚。这样能防止两个人同时下最后一份菜。3.2 下单接口的事务边界下单要同时写主表、写明细、扣库存这三步必须在一个事务里// 下单写订单 扣库存必须同一个事务 Transactional(rollbackFor Exception.class) public Result createOrder(OrderDTO dto) { // 1. 先扣库存用带条件的 update 防止超卖 for (OrderItem item : dto.getItems()) { int rows dishMapper.reduceStock(item.getDishId(), item.getCount()); if (rows 0) { // 库存不足抛异常触发回滚 throw new BizException(库存不足: item.getDishId()); } } // 2. 写订单主表 OrderMain order new OrderMain(); order.setOrderNo(generateOrderNo(dto.getTableNo())); order.setOpenid(dto.getOpenid()); order.setTotalAmount(dto.getTotalAmount()); order.setStatus(0); orderMapper.insert(order); // 3. 写明细 for (OrderItem item : dto.getItems()) { item.setOrderNo(order.getOrderNo()); orderItemMapper.insert(item); } return Result.ok(order.getOrderNo()); }逻辑说明扣库存用的是带条件的 updateSQL 类似update dish set stock stock - #{count} where id #{id} and stock #{count}返回影响行数为 0 就说明库存不够。这个写法靠数据库行锁保证原子性比先查再改安全得多。任何一步失败抛异常Transactional 会把前面扣的库存一起回滚。参数说明rollbackFor 一定要写 Exception.class默认只回滚 RuntimeException业务里抛的受检异常不会回滚这是血泪教训。generateOrderNo 里桌号要参与方便后厨按桌分单。3.3 微信支付回调的幂等处理支付回调是重灾区。微信会重复推送同一条回调网络抖动时可能推三次。如果你的回调逻辑没做幂等用户付一次钱会生成三笔已支付订单。处理办法是回调进来先查订单状态已经是「已支付」就直接返回成功不再处理。// 支付回调先判状态天然幂等 PostMapping(/api/order/notify) public String payNotify(RequestBody String body) { // 1. 验签防止伪造回调微信官方 SDK 里有方法 if (!wxPayService.verifySign(body)) { return FAIL; } JSONObject json JSON.parseObject(body); String orderNo json.getString(out_trade_no); // 2. 查订单已支付直接返回成功 OrderMain order orderMapper.selectByNo(orderNo); if (order null) { return FAIL; } if (order.getStatus() 1) { return SUCCESS; // 幂等重复回调直接放行 } // 3. 更新状态这里也要带条件 update 防并发 int rows orderMapper.markPaid(orderNo); if (rows 0) { return SUCCESS; // 别的线程已经改过了 } // 4. 通知后厨出单 printService.printTicket(orderNo); return SUCCESS; }逻辑说明第一步验签不能省否则有人伪造回调就能白吃。第二步查状态做幂等这是最关键的一行。第三步 markPaid 的 SQL 要带where order_no #{orderNo} and status 0靠数据库保证只有一个线程能改成功。第四步出单放在状态更新之后避免没付钱就出餐。参数说明回调返回的字符串必须是微信约定的 SUCCESS 或 FAIL返回别的微信会一直重推。out_trade_no 就是你下单时生成的 order_no两边要一致。4. 部署与联调把 Java 后端和小程序接起来4.1 本地联调怎么绕过域名校验微信小程序请求的域名必须是 https 且备案过的本地开发时用 http://localhost 会被拦。开发阶段在微信开发者工具里勾上「不校验合法域名」就能直接连本地 Java 服务。上线前必须换成正式域名且要在小程序后台「开发设置」里把 request 合法域名配上配完要重新编译小程序才生效。Java 服务本地起在 8080小程序里请求地址写成http://localhost:8080/api/...。真机调试时 localhost 指向手机自己连不上电脑要把地址换成电脑的局域网 IP比如http://192.168.1.100:8080同时手机和电脑连同一个 WiFi。4.2 打包部署的几条命令Java 后端用 Spring Boot 的话打包和启动就两条命令# 打包跳过测试加快速度 mvn clean package -DskipTests # 后台启动日志输出到文件 nohup java -jar order-server.jar --spring.profiles.activeprod app.log 21 逻辑说明-DskipTests 在赶时间时用但正式发版前建议跑一遍测试。nohup 加 让服务在后台跑关掉终端不会停。--spring.profiles.activeprod 指定读生产配置数据库密码、微信 appid 这些放 application-prod.yml 里别提交到代码仓库。参数说明日志文件 app.log 要配 logback 做切割不然几天就撑满磁盘。JVM 内存用 -Xms512m -Xmx1024m 控制小餐厅服务器 2G 内存够用。4.3 数据库和缓存的初始化建表 SQL 至少要有 dish、order_main、order_item、table_info 四张表。菜品表里 stock 字段设成 int别用 varchar。订单表 order_no 加唯一索引防止重复下单。如果用了 Redis 缓存菜单key 用menu:category:{id}过期时间设 5 分钟菜品改动时主动删缓存。5. 避坑与排查点餐系统上线后最常炸的五个地方5.1 用户扫码后一直转圈菜单加载不出来现象小程序进去白屏或一直 loading后端日志没请求进来。原因通常是 request 合法域名没配或者配了但没重新编译小程序。解决去小程序后台确认域名已添加开发者工具里点「编译」重新生成真机测试时确认手机网络能访问到服务器。还有一种情况是后端服务挂了用curl http://你的域名/api/menu/list在服务器上自测一下。5.2 支付成功但订单还是待支付现象用户微信扣款了后台订单状态还是 0。原因八成是支付回调地址配错了或者回调接口返回的不是 SUCCESS。解决先看微信支付后台的回调日志确认微信有没有推过来再看 Java 日志里 notify 接口有没有报错。常见错误是验签失败直接返回 FAIL微信会重推但如果一直失败就永远改不了状态。验签用的密钥要和下单时一致。5.3 两个人同时下最后一份菜库存变成负数现象库存明明只有 1两个订单都下成功了。原因是用「先查库存再更新」的写法两个线程都查到 1都去减。解决改成带条件的 updatewhere stock count靠数据库行锁保证只有一个成功。这个坑我在第一个项目里踩过后来所有扣库存的 SQL 都加了条件。5.4 金额对不上差几分钱现象订单总价和菜品单价乘数量加起来差 0.01。原因是用了 double 或 float 算钱。解决所有金额字段用 BigDecimal数据库用 decimal(10,2)。前端展示时再格式化成两位小数别在后端提前四舍五入累加过程要保持精度。5.5 后厨打印机不出单现象订单已支付但后厨没动静。原因可能是打印服务挂了或者出单逻辑放在事务里被回滚了。解决出单不要放在下单事务里放在支付回调成功之后单独调。打印服务要做重试失败三次记日志告警。打印机本身要确认网络通、纸够、IP 没变。6. 把这套源码跑通之后我建议你往哪再走一步跑通基础点餐只是起点。真正让这套系统值钱的是后面这几个进阶方向我按投入产出比排个序。第一个是加「桌台管理」。现在桌号是扫码带进来的但餐厅需要知道哪些桌在用、哪些桌空着。加一张 table_info 表字段有桌号、状态、当前订单号。顾客下单时把桌状态改成「占用」订单完成改成「空闲」。前台收银台就能看到一张桌位图这个功能餐厅老板特别买账。第二个是「菜品规格」。一份面有大小碗、加不加辣这些是 SKU。做法是在 dish 表下面挂一张 dish_spec 表一个菜品对应多个规格每个规格有自己的价格和库存。下单时传的是规格 id 而不是菜品 id。这个改动会影响算价和库存两处逻辑建议一开始就设计进去后期加会很痛。第三个是「订单超时取消」。用户下单不付钱库存一直被占着。用定时任务扫 status0 且创建超过 15 分钟的订单改成已取消并回滚库存。Spring 的 Scheduled 就能做注意多实例部署时要加分布式锁不然两个实例同时扫会重复回滚。验证这套系统好不好用我有个笨办法但很有效找三个人同时扫同一桌的码一个正常下单支付一个下单不付一个反复加购物车再删。跑一遍看库存、订单状态、金额对不对。能扛住这个测试基本就能上真实餐厅了。最后说个我自己的习惯。每次改完支付相关的代码我一定会用微信支付的沙箱环境先跑一遍完整流程再上生产。支付这块没有后悔药线上出问题就是真金白银。还有所有涉及金额和库存的 SQL我都会在代码 review 时单独拎出来看一遍条件写没写全。这套点餐系统源码不难难的是细节上不翻车。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。