94 lines
5.7 KiB
Plaintext
Raw Normal View History

2026-03-10 16:40:19 +08:00
服务器异步通知页面特性
必须保证服务器异步通知页面notify_url上无任何字符如空格、HTML标签、开发系统自带抛出的
异常提示信息等;
支付宝是用POST方式发送通知信息因此该页面中获取参数的方式
request.Form(“out_trade_no”)、$_POST[out_trade_no]
支付宝主动发起通知,该方式才会被启用;
只有在支付宝的交易管理中存在该笔交易,且发生了交易状态的改变,支付宝才会通过该方式发起服务
器通知(即时到账交易状态为“等待买家付款”的状态默认是不会发送通知的);
服务器间的交互,不像页面跳转同步通知可以在页面上显示出来,这种交互方式是不可见的;
第一次交易状态改变(即时到账中此时交易状态是交易完成)时,不仅会返回同步处理结果,而且服务器
异步通知页面也会收到支付宝发来的处理结果通知;
程序执行完后必须打印输出“success”不包含引号。如果商户反馈给支付宝的字符不是success这
7个字符支付宝服务器会不断重发通知直到超过24小时22分钟。一般情况下25小时以内完成8次通
通知的间隔频率一般是4m,10m,10m,1h,2h,6h,15h
程序执行完成后该页面不能执行页面跳转。如果执行页面跳转支付宝会收不到success字符
被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知;
cookies、session等在此页面会失效即无法获取这些数据
该方式的调试与运行必须在服务器上,即互联网上能访问;
该方式的作用主要防止订单丢失,即页面跳转同步通知没有处理订单更新,它则去处理;
当商户收到服务器异步通知并打印出success时服务器异步通知参数notify_id才会失效。也就是
说在支付宝发送同一条异步通知时包含商户并未成功打印出success导致支付宝重发数次通知
服务器异步通知参数notify_id是不变的。
异步返回结果的验签
某商户设置的通知地址为https://api.xx.com/receive_notify.htm对应接收到通知的示例如下
1
https://api.xx.com/receive_notify.htm?
total_amount=2.00&buyer_id=2088102116773037&body=大乐透2.1
&trade_no=2016071921001003030200089909&refund_fee=0.00
&notify_time=2016-07-19 14:10:49&subject=大乐透2.1
&sign_type=RSA&charset=utf-8&notify_type=trade_status_sync
&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46
&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS
&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/Hmf
WL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhu
xNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9
FPqRS6ZKxnzM=
&gmt_create=2016-07-19 14:10:44&app_id=2015102700040153
&seller_id=2088102119685838&notify_id=4a91b7a78a503640467525113fb7d8bg8e
第一步: 在通知返回参数列表中除去sign、sign_type两个参数外凡是通知返回回来的
参数皆是待验签的参数。
第二步: 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串:
1
body=大乐透2.1&
buyer_id=2088102116773037&
charset=utf-8&
gmt_close=2016-07-19 14:10:46&
gmt_payment=2016-07-19 14:10:47&
notify_time=2016-07-19 14:10:49&
notify_type=trade_status_sync&
out_trade_no=0719141034-6418&
refund_fee=0.00&
subject=大乐透2.1&
total_amount=2.00&
trade_no=2016071921001003030200089909&
trade_status=TRADE_SUCCESS&
version=1.0
第三步: 将签名参数sign使用base64解码为字节码串。
第四步: 使用RSA的验签方法通过签名字符串、签名参数经过base64解码及支付宝公钥验证签名。
第五步:在步骤四验证签名正确后,必须再严格按照如下描述校验通知数据的正确性。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
2、判断total_amount是否确实为该订单的实际金额即商户订单创建时的金额
3、校验通知中的seller_id或者seller_email) 是否为out_trade_no这笔单据的对应
的操作方有的时候一个商户可能有多个seller_id/seller_email
4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过则表明本次通知
是异常通知,务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进
行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态
为TRADE_SUCCESS或TRADE_FINISHED时支付宝才会认定为买家付款成功。
验签过程代码描述【这里列举java示例按照服务端SDK中提供的工具类】
Map<String, String> paramsMap = ... //将异步通知中收到的待验证所有参数都存放到map中
boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap,
ALIPAY_PUBLIC_KEY, CHARSET) //调用SDK验证签名
if(signVerfied){
// TODO 验签成功后
//按照支付结果异步通知中的描述对支付结果中的业务内容进行1\2\3\4二次校验
校验成功后在response中返回success校验失败返回failure
}else{
// TODO 验签失败则记录异常日志并在response中返回failure.
}
注意:
状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下买家付款成功
交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下
家付款成功;或者,商户签约的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限。