资讯详情

微信小程序点餐系统开发实战:从登录、支付到后厨订单流转

📅 2026/10/9 6:02:16 | 华诺云谱 👁 阅读
微信小程序点餐系统开发实战:从登录、支付到后厨订单流转
1. 项目背景与需求拆解聊一个我最近完整落地的小程序项目咖啡店点餐系统。做这项目的初衷很直接——店里人工收银排队时间太长顾客到柜台后还要抬头看菜单、反复确认冷热/糖度/杯型高峰期很容易乱。用微信小程序做点餐本质就是把“人的口头沟通”换成“屏幕上的标准化选择”顾客自己扫码、自己下单、自己付款后厨直接接单这样前台压力小顾客也少等。这类系统在小程序生态里已经很常见但真正做完一遍你会发现网上教程一堆能直接照着跑通的少。尤其是微信登录、手机号授权、扫码进店、订单推送、支付回调这套链路步步都是坑。这里我就按自己实际开发的顺序把这个咖啡店点餐系统的设计与实践过程完整拆开讲。1.1 咖啡店点餐系统的核心需求先别急着写代码必须先把需求定清楚。我做完之后的体会是点餐系统“看起来只是下单”但拆开后有四个核心角色需求完全不同。第一是顾客。顾客要的是快、清晰、不出错。进店扫码后能看到商品分类、商品详情、加料选项、购物车、结算最好还能看到自己订单的制作状态。顾客不关心后厨怎么处理只关心“我选好了没”“还要等多久”。第二是收银/前台。前台需要一个既能处理堂食又能处理自提的入口最好还能核销订单、处理退款、看到实时营业额。第三是后厨。后厨要接单、要显示待制作队列、要能标记“开始制作”“出餐完成”。这里非常关键很多点餐系统只做前台和顾客后厨没有独立视图结果就是单子到了后厨只能靠吼等于没做。第四是店长/管理员。要能上下架商品、管理分类、设置库存、查看数据报表。这是后台管理端的重点。我做系统时把需求拆成了两期第一期只做顾客自助点餐后厨接单支付保证门店能跑起来第二期再做会员储值、优惠券、多门店、数据报表。上线初期别想一口吃成胖子不然项目周期会无限拉长。1.2 角色与业务流程梳理我梳理后的核心流程是这样顾客到店或在家提前点→ 微信扫码进入小程序 → 选择自提/堂食 → 浏览菜单加购 → 确认规格和加料 → 提交订单并支付 → 后厨端实时收到新的待制作单 → 制作完成标记出餐 → 顾客端订单状态同步更新 → 顾客取餐或由店员送餐。这里有一个容易忽略的点点餐系统不是“下单支付”就结束的订单状态流转才是核心。如果订单状态只有“待支付”和“已完成”两档后厨和顾客都会迷茫。我在系统里设了五个状态待支付、已支付/待制作、制作中、待取餐、已完成。另外还有取消/退款状态。状态机画清楚之后前后端设计都顺了。另外一个业务决策是小程序端不做复杂的“注册账号”一切以微信身份为主。用户进入小程序时静默登录需要时获取手机号订单与openid绑定。这样免去了手机验证码注册流程顾客体验最轻。2. 技术选型与整体架构选型这一步很多人不重视结果做到一半发现框架卡脖子。我的选型思路是从“现有团队能力”“长期维护成本”“微信生态兼容性”三个维度出发的。2.1 原生小程序还是uniapp我的选择这个项目我最终选了微信小程序原生框架而不是uniapp。原因有三第一项目本身只做微信端不需要同时输出App和H5。uniapp强在跨端但引入了一整套编译层出问题时要查两层代码排查成本高。原生小程序虽然语法有自己的脾气但最贴近微信官方能力遇到问题找文档最直接。第二点餐系统的核心交互菜单滚动、购物车、规格弹层用原生写法反而更可控。微信小程序原生支持wxml、wxss、js、json四件套页面级组件化足够用不需要引入第三方UI框架。我自己封装了菜单分类、商品卡片、购物车侧边栏、规格选择这几个组件后面维护起来非常舒服。第三是考虑到后续要用到的微信开放能力手机号快捷验证、订阅消息、支付、云开发或自建后端。原生小程序在调用这些API时最稳没有中间层类型丢失问题。当然如果团队同时要做抖音小程序、支付宝小程序或者以后要输出App那选uniapp是对的。没有绝对好坏只有适不适合。2.2 后端与数据库设计思路后端我采用的是一套轻量级方案Java Spring Boot MySQL Redis。为什么选Java因为后续要接微信支付、对接第三方打印机、做管理后台Java生态的成熟库最多招人也好招。另一个选择是Node.js或PHP也能做但我在订单并发、事务控制上更信任Spring。数据库设计了这些核心表用户表id、openid、unionid、昵称、头像、手机号、注册时间门店表id、名称、地址、营业时间、状态商品表id、门店id、分类id、名称、描述、图片、价格、状态、排序商品规格表id、商品id、规格名、价格加成用于大杯/中杯、冷/热等加料表id、商品id、加料名、价格加成、库存购物车表可选我用的是前端本地存储加后端落库双保险订单表id、订单号、用户id、门店id、类型、金额、支付状态、订单状态、备注、创建时间订单明细表id、订单id、商品id、规格、加料快照、数量、单价特别提醒订单明细里一定要存商品快照而不是关联商品表。因为商品价格和名称随时可能改如果只存商品id历史订单打印出来可能变成改了后的价格这在咖啡店售后来看会出大问题。所以我在订单明细表里冗余了商品名称、规格、加料、单价等所有信息。Redis我用来做两件事一是维护门店级购物车缓存key为openid门店id二是微信access_token缓存。access_token有效时间7200秒不能每次请求都向微信要必须缓存在服务端。2.3 系统架构与关键数据流整体架构分三层前端小程序用户端后端API服务Spring Boot管理端Web后台我用的是VueElement Plus小程序和后端之间用HTTPS JSON交互。所有涉及用户身份识别的接口都要求请求头带token。登录时会调用微信的code2Session接口拿openid和session_key后端生成自己的token返回给小程序。后续请求小程序带token即可。关键数据流有两个一个是点单流用户选商品加入购物车前端本地→ 每次加购时同步一份到Redis → 点击结算时小程序把购物车数据发送给后端创建订单 → 订单状态为待支付 → 调用微信支付接口 → 支付成功后回调通知后端 → 后端把订单状态改为已支付/待制作 → 推送给后厨屏。另一个是订单状态流小程序端通过订阅消息接收订单状态变化同时后厨管理端轮询或WebSocket获取最新订单。考虑到并发量门店场景用轮询就够了我设置的间隔是10秒一次。3. 核心功能模块的实现细节这一部分我按实际开发时的顺序把踩过的坑和最终实现方式都写清楚。重点内容比较多挑几个含金量高的展开。3.1 微信登录与手机号获取从wx.login到getPhoneNumber先说登录。小程序端最标准的方式是wx.login({ success: async (res) { if (res.code) { // 将 code 发送到后端 const loginRes await fetch(/api/login, { method: POST, data: { code: res.code } }); // 后端用 code 换 openid 和 session_key并返回自定义 token storage.set(token, loginRes.data.token); } } });后端对应逻辑是用code调用微信接口jscode2session获取openid。如果你用的是云开发更简单云函数里直接有cloud.getWXContext()能拿到openid。我自建后端所以走的传统接口方式。这里有个变化要提醒微信官方在2023年前后调整过登录能力现在的推荐方案是wx.login只负责静默登录获取身份不再直接返回用户手机号。手机号必须通过用户点击按钮使用button open-typegetPhoneNumber来收集。获取手机号的实操写法button open-typegetPhoneNumber bindgetphonenumberonGetPhoneNumber手机号快捷登录/buttonasync onGetPhoneNumber(e) { if (e.detail.code) { // 将动态 code 发给后端后端调用 phoneNumber 接口换取手机号 const res await fetch(/api/getPhone, { method: POST, data: { code: e.detail.code } }); this.setData({ phone: res.data.phone }); } }必须强调现在e.detail里已经不是直接返回手机号明文而是一个动态code需要后端用code换手机号。这个改动让很多老教程失效你自己搜的时候要认准最新接口版本。后端换取手机号的接口是POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_tokenACCESS_TOKEN请求体是{ code: xxx }返回结果里能拿到phone_info.phone。这个流程适合需要获取用户手机号做会员或点单通知的场景。如果只是点餐不注册会员其实可以不拿手机号用openid做身份识别就足够。我建议登录是必须的手机号则根据业务需要来决定是否收集少一步授权顾客下单转化率会高不少。3.2 菜单、加料与规格的交互设计咖啡产品天然有规格大杯/中杯、冷/热、加糖/不加糖还有加浓缩、换燕麦奶、加奶油等加料项。这就引出小程序里一个非常关键的交互组件——规格弹层。我的实现思路是点击商品卡片时不直接加购而是弹出底部弹层。弹层里展示商品图片、基础信息、规格选择单选、加料列表多选、数量以及实时计算的总价。确认后加入购物车。用微信小程序原生实现时要注意radio和checkbox的样式定制。微信小程序的radio和checkbox默认样式比较丑而且在不同机型上显示有差异。我最后没有用原生radio而是自己用view模拟点击某个规格时设置一个selectedSkuId通过判断来切换选中样式。这样可控性最高也不会遇到原生组件层级遮挡问题。view wx:for{{skuList}} wx:keyid classsku-item {{selectedSkuId item.id ? active : }} bindtaponSelectSku>cart [ { cartItemId: uuid, // 唯一ID由前端生成 productId: 1001, skuId: 201, // 规格ID skuName: 大杯, additions: [301, 302], // 加料id列表 price: 28, quantity: 1, note: } ]每次加入购物车时先判断有没有相同productId skuId additions note的组合有就数量1没有就新增一条。结算时后端再校验一次价格防止有人篡改前端价格直接低价下单。后端校验逻辑是根据购物车明细里的productId、skuId、additions重新从数据库计算金额而不是直接信任前端传过来的金额。这是支付系统的基础安全底线。购物车的UI我用了两种形态普通页面购物车和悬浮侧边栏购物车。咖啡店场景更适合悬浮侧边栏因为顾客一边浏览菜单一边加购购物车要随时可见。侧边栏展开后可以修改数量、删除商品、看到总价、点击去结算。这里提一个交互细节当顾客切换门店时必须清空当前购物车否则会出现A店的商品带到B店下单的情况。我是在切换门店时触发clearCart()并且同步删除Redis里的购物车缓存。3.4 订单创建与支付回调处理下单接口是核心中的核心设计得不好会造成超卖和重复支付。我的下单流程分四步前端提交购物车数据、门店id、自提/堂食标记、备注。后端创建订单状态为待支付同时冻结库存Redis里扣减并设置有效期。后端调微信支付统一下单接口拿到prepay_id返回给前端。前端调wx.requestPayment拉起支付。上面第二步非常关键。如果不先冻结库存而是支付回调后才扣库存高峰期两杯燕麦拿铁就可能被三个顾客同时买走。所以我在Redis里用库存key过期时间做了预占用户下单时扣减库存若15分钟未支付则自动释放支付回调用事务标记订单已支付真正落库若支付失败则释放冻结库存。微信支付回调是异步的且同一笔支付通知可能会重复送达。我在回调处理里做了幂等处理通过订单号查询如果订单已经是“已支付”状态就直接返回成功不再重复修改。回调里还要验签必须用微信支付平台证书公钥验签验证不通过直接拒绝。支付成功后的动作也别忘了更新订单状态、清空Redis购物车、给后厨端发送新订单通知、给顾客发送订阅消息。4. 页面适配与体验优化小程序页面写好只是第一步。我在真机测试时发现了不少问题主要集中在导航栏、安全问题、启动加载这几个方面。4.1 顶部导航栏高度与安全区适配这是很多新手容易忽略又非常影响观感的点。微信小程序的顶部导航栏分为两部分状态栏显示时间、电量和导航栏标题栏。不同机型状态栏高度不一样尤其刘海屏和灵动岛设备差距很大。我第一次做的时候把标题写死居中结果iPhone 14 Pro上直接顶到状态栏里看起来非常奇怪。后来统一用胶囊按钮位置来自适应const systemInfo wx.getSystemInfoSync(); const menuButtonRect wx.getMenuButtonBoundingClientRect();通过wx.getMenuButtonBoundingClientRect()获取胶囊按钮位置配合systemInfo.statusBarHeight就能算出导航栏内容的安全居中区域。具体来说状态栏高度systemInfo.statusBarHeight导航栏高度(menuButtonRect.top - statusBarHeight) * 2 menuButtonRect.height这是业界通用公式用来自定义导航栏组件非常稳。页面里加安全区也可以用padding-bottom: env(safe-area-inset-bottom)适配底部横条尤其是购物车侧边栏底部按钮千万别被Home指示条挡住。4.2 小程序启动加载与分包优化微信小程序主包有大小限制一般认为最大2MB实际现在放宽到更高但仍是越轻越好。我正常开发完主包后一打包发现超过了2MB先去做了图片压缩、移除无用组件还是超。最后用分包解决了把后厨订单页、商品管理页、订单列表页都放进了分包主包只保留首页、菜单、购物车、结算、登录等核心页面。使用分包很简单在app.json里配置{ pages: [ pages/index/index, pages/menu/menu, pages/cart/cart, pages/checkout/checkout ], subpackages: [ { root: pages/kitchen, pages: [ order-list/order-list, order-detail/order-detail ] }, { root: pages/admin, pages: [ product-manage/product-manage, category-manage/category-manage ] } ] }注意小程序启动只会加载主包进入对应分包页面时才加载分包内容。这样启动速度明显提升包体也不再是瓶颈。另外在首页加载时我会用骨架屏占位而不是白屏。布局上先显示门店图片和推荐位骨架等接口返回再填充商品数据。这个体验提升很直接。4.3 性能测试与常见问题排查上线前一定要做性能和稳定性测试。小程序开发者工具里的“性能面板”可以看到页面渲染耗时、脚本耗时、网络请求耗时。我重点优化了几个点图片全部走CDN并做尺寸压缩菜单图片控制在100KB以内。接口返回数据按需精简大列表用分页。避免在onPageScroll里频繁setData尤其购物车角标这种高频更新的用selectComponent局部更新不要整页刷新。做好异常处理网络失败、支付取消、库存不足都要有明确的toast提示不能让用户卡住。真机测试时我还遇到过一个经典问题苹果设备上wx.login返回的code有时会失败。后来排查发现是用户没同意隐私协议或者小程序隐私接口配置不全。解决方法是在app.json里配置requiredPrivateInfos并按微信要求弹隐私弹窗用户同意后相关接口才能正常调用。再有就是小程序“息屏和切出”要分开处理。点餐过程中用户可能切出去回微信消息再回来时页面状态还在但一些定时器或支付回调需要恢复。我在onShow里主动拉一次订单状态保证前端显示不落后。5. 上线配置与运营避坑功能开发完不是结束上线前的配置和运营保障一样不能省。这里写几个实际遇到的坑。5.1 小程序认证与支付开通流程微信小程序个人主体很多功能不可用尤其是微信支付和部分接口。做咖啡店点餐这种商业项目必须用企业主体注册小程序并且完成微信认证认证费用每年300元这是官方规定。认证通过后才能申请微信支付商户号然后在小程序后台关联商户号开通“微信支付”权限。这里有个容易混淆的地方小程序AppID、微信支付商户号、APIv3密钥是三个不同的东西。我在对接支付时就被绕晕过。要点是小程序AppID在微信公众平台创建小程序后获取。商户号mch_id在微信支付商户平台申请审核通过后得到。APIv3密钥在商户平台设置用于签名和加密。支付回调地址需要配置HTTPS公网域名而且必须在微信支付商户平台和微信公众平台后台都配置两边都加才保险。我第一次就是漏了商户平台那边的回调配置结果支付成功了但小程序端一直显示“待支付”排查了一整天才发现。5.2 门店打印与订单通知联动咖啡店点餐系统接上小票打印机才算闭环。我用的方案是后端在订单支付成功后调用打印机的云接口把订单内容按模板打印出来。要注意打印机联动的时机不要在支付回调时同步打印因为回调响应时间太长会超时。正确做法是回调更新状态后把打印任务丢进消息队列异步处理失败还可以重试。后厨端我并没有做成App而是直接用小程序分包做了一个“后厨模式”。登录时判断用户角色如果是店员首页显示待制作订单如果是顾客显示点餐页。这样省去了单独开发后厨App的成本一个小程序搞定所有角色。当然多角色入口要有权限控制不能随便打开后厨页。我用的是后端返回的用户角色字段来控制路由展示。5.3 常见问题速查表我在开发中遇到过不少问题这里整理成速查表按场景分类方便你对照排查。问题现象可能原因排查方法wx.login返回code无效用户未同意隐私协议或基础库版本过低检查隐私弹窗授权升级基础库获取手机号失败后端没有用code换取或appid与secret不匹配查看后端日志确认是code2Session还是getuserphonenumber流程下单回调后小程序状态不更新回调地址没有在商户平台配置检查微信支付商户平台的回调URL支付金额与订单不一致前端篡改金额后端必须在创建订单时重新计算金额订阅消息发送失败用户没有授权订阅用弹窗引导用户点击订阅允许真机上图片加载不出来图片域名未配置到downloadFile合法域名微信公众平台后台配置合法域名自定义导航栏在刘海屏错位没有使用小程序胶囊按钮位置计算用getMenuButtonBoundingClientRect动态计算这个表里的经验不一定每个项目都能遇到但遇到了至少有个排查方向。最后再分享一个小技巧上线前一定要用真机预览小程序开发者工具模拟器和真机在某些API行为上并不完全一致。我吃过亏的地方是wx.requestPayment在开发工具里能调起但真机上偶尔会返回requestPayment:fail这种问题只能通过真机调试日志定位工具上看不出来。这个咖啡店点餐系统做完、跑顺之后我最大的感受是小程序开发并不难难的是把业务状态梳理清楚再把微信生态里那些细碎的能力拼起来。只要有耐心一步步排查最终系统上线那一刻看着顾客扫码下单、后厨打印机滋滋出票还是挺有成就感的。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