文档名称

支付宝扫码 V2.0 支付接口文档

文档概述:

本文件描述针对线下 O2O 手机支付行业提供的支付解决方案。供内部相关开发和技术支持人员与商户平台服务方技术人员使用。文档分别从交互模式、签名、接口、注意事项等方面详细介绍了工作方式和开发过程,可以帮助开发人员快速入门并掌握开发技能,同时也可以作为日后接口参数以及参数类型的速查手册。

文档版本:

版本号 修定人 制定日期 修订日期
2.1.0 杨敏 2017-03-20 2019-12-18

行业场景:

支付宝扫码支付,是基于支付宝钱包提供的支付服务功能。同时向商户提供销售经营分析、 账户和资金管理的功能支持。 用户通过扫描二维码、 反扫二维码等多种方式调起支付宝支付模块完成支付。

流程说明:

扫码支付业务
使用场景:

步骤( 1) :左图, 商户根据支付宝支付的规则,在 POS 终端或 PC 端生成订单二维码。
步骤( 2) :右图,用户使用支付宝钱包扫描二维码后,获取商品信息,同时到商户后台下单。


步骤( 3) :左图,用户开始支付,输入支付密码。
步骤( 4) :右图,支付成功,商户后台得到通知,进行发货处理。


接口调用时序:
商户生成订单,先调用统一下单接口获取到 code_url,此 URL 直接生成二维码,用户扫码后调起支付。
时序图如下:

接口说明:

扫码支付接口
业务功能

初始化扫码请求,通过该请求生成二维码来进行扫码支付。

交互模式

请求:后台请求交互模式
返回结果+通知:后台请求交互模式+后台通知交互模式

请求参数列表
请求 url:
http://pay.xrtpay.com/xrtpay/gateway

POST XML 内容体进行请求

字段名 变量名 必填 类型 说明
业务参数 ———— ———— ———— ————
接口类型 service String(32) pay.alipay.native
版本号 version String(8) 版本号, version 默认值是 2.0
字符集 charset String(8) 可选值 UTF-8 ,默认为 UTF-8
签名方式 sign_type String(8) 签名类型,取值: MD5 默认: MD5
商户号 mch_id String(32) 商户号,由技术部分配
商户订单号 out_trade_no String(32) 商户系统内部的订单号 ,32个字符内、可包含字母,确保在商户系统唯一
设备号 device_info String(32) 终端设备号
商品描述 body String(127) 商品描述
附加信息 attach String(128) 商户附加信息,可做扩展参数, 255 字符内
总金额 total_fee Int 总金额,以分为单位,不允许包含任何字、符号
终端 IP mch_create_ip String(16) 订单生成的机器 IP
通知地址 notify_url String(255) 接收…通知的 URL,需给绝对路径, 255字 符 内 格 式 如:http://wap.tenpay.com/tenpay.asp, 确保…能通过互联网访问该地址
订单生成时间 time_start String(14) 订单生成时间,格式为 yyyymmddhhmmss,如2009 年 12 月 25 日 9 点 10 分 10 秒表示为20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器
订单超时时间 time_expire String(14) 订单失效时间,格式为 yyyymmddhhmmss,如2009 年 12 月 27 日 9 点 10 分 10 秒表示为20091227091010。时区为 GMT+8 beijing。该时间取自商户服务器
操作员 op_user_id String(32) 操作员帐号,默认为商户号
商品标记 goods_tag String(32) 商品标记,用于优惠券或者满减使用
商品 ID product_id String(32) 预留字段此 id 为静态可打印的二维码中包含的商品ID,商户自行维护。
随机字符串 nonce_str String(32) 随机字符串,不长于 32 位
签名 sign String(32) MD5 签名结果,详见“下文数据格式 MD5 签名规则”
返回结果

数据按 XML 的格式实时返回

