虚拟商品自动发货的技术要点:从状态机到重试与幂等
把交付链路做成可追溯系统:状态机怎么拆?哪些字段必须记录?失败如何重试?幂等如何落地?
“自动发货”听起来像一个按钮,实际是一个系统:它需要在可控风险下完成交付,并且在出现问题时能复盘、能恢复、能对账。 下面给出一套更接近工程实践的拆解方式,适合用来写官网的解决方案页,也适合做内部对接文档的骨架。
目录
1)订单状态机:把“交付”写成可枚举的流程
最容易出问题的写法是只用两个状态:成功/失败。实践中你需要更多中间态,才能描述“正在处理”“可重试失败”“需要人工介入”等情况。 一个常见的最小状态机如下(可按品类扩展):
- CREATED:订单创建,尚未占用库存
- RESERVED:库存已占用(或卡密已锁定)
- DELIVERING:正在交付(发码/激活/调用上游)
- DELIVERED:交付完成(获得交付凭证)
- FAILED_RETRYABLE:失败但可重试(网络/回调超时等)
- FAILED_FINAL:最终失败(库存不足/签名错误等)
重要的是:每个状态都要有明确含义、允许的下一跳、以及对账口径。这样写在官网上,搜索引擎也能更容易理解你的业务图谱。
2)幂等与重试:避免重复发货与无穷重试
幂等与重试是一对“经常被混用”的概念。幂等解决的是重复请求;重试解决的是暂时性失败。 对接时建议遵循两条原则:
- 幂等键唯一:以外部订单号或 idempotency_key 作为唯一键;同一个键永远返回同一份交付结果。
- 重试有边界:对可重试错误采用指数退避(例如 2s/5s/15s/60s),并设置最大次数与告警。
另外,回调(Webhook)也必须幂等:对方可能重复推送同一事件,你需要以事件 ID 或订单号去重消费。
3)关键字段:为什么需要审计与事件日志
自动发货系统的“专业度”往往体现在你是否能回答这些问题:这单是谁触发的?用了哪一批库存?交付凭证是什么?回调失败过几次? 建议最少保留以下字段(不一定公开,但必须在系统中存在):
request_id
每次请求的追踪 ID,用于串联接口日志与排障。
batch_id
库存批次号(或供应来源标识),用于审计与召回。
delivery_proof
交付凭证(发出的码/激活结果摘要),用于对账与售后。
4)对账口径:成功、失败、补发、退款怎么定义
规模化之后,真正消耗成本的往往不是“发货慢”,而是“口径不一致”。建议把对账口径写成一张表:
- 成功:是否以 DELIVERED 为准?还是以回调成功为准?
- 失败:FAILED_FINAL 才计入失败?FAILED_RETRYABLE 如何处理?
- 补发:是否生成新的交付流水?是否关联原订单?
- 退款/取消:库存是否回滚?如何在账务上标记?
这些内容同样适合沉淀在官网的解决方案页与 FAQ 中,长期来看会显著降低沟通与维护成本。