第三方支付 回调失败 同步返回通知 异步通知 签名 验签
第三方支付 回调通知款项收到 通知失败
失败原因
己方服务器对通知信息的处理发生了异常
passback_params 支付回调的 原样返回字段 自定义字段的存放字段
开放平台文档中心 https://docs.open.alipay.com/204/105465/
passback_params | String | 否 | 512 | 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝 | merchantBizType%3d3C%26merchantBizNo%3d2016010101111 |
passback_params 支付回调的 原样返回字段 自定义字段的存放字段
支付结果通知
应用场景
支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并返回应答。
对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)
注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。技术人员可登进微信商户后台扫描加入接口报警群。
查询订单
应用场景
该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
需要调用查询接口的情况:
- ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
- ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
- ◆ 调用刷卡支付API,返回USERPAYING的状态;
- ◆ 调用关单或撤销接口API之前,需确认支付状态;
接口链接
https://api.mch.weixin.qq.com/pay/orderquery
蚂蚁金服开发者社区 一,什么是同步通知 同步通知是指在请 经验交流 同步返回通知与异步通知区别解析 1 https://openclub.alipay.com/read.php?tid=7335&fid=72&page=1
一,什么是同步通知
同步通知是指在请求参数中传入return_url参数,支付成功后跳转到return_url地址后携带的返回参数,如下可以在同步跳转的地址栏看到同步返通知:
return_url参数 后面?拼接的就是同步返回参数。
注:目前在支付接口中只有手机网站支付的接口和电脑网站支付的接口可以传入return_url参数 来接收到同步通知 其他的支付接口 如APP支付和当面付的接口都是不支持的。
二、什么是异步返通知
异步通知是指在请求参数中传入notify_url参数,在用户支付成功后,支付宝服务器会按照这个异步地址使用post方式给notify_url来发送交易信息,如下:
gmt_create=2018-06-19[/url] 10:45:21&charset=UTF-8&seller_email=$$$&subject=使用充值:0.01元&sign=$$$&body=欢迎使用&buyer_id=2088902846029999&invoice_amount=0.01¬ify_id=fa5f28482957168bb30be6230000bb7m3l&fund_bill_list=[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}]¬ify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&app_id=2018061260369999&buyer_pay_amount=0.01&sign_type=RSA2&seller_id=2088131465899999&gmt_payment=2018-06-19 10:45:22¬ify_time=2018-06-19 10:59:12&passback_params=1007511859282415616&version=1.0&out_trade_no=20180619109999&total_amount=0.01&trade_no=2018061921001004790596169999&auth_app_id=2018061260369999&buyer_logon_id=124***@qq.com&point_amount=0.00
notify_url地址由商户自己定义保证可以正常使用外网post方式访问,否则是无法正常接收到异步通知的。
三、同步通知和异步通知的区别
1、接收方法不同
同步通知是在同步返回的页面使用get方式来获取的 异步通知是使用post方式发送到异步地址上的,只能使用post方式来接收。
2、返回的参数不同
同步通知返回的参数比异步通知返回的参数是要少一些的,最明显的就是异步返回参数会返回trade_status(交易状态)参数 但是同步返回的参数是没有的,所以建议使用异步返回的参数来确认交易是否成功 如果trade_status=TRADE_SUCCESS表示就是交易成功了
3、发送的时间不同
一般情况下,异步通知比同步通知稍慢(几乎无感知)。同步和异步通知的发送和网络环境、服务器处理速度等因素关系较大,具体是先接收到同步通知还是异步通知,建议以实际接收到的为准。
4、参数返回的逻辑不一样
(1.)同步通知是在支付成功后的页面跳转,一般是用于展示给用户的,以手机网站支付为例:
付款成功会跳转到商户请求参数中传入的return_url地址页面:
(2.)异步通知参数是直接由支付宝服务器发送到商户的异步地址上的 不存在页面跳转是直接的服务器交互。
四、关于验签
同步通知和异步通知都是使用相同的验签方法验签的,如果是调用的SDK那就是都是使用的rsaCheckV1方法。
详细的验签建议参考:
关于支付宝异步通知的那些事:https://openclub.alipay.com/read.php?tid=1314&fid=69&ant_source=zsearch
验签失败自查方案:https://openclub.alipay.com/read.php?tid=1598&fid=69
注:同步通知参数和同步响应参数是不一样的,同步通知返回是return_url参数返回的信息,同步响应则是请求成功接口返回的信息
详细的建议参考:https://openclub.alipay.com/read.php?tid=7328&fid=69
一、同步返回参数和同步响应参数的区别
1.同步返回的参数是指在接口的请求参数中传入return_url参数,在支付成功后在return_url地址后面返回的如:
2.同步响应的参数是指调用接口,接口响应的参数,以退款接口的响应参数为例:
二、验签注意:开放平台SDK封装了同步返回响应参数的验签方法,只需在创建DefaultAlipayClient对象进行初始化,设置请求网关(gateway),应用id(app_id),应用私钥(private_key),编码格式(charset),支付宝公钥(alipay_public_key),签名类型(sign_type)即可,同步返回响应参数报文时会自动进行验签。
同步返回的参数和同步响应的参数都是可以使用SDK封装的
方法来验签,params参数就是同步响应或是返回的参数 但是同步响应的参数是json格式的 在处理的时候如果处理不好可能会导致验签失败,此时建议大家可以使用下面的方法来验证同步的响应参数
1、使用RSA格式的秘钥验签同步响应参数,以上面的退款同步的响应参数为例:
2、使用RSA2格式的秘钥验签同步响应参数,同样以上面的退款同步的响应参数为例:
注意: 1、这边的是使用RSA验签还是RSA2 是依据商户自己请求的时候使用的秘钥格式是RSA还是RSA2来确定的 只能使用对应的格式的秘钥来验签,否则就会验签失败 这边示例的退款的请求信息中我这边使用的是RSA2的秘钥 所以使用RSA的验签代码就会验签失败的 建议只参考传参方式 如果使用RSA2的秘钥格式来验签是可以成功的 2、返回的响应参数中已带有反斜杠,需转义处理,需使用两个反斜杠进行标记,如扫码支付返回参数信息。
如有其它疑问欢迎大家可以在本帖后发帖追问。 |
重复收到支付宝发送的异步通知-异步返回问题 https://opensupport.alipay.com/support/knowledge/20070/201602062547
重复收到支付宝发送的异步通知
重复收到异步通知解决方案:
收到异步通知后,需打印输出success返回给支付宝,支付宝才会停止发送异步通知。
请在收到支付宝的异步通知后,程序执行完必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h)。
注:返送success后带有其他信息,可能会影响判断,仍然会发送通知。
返回success后仍然收到异步通知:
1、若在已经返回success后还会收到支付宝异步回调,请检查通知内容中的支付状态是否是不同的。在交易状态发生改变后,支付宝会触发不同交易状态的异步通知,都需要按以上原则进行处理。
2、返回给支付宝的必须是success这7个字符,不要含有其他字符。
微信支付-开发者文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
通知签名
加密不能保证通知请求来自微信。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP头Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。签名验证的算法请参考《微信支付API v3签名方案》
加密不能保证通知请求来自微信。
微信支付-开发者文档 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_3.shtml
签名
微信支付API v3通过验证签名来保证请求的真实性和数据的完整性。
请求签名
商户需要使用自身的私钥对API URL、消息体等关键数据的组合进行SHA-256 with RSA签名。请求的签名信息通过HTTP头Authorization
传递,具体说明请见 签名生成指南。没有携带签名或者签名验证不通过的请求,都不会被执行,并返回401 Unauthorized
。
应答签名
对于签名验证成功的请求,微信支付API v3会使用微信支付的平台私钥对应答进行签名。签名的信息包含在HTTP头部中,具体说明请见 签名验证指南。
回调通知签名
当调用商户的接口时,微信支付会使用微信支付的平台私钥对回调请求进行签名。签名的方法同应答签名的方式一致,商户必须使用微信支付公钥验证回调的签名。
微信支付-开发者文档 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
签名验证
商户可以按照下述步骤验证应答或者回调的签名。
如果验证商户的请求签名正确,微信支付会在应答的HTTP头部中包括应答签名。我们建议商户验证应答签名。
同样的,微信支付会在回调的HTTP头部中包括回调报文的签名。商户必须 验证回调的签名,以确保回调是由微信支付发送。
获取平台证书
微信支付API v3使用微信支付 的平台私钥(不是商户私钥 )进行应答签名。相应的,商户的技术人员应使用微信支付平台证书中的公钥验签。目前平台证书只提供API进行下载,请参考 获取平台证书列表。
检查平台证书序列号
微信支付的平台证书序列号位于HTTP头 微信支付平台证书的序列号一致。如果不一致,请重新获取证书。否则,签名的私钥和证书不匹配,将无法成功验证签名。
。验证签名前,请商户先检查序列号是否跟商户当前所持有的
构造验签名串
首先,商户先从应答中获取以下信息。
- HTTP头 中的应答时间戳。
- HTTP头 中的应答随机串
- 应答主体(response Body)
然后,请按照以下规则构造应答的验签名串。签名串共有三行,行尾以
结束,包括最后一行。 为换行符(ASCII编码值为0x0A)。若应答报文主体为空(如HTTP状态码为 ),最后一行仅为一个 换行符。
应答时间戳\n
应答随机串\n
应答报文主体\n
如某个应答的HTTP报文为(省略了ciphertext的具体内容):
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 02 Apr 2019 12:59:40 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 2204
Connection: keep-alive
Keep-Alive: timeout=8
Content-Language: zh-CN
Request-ID: e2762b10-b6b9-5108-a42c-16fe2422fc8a
Wechatpay-Nonce: c5ac7061fccab6bf3e254dcf98995b8c
Wechatpay-Signature: CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==
Wechatpay-Timestamp: 1554209980
Wechatpay-Serial: 5157F09EFDC096DE15EBE81A47057A7232F1B8E1
Cache-Control: no-cache, must-revalidate
{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"4de73afd28b6","associated_data":"certificate","ciphertext":"..."}}]}
则验签名串为
1554209980
c5ac7061fccab6bf3e254dcf98995b8c
{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"4de73afd28b6","associated_data":"certificate","ciphertext":"..."}}]}
获取应答签名
微信支付的应答签名通过HTTP头
传递。(注意,示例因为排版可能存在换行,实际数据应在一行)Wechatpay-Signature: CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==
对
的字段值使用Base64进行解码,得到应答签名。
验证签名
很多编程语言的签名验证函数支持对验签名串和签名 进行签名验证。强烈建议商户调用该类函数,使用微信支付平台公钥对验签名串和签名进行SHA256 with RSA签名验证。
下面展示使用命令行演示如何进行验签。假设我们已经获取了平台证书并保存为
。首先,从微信支付平台证书导出微信支付平台公钥
$ openssl x509 -in 1900009191_wxp_cert.pem -pubkey -noout > 1900009191_wxp_pub.pem
$ cat 1900009191_wxp_pub.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4zej1cqugGQtVSY2Ah8R
MCKcr2UpZ8Npo+5Ja9xpFPYkWHaF1Gjrn3d5kcwAFuHHcfdc3yxDYx6+9grvJnCA
2zQzWjzVRa3BJ5LTMj6yqvhEmtvjO9D1xbFTA2m3kyjxlaIar/RYHZSslT4VmjIa
tW9KJCDKkwpM6x/RIWL8wwfFwgz2q3Zcrff1y72nB8p8P12ndH7GSLoY6d2Tv0OB
2+We2Kyy2+QzfGXOmLp7UK/pFQjJjzhSf9jxaWJXYKIBxpGlddbRZj9PqvFPTiep
8rvfKGNZF9Q6QaMYTpTp/uKQ3YvpDlyeQlYe4rRFauH3mOE6j56QlYQWivknDX9V
rwIDAQAB
-----END PUBLIC KEY-----
然后,把签名base64解码后保存为文件
$ openssl base64 -d -A <<< \ 'CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==' > signature.txt
最后,验证签名
$ openssl dgst -sha256 -verify 1900009191_wxp_pub.pem -signature signature.txt << EOF
1554209980
c5ac7061fccab6bf3e254dcf98995b8c
{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"d215b0511e9c","associated_data":"certificate","ciphertext":"..."}}]}
EOF
Verified OK