目录:
- 场景介绍
- 接入指引
2.1 准备工作
2.2 接口调用规范
2.2.1 请求说明 - API列表
3.1 微信/支付宝支付跳转页面接口
3.2 交易结果查询接口
3.3 交易退款接口
3.4 交易退款结果查询接口
3.5 交易结果通知 - 支付全流程了解
1. 场景介绍
H5支付是指商户在微信或者支付宝客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信或支付宝支付时,商户发起本服务呼起微信或支付宝客户端进行支付。
主要用于触屏版的手机浏览器请求支付的场景,可以方便的从外部浏览器唤起微信或支付宝支付。
提醒:H5支付不建议在APP端使用,如需要在APP中使用微信和支付宝支付,请接入APP支付
提醒: 微信h5支付只能用在微信外 比如自研app或手机系统浏览器。微信H5支付在微信app内不能支付。微信App内请使用JSAPI支付或小程序支付
2. 接入指引
2.1 准备工作
第一步、获取开发者数据
调用聚合支付平台接口,需要与平台商务对接后,获取开发者ID(developId),密钥(privateKey),公钥(publicKey)和对称密钥(desKey),这些参数让商户拥有调用平台接口的权限,对请求的数据进行加密以保证数据的安全性。
- 开发者ID(developerId):
developerId在所有的请求中都需要传入,与密钥公钥信息相对应,鉴别请求是否是由平台商户发起。
- 密钥(privateKey):
密钥在接口请求中用于对数据进行RSA加密,生成签名sign。
- 公钥(publicKey):
公钥用于对签名进行解密
- 对称秘钥(desKey):
<body>标签的中的参数,需要通过des进行对称加解密,请求时使用密文,返回密文通过对称秘钥进行解密。
第二步、获取平台商户号
每个商户对接聚合支付平台,在第三方平台想要拥有的支付能力,需要在支付宝或者微信签约对应的支付方式,平台的商务会为每个商户分配一个平台商户号(merchantNo),该商户号账户下所有的交易流水都会进入到对应的支付宝和微信的账户下,并且平台账单流水都是以商户号进行隔离,这是一个非常重要的参数。
第三步、下载demo
- java版本:下载demo
2.2 接口调用规范
2.2.1 请求说明
接口通信地址:
测试环境:http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute
正式环境:由平台商务对接人员提供http请求格式:
Content-type:application/xml
实体对象为 xml 格式,严格区分大小写,xml格式如下:
<?xml version='1.0' encoding='UTF-8'?> <Root> <Head></Head> <Body> </Body> </Root>
公共参数说明:
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例 |
---|---|---|---|---|---|
MerchantNo | String | 是 | 10 | 注意:这是开发者id(developerId) |
12345 |
FuncId | String | 是 | 20 | 功能码 | P7005 |
Signature | String | 是 | 100 | 签名 | Sa/hb9jaTZZZq89mN62DDooLv/YTvfE9ayrbzgOMsucfIPZfJGmhUia6YWK8vQ5/NQana3Pub7BDswEenm0sBg== |
Timestamp | String | 是 | 100 | 当前时间戳(自1970-1-01 00:00:00.000 到当前时刻的时间距离【精确到毫秒】) | 1564120486130 |
RetCode | String | 是 | 30 | 0000:表示接口业务调用正常,9999:表示处理失败,如参数错误,验签失败等(注:RetCode并不表示交易行为成功或失败,某笔交易是否成功请根据对应接口返回报文的状态字段来判定) | 0000 |
RetMsg | String | 是 | 100 | 接口调用异常返回信息 | 验签失败 |
注意:Signature签名的生成过程,是先通过‘对称秘钥’对<Body>中的数据域进行DES加密,得到密文之后,再用‘私钥’对密文进行RSA加密
- 请求报文示例:
<?xml version='1.0' encoding='UTF-8'?> <Root> <Head> <MerchantNo>开发者id</MerchantNo> <FuncId>P7006</FuncId> <Timestamp>12312312312324</Timestamp> <Signature>kLRyaxQXe6yLu+ktZUOiB+afVgeY5Doq9fTB27rAkW7/MBMK10tcxWM7eVVtmzxju0Xi1rtW16D7cV5PgM+zDA==</Signature> </Head> <Body>ql1e6Mhtmrq7yA6wGuE4biskwAEq8ALzOFr5kJxbVoP7VuaeoasTxHkdf8GTwlLihUhSk+ZcGsnJWNJHfMCtr9valAWD/y8sOAQut1/sWhg=</Body> </Root>
注意:请求参数中 MerchantNo 是 开发者id
- 返回报文示例:
<?xml version="1.0" encoding="UTF-8"?> <Root> <Head> <MerchantNo>开发者id</MerchantNo> <FuncId>P7006</FuncId> <Timestamp>1533718324024</Timestamp> <Signature><![CDATA[hNCUjy30FibXT8YuqhEwaMFv6dzERMRWAVa0XjcKDmzjZ jkQ1DPXzJtJooe43QfLLmW+38eDLmeUK7Y17nMfjA==]]> </Signature> <RetCode>0000</RetCode> <RetMsg></RetMsg> </Head> <Body> <![CDATA[NLB9nF8xXHoJgCgwYtRkMG9vhJlpSl9hjIF6LMQduYoaNNwmDqKKhBfUVBn u6ZPH33q3DLWEfnzUP5E2Mvzz2gK7riCvIfe1yJ/D5b3Ia67vFkHI6HBPhykm6uVLsbdW 7Q1xSLuEv2jGqfwzSl35GPAJrwrd8wylCRp6B2aLv4x3DYmUROKXVk+fPObHTb0nU7a1Z Hkw7Nhj+15CPHnMLDj/s4jK9OOdkhKrWg/NTDvnZR65jFXsvqPfitPmkYsTEzuXwQSq88GF 9YAmP+dcVeHHxBpaYkcV0N+JdN9h1TJg+uENaZIgU4ayDF2N7dVhYO54+vgSd/3HLHloow zXUVo2XdPVZgrvDRpmyqpk3YA8Pe4njAgZnA7/RRXvqX1ueOyQVEt1br7i4F5mGwnSuM9 KOCDIkTNre9rvCdbsui5U0CpxgeM3WQ==]]> </Body> </Root>
注意:这里的返回数据域为密文,需要接入方使用‘对称秘钥’进行DES解密,即可得到原文数据。如果需要验证数据的有效性,可以利用‘公钥’对Signature进行验签
注意:这里的返回数据中MerchantNo 是 开发者id
利用java工具类解密示例:
利用java工具类验签示例:String xml = SecurityUtil.decryptDes(Body,[your desKey], "utf-8");
boolean verify = SecurityUtil.verifyRSA(data, [your publicKey], Signature, "utf-8");
3. API列表
3.1 微信/支付宝支付跳转页面接口
- 功能码:P7006
- 接口说明:商户在移动端网页展示商品或服务,用户在网页中确认支付时,商户唤起对应的微信、支付宝客户端进行支付,主要方便从外部浏览器唤起对应的支付。该接口用于提交订单去第三方支付平台进行预下单。
- 请求参数:
<Data>
参数 | 名称 | 类型 | 长度 | 必填 | 说明 | 示例 |
---|---|---|---|---|---|---|
merchant_no | 收款商户号 | String | 30 | 是 | 创业聚合支付系统为医院分配的平台商户号 | 809900000001 |
user_name | 支付者姓名 | String | 30 | 是 | 付款者姓名 | 张三 |
order_no | 业务单号 | String | 30 | 是 | 商户业务系统的唯一订单号 | BX20190722902141 |
paytype | 支付渠道 | String | 2 | 是 | 2=支付宝; 3=微信 | 2 |
trade_type | 交易类型 | String | 2 | 是 | 5=h5支付 | 5 |
total_amt | 支付金额 | Price | 20.2 | 是 | 以元为单位 | 0.01 |
spbill_create_ip | 用户IP | String | 10 | 是 | 客户端实际ip(微信需要,如果不是真实地址,微信会报错) | 183.156.115.113 |
order_subject | 商品标题 | String | 150 | 是 | 如:门诊、住院预交、住院结算、自助缴费等 | 门诊 |
order_detail | 商品描述 | String | 300 | 是 | 如:门诊挂号、门诊结算、住院预交、住院结算、自助挂号、自助结算、自助住院预交等 | 门诊挂号 |
wap_url | WAP网站URL地址 | String | 64 | 否 | 当支付渠道为3=微信时,必填 | http://xx.merchantno.com/wapurl |
wap_name | WAP 网站名 | String | 64 | 否 | 当支付渠道为3=微信时,必填 | 测试预约挂号网 |
redirect_url | 商户支付完成后回调网站地址 | String | 64 | 否 | 正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,就需要必填 | http://xx.merchantno.com/redirecturl |
timeout_express | 订单超时时间 | String | 3 | 否 | 单位是: m (分钟) 如果不填,默认是 6分钟,如果填,必须大于5分钟 | 6 |
mobile | 手机号码 | String | 15 | 否 | 用户手机号 | 13211112222 |
sub_merchant | 分店号 | String | 30 | 否 | 商户内部区分订单字段 | 001 |
remark | 备注 | String | 200 | 否 | 备注 | |
notifyURL | 自定义支付结果通知地址 | String | 否 | 单独为此订单配置的支付结果通知地址 | http://test.com/callback |
- 响应参数:
参数 | 名称 | 类型 | 长度 | 必输 | 说明 | 示例 |
---|---|---|---|---|---|---|
order_no | 商户订单号 | String | 128 | 是 | 商户内部唯一订单号 | wap201907260001 |
pay_html | 支付页面 | String | 500 | 是 | 返回一个完整的html页面 | <html>...</html> |
Java请求示例:
public void P7006(){ String developerId = 【your developerId】; String privateKey =【your privateKey】; String desKey = 【your desKey】; String data = "<Data>" + "<merchant_no>809900000001</merchant_no>" + "<user_name>测试者</user_name>" + "<order_no>"+ "h5paytest20190726001"+"</order_no>" + "<paytype>3</paytype>" + "<trade_type>5</trade_type>" + "<total_amt>0.01</total_amt>" + "<spbill_create_ip>124.90.38.131</spbill_create_ip>" + "<order_subject>测试订单标题</order_subject>" + "<order_detail>测试订单描述</order_detail>" + "<wap_url>http://pay.bsoftpay.com/</wap_url>" + "<wap_name>聚合支付平台</wap_name>" + "<redirect_url>http://pay.bsoftpay.com/</redirect_url>" + "<timeout_express>6</timeout_express>" + "<mobile>13212341234</mobile>" + "</Data>"; HeaderDTO header = new HeaderDTO(); header.setFuncId("P7006"); header.setMerchantNo(developerId); header.setTimestamp(System.currentTimeMillis() + ""); header.setSignature(SecurityUtil.signRSA(data, privateKey, "UTF-8")); // DataDTO dataDTO = new DataDTO(); dataDTO.setHeader(header); dataDTO.setBody(SecurityUtil.encryptDes(data, desKey , "UTF-8")); String content = XMLUtil.toXml(dataDTO, DataDTO.class, "UTF-8"); String resData = null; try { CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build()); String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8); System.out.println(res); //解析返回xml DataDTO resultData = XMLUtil.fromXml(res, DataDTO.class); //回调成功-获取body内容 if ("0000".equals(resultData.getHeader().getRetCode())) { //解密body resData = SecurityUtil.decryptDes(resultData.getBody(), desKey,"UTF-8"); }else{ //异常信息 resData = resultData.getHeader().getRetMsg(); } } catch (Exception e) { e.printStackTrace(); } System.out.println(resData); }
返回示例:
<?xml version="1.0" encoding="utf-8"?> <Root> <Head> <MerchantNo>63447</MerchantNo> <FuncId>P7006</FuncId> <Timestamp>1564127089558</Timestamp> <Signature><![CDATA[hNCUjy30FibXT8YuqhEwaMFv6dzERMRWAVa0XjcKDmzjZ jkQ1DPXzJtJooe43QfLLmW+38eDLmeUK7Y17nMfjA==]]></Signature> <RetCode>0000</RetCode> <RetMsg></RetMsg> </Head> <Body><![CDATA[plNoHrFo3ZIhSaysDI4tNAeD4iJ6aIYtkK+b1aHS527KUeD2ybQNedCsGD87s4e58DfNir4OvENm7vQQp5K8yqzEIVSmV5bRbYUK9k6pKVkH00u9yWU935bmP5hnKyv9hoFZker+TCP6AMj/QaEXT3FblZ17J4ZvG1LHSPoLlMJ1f8OjKQMHxJHxzgz4oaovO9pKI+nFwvmcsxy5JwoQiDqB0pat4Myf0BU1NziJ3fClT54bFfDJ9sgM80WV23s3EVGjZ3TNTA4RAmg4PoR2UMGjyCeIT5xuH1Ql9GZKoP+YjqduUdBU4flDvVTzDyXXpKBQr9mWow/DbOTwFPHFZKNfpYsMqA6yPVbMeFiHHNidXduB6sKAjJiFgPnIhyoC7qF6xNIFSyFvIi04W8+GwB/85TXwGL4AQOAsx1wftloqsjpZ7p+PPv0KblPeIH4dpn652uvmXwBA9wmIf7wilTJeccE6+pksTx4dw4tJ1HCBxNV0jGd7SyXta7RGO8toXcMlLWUSLYCbxHts9PtvgYlhoLUHxRyzMoT5TJMe/XDFXtTtjwF4TP7G2Vb1f/LTJTl95+sZKAUbA3Py8ItfPa0M/8wPc27B3LVj3snAZtb6GagMc3jOM3kF1awBY96hLqBQsPb0JbyX6IDwBK4ScsMBvx1yVnvRsWiqtozDdZefSGg2NWO0yaHPQoZls09d114LNf//3CoYGL4iN2wNEca7rfrH6abaGCKeGGmi1ml3UHsFJWVknjgI4wlIe0dMZM2fneQNMzvpm26OtVkScYw4qacFOnwKwxbbMS5tr7rQL+omSr4eY9yJhZot6zYeUzs4rhLYwOuL18lBr2A98r8RJg6abXz/U5+lYUm4hrVXuz5M20h1plGC3E4Cz4gUsrgXVE88aIGX3Sksz2w7xbA/IMZxcMQN60FlKEq2rFurb9nDQgZjNWFh8YSKpuwDFpoaj7RZ2TPWQVW1Q2GPBKcroVpT1hmGWneeFun4tvq6RCpITdnKQcZZkGGxmRJKa9GKzm3EY7e/swX7IGiI+qpstM7zZaipylt8N2DEraoWM0D7natnaG9l1UkbaZfkQ8p31d6O9EcKvhJ7Q5aTkWrrizcMNo+GTDS2JDkg3wQbVGZ7QJUewkncwDQnPeX5n2EU7RIyiH6sfLnAK+nJY6Z4Uhwk7LGhGf3TNW9EvOAZjDsC4yTnW49pXlJHyDfsgCV7uuO8JOPPwT82GSHGXyhnX8PBcpw1EaKNbg9zg+yR1gPHo38eNSOPR9JmY97h9IOstPaUnHAlYCG5pTyRAFrGYesxNHyxXgL+N3W/p7e0Tqa3MBBVV4mUg7nF2bOwoO+XcupVIhCp04tMyrC0dDk4g6aYTEwi8NHXt7H+ii53NOocdW7xjKjCi7DUKFuU7F7jNbiFpq0F0q+ZZymhZdlq92T+i3psG51o80v6NrkAhy8NsWEdw0gflS1rhVOVgCV7uuO8JOOclc+d0A86oanZEbzZhHDaF2qZP6BJ8d+vhcCNAw9xTwxqjguuXJM8gCV7uuO8JOPJ7qm3PXpB6JL9PIznO52qAWO8U1u02AbMUSDHC06Im6MGFDSWZ9aSbtsylhhxJQElK3DsohiQlBGijW4Pc4PskdYDx6N/HjUeTANfh3Wba0sqAte+jJDzgCV7uuO8JOOqy79YHvEp3hudaPNL+ja5o4JwThkt3SLvg3rLeYkyKYAle7rjvCTjuRbpquur1u0w6NmEbaCeRUJOJ6QKUpUflzWTM0DS708A+qu8UPPHDEQ2TL3yUnzdyV2DG3QirT+Z9IcVkmWg4jS9YWwwHW2Q3T8QfnST7Dq4R9VcjaH9AJWRQBom7IzUooJ5JV3jyhRO/QBT3g9i3TFxscMncTvu6CugTcygrEm2csH3I4IhCwoAo9ibZl7y]]></Body> </Root>
注意:返回信息中MerchantNo 是 开发者id
对<Body>
des解密后得到结果示例:
<Data>
<order_no>330104501564105987172</order_no>
<pay_html>
<form xxxx></form><script>document.forms[0].submit();</script>
</pay_html>
</Data>
3.2 交易结果查询接口
- 功能码:P2005
- 接口说明:该接口提供所有支付订单的结果查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑,当商户在一定时间(建议3秒)没有收到支付平台异步通知时,可以主动调用该接口查询某笔订单的交易状态
- 请求参数:
<Data>
参数 | 名称 | 类型 | 长度 | 是否必填 | 说明 | 示例 |
---|---|---|---|---|---|---|
order_no | 业务单号 | String | 32 | 是 | 商户内部业务单号 | WX2019072200001 |
merchant_no | 收款商户号 | String | 32 | 是 | 商户号 | 809900000001 |
- 响应参数:
参数 | 名称 | 类型 | 长度 | 是否必输 | 说明 | 示例 |
---|---|---|---|---|---|---|
TradeNo | 平台流水号 | String | 32 | 是 | 聚合支付平台流水号 | 34411000 |
PayTradeNo | 渠道流水号 | String | 32 | 是 | 各个支付渠道返回的流水号 | 4200000376201907220000000000 |
OrderNo | 业务单号 | String | 32 | 是 | 商户内部业务单号 | WX2019072200001 |
Amt | 实际支付金额 | Price | 16.2 | 是 | 用户实际付款金额 | 0.01 |
PayTime | 实际支付时间 | String | 16 | 是 | yyyy-MM-dd hh:mm:ss | 2019-07-22 21:37:31 |
PayStatus | 支付状态 | String | 6 | 是 | 0=未支付;1=支付成功;2=支付失败;-1=关闭或撤销 | 1 |
receipt_amount | 商户收到的金额 | Price | 16.2 | 是 | 相当于订单支付金额 | 0.01 |
JAVA请求示例:
String data = "<Data>" + "<order_no>WX2019072200001</order_no>\n" + "<merchant_no>809900000001</merchant_no>\n"+ "</Data>"; HeaderDTO header = new HeaderDTO(); header.setFuncId("P2005"); header.setMerchantNo(【your developerId】); header.setTimestamp(System.currentTimeMillis() + ""); header.setSignature(SecurityUtil.signRSA(data, 【your privateKey】, "UTF-8")); // DataDTO dataDTO = new DataDTO(); dataDTO.setHeader(header); dataDTO.setBody(SecurityUtil.encryptDes(data, 【your desKey】 , "UTF-8")); String content = XMLUtil.toXml(dataDTO, DataDTO.class, "UTF-8"); String resData = null; try { CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://onlinetest.bsoftpay.com/gatewayOnline/gateway/portal/execute").setEntity(new StringEntity(content, ContentType.APPLICATION_XML.withCharset(Consts.UTF_8))).build()); String res = EntityUtils.toString(response.getEntity(), Consts.UTF_8); System.out.println(res); //解析返回xml DataDTO resultData = XMLUtil.fromXml(res, DataDTO.class); //回调成功-获取body内容 if ("0000".equals(resultData.getHeader().getRetCode())) { //解密body resData = SecurityUtil.decryptDes(resultData.getBody(), 【your desKey】,"UTF-8"); }else{ //异常信息 resData = resultData.getHeader().getRetMsg(); } } catch (Exception e) { e.printStackTrace(); } System.out.println(resData);
对
<Body>
des解密后得到结果示例:<Data> <TradeNo>9000010155</TradeNo> <PayTradeNo>2019071622001473731042322248</PayTradeNo> <OrderNo>paymentTest201907160001</OrderNo> <Amt>0.01</Amt> <receipt_amount>0.01</receipt_amount> <PayStatus>1</PayStatus> </Data>
注意: P2005功能中数据域是用
<Data></Data>
包围
3.3 交易退款接口
- 功能码:P2008
- 接口说明:当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家(原路返回)。注意的地方:微信超过1年的订单无法提交退款,支付宝超过3个月的订单无法提交退款,可以一笔订单多次退款,但是累计金额不能超过原支付金额
- 请求参数:
<Data>
参数 | 名称 | 类型 | 长度 | 必填 | 说明 | 示例 |
---|---|---|---|---|---|---|
RequestNo | 退款订单号 | String | 32 | 是 | 商户内部唯一退款单号 | TK20190722001 |
PayType | 退款渠道 | String | 2 | 是 | 2=支付宝;3=微信 | 2 |
Amt | 退款金额 | Price | 16.2 | 是 | 退款金额不得超过原支付金额 | 0.01 |
TradeNo | 原支付业务单号 | String | 32 | 是 | 商户原支付订单号 | WX2019072200001 |
merchant_no | 商户号 | String | 32 | 是 | 平台商户号 | 809900000001 |
- 响应参数:
参数 | 名称 | 类型 | 长度 | 必输 | 说明 | 示例 |
---|---|---|---|---|---|---|
RequestNo | 退款订单号 | String | 32 | 是 | 申请退款订单号 | TK20190722001 |
Amt | 退款金额 | Price | 16.2 | 是 | 申请退款金额 | 0.01 |
- 请求数据域示例:
<Data> <RequestNo>MZ18007960352737_tk</RequestNo> <PayType>3</PayType> <Amt>0.01</Amt> <TradeNo>MZ18007960352737</TradeNo> <merchant_no>809900000001</merchant_no> </Data>
- 返回数据域示例:
<Data> <RequestNo>MZ18007960352737_tk</RequestNo> <Amt>66.6</Amt> </Data>
- 注意: P2008功能中数据域是用
<Data></Data>
包围
3.4 交易退款结果查询接口
- 功能码:P2009
- 接口说明:提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用微信零钱或者支付宝余额宝、花呗等支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态(20分钟、3 个工作日都是大概时间,不一定为准,有可能提前,有可能延迟)
- 请求参数:
<Data>
参数 | 名称 | 类型 | 长度 | 是否必填 | 说明 | 示例 |
---|---|---|---|---|---|---|
RequestNo | 退款订单号 | String | 32 | 是 | 商户内部唯一退款单号 | TK20190722001 |
PayType | 退款渠道 | String | 2 | 是 | 2=支付宝;3=微信 | 2 |
- 响应参数:
参数 | 名称 | 类型 | 长度 | 是否必输 | 说明 | 示例 |
---|---|---|---|---|---|---|
RequestNo | 退款订单号 | String | 32 | 是 | 申请退款订单号 | TK20190722001 |
Amt | 退款金额 | Price | 16.2 | 是 | 当code为1时这里会显示退款金额 | 0.01 |
Code | 退款状态 | String | 2 | 是 | -1交易不存在 1 成功 2 失败 | 1 |
Msg | 错误信息描述 | String | 100 | 是 | 当code为2时这里会显示错误信息 | 0.01 |
- 请求数据域示例:
<Data> <RequestNo>MZ18007960352737_tk</RequestNo> <PayType>3</PayType> </Data>
- 返回数据域示例:
<Data> <RequestNo>MZ18007960352737_tk</RequestNo> <code>1</code> <Msg></Msg> <Amt>66.6</Amt> </Data>
- 注意: P2009功能中数据域是用
<Data></Data>
包围
3.5 交易结果通知
- 功能码:P3001
- 接口说明:支付状态改变(支付或作废)后,平台异步通知用户端(平台不保证异步通知能够准时到达,建议接入方有自己的定时主动查询策略,以异步通知作为辅助查询)。交易结果通知的地址,需要提前告知平台商务对接人员进行配置。
注意:商户在接受到支付平台回调后,如果业务成功,返回 success
,失败返回 fail
,注意都是小写,不要用空格或者换行。
支付平台服务器在没有收到业务成功回调信息时,会尝试重发消息,总共3
次通知(通知的间隔频率一般是:30s,1m,2m),3 次以后将不再通知,所以不保证通知最终能成功(建议以交易结果查询接口为主,异步通知为辅,如果 3 秒左右还没有接受到异步通知,就应该主动调用交易结果查询接口)
- 响应参数:
参数 | 名称 | 类型 | 长度 | 是否必输 | 说明 | 示例 |
---|---|---|---|---|---|---|
TradeNo | 支付平台交易流水号 | String | 32 | 是 | 支付平台交易流水号 | 32013134 |
PayTradeNo | 渠道流水号 | String | 32 | 是 | 第三方支付渠道流水号 | 20192323971391918391121 |
OrderNo | 业务单号 | String | 32 | 是 | 商户内部业务单号 | wx201907150001 |
Amt | 支付金额 | Price | 16.2 | 是 | 支付金额 | 0.01 |
PayTime | 实际支付时间 | String | 16 | 是 | yyyy-MM-dd hh:mm:ss | 2019-07-25 12:30:12 |
PayStatus | 支付状态 | String | 6 | 是 | 0=未支付;1=支付成功;2=支付失败;-1=关闭或撤销 | 1 |
- 返回示例:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Root> <Head> <MerchantNo>开发者id</MerchantNo> <FuncId>P3001</FuncId> <Timestamp>1564047104204</Timestamp> <Signature>O/qiP7mMk+aPrlyVursZRX7+lpcxpXyuwkD7wXLm2g+9k7jR2OVQUfeSUZz2ImsTwL1BwBbRNl/N8hIUrKmMJw==</Signature> </Head> <Body>q9bLT3/3k9fmPk5WBu4Z3BOLbGJBX9BoIymWbEp67FOrWlZRuBOyQ7OFyDRLRhi5RamJcI+WOsbD2vzG4KOYcZkXOgg/cU433T9URVZCxV8nUv8MlTHGSTg2Oz8Ws7slVrBTSfSuzkP6WIQ5FUSNen9UGSqVdpk155DK0iDi74TbF+5o9bSfO5fLFQVjIaqQayxjBSvOR3/3I9hKZaOVMpkIct/InCCGBliKd2dUIw1apNJJxhK75L+a1C0DD2gOyhOh8qKtFNA=</Body> </Root>
注:返回参数数据在<body>已经被DES加密,需要接入方利用对接时获取的“对称密钥”,对密文使用下载的加解密工具进行解密
注意:返回参数中 MerchantNo 是 开发者id
- 解密java示例:
String xml = SecurityUtil.decryptDes(body, [your 对称秘钥], "utf-8");
4. 支付全流程了解
- H5支付时序图:
- 外部链接:
微信H5支付介绍
支付宝H5支付介绍