
很多平台前端看着差不多,但一旦订单量上来,状态错乱、重复结算、骑手账目对不上,问题马上爆发。
今天我们从系统设计角度,把核心逻辑拆清楚,并附带关键代码示例。

一个成熟的外卖配送开发系统,订单至少包含以下状态:
1. CREATED 已创建(待支付)
2. PAID 已支付(待接单)
3. ACCEPTED 商户已接单
4. PREPARING 制作中
5. WAITING_DELIVERY 待骑手接单
6. DELIVERING 配送中
7. COMPLETED 已完成
8. CANCELLED 已取消
9. REFUNDING 退款中
10. REFUNDED 已退款CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
merchant_id BIGINT NOT NULL,
rider_id BIGINT,
total_amount DECIMAL(10,2),
pay_amount DECIMAL(10,2),
status VARCHAR(32),
created_at DATETIME,
updated_at DATETIME,
version INT DEFAULT 0
);CREATE TABLE order_status_logs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT,
from_status VARCHAR(32),
to_status VARCHAR(32),
operator_type VARCHAR(32),
created_at DATETIME
);public enum OrderStatus {
CREATED,
PAID,
ACCEPTED,
PREPARING,
WAITING_DELIVERY,
DELIVERING,
COMPLETED,
CANCELLED,
REFUNDING,
REFUNDED
}@Transactional
public void changeStatus(Long orderId, OrderStatus newStatus) {
Order order = orderRepository.findById(orderId);
OrderStatus oldStatus = order.getStatus();
if (!canTransfer(oldStatus, newStatus)) {
throw new RuntimeException("非法状态流转");
}
order.setStatus(newStatus);
order.setVersion(order.getVersion() + 1);
orderRepository.update(order);
orderStatusLogRepository.save(
new OrderStatusLog(orderId, oldStatus, newStatus)
);
}private boolean canTransfer(OrderStatus from, OrderStatus to) {
Map<OrderStatus, List<OrderStatus>> flowMap = new HashMap<>();
flowMap.put(OrderStatus.CREATED, Arrays.asList(OrderStatus.PAID, OrderStatus.CANCELLED));
flowMap.put(OrderStatus.PAID, Arrays.asList(OrderStatus.ACCEPTED, OrderStatus.CANCELLED));
flowMap.put(OrderStatus.ACCEPTED, Arrays.asList(OrderStatus.PREPARING));
flowMap.put(OrderStatus.PREPARING, Arrays.asList(OrderStatus.WAITING_DELIVERY));
flowMap.put(OrderStatus.WAITING_DELIVERY, Arrays.asList(OrderStatus.DELIVERING));
flowMap.put(OrderStatus.DELIVERING, Arrays.asList(OrderStatus.COMPLETED));
return flowMap.getOrDefault(from, Collections.emptyList()).contains(to);
}这一层是系统稳定的关键。 没有这层控制,订单一定乱。

一个标准分账模型:
用户支付金额 = 商品金额 + 配送费
平台抽佣 = 商品金额 × 抽佣比例
骑手收入 = 配送费
商户收入 = 商品金额 - 平台抽佣CREATE TABLE order_settlement (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT,
merchant_income DECIMAL(10,2),
rider_income DECIMAL(10,2),
platform_income DECIMAL(10,2),
settlement_status VARCHAR(32),
created_at DATETIME
);@EventListener
public void handleOrderCompleted(OrderCompletedEvent event) {
settle(event.getOrderId());
}@Transactional
public void settle(Long orderId) {
Order order = orderRepository.findById(orderId);
BigDecimal commissionRate = new BigDecimal("0.15");
BigDecimal platformIncome =
order.getTotalAmount().multiply(commissionRate);
BigDecimal merchantIncome =
order.getTotalAmount().subtract(platformIncome);
BigDecimal riderIncome =
order.getDeliveryFee();
OrderSettlement settlement = new OrderSettlement();
settlement.setOrderId(orderId);
settlement.setMerchantIncome(merchantIncome);
settlement.setPlatformIncome(platformIncome);
settlement.setRiderIncome(riderIncome);
settlement.setSettlementStatus("PENDING");
settlementRepository.save(settlement);
}解决方案:
UNIQUE KEY uk_order_id (order_id)使用:
建议:
通过消息队列解耦,避免强依赖。
外卖配送开发系统真正的核心不是:
而是:
如果你的系统不能清楚回答:
“这笔钱从哪来,分给谁,什么时候分,为什么这么分?”
那平台一定走不远。

外卖配送开发系统本质是:
订单驱动型 + 资金驱动型平台。
前端只是表象, 真正的壁垒在于:
如果你在做本地生活或同城配送项目,建议优先把这两块打牢。 系统稳定,商业模式才有意义。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。