{
  "synthetic": true,
  "execution": "Teaching record only; no live integration tested",
  "slug": "stripe-request-retry-register",
  "group": "commerce",
  "title": [
    "A timed-out payment request needs a retry register",
    "付款请求超时后，先查重试登记"
  ],
  "intro": [
    "A connection timeout does not tell a business whether the provider created an object. Before approving a retry button, agree how the same business operation keeps its identity. This concerns outbound creation requests, separately from receiving duplicate webhooks.",
    "网络超时不能告诉商家平台是否已创建对象。批准“重试”按钮前，应约定同一商业操作怎样保持身份。这处理发出的创建请求，与接收重复webhook是不同决定。"
  ],
  "facts": [
    [
      "Stripe API v1 can replay the saved response for the same idempotency key, including a 500; changed parameters are checked, and pruned keys can lead to a new request.",
      "Stripe API v1可按同一幂等键重放已保存响应，包括500；会核对参数，键被清理后再次使用可能成为新请求。",
      "https://docs.stripe.com/api/idempotent_requests"
    ]
  ],
  "columns": [
    [
      "Register entry",
      "Observed condition",
      "Decision"
    ],
    [
      "登记项",
      "观察条件",
      "决定"
    ]
  ],
  "example": [
    [
      [
        "Order O41 / attempt K41 / AUD 120",
        "Timeout after send; result unknown",
        "Retrieve/reconcile; retry same operation with K41"
      ],
      [
        "订单O41／尝试K41／AUD120",
        "发送后超时；结果未知",
        "先回读核对；同一操作沿用K41重试"
      ]
    ],
    [
      [
        "K41 / original AUD 120",
        "User now requests AUD 150",
        "Parameter change; do not reuse as the same request"
      ],
      [
        "K41／原AUD120",
        "用户改为AUD150",
        "参数改变；不能冒充原请求"
      ]
    ],
    [
      [
        "K42 / saved 500",
        "Second request returns 500 again",
        "Escalate/reconcile; a new key is not a safe fix"
      ],
      [
        "K42／已保存500",
        "再次仍返回500",
        "升级核对；换新键不是安全修复"
      ]
    ],
    [
      [
        "K43 / historical attempt",
        "Beyond provider retention; state unresolved",
        "Manual reconciliation before creating anything new"
      ],
      [
        "K43／历史尝试",
        "已超过平台保留窗口；结果未明",
        "先人工对账，再决定是否新建"
      ]
    ]
  ],
  "steps": [
    [
      "Allocate an opaque operation ID before sending and store its payload fingerprint, provider object ID when known, response and timestamps. Do not put customer email or card data in the key.",
      "发送前分配不含个人信息的操作ID，保存参数指纹、已知平台对象ID、响应和时间；键不能含邮箱或银行卡资料。"
    ],
    [
      "Simulate a lost response after successful creation. The acceptance output must contain one business object after reconciliation, not two objects with different keys.",
      "模拟创建成功但响应丢失；核对后应只有一个商业对象，不能因为换键而出现两个。"
    ],
    [
      "Separate network retry, validation correction and a genuinely new order into different states. Define bounded retries and a human resolution path for unknown outcomes.",
      "区分网络重试、参数纠错与真正新订单；设有界重试及未知结果的人工处理路径。"
    ]
  ],
  "result": [
    "The register makes an uncertain request resumable without treating uncertainty as failure. A same-key replay is not proof that downstream fulfilment happened, and an endpoint response is not a bank settlement. A useful supplier handover can trace O41 to its request identity and final provider object without exposing credentials.",
    "登记表让未知请求可接续，而不把未知当失败。同键重放不证明后续已履约，接口响应也不等于银行结算。合格交付能从O41追到请求身份及最终平台对象，无需暴露凭证。"
  ],
  "accept": [
    "Require a loss-of-response exercise, a changed-payload exercise and a retained 500 exercise against the documented API version. Record final object count and unresolved outcomes.",
    "按文档版本演练丢响应、参数改变和已保存500三种情况，记录最终对象数及未明结果。"
  ],
  "limit": [
    "Synthetic register, no Stripe request sent. This is specifically API v1 behaviour; API v2 differs. Keys do not provide permanent business deduplication or replace database constraints and reconciliation.",
    "合成登记表，没有发送Stripe请求。这里专指API v1，v2行为不同；幂等键不提供永久业务去重，也不能代替数据库约束及对账。"
  ]
}
