全球收单 › Webhook
扫码付订单状态
一笔扫码付到达终局时发送。
事件类型
| 事件 | 什么时候发 |
|---|---|
qrpay.order.completed | 扫码付成功,上游已向收单商户放行 |
qrpay.order.failed | 扫码付未成功,扣款已全额退回可用余额 |
qrpay.order.refunded | 扫码付被退款,款项已退回会员可用余额 |
投递约定
- 我方向你配置的端点发
POST,application/json,超时 10 秒。 - 回任意 2xx 即视为收到。 非 2xx 或超时会按退避重投。
- 请求头四个:
content-type·z-signature·z-event-id·z-event-type。 - 按
z-event-id去重 —— 同一条事件可能到达多次。
事件体只带 ID 与状态
没有金额、没有资产代码、没有卡号的任何片段、没有风控原因。这不是省字节 ——
webhook 端点是你的服务,我方没有办法保证它的传输与存储;
而 GET /v1/<资源>/{id} 那条路径上有 API Key、scope、
代理会员三层校验。要详情就拿 data.id 回查,
别指望从事件体里读出金额来记账。
逐条
qrpay.order.completed
扫码付成功,上游已向收单商户放行什么时候发
上游确认该笔付款完成那一刻。这是终态。
事件体
{
"event_id": "evt_bd15c8073e4a49f2861b09df7ac35e10",
"event_type": "qrpay.order.completed",
"created_at": "2026-08-12T15:07:52Z",
"merchant_id": "acme",
"livemode": true,
"data": {
"object": "qrpay_order",
"id": "6d3f9b21-8c07-4a5e-91d4-27e0b6a3fc58",
"external_member_id": "u_88123",
"status": "completed",
"status_version": 4
}
}qrpay.order.failed
扫码付未成功,扣款已全额退回可用余额什么时候发
上游拒付、走廊未开通、报价过期都会走到这里 —— 失败不是罕见路径。没有这条事件时你唯一的知情方式是轮询,而轮询要先知道有单可查:你等到的会是一条永远不来的 completed。
事件体
{
"event_id": "evt_af02e71d94b6435c8071cd23e6b95f4a",
"event_type": "qrpay.order.failed",
"created_at": "2026-08-12T15:09:03Z",
"merchant_id": "acme",
"livemode": true,
"data": {
"object": "qrpay_order",
"id": "6d3f9b21-8c07-4a5e-91d4-27e0b6a3fc58",
"external_member_id": "u_88123",
"status": "failed",
"status_version": 3
}
}qrpay.order.refunded
扫码付被退款,款项已退回会员可用余额什么时候发
收单侧退款到达之后。它直接影响会员余额,所以与 failed 分开一条 ——两者在你账上的含义不同(一个是这笔从没成过,一个是成了又退)。
事件体
{
"event_id": "evt_5c8b0a2f61d7452e93af6b04d18e37c9",
"event_type": "qrpay.order.refunded",
"created_at": "2026-08-13T10:21:35Z",
"merchant_id": "acme",
"livemode": true,
"data": {
"object": "qrpay_order",
"id": "6d3f9b21-8c07-4a5e-91d4-27e0b6a3fc58",
"external_member_id": "u_88123",
"status": "refunded",
"status_version": 6
}
}验签
验签方式与所有事件一致,见 Webhook 概览; 可以用签名调试器逐字符比对签名串。