过去两年我陆续做过三个外卖类小程序,踩过的坑比写过的代码还多。这篇文章不讲空泛的架构理论,只聊外卖小程序开发中最容易翻车的几个点,以及我是怎么解决的。
一、先想清楚:你真的需要自研外卖小程序吗?
很多个人开发者或小商家一上来就问“怎么从零做一个外卖小程序”,但外卖系统的复杂度被严重低估了。它至少包含:
- 用户端:商品浏览、购物车、下单、支付、订单追踪
- 商家端:接单、出餐、库存、营业状态
- 配送端:骑手调度、路线、送达确认
- 后台:结算、对账、退款、营销
如果你只是给一家店做点单工具,用现成的 SaaS 模板接入会省下 80% 的工期。自研只适合有明确定制需求(比如多商户平台、特殊分佣逻辑)的情况。
二、外卖小程序开发的核心注意事项
1. 支付与退款必须做幂等
外卖场景下用户重复点击支付、网络超时重试非常常见。微信支付回调可能重复推送,如果订单状态机没做好,就会出现“一次下单扣两次钱”。
// 伪代码:基于订单号做幂等锁
async function handlePayNotify(orderId, transactionId) {
const order = await db.getOrder(orderId);
if (order.status !== 'PENDING') {
return { code: 'SUCCESS' }; // 已处理,直接返回成功
}
const updated = await db.updateOrderStatus(
orderId,
'PENDING',
'PAID',
{ transactionId }
);
if (!updated) {
return { code: 'SUCCESS' };
}
await notifyMerchant(orderId);
return { code: 'SUCCESS' };
}关键点:用数据库的条件更新(WHERE status = 'PENDING')来保证原子性,而不是先查再改。
2. 地址与定位的边界处理
用户下单地址经常出现“定位到了但门牌号不对”“超出配送范围却还能下单”的问题。我的做法是:
- 用微信
chooseLocation获取经纬度,但必须让用户手动补全门牌号 - 配送范围用多边形或半径判断,在提交订单前二次校验,而不是只在进入页面时校验
- 保存地址时记录经纬度,方便后续骑手导航
3. 库存与超卖
外卖的库存和电商不同,很多菜品是现做的,库存可以“虚”。但套餐、限量商品必须防超卖。推荐用 Redis 预扣减 + 数据库最终扣减:
// 下单前预扣库存
const remain = await redis.decr(`stock:${skuId}`);
if (remain < 0) {
await redis.incr(`stock:${skuId}`);
throw new Error('库存不足');
}
// 支付成功后落库,超时未支付则回补4. 订单状态机要清晰
外卖订单状态比普通电商多,建议提前画好状态流转图。常见状态:待支付 → 待接单 → 制作中 → 待配送 → 配送中 → 已送达 → 已完成,外加已取消、已退款。每个状态变更都要记录操作人和时间,方便对账和客诉。
5. 消息通知与推送
用户最关心“我的餐到哪了”。微信小程序的订阅消息有次数限制,建议:
- 在支付成功页引导用户订阅“订单状态变更”
- 关键节点(接单、配送、送达)各推一次,不要滥用
- 商家端用 WebSocket 或轮询保证接单及时
三、性能与体验上的小细节
- 菜单页图片全部走 CDN 并压缩,外卖用户多在移动网络下浏览
- 购物车用本地缓存 + 服务端校验,避免切换设备后数据丢失
- 下单接口做防抖,防止用户狂点提交
- 金额统一用整数分计算,避免浮点误差
外卖小程序开发最怕的不是技术难,而是业务边界没想清楚。支付、库存、状态机这三块一旦出问题,就是真金白银的损失。
四、上线前必做的检查清单
- 支付回调幂等测试(模拟重复通知)
- 订单超时未支付自动取消并回补库存
- 配送范围边界测试(刚好超出 1 米)
- 退款流程走通,包括部分退款
- 商家端断网重连后能补拉未接订单
如果你正在做外卖小程序,建议先把订单状态机和支付幂等这两块写扎实,后面的功能都是在这上面叠加。希望这篇避坑指南能帮你少熬几个夜。
评论 (0)
还没有评论,快来抢沙发吧~