字段名 变量名 必填 类型 说明
版本号 version String(8) 默认值是 2.0。
字符集 charset String(8) 可选值 UTF-8 ,默认为 UTF-8。
签名方式 sign_type String(8) 取值: MD5 默认: MD5
返回状态码 status String(16) 0 表示成功非 0 表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断
返回信息 message String(128) 返回信息,如非空,为错误原因签名失败参数格式校验错误
以下字段在 status 为 0 的时候有返回
业务结果 result_code String(16) 0 表示成功非 0 表示失败
商户号 mch_id String(32) 由技术部分配
设备号 device_info String(32) …支付分配的终端设备号
随机字符串 nonce_str String(32) 随机字符串,不长于 32 位
错误代码 err_code String(32) 参考错误码
错误代码描述 err_msg String (128) 结果信息描述
签名 sign String(32) MD5 签名结果,详见“下文数据格式 MD5 签名规则”
以下字段在 status 和 result_code 都为 0 的时候有返回
二维码链接 code_url String(64) 此参数可直接生成二维码展示出来进行扫码支付
二维码图片 code_img_url String(128) 直接用此链接请求二维码图片
扫码通知接口
通知结果参数列表

通知 URL 是 扫码支付接口提交的参数 notify_url,支付完成后,…会把相关支付和用户信息发送到该 URL,商户需要接收处理信息。
对后台通知交互时,如果收到商户的应答不是成功或超时,…认为通知失败, …会通过一定的策略(如 25 小时内共 8 次, 通知的间隔频率一般是: 2m,10m,10m,1h,2h,6h,15h)定期重新发起
通知,尽可能提高通知的成功率,但不保证通知最终能成功。
由于存在重新发送后台通知的情况, 因此同样的通知可能会多次发送给商户系统。 商户系统必须能够正确处理重复的通知。
推荐的做法是, 当收到通知进行处理时, 首先检查对应业务数据的状态, 判断该通知是否已经处理过, 如果没有处理过再进行处理, 如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
后台通知通过请求中的 notify_url 进行, post

字段名 变量名 必填 类型 说明
接口类型 service String(32) pay.alipay.jspay
版本号 version String(8) version 默认值是 2.0。
字符集 charset String(8) UTF-8 ,默认为 UTF-8
签名方式 sign_type String(8) 取值: MD5 默认: MD5
返回状态码 status String(16) 0 表示成功非 0 表示失败此字段是通信标识,非交易标识, 交易是否成功需要查看 result_code 来判断
返回信息 message String(128) 返回信息, 如非空, 为错误原因签名失败参数格式校验错误
以下字段在 status 为 0 的时候有返回
业务结果 result_code String(16) 0 表示成功非 0 表示失败
商户号 mch_id String(32) 商户号, 由技术部分配
设备号 device_info String(32) 终端设备号
随机字符串 nonce_str String(32) 随机字符串, 不长于 32 位
错误代码 err_code String(32) 参考错误码
错误代码描述 err_msg String(128) 结果信息描述
签名 sign String(32) MD5 签名结果, 详见“ 下文数据格式 MD5 签名规则”
以下字段在 status 和 result_code 都为 0 的时候有返回
用户标识 openid String(128) 用户支付宝的账户名
交易类型 trade_type String(16) pay.alipay.native
支付结果 pay_result Int 支付结果: 0—成功; 其它—失败
支付结果信息 pay_info String(64) 支付结果信息,支付成功时为空
…订单号 transaction_id String(32) 对应支付宝交易记录账单详情中的商户订单号
第三方商户号 out_transaction_id String(32) 对应支付宝交易记录账单详情中的交易号
商户订单号 out_trade_no String(32) 商户系统内部的定单号, 32 个字符内、 可包含字母
总金额 total_fee Int 总金额, 以分为单位, 不允许包含任何字、 符号
货币种类 fee_type String(8) 货币类型, 符合 ISO 4217 标准的三位字母代码, 默认人民币: CNY
附加信息 attach String(128) 商家数据包, 原样返回
支付完成时间 time_end String(14) 支付完成时间, 格式为 yyyyMMddhhmmss, 如2009 年 12 月 27 日 9 点 10 分 10 秒表示为20091227091010。 时区为 GMT+8 beijing。 该时间取自…服务器

后台通知结果反馈

…后台通过 notify_url 通知商户, 商户做业务处理后, 需要以字符串的形式反馈处理结果, 内容如下:

返回结果 结果说明
success 处理成功, …系统收到此结果后不再进行后续通知
fail 或其它字符 处理不成功, …收到此结果或者没有收到任何结果, 系统通过补单机制( 详见下午补单机制) 再次通知

