跳转至

失败后重新建单

客户在收银台支付失败(拒付、鉴权失败等)后,若希望换一条支付通道再试,请再调用一次创建收款单,并传入 retry_of

平台不会在同一张未支付订单上自动换通道;失败转移靠「新单 + retry_of」完成。

旧链接必须由你回收

未支付的前序订单仍为 PENDING,平台不会自动关闭。请在创建重试单后立即停止分发旧 payment_url,否则客户仍可能用旧链接付款,造成同一笔业务重复收款。


如何拿到前序订单 ID

任选其一:

来源 字段
首次建单响应 order.id
Webhook / 查询接口 order.id
客户浏览器回跳 return_url 查询串中的 pay_order_id(平台支付订单 UUID)

return_url 示例(失败回跳):

https://merchant.example.com/pay/return
  ?payment_result=failed
  &pay_order_id=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
  &merchant_order_id=ORD-20260814-001

请用 pay_order_id 作为下一次请求的 retry_of不要merchant_order_idretry_of


先问一句:这单值得重试吗

建单前先调重试建议接口,避免无意义的重复建单:

curl -sS "{BASE_URL}/api/v1/open/charges/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/retry-advice" \
  -H "Authorization: Bearer sk.YOUR_MERCHANT.YOUR_SECRET"
{
  "retry_recommended": true,
  "reason": "declined",
  "last_failure": { "fail_kind": "DECLINE", "fail_code": "card_declined" },
  "attempts": { "total": 3, "failed": 2 },
  "alternatives_available": true,
  "retry_of": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}

怎么用这个结果:

字段 决策
retry_recommended: false + reason: already_paid 不要重试,这笔已经收到款(重复建单会有重复收款风险)
retry_recommended: false + reason: in_progress 客户可能正在付,稍后再查
retry_recommended: true + alternatives_available: true 存在可选通道。仅传 retry_of 的自动重试仍可能落到同一通道;要确保换目标请配合 gateway_id(见下方「人工干预换通道」)
retry_recommended: true + alternatives_available: false 列表口径下已无别的支付通道可换。建议引导客户改用其它支付方式,而不是反复重试
alternatives_available: null 平台暂时判定不了,可照常重试

reason 全部取值:already_paidin_progressdeclinedauth_failedcancelled_by_customertechnical_failureexpiredorder_closed

这是纯查询接口,不会占用任何支付额度、不影响后续路由。限流与查单一致(商户 300 次/分)。


人工干预换通道

运营确认客户在已发出的链接里付不了、需要指定另一条通道再发新链接时,按下面 4 步做:

  1. GET /api/v1/open/charges/{orderId}/retry-advice:确认值得重试(retry_recommended),并记下 retry_of
  2. GET /api/v1/open/payment-gateways?retry_of={orderId}:查看当前可用通道;优先选 used_in_retry_groupshares_account_with_retry_group 均为 false 的项。详见 获取可用支付通道
  3. POST /api/v1/open/charges:同时传 retry_ofgateway_id新的 merchant_order_id(不可复用前序业务单号)。不要同时传 payment_methods
  4. 立即停止分发旧 payment_url,只把新链接给客户。

指定 gateway_id 的订单按 V1 收银台建单,收银页为 /pay/{charge_code},域名可能与该商户平时的收银页不同。


请求要点

  1. retry_of:上表得到的 UUID(须属于当前 API 密钥对应商户)。
  2. merchant_order_id:必须换新业务单号;复用前序单号会 409
  3. 金额、币种、账单地址等按本次应收重新传入(可与前序相同)。
  4. 建议为重试请求使用新的 Idempotency-Key
  5. 成功后引导客户打开新的 payment_url

平台行为摘要:

  • 平台会避开该重试组内已用过的支付通道。
  • 传了 retry_of 就视为你明确要换通道,不区分前序单的失败类型(拒付、鉴权失败、客户取消一视同仁)。
  • 若已无其它通道可用,会保底回退到原通道并仍创建成功(不会仅因换不了通道而 422)。
  • 同一条重试链换过 5 次通道后,平台不再继续排除历史通道(此时通常已经把所有通道都试过了), 但仍会把新单归入同一重试组。建议在此之前就通过重试建议接口判断是否值得继续。

前序单不会自动关闭

创建重试单不会把前序单置为已取消,它仍是 PENDING。请停止向客户分发旧的 payment_url, 否则客户回到旧链接仍可完成支付,造成同一笔业务重复收款。

已付款的单不能作为重试起点

retry_of 指向的订单已经收到款,接口返回 409 且不创建新单——这是防重复收款的护栏。 重试前请先确认前序单确实未付(用查单接口或重试建议接口的 reason: already_paid)。


完整示例

假设首次建单返回 order.id = aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee,客户支付失败后回跳带上同一 pay_order_id

curl -sS -X POST "{BASE_URL}/api/v1/open/charges" \
  -H "Authorization: Bearer sk.YOUR_MERCHANT.YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "merchant_order_id": "ORD-20260814-001-RETRY1",
    "sales_channel": "WEB",
    "customer_region": "US",
    "amount": 99.00,
    "currency": "USD",
    "description": "Order ORD-20260814-001 retry",
    "retry_of": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "return_url": "https://merchant.example.com/pay/return",
    "notify_url": "https://merchant.example.com/hooks/3glob",
    "billing_address": {
      "name": "Jane Doe",
      "phone_national": "2025550123",
      "email": "jane@example.com",
      "country": "US",
      "state": "US-NY",
      "city": "New York",
      "address1": "1 Example St",
      "zip": "10001"
    }
  }'

成功时同样返回 201(或幂等命中 200)与新的 payment_url。将新链接发给客户即可。


错误

建单(POST /api/v1/open/charges):

HTTP 说明
404 retry_of 不存在或不属于当前商户(跨商户探测亦返回同一文案)
409 merchant_order_id 与历史单冲突;或 retry_of 指向的订单已支付
400 retry_of 非合法 UUID 等字段校验失败

重试建议(GET /api/v1/open/charges/:orderId/retry-advice):

HTTP 说明
401 鉴权失败
404 订单不存在或不属于当前商户
429 限流(商户 300 次/分)

字段表见 创建收款单