摘要

  • Stripe API v1 的 POST 一旦开始执行,就保存该幂等键第一次请求的状态码与响应体,连 500 也保存。同键重试在记录保留期间会拿到旧响应。
  • Stripe 指出 500 的实际结果不确定;事故恢复可能生成对象并通过 webhook 通知,而缓存响应不随之更新。API v2 的重试规则另有设计。

错误回执不会自动改口

支付系统收到 500,沿用同一幂等键重试,又收到 500。第二张红票看着像第二次失败;在 API v1,它可能只是第一张票的复印件。Stripe 在端点开始执行后保存状态码和响应体,Idempotent-Replayed: true 标记这次读取是重播。若监控只数 500 次数,便把回执数量当成了业务结果。

Stripe 对 500 的定义更棘手:操作可能已经产生副作用。事故恢复期间,Stripe 会尝试对账,并可能就创建的对象发出 webhook;缓存中的 500 不会因此变成成功响应。对账也未必完成。于是有两条需要并列记录的线:HTTP 回执和对象的实际状态。只凭其中一条下结论,都可能让下一次操作走错方向。

本地业务操作 ID 应在首次请求前生成,并写进对象元数据。收到 500 后,以该 ID 查找对象,检查 Dashboard 请求日志,核对签名验证后的 webhook。若尚无结果,就保留未决状态;此时换一把幂等键可能启动另一项操作。客服、财务和工程须对着同一个业务 ID 说话,而不是各自拿一张不同时间的回执。

版本差异同样关键。Stripe 描述的 API v2 重试不会重复已成功的操作,并会在可能时继续完成失败或部分失败的工作,返回更新后的响应。迁移时应把“同键重试会看到什么”写成明确合同;v1 的旧 500 与 v2 的新结果不能混进同一套仪表盘解释。

来源