数据格式:

提交数据

采用 HTTP 标准的 POST 协议,为了保证接收方接收数据正确,传输数据必须签名。

<xml>
<service>pay.alipay.native </service>
<body><![CDATA[支付测试]]></body>
<mch_id>7551000001</mch_id>
<nonce_str>adf880d5c8986bd0deb6423c92c9d948</nonce_str>
<out_trade_no>1406046836</out_trade_no>
<mch_create_ip>127.0.0.1</mch_create_ip>
<total_fee>1</total_fee>
<sign><![CDATA[F53145E553092CE52E4CAA4D2B49A91C]]></sign>
</xml>
XML 数据格式

采用标准 XML 协议,所有参数只存在一级节点中,不采用多级节点嵌套。

协议级错误返回:
<xml>
<status>500</status>
<message><![CDATA[SYSERR]]></message>
</xml>
正确返回数据:
<xml><attach><![CDATA[附加信息]]></attach>
<charset><![CDATA[UTF-8]]></charset>
<coupon_fee><![CDATA[0]]></coupon_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<mch_id><![CDATA[7551000001]]></mch_id>
<nonce_str><![CDATA[1433449452669]]></nonce_str>
<openid><![CDATA[afas@sina.com]]></openid>
<out_trade_no><![CDATA[5843788255006075]]></out_trade_no>
<out_transaction_id><![CDATA[2015060421001004530034316725]]></out_transaction_i
d>
<pay_result><![CDATA[0]]></pay_result>
<result_code><![CDATA[0]]></result_code>
<sign><![CDATA[DE59A5A567452FCD41F0D0992A757106]]></sign>
<sign_type><![CDATA[MD5]]></sign_type>
<status><![CDATA[0]]></status>
<time_end><![CDATA[2015-06-04 18:59:07]]></time_end>
<total_fee><![CDATA[1]]></total_fee>
<trade_type><![CDATA[pay.alipay.native]]></trade_type>
<transaction_id><![CDATA[7551000001201506040012062128]]></transaction_id>
<version><![CDATA[2.0]]></version>
</xml>
业务级错误返回:
<xml>
<status>0</status>
<message><![CDATA[OK]]></message>
<mch_id><![CDATA[10000100]]></mch_id>
<device_info><![CDATA[1000]]></device_info>
<nonce_str><![CDATA[sthBJ9QyUG6vkrjJ]]></nonce_str>
<sign><![CDATA[6277A96D7875D4FF23AA7B6A4C3046AB]]></sign>
<result_code>1</result_code>
<err_code><![CDATA[AUTHCODE_EXPIRE]]></err_code>
<err_code_des><![CDATA[二维码已过期,请刷新再试]]></err_code_des>
</xml>

一般有返回有 status 参数, 0 表示调用成功; 非 0 表示调用失败。

数字签名:

为了保证数据传输过程中的数据真实性和完整性,我们需要对数据进行数字签名,在接收签名数据之后进行签名校验。
数字签名有两个步骤,先按一定规则拼接要签名的原始串,再选择具体的算法和密钥计算出签名结果。
一般失败的结果不签名。
4.1.签名原始串
无论是请求还是应答,签名原始串按以下方式组装成字符串:
1、 除 sign 字段外, 所有参数按照字段名的 ascii 码从小到大排序后使用 QueryString 的格式(即key1=value1&key2=value2…)拼接而成,空值不传递,不参与签名组串。
2、签名原始串中, 字段名和字段值都采用原始值,不进行 URL Encode。
3、 …返回的应答或通知消息可能会由于升级增加参数,请验证应答签名时注意允许这种情况。
举例:
调用某个接口,接口有如下字段:

