同步跳转
概述
同步跳转(Sync Callback)是支付完成后,平台将用户浏览器(而非商户服务器)跳转回商户 returnUrl 的通知方式。跳转 URL 在商户 returnUrl 基础上追加订单关键参数,并用平台私钥签名,商户可用平台公钥验签确认跳转来源可信。
与 异步回调 的本质区别:
| 维度 | 同步跳转 | 异步回调 |
|---|---|---|
| 接收方 | 商户页面(浏览器) | 商户服务器 |
| 传递方式 | 浏览器 302 跳转,参数拼在 URL query | 服务端 HTTP POST(JSON)或 MQ 推送 |
| 触发时机 | 用户支付完成后浏览器回跳 | 订单状态变更后立即投递 |
| 可靠性 | 一次,无重试(用户可关闭浏览器) | 16 次递增重试 |
| 验签 | 平台公钥验签 query 参数 | 平台公钥验签报文 |
| 用途 | 展示"支付成功"结果页 / 引导用户回商户 | 处理订单状态变更业务 |
同步跳转不是支付成功的权威依据
同步跳转依赖浏览器行为:用户可能关闭页面、网络中断、浏览器崩溃,导致跳转丢失或重复。订单最终状态必须以异步回调或主动查询接口为准,商户不应仅凭同步跳转参数落库对账。
完整流程
- 商户下单时传入
returnUrl(统一支付 / 网关预下单)。 - 平台发起支付;仅支付宝 PC/WAP 网页支付会把通道同步回跳地址设置为平台 H5 结果页
{paymentGatewayBaseUrl}/pay-result/{tradeNo}。 - 支付完成后,通道把用户浏览器带回平台结果页。
- 结果页凭
tradeNo调用平台无签名查询接口,获取订单权威状态。 - 状态为
paid且订单存在商户returnUrl时,平台生成带签名的跳转地址(订单参数追加到 returnUrl)。 - 结果页倒计时(3 秒)后自动跳转商户页面;无
returnUrl或非paid则展示平台结果结束页。 - 商户页面收到跳转后先验签,再展示结果;最终订单状态以异步回调为准。
跳转参数
平台生成的跳转地址 = 商户 returnUrl + query 参数。若 returnUrl 自身已携带参数,平台以 & 衔接;参数值做 URL 编码。
| 参数 | 类型 | 描述 |
|---|---|---|
| code | int | 状态码(0 = 成功) |
| msg | string | 状态描述 |
| tradeNo | string | 资金交易号(平台生成,反查权威) |
| orderNo | string | 平台业务单号(空值时不携带) |
| bizOrderNo | string | 商户业务单号(空值时不携带) |
| status | string | 订单状态(同步跳转恒为 paid) |
| amount | long | 订单金额(分,空值时不携带) |
| sign | string | 平台 RSA 签名(Base64,URL 编码) |
跳转地址示例:
https://merchant.example.com/return?code=0&msg=success&tradeNo=T2024120112345700001&orderNo=P2024120112345700001&bizOrderNo=ORDER20241201001&status=paid&amount=100&sign=Base64%E7%AD%BE%E5%90%8D%E5%80%BC验签方式
商户接收同步跳转后,必须验证 sign 字段,确认跳转由 DaxPay 平台发出且参数未被篡改。验签规则与异步回调一致:
- 取 URL 中全部 query 参数。
- 移除
sign参数。 - 排除值为空的参数。
- 按 key 的 ASCII 码升序排列。
- 拼接为
key1=value1&key2=value2格式(注意 query 中的值是 URL 解码后的原文)。 - 使用平台公钥以
SHA256withRSA验签。
验签代码示例参见 签名机制。
注意事项
以异步回调为准
同步跳转仅用于"支付完成后把用户带回商户页面并展示结果",不作为订单状态落库依据。用户可能关闭浏览器导致跳转丢失、也可能反复回访触发重复跳转。请始终以异步回调或查询接口为准。
- 通道覆盖有限:真正走"通道回跳 → 平台结果页 → 带签名跳商户"闭环的仅支付宝 PC/WAP 网页支付。微信/银联/抖音等 JSAPI 场景由前端 H5 查单判定支付成功后跳转;未接入同步回跳的通道,
returnUrl不生效(商户仍可自行轮询)。 - 仅
paid回跳:failed/closed/expired状态不会跳转商户,用户在平台结果页看到对应状态与"关闭页面"按钮。 - 状态未就绪不跳转:支付成功后通道回调可能有短暂延迟。平台倒计时(3 秒)缓冲后查单;若订单仍未进入
paid,平台不生成跳转地址、不跳转——宁可停留在结果页,也不会裸跳无签名的 returnUrl(无签名地址商户无法验签,且会掩盖真实问题)。 - 重入已支付订单不自动跳:已支付订单被再次扫码或回访时,只展示成功结果卡,不自动跳转;用户可点击"返回商户"按钮手动跳转。
- PC 聚合引导页不回跳:PC 端展示二维码的聚合引导页在支付完成后不回跳商户
returnUrl(支付发生在手机端,手机端才是回跳设备),避免手机与 PC 双端重复回跳商户造成重复处理。 - 会话级幂等:同一浏览器会话内仅自动跳转一次(前端 sessionStorage 标记)。换设备、清缓存、无痕模式下可能再次触发跳转——无服务端幂等,商户侧需自行容忍重复跳转。
- tradeNo 获取:跳转参数中的
tradeNo与支付发起响应NormalPayResult.tradeNo对应。商户如需提前保存,应使用支付发起响应中的值;预下单/查单早期阶段tradeNo可能为空(资金交易在发起支付时才创建)。 - 不含 attach:同步跳转是精简参数集,不携带商户扩展参数
attach。需要完整订单快照(含 attach、通道、支付时间等)请以异步回调为准。 - returnUrl 拼接兼容:
returnUrl自身若已有 query 参数,平台以&衔接;空字段参数不会出现(如orderNo/bizOrderNo/amount可能缺失)。商户页面需容忍未知/缺失参数。 - 平台配置:平台需配置
paymentGatewayBaseUrl(平台配置-基础配置),否则无法生成支付宝同步回跳地址。 - 必做验签:跳转 URL 可被任何人构造(returnUrl 本身公开),必须验签后再处理,防止伪造跳转诱导用户。