关键字:支付宝支付、支付宝扫码支付
一、支付场景
用户使用支付宝钱包上的“扫一扫”功能,扫码商户针对每个订单实时生成的订单二维码,并在手机端确认支付。
二、调用流程
图2.1 支付宝扫码支付调用流程
a. 商户系统调用支付宝【预下单接口alipay.trade.precreate】,获得该订单二维码图片地址。
b. 发起轮询获得支付结果:等待5秒后调用【交易查询接口alipay.trade.query】,通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数TRADE_STATUS),如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待5秒后继续查询,直到返回确切的支付结果(成功TRADE_SUCCESS或已撤销关闭TRADE_CLOSED),或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用【交易撤销接口alipay.trade.cancel】将这笔交易撤销,避免用户继续支付。
c. 除了主动轮询,也可以通过接收异步通知获得支付结果,详见扫码异步通知,注意一定要对异步通知做验证签名,确保通知是支付宝发出的。
三、参数格式
请求和接收均为JSON格式
四、接口地址
正式环境:https://openapi.alipay.com/gateway.do
沙箱测试环境:https://openapi.alipaydev.com/gateway.do
五、统一收单线下交易预创建
1.请求参数
公共参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
app_id |
String |
是 |
32 |
2014072300007148 |
支付宝分配给开发者的应用ID |
method |
String |
是 |
128 |
接口名称 |
alipay.trade.precreate |
format |
String |
否 |
40 |
仅支持JSON |
JSON |
charset |
String |
是 |
10 |
utf-8 |
请求使用的编码格式,如utf-8,gbk,gb2312等 |
sign_type |
String |
是 |
10 |
RSA2 |
商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 |
sign |
String |
是 |
256 |
详见示例 |
商户请求参数的签名串,详见签名 |
timestamp |
String |
是 |
19 |
2014-07-24 03:07:50 |
发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" |
version |
String |
是 |
3 |
1.0 |
调用的接口版本,固定为:1.0 |
notify_url |
String |
否 |
256 |
http://api.test.alipay.net/atinterface/receive_notify.htm |
支付宝服务器主动通知商户服务器里指定的页面http/https路径。 |
app_auth_token |
String |
否 |
40 |
|
|
biz_content |
String |
是 |
- |
|
请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
请求参数(以下只列出了必填参数及少数重要选填参数)
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
out_trade_no |
String |
必须 |
64 |
20150320010101001 |
商户订单号,64个字符以内、只能包含字母、数字、下划线;需保证在商户端不重复 |
seller_id |
String |
可选 |
28 |
2088102146225135 |
卖家支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID |
total_amount |
Price |
必须 |
11 |
88.88 |
订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】 |
discountable_amount |
Price |
可选 |
11 |
88.88 |
可打折金额. 参与优惠计算的金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 如果该值未传入,但传入了【订单总金额】,【不可打折金额】则该值默认为【订单总金额】-【不可打折金额】 |
buyer_logon_id |
String |
可选 |
100 |
15901825620 |
买家支付宝账号 |
subject |
String |
必须 |
256 |
Iphone6 16G |
订单标题 |
body |
String |
可选 |
128 |
Iphone6 16G |
对交易或商品的描述 |
goods_detail |
GoodsDetail [] |
|
- |
- |
订单包含的商品列表信息.Json格式. 其它说明详见:“商品明细说明” |
operator_id |
String |
可选 |
28 |
yx_001 |
商户操作员编号 |
store_id |
String |
可选 |
32 |
NJ_001 |
商户门店编号 |
terminal_id |
String |
可选 |
32 |
NJ_T_001 |
商户机具终端编号 |
...更多参数,请移步支付宝开发者文档中心: https://doc.open.alipay.com/docs/api.htm?spm=a219a.7629065.0.0.5GZNbY&apiId=862&docType=4 |
2.返回参数
公共参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
code |
String |
是 |
- |
40004 |
|
msg |
String |
是 |
- |
Business Failed |
|
sub_code |
String |
否 |
- |
ACQ.TRADE_HAS_SUCCESS |
|
sub_msg |
String |
否 |
- |
交易已被支付 |
|
sign |
String |
是 |
- |
DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
|
响应参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
out_trade_no |
String |
必填 |
64 |
6823789339978248 |
商户的订单号 |
qr_code |
String |
必填 |
1024 |
https://qr.alipay.com/bavh4wjlxf12tper3a |
当前预下单请求生成的二维码码串,可以用二维码生成工具根据该码串值生成对应的二维码 |
3.请求示例
1 <?php 2 $params = array( 3 //公共参数 4 5 'app_id' => '2016080200150898', 6 7 'method' => 'alipay.trade.precreate', 8 9 'format' => 'json', 10 11 'charset' => 'utf-8', 12 13 'sign_type' => 'RSA2' 14 15 'timestamp' => '2017-03-31 15:53:42', 16 17 'version' => '1.0', 18 19 'notify_url' => 'http://www.xxxxx.com/notify_url.php', 20 21 'biz_content' => '{"out_trade_no":1490946822,"total_amount":"0.01","subject":"\u6d4b\u8bd5\u5546\u54c1"}', 22 23 'sign'=> 'idFoPOgosWazzgTjKj3MWVdICEw9mNQEj+mJr7TB8uhxacwcASlzN7Qfeqn7v6gncth/oV4uaZ8F2KBkBYenZb2563xJ+foYWFj2HZ8vhcdnVGYMl7U7SJ7jurjTKYOWqILDtIGDw8HcSFNNn+e3ryqMOJjc9neTSIXAqftFNojmHUGnEc9g7y4HH2pnXIri618jZ7wy2HfcpYd1JW5Ku46q+vAEHkTW9u4+hBQ37QwI10Gfi6c+aB21sabj2gjvyEdSHGdy3SbDHeinOM/CqEnw32ArfSfqjGVecJAkRwq/dXhqJlrIukED0scaT6sDepqcUZ2xSGbQMj2djByiqA==', 24 25 26 //请求参数 27 28 'out_trade_no' => '1490946822', 29 30 'total_amount' => '0.01', 31 32 'subject' => '测试商品', 33 );
a. 将公共参数按照URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA:
app_id=2016080200150898&method=alipay.trade.precreate&charset=utf-8&sign_type=RSA2×tamp=2017-03-31+16%3A09%3A34&version=1.0¬ify_url=http%3A%2F%2F10.10.19.39%2Fqhshop%2Fali_notify_url.php&format=json&biz_content=%7B%22out_trade_no%22%3A1490947774%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22%5Cu6d4b%5Cu8bd5%5Cu5546%5Cu54c1%22%7D&sign=vAs%2Bpy%2BQWxed0qdHXEuuyz5VKGgvrMgy2v%2FK85zUg3lMe5YjJ7WC0OESdB4SHPh0r675wQ%2FPPpPPhE%2Bb%2BNGTGpS%2F49r3j6AodcytkYmP8%2FSadxTQ2ah0j0culPxdDmRRD0%2FzRXHWZOWS9s4K52k6XP0i6dGjAhVOP%2Ffh59SIuK8YWuzfLEAss6CSyv3BDs4RPQ%2FNVE6HFIJJRNBFKQTFoRIqeo9Oan3Pc%2BKhPhLzadjo811wj01MqEmXMc8aQ75wdjvnWm1FBBhZga1lHZ0wlpgbQb0hXyakhwlJFZNx4CBCAI%2Fl%2FVMKerTpp8%2F%2FJWTd6xd%2Fi96C6Pt8UQhIVWiYKQ%3D%3D
b. 将字符串stringA拼接在接口地址后面,得到新的URL地址:
https://openapi.alipaydev.com/gateway.do?app_id=2016080200150898&method=alipay.trade.precreate&charset=utf-8&sign_type=RSA2×tamp=2017-03-31+16%3A09%3A34&version=1.0¬ify_url=http%3A%2F%2F10.10.19.39%2Fqhshop%2Fali_notify_url.php&format=json&biz_content=%7B%22out_trade_no%22%3A1490947774%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22%5Cu6d4b%5Cu8bd5%5Cu5546%5Cu54c1%22%7D&sign=vAs%2Bpy%2BQWxed0qdHXEuuyz5VKGgvrMgy2v%2FK85zUg3lMe5YjJ7WC0OESdB4SHPh0r675wQ%2FPPpPPhE%2Bb%2BNGTGpS%2F49r3j6AodcytkYmP8%2FSadxTQ2ah0j0culPxdDmRRD0%2FzRXHWZOWS9s4K52k6XP0i6dGjAhVOP%2Ffh59SIuK8YWuzfLEAss6CSyv3BDs4RPQ%2FNVE6HFIJJRNBFKQTFoRIqeo9Oan3Pc%2BKhPhLzadjo811wj01MqEmXMc8aQ75wdjvnWm1FBBhZga1lHZ0wlpgbQb0hXyakhwlJFZNx4CBCAI%2Fl%2FVMKerTpp8%2F%2FJWTd6xd%2Fi96C6Pt8UQhIVWiYKQ%3D%3D
c. 最后将请求参数post到新的URL地址;
4.返回示例
请求接口后,返回的数据格式为JSON格式的字符串。
接口调用成功:
接口调用失败:
六、支付结果通知
1. 说明
a. 用户通过手机扫码二维码进行支付,支付宝会将该笔订单的变更信息,沿着商户调用预下单请求时所传入的通知地址notify_url主动推送给商户。
b. 支付宝使用POST方式发送通知信息,因此notify_url页面中获取参数的方式为:$_POST[‘out_trade_no’];
c. 程序执行完,如果交易付款成功必须打印输出“success”(不包含引号)。否则支付宝服务器会不断重发通知,直到24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);
d. cookie、session等在此页面会失效,即无法获取这些数据;
2. 通知参数(部分重要参数)
参数 |
参数名称 |
类型 |
必填 |
描述 |
范例 |
notify_time |
通知时间 |
Date |
是 |
通知的发送时间。格式为yyyy-MM-dd HH:mm:ss |
2015-14-27 15:45:58 |
notify_type |
通知类型 |
String(64) |
是 |
通知的类型 |
trade_status_sync |
notify_id |
通知校验ID |
String(128) |
是 |
通知校验ID |
ac05099524730693a8b330c5ecf72da9786 |
sign_type |
签名类型 |
String(10) |
是 |
商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 |
RSA2 |
sign |
签名 |
String(256) |
是 |
请参考异步返回结果的验签 |
601510b7970e52cc63db0f44997cf70e |
trade_no |
支付宝交易号 |
String(64) |
是 |
支付宝交易凭证号 |
2013112011001004330000121536 |
app_id |
开发者的app_id |
String(32) |
是 |
支付宝分配给开发者的应用Id |
2014072300007148 |
out_trade_no |
商户订单号 |
String(64) |
是 |
原支付请求的商户订单号 |
6823789339978248 |
seller_id |
卖家支付宝用户号 |
String(30) |
否 |
卖家支付宝用户号 |
2088101106499364 |
seller_email |
卖家支付宝账号 |
String(100) |
否 |
卖家支付宝账号 |
zhuzhanghu@alitest.com |
trade_status |
交易状态 |
String(32) |
是 |
TRADE_CLOSED |
|
total_amount |
订单金额 |
Number(9,2) |
否 |
本次交易支付的订单金额,单位为人民币(元) |
20 |
receipt_amount |
实收金额 |
Number(9,2) |
否 |
商家在交易中实际收到的款项,单位为元 |
15 |
subject |
订单标题 |
String(256) |
否 |
商品的标题/交易标题/订单标题/订单关键字等,是请求时对应的参数,原样通知回来 |
当面付交易 |
body |
商品描述 |
String(400) |
否 |
该订单的备注、描述、明细等。对应请求时的body参数,原样通知回来 |
当面付交易内容 |
...更多参数,请移步支付宝开发者文档中心: https://doc.open.alipay.com/docs/doc.htm?treeId=194&articleId=103296&docType=1 |
3. 签名验证
第一步: 在通知返回参数列表中,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是待验签的参数。
第二步: 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串:
第三步: 将签名参数(sign)使用base64解码为字节码串。
第四步: 使用RSA的验签方法,通过签名字符串、签名参数(经过base64解码)及支付宝公钥验证签名。
第五步:需要严格按照如下描述校验通知数据的正确性:
* 验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
* 判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
* 校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
* 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功;
4. 返回参数
支付成功则返回“success”,否则返回其他字符;
七、订单查询
该接口提供所有支付宝支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。
1. 请求参数
公共参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
app_id |
String |
是 |
32 |
2014072300007148 |
支付宝分配给开发者的应用ID |
method |
String |
是 |
128 |
接口名称 |
alipay.trade.query |
format |
String |
否 |
40 |
仅支持JSON |
JSON |
charset |
String |
是 |
10 |
utf-8 |
请求使用的编码格式,如utf-8,gbk,gb2312等 |
sign_type |
String |
是 |
10 |
RSA2 |
商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 |
sign |
String |
是 |
256 |
详见示例 |
商户请求参数的签名串,详见签名 |
timestamp |
String |
是 |
19 |
2014-07-24 03:07:50 |
发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" |
version |
String |
是 |
3 |
1.0 |
调用的接口版本,固定为:1.0 |
app_auth_token |
String |
否 |
40 |
|
|
biz_content |
String |
是 |
- |
|
请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
请求参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
out_trade_no |
String |
特殊可选 |
64 |
20150320010101001 |
订单支付时传入的商户订单号,和支付宝交易号不能同时为空。 trade_no,out_trade_no如果同时存在优先取trade_no |
trade_no |
String |
特殊可选 |
64 |
2014112611001004680 073956707 |
支付宝交易号,和商户订单号不能同时为空 |
2. 返回参数
公共参数
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
code |
String |
是 |
- |
40004 |
|
msg |
String |
是 |
- |
Business Failed |
|
sub_code |
String |
否 |
- |
ACQ.TRADE_HAS_SUCCESS |
|
sub_msg |
String |
否 |
- |
交易已被支付 |
|
sign |
String |
是 |
- |
DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
|
响应参数(以下只列出了必填参数及少数重要选填参数)
参数 |
类型 |
必填 |
最大长度 |
示例值 |
描述 |
trade_no |
String |
必填 |
64 |
2013112011001004330000121536 |
支付宝交易号 |
out_trade_no |
String |
必填 |
64 |
6823789339978248 |
商家订单号 |
trade_status |
String |
必填 |
32 |
TRADE_CLOSED |
交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款) |
total_amount |
Price |
必填 |
11 |
88.88 |
交易的订单金额,单位为元,两位小数。该参数的值为支付时传入的total_amount |
receipt_amount |
Price |
必填 |
11 |
15.25 |
实收金额,单位为元,两位小数。该金额为本笔交易,商户账户能够实际收到的金额 |
...更多参数,请移步支付宝开发者文档中心: https://doc.open.alipay.com/doc2/apiDetail.htm?spm=a219a.7629065.0.0.1hBqdQ&apiId=757&docType=4 |
3. 请求示例
1 <?php 2 $params = array( 3 //公共参数 4 5 'app_id' => '2016080200150898', 6 7 'method' => 'alipay.trade.query', 8 9 'format' => 'JSON', 10 11 'charset' => 'utf-8', 12 13 'sign_type' => 'RSA2', 14 15 'timestamp' => '2017-03-31 17:40:53', 16 17 'version' => '1.0', 18 19 'biz_content' => '{"out_trade_no":"20170331125451"}', 20 21 'sign' => 'CqVzz7bZ2PCnAGczJcciEqMsbtBe2eEArNoiOjD2iY7DwGsGrXicYLk6lnlc6Pq5uJaOwHRGbae8Y6R7bvGpX9lPEH/zlTkT56fTtfQ1EQbk5UYcW/Z8q5mhje3c/DNIQ4tOiRX5K9RSctbvC/8kQMx4MUDMc9xiJZfzl9WRfAH45Bn3PGme91QoX1lcw8Ztyz+rKF7UCAIjerIVXrAcrHWL9e7B7UEM1BJJ8WEwMQ1nIsW7tiTuKWfbZ/vOHeyUsFUqWShQoXV38v3qADAotYDtQt6v0y4Uell+A4NlXuDT7++jmGsa+NTPaTM4mhXfFt3Sa1rkmO9fky/6sR+CkQ==', 22 23 24 //请求参数 25 26 'out_trade_no' => '20170331125451' 27 );
剩下操作步骤,参考【五、统一收单线下交易创建 -> 3.请求示例】,此处不再赘述。
4. 返回示例
请求接口后,返回的数据格式为JSON格式的字符串。
接口调用成功:
接口调用失败: