摘要:反向海淘订单生命周期长、环节多,状态管理是技术难点。本文基于Taocarts系统的工程实践,详解订单状态机的设计与实现,涵盖8个核心状态的转换规则、超时自动处理机制,以及分布式订单创建场景下的本地消息表+MQ最终一致性方案。
一、订单状态定义
反向海淘订单相比普通电商订单多出采购、到仓等环节。Taocarts定义了以下8个核心状态:
PENDING_PAYMENT:待支付
PENDING_PURCHASE:待采购
PURCHASED:已采购
WAREHOUSED:已到仓
PENDING_SHIP:待发货
SHIPPED:已发货
COMPLETED:已完成
CANCELLED:已取消
二、状态机实现
使用有限状态机模型,定义状态间的合法转换。
python
class OrderStateMachine:
transitions = {
OrderState.PENDING_PAYMENT: [OrderState.PENDING_PURCHASE, OrderState.CANCELLED],
OrderState.PENDING_PURCHASE: [OrderState.PURCHASED, OrderState.CANCELLED],
OrderState.PURCHASED: [OrderState.WAREHOUSED, OrderState.CANCELLED],
# 更多转换规则...
}
def can_transition(self, current, target):
return target in self.transitions.get(current, [])
状态变更时记录操作日志,便于追溯。
三、超时自动处理
python
定时任务扫描超时订单
@task
def check_timeout_orders():
# 24小时未支付自动取消
pending_orders = Order.objects.filter(
status=OrderState.PENDING_PAYMENT,
created_at__lt=timezone.now() - timedelta(hours=24)
)
for order in pending_orders:
order.status = OrderState.CANCELLED
order.save()
类似逻辑处理待采购超时(3天提醒)、运输中超时(30天预警)。
四、分布式订单创建的最终一致性
反向海淘下单涉及跨系统调用:扣减虚拟库存、创建订单、发起支付、记录日志。Taocarts采用本地消息表+MQ方案保证最终一致性。
sql
-- 订单创建时同时写入消息表
BEGIN;
INSERT INTO orders(...);
INSERT INTO message_queue(topic, payload, status)
VALUES('order_created', '{"order_id":123}', 'pending');
COMMIT;
后台轮询消息表,发送成功则更新状态为processed,失败则重试3次后进入死信队列人工介入。
这套订单系统设计支撑Taocarts跨境电商独立站日均处理数千订单,零漏单、零重复。
- 反向海淘集运计费引擎:策略模式实现多渠道运费计算
摘要:国际集运费计算比普通快递复杂得多——首重续重、体积重、多国家差异化定价、多渠道路由。本文基于Taocarts系统的集运计费引擎,通过策略模式实现灵活可扩展的运费计算,代码可直接落地。
一、需求拆解
跨境电商独立站的运费计算需支持以下场景:
按重量计费或按体积重(长×宽×高÷5000)计费
首重+续重的阶梯计价
不同国家不同渠道价格表
多包裹合并时重新计算总运费
拼单场景下按重量比例分摊运费
二、策略模式实现
定义计费策略接口,不同渠道实现不同策略:
java
public interface FreightStrategy {
BigDecimal calculate(PackageInfo pkg, FreightRule rule);
}
// 实际重量策略
@Service
public class ActualWeightStrategy implements FreightStrategy {
@Override
public BigDecimal calculate(PackageInfo pkg, FreightRule rule) {
double weight = pkg.getActualWeight();
return rule.getFirstWeightPrice()
+ Math.ceil((weight - rule.getFirstWeight()) / rule.getAdditionalUnit())
* rule.getAdditionalPrice();
}
}
// 体积重策略
@Service
public class VolumetricWeightStrategy implements FreightStrategy {
@Override
public BigDecimal calculate(PackageInfo pkg, FreightRule rule) {
double volumetric = pkg.getLength() pkg.getWidth() pkg.getHeight() / 5000.0;
double weight = Math.max(pkg.getActualWeight(), volumetric);
// 后续同实际重量计算
}
}
三、多包裹合并与拼单分摊
java
public class CombinedFreightCalculator {
public BigDecimal calculate(List packages, String channel, String country) {
// 合并计算总重量和总体积重
double totalWeight = packages.stream().mapToDouble(PackageInfo::getActualWeight).sum();
double totalVolumetric = packages.stream()
.mapToDouble(p -> p.getLength() p.getWidth() p.getHeight() / 5000.0)
.max().orElse(0);
double finalWeight = Math.max(totalWeight, totalVolumetric);
// 使用首重续重公式计算
return freightStrategy.calculate(new PackageInfo(finalWeight), rule);
}
}
拼单场景下,系统按每个参与者的商品重量占比自动计算分摊运费,分摊明细在结算页展示。
四、渠道路由策略
Taocarts还实现了智能渠道路由——根据商品品类、目的地、客户时效要求自动推荐最优渠道。
python
def recommend_channel(product_category, destination, urgency):
if urgency == 'urgent':
return 'DHL'
elif product_category in ['electronics', 'luxury']:
return 'EMS' # 更稳妥的渠道
else:
return 'YunExpress' # 性价比最高
Taocarts的计费引擎已将主流渠道(云途、燕文、EMS、DHL)的价格表内置,后台配置后自动调用,无需开发。