1. 文档说明
1.3. 签名规则
用户可以在HTTP请求中增加 Authorization 的Header来包含签名(Signature)信息,表明这个消息已被授权。
HmacUtils.hmacSha1Hex( (1)
key, (2)
verb + "\n" + (3) (4)
resource + "\n" + (5)
body + "\n" + (6)
timestamp + "\n"); (7)
1 | 使用hmacSha1进行签名转16进制 |
2 | key 为AccessKeySecret,表示签名所需的密钥,该密匙是在控制台生成 |
3 | verb 表示HTTP 请求的Method,主要有PUT,GET,POST,HEAD,DELETE等 |
4 | \n 表示换行符 |
5 | resource 为参数拼接串,内容为请求接口的 path+?+query |
6 | body 表示请求体的json完整json内容 |
7 | timestamp 表示时间戳表示此次操作的时间,且必须为GMT格式, 如"Sun, 22 Nov 2015 08:16:38 GMT",该时间戳也将加入到 Header 中,键为 Date |
没有请求体的HttpMethod的签名body用空字符串
HmacUtils.hmacSha1Hex("3zKciJOwhWE4SSRUxXzCsABcIhJWd5Gb",
"POST" + "\n" +
"/charges?a=a&b=b&c=c" + "\n" +
"{"a":"a","b":"b","c":"c"}" + "\n" +
"Sun, 22 Nov 2015 08:16:38 GMT" + "\n"
再将签名前面加入accessKeyId进行base64编码,在结果前面加入Basic+空格组成Authorization
"Basic " + Base64.encodeBase64String((accessKeyId + ":" + signature).getBytes()));
Content-Type:application/json; charset=UTF-8
Authorization:Basic NTgzMTM1NDZlZjE5MGM1MWMwYmVhYzZmOjA2NzY2NTUwMzdhOTQyZDc5M2JjOGM5YzRmNzE5M2QzZTRhYjY5YjE=
Date:Tue, 13 Dec 2016 03:22:13 GMT
1.4. 验签规则
为防止黑客伪造交易结果给商户造成损失,PayingCloud对所有发给商户的交易结果异步通知都进行了RSA签名,并将签名进行Base64编码后放在Http请求头 sign 中,开发者需要使用SHA1WithRSA算法和PayingCloud提供的RSA公钥对其进行验证:
// 从异步通知请求头中获取签名
String sign = request.getHeader("sign");
// 对签名Base64解码
byte[] signBytes = Base64.decodeBase64(sign)
// 获取异步通知请求体
String content = ...
// 对请求体进行UTF-8字符解码
byte[] contentBytes = content.getBytes("UTF-8")
// 采用SHA1WithRSA算法进行验证
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.decodeBase64(PayingCloud.DEFAULT_PUBLIC_KEY); // 使用PayingCloud提供的RSA公钥
PublicKey key = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance("SHA1WithRSA"); // 验签算法SHA1WithRSA
signature.initVerify(key);
signature.update(contentBytes);
return signature.verify(signBytes);
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPymtLbRkHgvVfUT933LrwWns6YZHLPpT1pP9TKJ+cgIZiQwZ4mtqoqPHSVtiT5HA8fwFzWuJ/6qWaQhER7TOISUFUHZlHyBjNK/Z5px6PNB7rT4OrLP0KuZ7nuX5qdnOKuAbrj1MBLSinOHQ8tDJhPrPKxuZlKw3SeL5auHlKWwIDAQAB
2. API接口
2.1. 付款接口
2.1.3. 请求参数
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
商户收款单号 |
chargeNo |
是 |
String(32) |
20150806125346 |
商户系统内部订单号,要求8到32个字符、且在同一个应用下唯一,只能包含字母和数字 |
商品名 |
subject |
是 |
String(32) |
iPhone7-32G |
展示在收银台的商品名称 |
收款金额 |
amount |
是 |
Int |
888 |
订单总金额,单位为分,不能小于1 |
备注 |
remark |
否 |
String(128) |
订单备注:1.XXXXXXXXX,2.XXXXXXXXX |
订单备注 |
收款渠道 |
channel |
是 |
String(20) |
ALIPAY_WEB |
具体渠道类型详见 渠道类型表 |
渠道额外参数 |
extra |
否 |
Map<String, String> |
{"returnUrl": "https://api.payingcloud.cn/returnUrl"} |
用键值对的map存储不同渠道之间的渠道额外参数 |
元数据 |
metadata |
否 |
String(512) |
… |
元数据,用于携带自定义数据,原样返回,如类似json数据也必须转换为字符串格式 |
异步通知地址 |
notifyUrl |
否 |
String(100) |
https://api.payingcloud.cn/callback |
支付成功后返回支付结果地址,必须为公网地址,如不填将发送到在控制台配置的Webhooks地址,如也没配置Webhooks地址的话将不发送通知 |
2.1.4. 同步返回参数
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
应用id |
appId |
是 |
String(24) |
583128ffef190c52ccec68a8 |
发起支付的应用id |
商户收款单号 |
chargeNo |
是 |
String(32) |
20150806125346 |
商户系统内部订单号 |
商品名 |
subject |
是 |
String(32) |
iPhone7-32G |
商品名称 |
备注 |
remark |
否 |
String(128) |
订单备注:1.XXXXXXXXX,2.XXXXXXXXX |
订单备注 |
收款渠道 |
channel |
是 |
String(20) |
ALIPAY_WEB |
具体渠道类型详见 渠道类型表 |
收款金额 |
amount |
是 |
Int |
888 |
订单总金额,单位为分 |
已退金额 |
refundedAmount |
是 |
Int |
100 |
已退款总额,单位为分 |
元数据 |
metadata |
否 |
String(512) |
元数据,用于携带自定义数据,原样返回,如类似json数据也必须转换为字符串格式 |
|
交易凭证 |
credentials |
是 |
Map<String,String> |
详见交易凭证样例 |
交易凭证,渠道最终返回的连接或者最终请求参数,用于客户端发起交易,见交易凭证详情 |
状态 |
status |
是 |
String |
SUCCEEDED |
具体详见订单状态表 |
错误描述 |
errorMessage |
否 |
String(128) |
退款总额超出订单金额 |
发生错误时的错误描述参数 |
开始时间 |
startedAt |
否 |
Date |
1482389429010 |
从1970年1月1日00:00至今的毫秒时间 |
完成时间 |
completedAt |
否 |
Date |
1482389429010 |
从1970年1月1日00:00至今的毫秒时间。成功或失败时有值 |
2.1.5. 异步通知参数
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
商户APP |
appId |
是 |
String(24) |
583128ffef190c52ccec68a8 |
订单的发起appId |
商户收款单号 |
chargeNo |
是 |
String(32) |
20150806125346 |
支付时订单号 |
商品名 |
subject |
是 |
String(32) |
iPhone7-32G |
商品名称 |
备注 |
remark |
否 |
String(1000) |
退单备注:1.XXXXXXXXX,2.XXXXXXXXX |
退单备注 |
收款渠道 |
channel |
是 |
String(20) |
ALIPAY_WEB |
具体渠道类型详见 渠道类型表 |
订单金额 |
amount |
是 |
Int |
100 |
订单总金额,单位为分 |
已退金额 |
refundedAmount |
是 |
Int |
100 |
已退款总额,单位为分 |
元数据 |
metadata |
否 |
String(512) |
… |
元数据,用于携带自定义数据,原样返回,如类似json数据也必须转换为字符串格式 |
状态 |
status |
是 |
String |
SUCCEEDED |
具体详见订单状态表 |
错误描述 |
errorMessage |
否 |
String(128) |
退款总额超出订单金额 |
发生错误时的错误描述参数 |
开始时间 |
startedAt |
否 |
Date |
1482389429010 |
退款申请成功的时间,从1970年1月1日00:00至今的毫秒时间 |
完成时间 |
completedAt |
否 |
Date |
1482389429010 |
从1970年1月1日00:00至今的毫秒时间。成功或失败时有值 |
2.2. 退款接口
2.2.2. 请求参数
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
商户收款单号 |
chargeNo |
是 |
String(32) |
20150806125346 |
支付时订单号 |
退款单号 |
refundNo |
是 |
String(32) |
1217752501201407033233368018 |
商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 |
退款金额 |
amount |
是 |
Int |
100 |
退款总金额,订单总金额,单位为分,只能为整数 |
备注 |
remark |
否 |
String(128) |
退单备注:1.XXXXXXXXX,2.XXXXXXXXX |
退单备注 |
元数据 |
metadata |
否 |
String(512) |
… |
元数据,用于携带自定义数据,原样返回,如类似json数据也必须转换为字符串格式 |
异步通知地址 |
notifyUrl |
是 |
String(100) |
https://api.payingcloud.cn/callback |
支付成功后返回支付结果地址,必须为公网地址,如不填将发送到在控制台配置的Webhooks地址,如也没配置Webhooks地址的话将不发送通知 |
2.2.3. 返回结果
字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
商户app |
appId |
是 |
String(24) |
583128ffef190c52ccec68a8 |
退款单的发起app |
商户退款单号 |
refundNo |
是 |
String(32) |
1217752501201407033233368018 |
商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 |
商户收款单号 |
chargeNo |
是 |
String(32) |
20150806125346 |
支付时订单号 |
收款渠道 |
channel |
是 |
String(20) |
ALIPAY_WEB |
具体渠道类型详见 渠道类型表 |
退款金额 |
amount |
是 |
Int |
100 |
退款总金额,订单总金额,单位为分,只能为整数 |
备注 |
remark |
否 |
String(128) |
退单备注:1.XXXXXXXXX,2.XXXXXXXXX |
退单备注 |
元数据 |
metadata |
否 |
String(512) |
… |
元数据,用于携带自定义数据,原样返回,如类似json数据也必须转换为字符串格式 |
状态 |
status |
是 |
String |
SUCCEEDED |
具体详见订单状态表 |
错误描述 |
errorMessage |
否 |
String(128) |
退款总额超出订单金额 |
发生错误时的错误描述参数 |
开始时间 |
startedAt |
否 |
Date |
1482389429010 |
退款申请成功的时间,从1970年1月1日00:00至今的毫秒时间 |
完成时间 |
completedAt |
否 |
Date |
1482389429010 |
从1970年1月1日00:00至今的毫秒时间。成功或失败时有值 |
2.2.4. 异步通知参数
和[退款同步参数]相同
2.3. 订单查询
2.3.3. 返回参数
和[订单异步通知参数]参数相同
2.4. 退款单查询
2.4.3. 返回参数
返回参数和[退款同步参数]相同
3. 备注
3.1. 渠道类型表
渠道名称 | 传输参数 |
---|---|
民生银行T0清算支付宝扫码支付 |
CMBCPAY_T0_ALI |
民生银行T1清算支付宝扫码支付 |
CMBCPAY_T1_ALI |
民生银行T0清算微信扫码支付 |
CMBCPAY_T0_WX_QR |
民生银行T1清算微信扫码支付 |
CMBCPAY_T1_WX_QR |
民生银行T0清算微信公众号支付 |
CMBCPAY_T0_WX_JSAPI |
民生银行T1清算微信公众号支付 |
CMBCPAY_T1_WX_JSAPI |
民生银行T1清算QQ扫码支付 |
CMBCPAY_T1_QQ |
民生银行T0清算QQ扫码支付 |
CMBCPAY_T0_QQ |
微众银行微信扫码支付 |
WEBANKPAY_WX_QR |
微众银行微信公众号支付 |
WEBANKPAY_WX_JSAPI |
支付宝APP支付 |
ALIPAY_APP |
支付宝即时到账 |
ALIPAY_DIRECT |
支付宝扫描付 |
ALIPAY_QR |
支付宝手机网页支付 |
ALIPAY_WAP |
微信APP支付 |
WXPAY_APP |
微信公众号支付 |
WXPAY_JSAPI |
微信扫码支付 |
WXPAY_NATIVE |
银联手机控件支付 |
UPACP_APP |
银联网关支付 |
UPACP_GATEWAY |
京东钱包PC网页支付 |
JDPAY_WEB |
京东钱包移动网页支付 |
JDPAY_WAP |
京东钱包扫码支付 |
JDPAY_QR |
百度钱包PC网页支付 |
BDPAY_WEB |
百度钱包移动网页支付 |
BDPAY_WAP |
百度钱包扫码支付 |
BDPAY_QR |
首信易支付PC网页支付 |
BJPAY_WEB |
首信易支付微信支付 |
BJPAY_WX |
首信易支付微信支付 |
CHINAPAY_WEB |
易宝PC网页支付 |
YEEPAY_WEB |
易宝移动网页支付 |
YEEPAY_WAP |
快付通微信扫码支付 |
KFTPAY_WX |
快付通支付宝扫码支付 |
KFTPAY_ALI |
3.2. 交易凭证样例
"url":"<form name=\"punchout_form\"method=\"post\" action=\"https://pay.yizhifubj.com/prs/user_payment.checkit?v_md5info=b00a57dc732366cbfed3da03fe064af5&v_orderstatus=1&v_rcvname=9466&v_moneytype=0&v_oid=20161222-9466-585b77b5ab5c986f049a0faa&v_ymd=20161222&v_url=http%3A%2F%2F127.0.0.1%3A9000%2Forder%2Fcharge%2Freturn&v_rcvaddr=9466&v_ordername=9466&v_rcvtel=9466&v_mid=9466&v_amount=0.01&v_rcvpost=9466\">\n<input type=\"submit\" value=\"[0xe7][0xab][0x8b][0xe5][0x8d][0xb3][0xe6][0x94][0xaf][0xe4][0xbb][0x98]\" style=\"display:none\" >\n</form>\n<script>document.forms[0].submit();</script>"
3.3. 交易凭证详情
-
BDPAY_WEB
-
BDPAY_WAP
-
从credentials中获取键: url
-
servletResponse.sendRedirect(charge.getCredentials().get("url"));
-
ALIPAY_DIRECT
-
BJPAY_WEB
-
CHINAPAY_WEB
-
JDPAY_WEB
-
JDPAY_WAP
-
YEEPAY_WAP
-
ALIPAY_WAP
-
从credentials中获取键: html(utf-8)
-
servletResponse.setContentType("text/html;charset=UTF-8");
servletResponse.getWriter().write(charge.getCredentials().get("html"));
-
YEEPAY_WEB
-
从credentials中获取键: html(gbk)
-
servletResponse.setContentType("text/html;charset=gbk");
servletResponse.getWriter().write(charge.getCredentials().get("html"));
-
BDPAY_QR
-
从credentials中获取键: url(图片地址)
-
-
WXPAY_NATIVE
-
BJPAY_WX
-
ALIPAY_QR
-
KFTPAY_WX
-
KFTPAY_ALI
-
JDPAY_QR
-
CMBCPAY_T0_ALI
-
CMBCPAY_T1_ALI
-
CMBCPAY_T0_WX_QR
-
CMBCPAY_T1_WX_QR
-
CMBCPAY_T0_QQ
-
CMBCPAY_T1_QQ
-
WEBANKPAY_WX_QR
-
从credentials中获取键: codeUrl(生成二维码的字符串)
-
-
WXPAY_JSAPI
-
CMBCPAY_T0_WX_JSAPI
-
CMBCPAY_T1_WX_JSAPI
-
WEBANKPAY_WX_JSAPI
-
从credentials中获取键:
-
appId
-
timeStamp
-
nonceStr
-
package
-
signType
-
paySign
-
-
在页面调用微信jsSDk 详情见 微信公众号h5调用文档