同城外卖小程序搭建指南:快速落地本地化O2O配送平台
本地生活消费持续增长,不少创业者、实体商家希望搭建自有同城外卖平台,摆脱第三方平台高额抽佣限制。这套同城外卖系统完整覆盖用户、商家、骑手、平台管理四端,支持二次开发与功能自定义,能够快速搭建餐饮外卖、商超零售、同城跑腿一体化本地服务平台。
本文将从系统架构、核心功能、数据库设计、关键代码、技术选型、业务扩展几个维度,讲解同城外卖小程序整体搭建思路。
一、同城外卖整体架构设计
整套系统采用前后端分离架构,四端共用同一套API服务层,保障数据实时同步,避免数据孤岛。包含四大业务终端:
1. 用户端小程序
面向普通消费者,主要能力:
- 附近商家浏览、商家筛选搜索
- 商品查看、规格选择、加入购物车
- 收货地址管理、在线下单支付
- 订单查询、实时配送轨迹跟踪
- 优惠券使用、订单评价、售后申请
2. 商家管理端(小程序+PC后台)
供入驻商家日常经营管理:
- 店铺基础信息、营业时间、配送围栏设置
- 商品分类维护、商品上下架、库存管理
- 订单接单/拒单、出餐操作
- 营销活动配置(满减、折扣)
- 店铺销售报表、营收数据查看
3. 骑手配送端(小程序/APP)
骑手履约接单模块:
- 待接单订单列表展示,支持抢单+平台自动派单
- 到店确认、取餐、送达更新配送状态
- 导航路线跳转,实时上报骑手位置
- 配送收益明细、提现申请
4. 平台总管理后台
平台运营方统一管控全平台业务:
- 用户、商家、骑手账号审核与管理
- 全部订单监控、异常订单处理
- 平台抽佣比例配置、财务结算对账
- 营销活动配置、全局数据统计分析
简化架构示意:
用户小程序
|
商家端 ---- API网关&服务层 ---- 平台管理后台
|
骑手端
|
MySQL + Redis 数据层
二、同城外卖核心功能设计
1. 商家与商品列表模块
用户打开小程序优先加载周边商家,进入店铺展示商品分类、菜品信息、售价库存。
商品数据表示例:
CREATE TABLE mc_goods (
id INT PRIMARY KEY AUTO_INCREMENT,
shop_id INT COMMENT '所属商家ID',
category_id INT COMMENT '商品分类ID',
name VARCHAR(100) COMMENT '商品名称',
image VARCHAR(255) COMMENT '商品图片',
price DECIMAL(10,2) COMMENT '售价',
original_price DECIMAL(10,2) COMMENT '原价',
stock INT DEFAULT 0 COMMENT '库存',
sales INT DEFAULT 0 COMMENT '销量',
status TINYINT DEFAULT 1 COMMENT '1上架 0下架'
);
商品查询接口示例(SpringBoot Controller)
@GetMapping("/goods/list")
public Result<?> getGoodsList(@RequestParam Integer shopId){
List<McGoods> list = goodsService.lambdaQuery()
.eq(McGoods::getShopId,shopId)
.eq(McGoods::getStatus,1)
.list();
return Result.success(list);
}
接口返回商品数据,小程序前端渲染商品列表页面。
三、购物车与订单生成功能
用户选择商品加入购物车,系统自动计算商品总价、配送费、优惠抵扣,生成正式订单。
购物车金额计算工具方法:
/**
* 计算购物车总金额
*/
public BigDecimal calculateCartAmount(List<CartItem> cartList){
BigDecimal total = BigDecimal.ZERO;
for(CartItem item : cartList){
BigDecimal itemTotal = item.getPrice().multiply(new BigDecimal(item.getNumber()));
total = total.add(itemTotal);
}
return total;
}
创建订单核心逻辑:
/**
* 创建外卖订单
*/
public OrderVO createOrder(Long userId, List<CartItem> cartList,Long shopId){
BigDecimal goodsAmount = calculateCartAmount(cartList);
//计算配送费、优惠金额
BigDecimal deliveryFee = calcDeliveryFee(shopId,userId);
BigDecimal discountAmount = calcCouponDiscount(userId,goodsAmount);
BigDecimal payAmount = goodsAmount.add(deliveryFee).subtract(discountAmount);
McOrder order = new McOrder();
order.setUserId(userId);
order.setShopId(shopId);
order.setGoodsAmount(goodsAmount);
order.setDeliveryFee(deliveryFee);
order.setDiscountAmount(discountAmount);
order.setPayAmount(payAmount);
order.setOrderStatus(OrderStatus.WAIT_PAY.getCode());//待支付
orderMapper.insert(order);
//保存订单明细、清空用户购物车
saveOrderDetail(order.getId(),cartList);
cleanUserCart(userId,shopId);
return convertOrderVO(order);
}
完整订单状态流转:
待支付
↓(用户付款)
已支付
↓(商家接单)
商家已接单
↓(骑手取餐)
配送中
↓(确认送达)
订单已完成
四、骑手配送调度与订单状态管理
系统支持抢单、自动派单两种模式,后台可以自由切换调度模式,订单状态变更实时推送小程序端。
订单状态常量定义:
public enum OrderStatus {
WAIT_PAY(1,"待支付"),
PAID(2,"已支付待接单"),
SHOP_ACCEPT(3,"商家已接单"),
DELIVERYING(4,"配送中"),
FINISH(5,"订单完成"),
CANCEL(-1,"订单取消");
}
骑手接单接口示例:
@PostMapping("/rider/acceptOrder")
public Result<?> acceptOrder(@RequestBody RiderAcceptDTO dto){
McOrder order = orderMapper.selectById(dto.getOrderId());
//状态校验,必须为已支付待接单才允许接单
if(!order.getOrderStatus().equals(OrderStatus.PAID.getCode())){
return Result.fail("订单状态异常,无法接单");
}
//更新骑手ID与订单状态
order.setRiderId(dto.getRiderId());
order.setOrderStatus(OrderStatus.SHOP_ACCEPT.getCode());
orderMapper.updateById(order);
//消息推送通知用户、商家
messagePushService.pushOrderAcceptNotice(order);
return Result.success("接单成功");
}
五、地图LBS配送路线能力
基于第三方地图SDK实现同城配送核心能力:
- 用户收货地址解析经纬度
- 商家配送围栏校验,判断用户是否可下单
- 骑手实时位置上报
- 取餐点到收货点路线规划,预估配送时长
路线请求示例:
/**
* 获取两点之间导航路线
* @param start 起点经纬度
* @param end 终点经纬度
* @return 路线信息
*/
public Map getRoute(String start,String end){
Map<String,Object> params = new HashMap<>();
params.put("origin",start);
params.put("destination",end);
params.put("key",mapConfig.getKey());
return restTemplate.getForObject(mapConfig.getDirectionUrl(),Map.class,params);
}
六、微信支付订单处理
完整支付业务流程:
用户提交订单
↓
生成平台业务订单
↓
调用微信统一下单接口获取支付参数
↓
小程序调起微信支付
↓
微信异步回调通知服务端
↓
校验回调签名,更新订单状态,推送消息通知
支付回调处理示例:
@PostMapping("/pay/wxNotify")
public String wxPayNotify(HttpServletRequest request){
//解析微信回调xml参数、校验签名
WxPayNotifyResp resp = wxPayUtil.parseNotify(request);
if(resp.isSuccess()){
String orderNo = resp.getOutTradeNo();
McOrder order = orderMapper.selectByOrderNo(orderNo);
order.setOrderStatus(OrderStatus.SHOP_ACCEPT.getCode());
order.setPayTime(new Date());
orderMapper.updateById(order);
//投递消息队列,后续执行营销、统计任务
rocketMQTemplate.convertAndSend("order-pay-topic",order);
}
return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
}
七、平台后台数据统计功能
平台运营依靠统计数据把控业务情况,部分SQL示例:
统计每日订单量:
SELECT DATE(create_time) AS day, COUNT(*) AS order_count
FROM mc_order
GROUP BY day ORDER BY day DESC;
统计平台实际成交总营收:
SELECT SUM(pay_amount) AS total_income
FROM mc_order
WHERE order_status = 5; --5代表已完成订单
商家维度销售统计:
SELECT shop_id,shop_name,COUNT(id) AS order_num,SUM(pay_amount) AS shop_sales
FROM mc_order
WHERE order_status=5
GROUP BY shop_id;
八、开发技术选型
小程序&前端
- 用户/商家/骑手小程序:UniApp,一套代码编译多端,支持H5、小程序
- PC平台管理后台:Vue3 + Element‑Plus
后端服务
- 核心框架:SpringBoot + MyBatis‑Plus
- 消息队列:RocketMQ(异步处理订单事件、消息推送、削峰填谷)
- 网关:SpringCloud Gateway(鉴权、限流)
数据库 & 缓存
- MySQL 8.0:存储业务主数据(订单、商品、商家、用户、结算)
- Redis:缓存商家列表、商品库存、骑手地理位置GEO索引、分布式锁防超卖
部署环境
- 服务器:Linux CentOS / Ubuntu
- Web服务:Nginx(反向代理、HTTPS证书)
- 容器:Docker & Docker‑Compose,快速部署整套环境
项目目录结构:
mc‑food‑system
├─user 用户模块
├─shop 商家门店模块
├─goods 商品模块
├─cart 购物车模块
├─order 订单核心模块
├─rider 骑手配送调度
├─payment 支付模块
├─marketing 营销优惠券
└─admin 平台后台
九、后期扩展方向
基础外卖系统部署完成后,可按需迭代拓展业务能力:
- 会员营销体系
会员等级、充值余额、优惠券、积分签到、拼团、预订单。 - 多商家入驻平台模式
商家在线申请入驻、平台审核、自定义抽佣比例、周期自动结算。 - 综合同城跑腿
代买、代取件、代送,不局限餐饮,拓展商超、鲜花、药品即时配送。 - 连锁门店能力
连锁品牌多门店管理、统一商品库、门店库存独立。 - 数据运营与BI报表
用户画像分析、商家经营看板、骑手效率统计、订单预警。
总结
同城外卖小程序不只是简单的点餐工具,是一套完整的本地生活O2O业务体系,打通用户消费‑商家经营‑骑手履约‑平台管控全链路。
通过合理的四端架构设计、订单状态机、缓存+消息队列处理高并发,能够满足中小城市、县城本地外卖创业需求。基于现有源码做二次开发,可以快速叠加会员、跑腿、连锁门店等业务,适配不同本地生活业务场景。