微信小程序点餐系统实战:从扫码点餐到后厨出单的完整链路

发布时间:2026/10/27 23:22:10

微信小程序点餐系统实战:从扫码点餐到后厨出单的完整链路 简介这是一套面向微信小程序初学者与前端开发者的点餐系统实战源码包围绕菜单展示、分类浏览、购物车、订单管理、微信支付、用户登录与后台管理等核心模块展开帮助读者在真实项目中理解小程序从原型设计、数据库规划到接口对接与上线审核的完整链路。压缩包共438个文件约1.44MB以117个js业务逻辑脚本、86个md说明文档、82个json配置、67个png界面素材为主另含wxss样式、wxml结构、ts类型文件及eslint、yml等工程配置目录层次清晰便于按模块检索与二次修改。目前已有13762人学习下载适合希望借助现成demo快速跑通点餐流程、对照源码补齐数据绑定、网络请求、本地存储与支付集成等关键知识点的开发者参考实践。1. 微信小程序点餐系统从扫码到后厨出单一条能跑通的链路长什么样周末去一家新开的快餐店桌上贴着一张二维码扫码后直接进小程序点餐、支付后厨打印机同步出单。这套流程背后就是微信小程序点餐系统在跑。它解决的核心问题很具体把「顾客看菜单、下单、付款」和「后厨接单、出餐」这两段原本靠服务员口头传递的链路压缩成一次扫码加一次点击。适合谁做中小餐饮门店想省人力、想接外卖平台之外的私域订单或者开发者想拿一个完整项目练手微信小程序开发实战。这篇文章不讲空泛概念只讲一条能跑通的链路前端页面怎么搭、登录和手机号怎么拿、订单怎么落到后端、后厨怎么收到通知以及我踩过的那些坑。读完你至少能判断这个方向值不值得投入以及第一步该动哪里。2. 点餐系统的小程序端页面结构、登录与手机号获取2.1 先定页面骨架再谈交互点餐小程序的页面数量不多但每个页面的职责必须切干净。常见做法是拆成五个页面首页门店信息加扫码入口、菜单页分类加菜品列表、购物车页已选菜品加数量加减、订单确认页桌号、备注、优惠、订单详情页状态流转。页面之间用wx.navigateTo跳转购物车数据用全局状态管理不要在每个页面里各存一份。我一般会在app.json里先把tabBar配好只留「点餐」和「我的订单」两个入口。菜单页的分类用左侧竖排、右侧菜品列表的经典布局滚动联动用scroll-view的scroll-into-view属性实现。这里有个容易忽略的点菜品图片一定要走 CDN 并压缩到 200KB 以内否则菜单页首屏加载会明显卡顿用户等三秒就可能退出。{ pages: [ pages/index/index, pages/menu/menu, pages/cart/cart, pages/order/order, pages/orderDetail/orderDetail ], tabBar: { list: [ { pagePath: pages/menu/menu, text: 点餐 }, { pagePath: pages/order/order, text: 我的订单 } ] }, window: { navigationBarTitleText: 点餐, navigationBarBackgroundColor: #ffffff } }这段配置决定了小程序的页面注册顺序和底部导航。pages数组第一项是启动页通常放首页tabBar的list至少两项每项要有pagePath和text。注意tabBar页面必须出现在pages数组里否则真机上底部导航会直接不显示这个坑我见过不止一次。2.2 登录换 code手机号要单独授权微信小程序的登录流程分两步先wx.login拿临时 code后端用 code 换openid和session_key再通过button的open-typegetPhoneNumber获取手机号。很多新手会把这两步混在一起结果发现拿不到手机号。原因是手机号获取需要用户主动点击按钮授权不能静默调用。// 第一步静默登录拿 code 换 openid wx.login({ success: (res) { if (res.code) { wx.request({ url: https://your-api.com/auth/login, method: POST, data: { code: res.code }, success: (resp) { // 后端返回自定义登录态 token存本地 wx.setStorageSync(token, resp.data.token); } }); } } }); // 第二步用户点击按钮授权手机号 // WXML 中button open-typegetPhoneNumber bindgetphonenumberonGetPhone onGetPhone(e) { if (e.detail.code) { // 把 e.detail.code 发给后端后端换真实手机号 wx.request({ url: https://your-api.com/auth/phone, method: POST, header: { Authorization: wx.getStorageSync(token) }, data: { code: e.detail.code } }); } }逻辑说明wx.login的 code 只能用一次五分钟内有效后端换完openid后要生成自己的 token 返回给前端。手机号授权返回的e.detail.code也是临时凭证同样要后端去换。参数上token建议放header的Authorization字段不要拼在 URL 里。注意如果用户拒绝授权手机号要有降级方案比如允许先下单、后补手机号否则转化率会掉一截。2.3 购物车与订单确认的数据流购物车不要只存在页面 data 里因为用户可能从菜单页加菜后直接跳订单页。我一般用getApp().globalData.cart存一份同时用wx.setStorageSync做持久化防止小程序被系统回收后数据丢失。订单确认页提交前必须做三件事校验桌号是否为空、校验购物车是否为空、把菜品列表和总价重新算一遍再发给后端。前端算价只是展示后端必须再算一次这是防止篡改的基本要求。// 提交订单 const app getApp(); const cart app.globalData.cart; if (!cart.length) { wx.showToast({ title: 请先选菜, icon: none }); return; } wx.request({ url: https://your-api.com/order/create, method: POST, header: { Authorization: wx.getStorageSync(token) }, data: { tableNo: this.data.tableNo, items: cart.map(i ({ dishId: i.id, count: i.count })), remark: this.data.remark }, success: (res) { // 清空购物车跳订单详情 app.globalData.cart []; wx.redirectTo({ url: /pages/orderDetail/orderDetail?id${res.data.orderId} }); } });参数说明tableNo来自扫码时带的参数或用户手输items只传菜品 ID 和数量单价和总价由后端查库计算。这样即使前端被改后端也不会算错钱。常见错误是把单价也传给后端并信任它这是典型的翻车点。3. 后端订单服务接口设计、状态机与后厨通知3.1 订单接口的最小集合一个能跑的点餐系统后端至少要有五个接口登录换 openid、手机号解密、菜单查询、创建订单、查询订单状态。菜单查询要支持按分类返回创建订单要返回订单号和支付参数。订单状态机建议用数字枚举0 待支付、1 已支付、2 制作中、3 已完成、4 已取消。状态流转只能单向不能从已完成跳回制作中否则后厨会重复出单。# Django 示例订单模型与状态枚举 from django.db import models class Order(models.Model): STATUS_CHOICES [ (0, 待支付), (1, 已支付), (2, 制作中), (3, 已完成), (4, 已取消), ] order_no models.CharField(max_length32, uniqueTrue) openid models.CharField(max_length64) table_no models.CharField(max_length16) total_price models.DecimalField(max_digits10, decimal_places2) status models.IntegerField(choicesSTATUS_CHOICES, default0) created_at models.DateTimeField(auto_now_addTrue) class OrderItem(models.Model): order models.ForeignKey(Order, related_nameitems, on_deletemodels.CASCADE) dish_id models.IntegerField() dish_name models.CharField(max_length64) price models.DecimalField(max_digits10, decimal_places2) count models.IntegerField()这段模型定义了两个表订单主表和订单明细表。order_no要唯一建议用时间戳加随机数生成。status用整数枚举方便前端判断和数据库索引。注意total_price用DecimalField而不是FloatField金额计算用浮点会出现 0.10.2 不等于 0.3 的经典问题对账时就是血泪经验。3.2 支付回调与状态推进微信支付的回调是订单状态从「待支付」变「已支付」的唯一可靠来源。不要依赖前端支付成功的回调来改状态因为用户可能支付后直接杀进程。后端收到支付回调后先验签再查订单是否已处理最后把状态改成已支付并触发后厨通知。这里必须做幂等同一笔回调可能来多次用order_no加transaction_id做唯一约束。# 支付回调处理伪代码验签逻辑按微信官方文档实现 def pay_callback(request): data parse_xml(request.body) if not verify_sign(data): return xml_response(FAIL, 签名错误) order_no data[out_trade_no] order Order.objects.filter(order_noorder_no).first() if not order: return xml_response(FAIL, 订单不存在) if order.status ! 0: # 已处理过直接返回成功保证幂等 return xml_response(SUCCESS, OK) order.status 1 order.save() notify_kitchen(order) # 触发后厨通知 return xml_response(SUCCESS, OK)逻辑说明先验签防止伪造回调再查订单状态做幂等最后改状态并通知后厨。参数上out_trade_no就是我们的order_notransaction_id是微信侧流水号建议存到订单表里方便对账。注意回调必须返回 XML 格式的SUCCESS否则微信会持续重试把服务器打满。3.3 后厨通知的三种落地方式后厨怎么收到新订单常见做法有三种一是后厨放一台平板页面轮询订单接口二是用 WebSocket 长连接推送三是接小票打印机通过云打印服务出单。轮询最简单但延迟高、请求多WebSocket 实时性好但需要维护连接云打印最省事但依赖第三方服务。我一般会先上轮询间隔五秒等单量上来再换 WebSocket。// 后厨平板轮询示例 setInterval(() { wx.request({ url: https://your-api.com/kitchen/pending, header: { Authorization: kitchenToken }, success: (res) { if (res.data.length) { // 有新订单播提示音并刷新列表 playNoticeSound(); this.setData({ orders: res.data }); } } }); }, 5000);参数说明kitchenToken是后厨账号的独立 token和顾客 token 分开权限只允许查待制作订单和改状态。轮询间隔不要低于三秒否则后端压力大。注意后厨页面要加自动重连和错误提示网络断了要能看出来不然漏单了都不知道。4. 避坑与排查点餐系统上线前必须过的五道坎4.1 手机号获取失败提示「该小程序不支持」现象用户点击获取手机号按钮弹窗提示不支持。原因手机号快速验证需要小程序主体为企业认证个人主体没有这个权限。解决个人开发者可以先用「手机号验证组件」的替代方案比如让用户手动输入手机号加短信验证码或者只保留 openid 登录手机号作为可选字段。4.2 支付回调没收到订单一直待支付现象用户明明付了钱订单状态还是 0。原因回调地址配置错误或者服务器防火墙拦了微信的请求。解决检查微信支付后台的回调地址是否公网可达用curl从外网访问一下再看服务器日志有没有收到请求。如果验签失败检查密钥和证书是否匹配。4.3 菜单页图片加载慢首屏白屏现象进入菜单页后图片一张张慢慢出来用户等不及就退了。原因图片没压缩、没走 CDN、没设懒加载。解决图片统一压到 200KB 以内上传到对象存储并开 CDNimage标签加lazy-load属性。首屏只加载前两个分类的图片后面的滚动到再加载。4.4 购物车数据丢失用户重新选菜现象用户加完菜切到微信聊天再回来购物车空了。原因小程序被系统回收页面 data 重置。解决购物车数据同时存globalData和wx.setStorageSync页面onShow时从本地恢复。注意存储有 10MB 上限购物车数据很小不用担心。4.5 后厨重复出单同一订单打印两次现象后厨小票机同一单出了两张。原因支付回调重复触发或者轮询接口没有做去重。解决回调处理加幂等判断轮询接口返回的订单列表要带printed标记后厨端打印后调接口标记已打印。更稳妥的做法是后端在状态变成「已支付」时只发一次通知用消息队列保证。5. 进阶技巧用订阅消息把「出餐提醒」做成闭环前面讲的链路到后厨出单就结束了但顾客还不知道餐好了。微信小程序的订阅消息可以补上这一环用户下单时授权「出餐提醒」后厨点「已完成」时后端调订阅消息接口给用户推一条「您的餐已准备好」。这个功能不难但有几个细节决定成败。首先订阅消息必须由用户主动点击授权且每次授权只能发一条。所以要在订单确认页放一个「接收出餐提醒」的勾选框用户勾了才调wx.requestSubscribeMessage。其次模板要提前在微信公众平台申请字段和内容要匹配否则发送会报错。最后后端发送时要带page参数让用户点消息直接跳到订单详情页。// 下单前请求订阅授权 wx.requestSubscribeMessage({ tmplIds: [YOUR_TEMPLATE_ID], success: (res) { if (res[YOUR_TEMPLATE_ID] accept) { // 用户同意把授权状态传给后端记录 wx.request({ url: https://your-api.com/order/subscribe, method: POST, header: { Authorization: wx.getStorageSync(token) }, data: { orderId: this.data.orderId, subscribed: true } }); } } });参数说明tmplIds是模板 ID 数组一次最多三个。res里对应模板 ID 的值为accept表示同意reject表示拒绝。注意这个接口必须在用户点击事件里调用不能放在onLoad里静默调否则会失败。后端发送订阅消息的代码大致如下# Django 调用微信订阅消息发送接口 import requests def send_ready_notice(openid, order_no): url https://api.weixin.qq.com/cgi-bin/message/subscribe/send params {access_token: get_access_token()} body { touser: openid, template_id: YOUR_TEMPLATE_ID, page: fpages/orderDetail/orderDetail?orderNo{order_no}, data: { thing1: {value: 您的餐已准备好}, character_string2: {value: order_no} } } resp requests.post(url, paramsparams, jsonbody) return resp.json()逻辑说明access_token要缓存不能每次现取否则会触发频率限制。data里的字段名要和模板定义一致thing类型限 20 个字符以内character_string限 32 位。注意发送失败要记日志常见错误是用户没授权或授权次数用完这时候不要重试重试也没用。验证方法很简单下单时勾选提醒后厨点完成后看手机有没有收到消息。如果没收到先查access_token是否有效再查模板 ID 和字段名是否匹配最后看用户授权次数是否已耗尽。我一般会在后端加一个「补发」按钮万一漏发可以手动补但补发也要消耗授权次数所以别滥用。这套点餐系统从扫码到出餐提醒核心链路就这些。我自己的习惯是先把登录和下单跑通再补支付和后厨通知最后加订阅消息。每加一个环节就用真机测一遍不要等全做完再联调否则问题堆在一起很难定位。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/27 23:17:10

智能体技术演进:从工具到行动的三大范式转移

1. 智能体技术演进的底层逻辑2006年我在实验室第一次接触多智能体系统时,整个领域还停留在理论推演阶段。如今大模型驱动的智能体已经能自主完成代码提交、商业谈判等复杂任务,这种跨越式发展背后是三次关键范式转移:1.1 工具智能阶段&#x…

2026/10/27 23:17:10

前端数据可视化:突破表格思维,提升用户体验

1. 为什么前端开发者需要突破表格思维在大多数前端项目中,当接到数据展示需求时,开发者的第一反应往往是:"用table标签实现"。这种思维定式源于几个现实因素:表格实现简单、浏览器原生支持良好、业务方对表格形态接受度…

2026/10/28 0:32:15

30天Caveman重启实验:原始饮食与自重训练改善代谢健康

提到“caveman”,你脑海里大概会蹦出两个画面:一个是举着石斧、浑身毛茸茸的原始人,在荒野里追着猛犸象跑;另一个是某个聊天群里甩出来的表情包,头发乱糟糟的男人被女朋友吼“你能不能讲点道理”。说实话,我…

2026/10/28 0:32:15

caveman哲学:用极简主义对抗工程复杂度,找回掌控感

别小看“caveman”这个标签,它是一套反内卷的工程哲学先说一句大实话:我第一次看到“caveman”这个词是在某个开源项目的README里,作者用这个词调侃自己的代码风格——“写得像个原始人那样简单”。当时我笑了一下就划过去了,直到…

2026/10/28 0:32:15

三菱CNC数据采集C#源码Demo:EZSocket、缓冲落库与断线重连

简介:面向三菱CNC数采开发与自动化调试场景的C#示例工程,适合具备一定C#基础、希望将机床数据接入上位机或业务系统的工程师参考,也可作为自动化技术爱好者学习数控通讯流程的入门材料。内容围绕与三菱数控系统建立连接、采集加工参数与设备状…

2026/10/28 0:32:15

营销技能体系全解析:从用户洞察到数据复盘的实战方法论

做营销这些年,我最常被问的问题不是“怎么做活动”,而是“marketing skills到底包含哪些?为什么学了很多课,还是觉得不会做营销?”说实话,“marketing skills”这个词看着宽泛,但拆开看其实就是…

2026/10/28 0:32:15

GAN中的流形几何学:从理论到实践

1. 项目概述:当几何学遇上生成对抗网络第一次看到"流形"这个概念是在研究生时代的微分几何课上,教授用一张揉皱的纸比喻流形空间——局部看似平坦,全局却可能极度扭曲。十年后,当我开始研究GAN的训练不稳定性问题时&…

2026/10/28 0:27:15

Agent-Reach:构建多智能体触达层的设计与实践

Agent-Reach 是我最近在团队里搭的一套多智能体触达层组件。它要解决的问题很具体:在多个 AI Agent 并存协作的场景里,A 怎么知道 B 存在、B 能做什么,以及怎样把一次请求安全、可控地送到 B 手里。如果这些全部靠硬编码去约定,系…

2026/10/27 14:24:03

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/27 9:34:54

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/27 0:59:21

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/28 0:02:13

Python股票自动交易系统源码解析:从行情获取到风控的完整链路

简介:这份资源是面向高校计算机、金融相关专业毕业设计场景的完整项目源码包,主题为基于Python的股票自动交易系统,适合需要完成毕设选题、课程设计或自学金融量化交易开发的学生与开发者参考。压缩包共收录687个文件,整体约14.93…

2026/10/28 0:02:13

视酷酷信IM源码部署指南:Java 17+MySQL 8.0.33实战配置

简介:这是一套2024年亲测可部署的视酷酷信IM即时通讯系统源码,面向具备Java、OC、C#及Vue开发能力的技术人员,解决私有化即时通讯平台快速搭建与二次定制需求,尤其适用于需集成商城、保障数据主权的中小型企业或独立开发者。资源共…

2026/10/28 0:02:13

Python爬取百度迁徙数据:接口解析、批量采集与避坑指南

简介:这份资源是一个用Python爬取百度迁徙数据的脚本压缩包,面向具备Python基础、希望入门网络爬虫与数据解析的开发者,解决按日期获取全国热门城市人口迁徙数据的问题。包内共1个文件,为单个py脚本,压缩包约1KB&#…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