做餐饮类微信小程序三年,我踩过最大的坑不是技术选型,而是低估了餐饮场景对实时性和并发的要求。这篇文章复盘一个真实上线的扫码点餐小程序,从架构到代码,聊聊那些文档里不会写的细节。
为什么餐饮场景适合微信小程序
餐饮的核心链路是「到店—扫码—点餐—支付—出餐」,用户停留时间短、操作路径要极短。微信小程序无需下载、扫码即用,天然匹配这个场景。相比 H5,它还能直接调用微信支付、获取用户手机号,省掉大量注册登录的摩擦。
常见的餐饮小程序功能模块包括:
- 桌码识别与门店定位
- 菜单分类、规格选择(如辣度、加料)
- 购物车与多人拼单
- 微信支付与订单状态推送
- 后厨打印与商家接单端
技术选型:原生还是云开发
如果你的团队只有 1-2 人,我强烈建议用微信云开发。餐饮小程序的数据库操作大多是简单的增删改查,云开发的云数据库、云函数、云存储足够覆盖,还能省掉服务器运维和 HTTPS 证书配置。
但要注意:云开发在高峰期(如午市 12 点)会有并发瓶颈。我的做法是核心下单逻辑走云函数,菜单读取走云数据库直接查询并加本地缓存,减少云函数调用次数。
菜单与购物车的数据结构设计
菜单分「分类—菜品—规格」三级,购物车项必须携带规格快照,否则改价后历史订单会错乱。下面是一个精简的购物车项结构:
// 购物车项
{
dishId: 'd_1001',
name: '宫保鸡丁',
specs: { spicy: '中辣', size: '大份' },
price: 3800, // 单位:分,避免浮点误差
count: 2,
remark: '不要葱'
}价格一律用整数分存储,展示时再除以 100。这是餐饮小程序最容易被忽略的坑:用浮点数算总价,最后支付金额对不上,用户投诉不断。
下单与支付的幂等处理
用户手抖连点两次下单按钮,或者网络超时重试,都会造成重复订单。解决方案是前端生成一个唯一 outTradeNo,云函数里先查这个单号是否已存在,存在则直接返回旧订单。
// 云函数:创建订单(简化)
exports.main = async (event) => {
const { outTradeNo, cart, tableId } = event
const db = cloud.database()
const exist = await db.collection('orders')
.where({ outTradeNo }).get()
if (exist.data.length) {
return { code: 0, orderId: exist.data[0]._id }
}
const res = await db.collection('orders').add({
data: { outTradeNo, cart, tableId, status: 'pending', createTime: Date.now() }
})
return { code: 0, orderId: res._id }
}支付回调同样要做幂等:微信支付会多次通知,必须用 outTradeNo 更新订单状态,且只在状态从 pending 变为 paid 时触发后厨打印。
后厨实时通知的两种方案
商家端要第一时间收到新订单,常见做法有:
- 云函数 + 数据库监听:商家端用
db.collection('orders').where({status:'pending'}).watch()监听变化,实时推送。优点是实现简单,缺点是连接数有限。 - 微信订阅消息:下单后调用订阅消息接口推送给商家,适合商家不在小程序前台时。需要用户提前授权,且每次授权只能推送一次。
我的实践是两者结合:商家端在线时用 watch 实时刷新,离线时用订阅消息兜底。
性能与体验优化清单
- 菜单图片用 WebP 并上传到云存储 CDN,首屏控制在 1 秒内
- 购物车数据存
wx.setStorageSync,防止页面跳转丢失 - 下单按钮点击后立即置灰,配合 loading 防重复提交
- 订单状态轮询改为 watch 监听,减少无效请求
- 用
wx.getSystemInfo判断机型,低端机关闭复杂动画
上线后的真实数据
这套小程序上线后服务了 30 多家中小餐饮门店,午市峰值单店每分钟约 40 单。最大的收获是:餐饮小程序的难点不在功能多,而在稳定和快。菜单加载慢一秒,用户就流失;支付重复扣款一次,商家就再也不敢用。
如果你也在做餐饮小程序,建议先把「下单—支付—出餐」这条主链路做到极致,再考虑会员、营销这些锦上添花的功能。
评论 (0)
还没有评论,快来抢沙发吧~