失败后重新建单¶
客户在收银台支付失败(拒付、鉴权失败等)后,若希望换一条支付通道再试,请再调用一次创建收款单,并传入 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_id 当 retry_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_paid、in_progress、declined、auth_failed、cancelled_by_customer、technical_failure、expired、order_closed。
这是纯查询接口,不会占用任何支付额度、不影响后续路由。限流与查单一致(商户 300 次/分)。
人工干预换通道¶
运营确认客户在已发出的链接里付不了、需要指定另一条通道再发新链接时,按下面 4 步做:
GET /api/v1/open/charges/{orderId}/retry-advice:确认值得重试(retry_recommended),并记下retry_of。GET /api/v1/open/payment-gateways?retry_of={orderId}:查看当前可用通道;优先选used_in_retry_group与shares_account_with_retry_group均为false的项。详见 获取可用支付通道。POST /api/v1/open/charges:同时传retry_of、gateway_id和新的merchant_order_id(不可复用前序业务单号)。不要同时传payment_methods。- 立即停止分发旧
payment_url,只把新链接给客户。
指定 gateway_id 的订单按 V1 收银台建单,收银页为 /pay/{charge_code},域名可能与该商户平时的收银页不同。
请求要点¶
retry_of:上表得到的 UUID(须属于当前 API 密钥对应商户)。merchant_order_id:必须换新业务单号;复用前序单号会409。- 金额、币种、账单地址等按本次应收重新传入(可与前序相同)。
- 建议为重试请求使用新的
Idempotency-Key。 - 成功后引导客户打开新的
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 次/分) |
字段表见 创建收款单。