异步通知参数说明
异步通知是指一笔订单支付完成后,支付宝会将该笔订单的变更信息,沿着商家调用支付请求时所传入的异步通知地址 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商家系统。
异步回调地址状态码(HTTP 状态码)为 200 时表示异步通知成功,返回码为 404 或 500 时则表示服务器内部错误,需要商家自行排查。
商家如果因为其它原因没有收到支付宝服务端返回的异步通知,可根据 异步通知问题 进行排查。
授权单状态流转图
接口与默认通知说明
接口/默认通知 | 通知地址 | 触发通知类型 | 通知类型说明 | 通知是否默认开启 |
---|---|---|---|---|
alipay.fund.auth.order.app.freeze | notify_url | fund_auth_freeze.init | 资金预授权订单创建 | 否 |
alipay.fund.auth.order.freeze | notify_url | fund_auth_freeze | 资金预授权冻结成功 | 是 |
alipay.fund.auth.order.voucher.create | notify_url | fund_auth_freeze.closed | 资金预授权订单关闭 | 否 |
alipay.fund.auth.order.unfreeze | notify_url | fund_auth_unfreeze | 资金授权订单解冻 | 是 |
alipay.fund.auth.operation.cancel | notify_url | fund_auth_operation_cancel | 资金预授权明细撤销 | 是 |
到达超时解冻时间触发自动解冻 | 应用网关配置地址 | fund_auth_unfreeze | 资金授权订单解冻 | 是 |
alipay.trade.pay | notify_url | trade_status_sync | 交易扣款 | 否 |
注意:alipay.trade.pay 异步通知相关说明可查看 当面付-异步通知参数说明。
异步通知参数
冻结、关闭、解冻等条件触发异步通知说明如下。
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
auth_no | String | 必须 | 64 | 支付宝资金授权订单号。 | 2014070800002001550000014417 |
notify_type | String | 必须 | 64 | 通知类型。取值见上文<接口与默认通知说明>。 | fund_auth_freeze |
out_order_no | String | 必须 | 64 | 商家的资金授权订单号。 | 4977164666634053 |
operation_id | String | 必须 | 64 | 支付宝的资金操作流水号。 | 2014070800032850551 |
out_request_no | String | 必须 | 64 | 商家资金操作流水号。 | 8077735255938032 |
operation_type | String | 必须 | 16 | 资金操作类型,枚举值如下:FREEZE:冻结。UNFREEZE:解冻。PAY:转交易。 | FREEZE |
amount | String | 必须 | 11 | 本次操作冻结的金额。单位为:元(人民币),精确到小数点后两位。 | 0.01 |
status | String | 必须 | 20 | 资金预授权明细的状态,枚举值如下:INIT:初始。SUCCESS: 该明细操作成功。CLOSED:该明细操作已关闭。 | SUCCESS |
gmt_create | String | 必须 | 20 | 明细创建时间。 | 2014-09-15 11:23:04 |
gmt_trans | String | 必须 | 20 | 明细处理完成时间。 | 2014-09-15 11:23:04 |
payer_logon_id | String | 必须 | 100 | 付款方支付宝账号登录号,脱敏。 | test***@alitest.com |
payer_user_id | String | 必须 | 32 | 付款方支付宝账号 UID。 | 2088102000275885 |
payee_logon_id | String | 可选 | 100 | 收款方支付宝账号,脱敏。 | 159****5620 |
payee_user_id | String | 可选 | 32 | 收款方支付宝账号 UID。 | 2088102000275795 |
total_freeze_amount | String | 必须 | 11 | 累计冻结金额。 | 0.01 |
total_unfreeze_amount | String | 必须 | 11 | 累计解冻金额。 | 0.01 |
total_pay_amount | String | 必须 | 11 | 累计支付金额。 | 0.01 |
rest_amount | String | 必须 | 11 | 剩余冻结金额。 | 0.01 |
credit_amount | String | 可选 | 11 | 本次操作中信用金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
fund_amount | String | 可选 | 11 | 本次操作中自有资金金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_freeze_credit_amount | String | 可选 | 11 | 累计冻结信用金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_freeze_fund_amount | String | 可选 | 11 | 累计冻结自有资金金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_unfreeze_credit_amount | String | 可选 | 11 | 累计解冻信用金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_unfreeze_fund_amount | String | 可选 | 11 | 累计解冻自有资金金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_pay_credit_amount | String | 可选 | 11 | 累计支付信用金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
total_pay_fund_amount | String | 可选 | 11 | 累计支付自有资金金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
rest_credit_amount | String | 可选 | 11 | 剩余冻结信用金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
rest_fund_amount | String | 可选 | 11 | 剩余冻结自有资金金额,单位为:元(人民币),精确到小数点后两位。 | 0.01 |
pre_auth_type | String | 可选 | 20 | 预授权类型,目前支持 CREDIT_AUTH(信用预授权); 商家可根据该标识来判断该笔预授权的类型,当返回值为"CREDIT_AUTH"表明该笔预授权为信用预授权,没有真实冻结资金;当返回值为空或者不为"CREDIT_AUTH"则表明该笔预授权为普通资金预授权,会冻结用户资金。 | CREDIT_AUTH |
credit_merchant_ext | String | 可选 | 128 | 芝麻透出给商家的信息,具体内容由商家与芝麻约定后返回。 | {"1003190":"true"} |
异步返回结果示例
假设商家传入的 notify_url 为:
https://www.merchant.com/receive_notify.htm
则示例异步通知如下:
https://www.merchant.com/receive_notify.htm?gmt_create=2021-12-06 23%3A59%3A55&charset=utf-8&rest_credit_amount=99.00&operation_type=FREEZE&sign=$$$&rest_fund_amount=0.00&auth_no=2021120610002001030501221111¬ify_id=2021120700222000000090241427601111&total_freeze_credit_amount=99.00¬ify_type=fund_auth_freeze&gmt_trans=2021-12-06 23%3A59%3A59&operation_id=20211206696407711111&total_pay_fund_amount=0.00&out_request_no=210781146788652855760491111&payer_user_id=2088122536931111&app_id=2021002110681111&sign_type=RSA2&amount=99.00&rest_amount=99.00¬ify_time=2021-12-07 00%3A00%3A00&fund_amount=0.00&total_pay_credit_amount=0.00&payee_user_id=2088041032831111&credit_amount=99.00&pre_auth_type=CREDIT_AUTH&out_order_no=2107811467886528557601111&total_freeze_fund_amount=0.00&payee_logon_id=it_***%40meituan.com&version=1.0&total_unfreeze_fund_amount=0.00&total_pay_amount=0.00&total_freeze_amount=99.00&total_unfreeze_credit_amount=0.00&total_unfreeze_amount=0.00&status=SUCCESS&payer_logon_id=131****1111
注意:第三方代商家调用支付接口得到的异步通知有所不同,会带上 auth_app_id,即第三方应用的 APPID,第三方代调用场景下,服务商收到的异步通知示例如下:
https://www.merchant.com/receive_notify.htm?gmt_create=2021-12-06 23%3A59%3A55&charset=utf-8&rest_credit_amount=99.00&operation_type=FREEZE&sign=$$$&rest_fund_amount=0.00&auth_no=2021120610002001030501221111¬ify_id=2021120700222000000090241427601111&total_freeze_credit_amount=99.00¬ify_type=fund_auth_freeze&gmt_trans=2021-12-06 23%3A59%3A59&operation_id=20211206696407711111&total_pay_fund_amount=0.00&out_request_no=210781146788652855760491111&payer_user_id=2088122536931111&app_id=2021002110681111&sign_type=RSA2&amount=99.00&rest_amount=99.00¬ify_time=2021-12-07 00%3A00%3A00&fund_amount=0.00&total_pay_credit_amount=0.00&payee_user_id=2088041032831111&credit_amount=99.00&pre_auth_type=CREDIT_AUTH&out_order_no=2107811467886528557601111&total_freeze_fund_amount=0.00&payee_logon_id=it_***%40meituan.com&version=1.0&total_unfreeze_fund_amount=0.00&total_pay_amount=0.00&total_freeze_amount=99.00&total_unfreeze_credit_amount=0.00&auth_app_id=2021002110681111&total_unfreeze_amount=0.00&status=SUCCESS&payer_logon_id=131****1111
异步通知结果验签
推荐使用官方 SDK 封装的 rsaCheckV1 或 rsaCertCheckV1 进行验签,若不使用 SDK,请按照以下流程处理验签。
- 在通知返回参数列表中,除去 sign、sign_type 两个参数外,凡是通知返回回来的参数皆是待验签的参数。
- 将剩下参数进行 URLDecode,然后进行字典排序,组成字符串,得到待签名字符串:
amount=99.00&app_id=2021002110681111&auth_app_id=2021002110681111&auth_no=2021120610002001030501221111&charset=utf-8&credit_amount=99.00&fund_amount=0.00&gmt_create=2021-12-06 23:59:55&gmt_trans=2021-12-06 23:59:59¬ify_id=2021120700222000000090241427601111¬ify_time=2021-12-07 00:00:00¬ify_type=fund_auth_freeze&operation_id=20211206696407711111&operation_type=FREEZE&out_order_no=2107811467886528557601111&out_request_no=210781146788652855760491111&payee_logon_id=it_***@meituan.com&payee_user_id=2088041032831111&payer_logon_id=131****1111&payer_user_id=2088122536931111&pre_auth_type=CREDIT_AUTH&rest_amount=99.00&rest_credit_amount=99.00&rest_fund_amount=0.00&status=SUCCESS&total_freeze_amount=99.00&total_freeze_credit_amount=99.00&total_freeze_fund_amount=0.00&total_pay_amount=0.00&total_pay_credit_amount=0.00&total_pay_fund_amount=0.00&total_unfreeze_amount=0.00&total_unfreeze_credit_amount=0.00&total_unfreeze_fund_amount=0.00&version=1.0
- 将签名参数(sign)使用 base64 解码为字节码串。
- 使用 RSA/RSA2 的验签方法(即发起请求时的加签方法),通过签名字符串、签名参数(经过 base64 解码)及支付宝公钥验证签名,根据返回结果判定是否验签通过。
- 需要严格按照如下描述校验通知数据的正确性:
-
- 商家需要验证该通知数据中的 out_order_no、out_request_no 是否为商家系统中创建的订单号。
- 判断 amount 是否确实为本次操作的金额(即商家发起冻结、解冻时的金额)。
- 校验通知中的 payee_user_id 是否为 out_order_no、out_request_no 这笔单据的收款方。
上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商家必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
服务器异步通知页面特性
- 商家设置的异步地址必须是外网能够顺利访问到的地址,且不能是重定向的网址,并且保证服务器异步通知页面(notify_url)上无任何字符,如空格、HTML 标签、开发系统自带抛出的异常提示信息等。
- 支付宝是用 POST 方式发送通知信息,因此该页面中获取参数的方式,如:request.Form("out_order_no")、$_POST['out_order_no']。
- 支付宝主动发起通知,该方式才会被启用。
- 服务器间的交互,不像页面跳转同步通知可以在页面上显示出来,这种交互方式是不可见的。
- 程序执行完后必须通过 PrintWriter 类打印输出 success 。如果商家反馈给支付宝的字符不是 success 这 7 个字符,支付宝服务器会不断重发通知,直到超过 24 小时 22 分钟。一般情况下,25 小时以内完成 8 次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h)。
- 程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知。
- cookies、session 等在此页面会失效,即无法获取这些数据。
- 该方式的调试与运行必须在服务器上,即互联网上能访问。
- 该方式的作用主要防止订单丢失,即页面跳转同步通知没有处理订单更新,它则去处理。
- 当商家收到服务器异步通知并打印出 success 时,服务器异步通知参数 notify_id 才会失效。也就是说在支付宝发送同一条异步通知时(包含商家并未成功打印出 success 导致支付宝重发数次通知),服务器异步通知参数 notify_id 是不变的。