主题
商户异步通知
通知协议
支付成功以及转账成功/明确失败后,网关向请求中指定的 notifyUrl 发送 POST application/x-www-form-urlencoded。通知不是 JSON,也不使用开放接口的外层 {code,data,sign} 包装。
支付通知字段与 支付查询 基本一致,另含 reqTime(毫秒时间戳)和 sign。转账通知使用转账响应字段加 reqTime、sign,不保证含 mchNo / appId,应通过原商户订单定位应用密钥。
签名按通知全部非空字段计算,排除 sign,使用原应用私钥。通知字段中数字以表单文本传输,验签时保留原值,不要提前把时间或金额转换成浮点数。地址尽量使用无查询参数的专用路径,避免自带参数与业务字段重名影响验签。
退款通知边界
当前退款接口虽接受并保存 notifyUrl,但未实现商户退款结果通知投递。必须使用退款查询确认结果。渠道发送给网关的退款回调不等于网关已通知商户。
商户处理顺序
- 解析表单,定位订单对应的应用私钥,验证签名。
- 核对商户订单号、金额、币种和状态。
- 在商户自己的数据库事务中幂等更新订单,重复通知不能重复发货或入账。
- 业务提交成功后返回 HTTP 2xx,响应正文为
SUCCESS,不要返回 JSON 包装。
网关忽略正文大小写和首尾空白;其他响应或 HTTP 非 2xx 都视为失败。浏览器 returnUrl 跳转不能替代此流程。
重试及恢复
最多自动发送 6 次。每次失败后按当前累计次数乘 30 秒等待,第一次失败等待 30 秒、第二次等待 60 秒,以此类推。达到上限后进入通知失败状态,可由管理端人工重发。
通知租约和待发送时间持久化;进程中断后自动恢复。商户必须仍然支持重复通知,因为“商户提交成功但响应丢失”无法靠网关租约消除。支付失败和关闭不应依赖成功通知发现,应主动查单。
支付通知示例
以下是解码后的表单字段示意,实际签名须按原字段计算;并非 JSON 请求:
text
payOrderId=P_DEMO
mchNo=M_DEMO
appId=APP_DEMO
mchOrderNo=ORDER_DEMO
ifCode=alipay
wayCode=ALI_QR
amount=100
currency=cny
state=2
subject=测试商品
body=一笔测试订单
reqTime=1792108800000
sign=实际签名实际可携带 channelOrderNo、paymentVoucherTradeNo、paymentVoucherMchOrderNo、extParam、successTime、createdAt 等查询映射字段。两个 paymentVoucher 字段分别为用户账单交易单号、用户账单商户单号,渠道未提供时省略;后到的凭证不会自动重发已经创建的通知。不要仅对白名单中的少数字段验签,要使用实际收到的全部非空业务字段。
正确确认响应:
http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
SUCCESS不要返回 {"code":0}、HTML 页面或重定向;也不要在业务事务提交前提前确认。