文档名称
微信APP接口文档
文档概述:
本文件描述…针对线下 O2O 手机App支付行业提供的支付解决方案。供内部相关开发和技术支持人员与商户平台服务方技术人员使用。文档分别从交互模式、签名、接口、注意事项等方面详细介绍了工作方式和开发过程,可以帮助开发人员快速入门并掌握开发技能,同时也可以作为日后接口参数以及参数类型的速查手册。
文档版本:
版本号 | 修定人 | 制定日期 | 修订日期 |
---|---|---|---|
2.1.0 | 杨敏 | 2017-03-20 | 2019-12-10 |
流程说明:
业务实现流程
适用于商户在移动端APP中集成微信支付功能。
商户APP调用微信提供的SDK调用微信,商户APP会跳转到微信,支付完后跳回到商户APP内,最后展示支付结果。
目前微信支付支持手机系统有:IOS(苹果)、Android(安卓)和WP(Windows Phone)。
使用场景 :
微信支付:
步骤1:用户进入商户APP,选择商品下单、确认购买,进入支付环节。商户服务后台生成支付订单,签名后将数据传输到APP端。以微信提 供的DEMO为例,见图8.1。
步骤2:用户点击后发起支付操作,进入到微信界面,调起微信支付,出现确认支付界面,见图8.2。
步骤3:用户确认收款方和金额,点击立即支付后出现输入密码界面,可选择零钱或银行卡支付见图8.3。
第四步:输入正确密码后,支付完成,用户端微信出现支付详情页面。见图8.4。
第五步:回跳到商户APP中,商户APP根据支付结果个性化展示订单处理结果。见图8.5。
接口业务流程:
接口说明:
App支付接口
非原生态预下单API
业务功能
初始化支付请求,通过该请求得到支持的支付类型和授权码。
交互模式
请求:后台请求交互模式
返回结果+通知:后台请求交互模式+后台通知交互模式
请求URL:
http://pay.xrtpay.com/xrtpay/gateway
请求参数列表
POST XML 内容体进行请求
字段名 | 变量名 | 必填 | 类型 | 说明 |
---|---|---|---|---|
业务参数 | ———— | ———— | ———— | ———— |
接口类型 | service | 是 | String(32) | 接口类型:unified.trade.pay |
版本号 | version | 否 | String(8) | 版本号,version 默认值是 1.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 |
限制信用卡 | limit_credit_pay | 否 | String(1) | 限定用户使用时能否使用信用卡,值为1,禁用信用卡,值为0或者不传此参数则不禁用 |
订单生成时间 | 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。该时间取自商户服务器 |
商户APP应用ID | sub_appid | 是 | String(32) | 微信开放平台审核通过的移动应用AppID |
商品标记 | goods_tag | 否 | String(32) | 商品标记,微信平台配置的商品标记,用于优惠券或者满减使用 |
随机字符串 | nonce_str | 是 | String(32) | 随机字符串,不长于32位 |
签名 | sign | 是 | String(32) | MD5 签名结果,详见“下文数字签名 MD5 签名规则” |
数据按 XML 的格式实时返回
字段名 | 变量名 | 必填 | 类型 | 说明 |
---|---|---|---|---|
版本号 | version | 是 | String(8) | 版本号,version 默认值是 1.0。 |
字符集 | charset | 是 | String(8) | 可选值 UTF-8 ,默认为 UTF-8。 |
签名方式 | sign_type | 否 | String(8) | 签名类型,取值:MD5 默认:MD5 |
返回状态码 | status | 是 | String(16) | 0 表示成功非 0 表示失败 |
返回信息 | message | 否 | String(128) | 返回信息,如非空,为错误原因签名失败参数格式校验错误 |
以下字段在 status 为 0 的时候有返回 |
---|
支付的支付类型 | services | 是 | String() | 支持的支付类型,多个以“”连接 |
---|---|---|---|---|
授权码 | token_id | 是 | String(64) | 支付授权码 |
签名 | sign | 是 | String(32) | MD5签名结果,详见“安全规范” |
非原生态预下单API
业务功能
用户在商家app内选择微信支付下单成功后,商家通过平台提供的接口获取到唤起微信支付的参数信息,然后在
商家app内唤起微信支付,用户在微信内确认支付后会自动返回到用户app内。
交互模式
请求:后台请求交互模式
返回结果+通知:后台请求交互模式+后台通知交互模式
请求URL:
http://pay.xrtpay.com/xrtpay/gateway
请求参数列表
POST XML 内容体进行请求
字段名 | 变量名 | 必填 | 类型 | 说明 |
---|---|---|---|---|
业务参数 | ———— | ———— | ———— | ———— |
接口类型 | service | 是 | String(32) | 接口类型:unified.trade.pay |
版本号 | version | 否 | String(8) | 版本号,version 默认值是 1.0 |
字符集 | 字符集 | 否 | 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 |
限制信用卡 | limit_credit_pay | 否 | String(1) | 限定用户使用时能否使用信用卡,值为1,禁用信用卡,值为0或者不传此参数则不禁用 |
订单生成时间 | 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。该时间取自商户服务器 |
商户APP应用ID | sub_appid | 是 | String(32) | 微信开放平台审核通过的移动应用AppID |
商品标记 | goods_tag | 否 | String(32) | 商品标记,微信平台配置的商品标记,用于优惠券或者满减使用 |
随机字符串 | nonce_str | 是 | String(32) | 随机字符串,不长于32位 |
签名 | sign | 是 | String(32) | MD5 签名结果,详见“下文数字签名 MD5 签名规则” |
返回结果
数据按 XML 的格式实时返回
字段名 | 变量名 | 必填 | 类型 | 说明 |
---|---|---|---|---|
版本号 | version | 是 | String(8) | 版本号,version 默认值是 1.0。 |
字符集 | charset | 是 | String(8) | 可选值 UTF-8 ,默认为 UTF-8。 |
签名方式 | sign_type | 否 | String(8) | 签名类型,取值:MD5 默认:MD5 |
返回状态码 | status | 是 | String(16) | 0 表示成功非 0 表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断 |
返回信息 | message | 否 | String(128) | 返回信息,如非空,为错误原因签名失败参数格式校验错误 |
业务结果 | 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 的时候有返回 |
---|
支付信息 | pay_info | 是 | String | Json格式的字符串,微信官方SDK中需要的参数信息 |
---|---|---|---|---|
商户订单号 | out_trade_no | 是 | String | 商户订单号 |
平台订单号 | Transaction_id | 是 | String | 平台订单号 |
支付通知接口
通知结果参数列表
通知 URL 是预下单接口中提交的参数 notify_url,支付完成后,平台会把相关支付和用户信息发送到该 URL,商户需要接收处理信息。
对后台通知交互时,如果平台收到商户的应答不是纯字符串success或超过5秒后返回时,平台认为通知失败,平台会通过一定的策略(通知频率为0/15/15/30/180/1800/1800/1800/1800/3600,单位:秒)间接性重新发起通知,尽可能提高通知的成功率,但不保证通知最终能成功。
由于存在重新发送后台通知的情况, 因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是, 当收到通知进行处理时, 首先检查对应业务数据的状态, 判断该通知是否已经处理过, 如果没有处理过再进行处理, 如果处理过直接返回结果成功。 在对业务数据进行状态检查和处理之前, 要采用数据锁进行并发控制, 以避免函数重入造成的数据混乱。
特别注意:商户需对接收到的通知参数中订单号和金额与自身业务系统中的单号和金额对比校验,校验一致后方可更新自身系统订单状态
后台通知通过请求中的notify_url进行, post方式给商户系统(通知参数内容为xml的字符串)
字段名 | 变量名 | 必填 | 类型 | 说明 |
---|---|---|---|---|
版本号 | version | 是 | String(8) | 版本号,version 默认值是 1.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) | 0 表示成功非 0 表示失败 |
随机字符串 | 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) | 用户在商户 appid 下的唯一标识 |
---|---|---|---|---|
交易类型 | trade_type | 是 | String (16) | pay.weixin.native、pay.weixin.micropay |
是否关注公众 | 账号is_subscribe | 是 | Int | 用户是否关注公众账号,0-关注,1-未关注,仅在公众账号类型支付有效 |
支付结果 | pay_result | 是 | Int | 支付结果:0—成功;其它—失败 |
支付结果信息 | pay_info | 否 | String(64) | 支付结果信息,支付成功时为空 |
…订单号 | transaction_id | 是 | String(32) | …交易号 |
商户订单号 | out_trade_no | 是 | String(32) | 商户系统内部的定单号,32 个字符内、可包含字母 |
总金额 | total_fee | 是 | Int | 总金额,以分为单位,不允许包含任何字、符号 |
现金券金额 | coupon_fee | 否 | Int | 现金券支付金额<=订单总金额, 订单总金额-现金券金额为现金支付金额 |
货币种类 | fee_type | 否 | String(8) | 货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY |
附加信息 | attach | 否 | String(128) | 商家数据包,原样返回 |
付款银行 | bank_type | 是 | String(16) | 银行类型 |
银行订单号 | bank_billno | 否 | String(32) | 银行订单号,若为微信支付则为空 |
支付完成时间 | time_end | 是 | String(14) | 支付完成时间,格式为 yyyyMMddhhmmss,如2009 年 12 月 27 日 9 点 10 分 10 秒表示为20091227091010。时区为 GMT+8 beijing。该时间取自…服务器 |
后台通知结果反馈
…后台通过 notify_url 通知商户, 商户做业务处理后, 需要以字符串的形式反馈处理结果, 内容如下:
返回结果 | 结果说明 |
---|---|
success | 处理成功, …系统收到此结果后不再进行后续通知 |
fail 或其它字符 | 处理不成功, …收到此结果或者没有收到任何结果, 系统通过补单机制( 下文补单机制) 再次通知 |
数据格式:
提交数据:
采用 HTTP 标准的 POST 协议,为了保证接收方接收数据正确,传输数据必须签名。
<xml>
<service>pay.weixin.native </service>
<attach><![CDATA[att]]></attach>
<body><![CDATA[支付测试]]></body>
<device_info>1000</device_info>
<mch_id>10000100</mch_id>
<nonce_str>adf880d5c8986bd0deb6423c92c9d948</nonce_str>
<out_trade_no>1406046836</out_trade_no>
<spbill_create_ip>127.0.0.1</spbill_create_ip>
<total_fee>1</total_fee>
<sign><![CDATA[F53145E553092CE52E4CAA4D2B49A91C]]></sign>
</xml>
XML 数据格式:
采用标准 XML 协议,所有参数只存在一级节点中,不采用多级节点嵌套。
协议级错误返回:
<xml>
<status>500</status>
<message><![CDATA[SYSERR]]></message>
</xml>
正确返回数据:
<xml>
<status>0</status>
<message><![CDATA[OK]]></message>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<device_info><![CDATA[1000]]></device_info>
<nonce_str><![CDATA[FvYSnPuFFPkAr77M]]></nonce_str>
<sign><![CDATA[63238039D6E43634297CF2A6EB5F3B72]]></sign>
<result_code>0</result_code>
<openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<trade_type><![CDATA[MICROPAY]]></trade_type>
<bank_type><![CDATA[CCB_CREDIT]]></bank_type>
<total_fee>1</total_fee>
<coupon_fee>0</coupon_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<transaction_id><![CDATA[1008450740201407220000058756]]></transaction_id>
<out_trade_no><![CDATA[1406033828]]></out_trade_no>
<attach><![CDATA[att]]></attach>
<time_end><![CDATA[20140722160655]]></time_end>
</xml>
业务级错误返回:
<xml>
<status>0</status>
<message><![CDATA[OK]]></message>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<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 表示调用失败。
数字签名:
为了保证数据传输过程中的数据真实性和完整性,我们需要对数据进行数字签名,在接收签名数据之后进行签名校验。
数字签名有两个步骤,先按一定规则拼接要签名的原始串,再选择具体的算法和密钥计算出签名结果。
一般失败的结果不签名。
签名原始串
无论是请求还是应答,签名原始串按以下方式组装成字符串:
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.weixin.scancode]]></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¬ify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.weixin.scancode&total_fee=1
签名算法
目前暂只支持 MD5 签名
MD5 签名
MD5 是一种摘要生成算法,通过在签名原始串后加上商户通信密钥的内容,进行 MD5 运算,形成的摘要字符串即为签名结果。为了方便比较,签名结果统一转换为大写字符。
注意:签名时将字符串转化成字节流时指定的编码字符集应与参数 charset 一致。
MD5 签名计算公式:
sign = Md5( 原字符串 &key= 商户密钥) ). . to Upper Case
如:
假设以下为 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.weixin.scancode]]></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¬ify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.weixin.scancode&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¬ify_url=http://227.0.0.1:9001/javak/sds?123&23=3&out_trade_no=141903606228&service=pay.weixin.scancode&total_fee=1&key=e1cf0ddcf6b47b59c351565d8ad717af
).toUpperCase()
=”83684D9546F261997EFF2ECFAC372583”
补单机制
注意:对后台通知交互模式,如果收到商户的应答不“success”或超时,…认为通知失败,会通过一定的策略(如30分钟共8 次)定期重新发起通知,尽可能提高通知的成功率,但不保证通知最终能成功。
由于存在重新发送后台通知的情况,因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回“success”。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
注意事项:
1、所有涉及到金额的单位都是分,最小的单位是1分,不能有小数出现
2、notify_url是平台服务器从后台直接发起请求到商户服务器,商户处理时不能检查用户的cookie或session;商户更新DB等发货流程需要在 notify_url完成后,以确保掉单时,平台补单能成功补上
3、notify_url有可能重复通知,商户需要做去重处理,避免多次发货
4、notify_url收到的通知,商户处理成功或检查订单已经处理,需要返回处理成功的标志纯字符串success,字符串success不区分大小写;如 果我们没有收到返回的success,我方服务器继续向你们发送通知,在三小时后将不再通知;假设所有订单都没有返回success,将增加我 们服务器的通知负载,最坏的情况,可能就是导致正常通知商户的通知发生延迟;另外我们会催促你们完善,如果长期不改善,研发或运 维技术将对贵司开通的支付接口采取控制措施。
5、文档中请求接口时传的参数,必填为是的参数是必须要传的(如有缺少会报错),必填为否的参数可以传也可以不传
6、返回参数中必填为是的参数是一定会返回的,必填为否的参数则不一定返回,因升级或配置等情况实际返回参数可能不会跟文档完全一 致,必须以实际接收到的参数为准
7、其它注意事项
(1) 参数大小写问题
请留意文档中要求的字符大小写问题, 如 “md5 运算后, 字符串的字符要转换为大写” 。
(2) 参数格式问题
所有传入参数,均为字符串类型,请注意文档中各处的具体要求。
(3) 时间戳问题
请使用 Linux 时间戳,注意为字符串格式。
(4) 同一商户订单号支付问题
商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。
问题排查:
备注:
- 更多返回错误代码请看首页的错误代码描述