<xml><body><![CDATA[测试支付]]></body>
<mch_create_ip><![CDATA[127.0.0.1]]></mch_create_ip>
<mch_id><![CDATA[001075552110006]]></mch_id>
<nonce_str><![CDATA[1409196838]]></nonce_str>
<notify_url><![CDATA[http://227.0.0.1:9001/javak/sds?123&23=3]]></notify_url>
<out_trade_no><![CDATA[141903606228]]></out_trade_no>
<service><![CDATA[pay.alipay.native]]></service>
<sign><![CDATA[83684D9546F261997EFF2ECFAC372583]]></sign>
<total_fee><![CDATA[1]]></total_fee>
</xml>

正确的签名字段排序为:
body=测试支付
&mch_create_ip=127.0.0.1&mch_id=001075552110006&nonce_str=1409196838&notify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.alipay.native&total_fee=1
4.2.签名算法
目前暂只支持 MD5 签名
MD5 签名
MD5 是一种摘要生成算法,通过在签名原始串后加上商户通信密钥的内容,进行 MD5 运算,形成的摘要字符串即为签名结果。为了方便比较,签名结果统一转换为大写字符。
注意:签名时将字符串转化成字节流时指定的编码字符集应与参数 charset 一致。
MD5 签名计算公式:
sign = Md5(原字符串&key=商户密钥). toUpperCase
如:
假设以下为 XML 传入参数:

<xml><body><![CDATA[测试支付]]></body>
<mch_create_ip><![CDATA[127.0.0.1]]></mch_create_ip>
<mch_id><![CDATA[001075552110006]]></mch_id>
<nonce_str><![CDATA[1409196838]]></nonce_str>
<notify_url><![CDATA[http://227.0.0.1:9001/javak/sds?123&23=3]]></notify_url>
<out_trade_no><![CDATA[141903606228]]></out_trade_no>
<service><![CDATA[pay.alipay.native]]></service>
<sign><![CDATA[83684D9546F261997EFF2ECFAC372583]]></sign>
<total_fee><![CDATA[1]]></total_fee>
</xml>

假设商户密钥为: e1cf0ddcf6b47b59c351565d8ad717af
i:经过 a 过程 URL 键值对字典序排序后的字符串 string1 为:
body=测试支付
&mch_create_ip=127.0.0.1&mch_id=001075552110006&nonce_str=1409196838&notify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.alipay.native&total_fee=1
ii:经过 b 过程后得到 sign 为:
sign=md5(string1&key=e1cf0ddcf6b47b59c351565d8ad717af).toUpperCase
=md5(body=测试支付
&mch_create_ip=127.0.0.1&mch_id=001075552110006&nonce_str=1409196838&notify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.alipay.native&total_fee=1&key=e1cf0ddcf6b47b59c351565d8ad717af).toUpperCase()
=”83684D9546F261997EFF2ECFAC372583”

补单机制:

注意:对后台通知交互模式,如果收到商户的应答不是“ success”或超时,…认为通知失败,通过一定的策略(如 25小时内共 8 次,通知的间隔频率一般是:2m,10m,10m,1h,2h,6h,15h)定期重新发起通知,尽可能提高通知的成功率,但不保证通知最终能成功。
由于存在重新发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回“ success”。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

注意事项:

所有涉及到金额的单位都是分,最小的单位是 1 分,不能有小数出现
2、 notify_url 是…服务器从后台直接发起请求到商户服务器,商户处理时不能检查用户的 cookie 或 session;商户更新 DB 等发货流程需要在 notify_url 完成后,以确保掉单时,…补单能成功补上
3、 notify_url 有可能重复通知,商户需要做去重处理,避免多次发货
4、 notify_url 收到的通知,商户处理成功或检查订单已经处理,需要返回处理成功的标志“ success”,以告知不再通知
5、 其它注意事项
(1) 参数大小写问题
请留意文档中要求的字符大小写问题, 如 “ md5 运算后, 字符串的字符要转换为大写” 。
(2) 参数格式问题
所有传入参数,均为字符串类型,请注意文档中各处的具体要求。
(3) 时间戳问题
请使用 Linux 时间戳,注意为字符串格式。精确到秒,不需要到毫秒,即 10 位数字。
(4) 同一商户订单号支付问题
商户的 out_trade_no 必须全局唯一,调试和生产环境,都需要使用唯一的订单号。注意:
当商户的同一个商户号绑定了多种支付方式也需要加标识来区分,不能出现重复。当发起支付返回失败时,
一定要用原订单的 out_trade_no 而不能重新生成新的订单号发起支付,避免同一单重复支付。

问题排查:

备注:

  • 更多返回错误代码请看首页的错误代码描述
文档更新时间: 2021-03-06 11:16   作者:杨敏