为了方便大家理解,我们将使用测试的一对公私钥,通过命令行形式一步一步介绍如何生成"JSAPI调起支付"的签名,强烈建议你使用测试的公私钥,按照本文实际操作一下,如果算出来的签名和文档的一致则说明计算无误。实际业务中请替换为你的真实的参数。
1. 获取商户API证书
此处我们已经拿到了商户API证书,并且将对应的商户API私钥apiclient_key.pem,保存在了本地
证书序列号:408B07E79B8269FEC3D5D3E6AB8ED163A6A380DB
API证书私钥:你需要将以下文件保存为pem格式,为了避免大家和自己的真实的公私钥混淆,此处将其保存为了apiclient_test_key.pem
| 以下只是一个示例密钥,实际上并不可用,且示例的密钥是以-----BEGIN RSA PRIVATE KEY-----,实际你获取到的商户API私钥是以-----BEGIN PRIVATE KEY----- |
|
1-----BEGIN RSA PRIVATE KEY-----
2MIIEogIBAAKCAQEAptpm+qvIDCh/9wjU26SQCK26ogYkBhDrYxnAaw2JbbBsp1oD
3bHKk+1r381NeBUG2HEFAuU+Fr72u5ot3yKdzoF/FajAzQNKnm569/D3upKoi8mYB
4aST15Uig8j8qoUW1U217LL0jEHlSnHV3lcaDTXqDpTRR4Bfz9IqOgJgFZ8/oTfEo
5mSrjrLYef81Eyxr7ZIMQXEKKEK7V4UXKS0+/fDsiG/cXidhzt8UbTL9vqXqxM2+I
6DImyO+FAc/tkBG55LmzxPto1Nq0WbnZzRM/wTzrd0I/8NlevxtFbphg4evlHjFNI
77+GrqR87ViEwuAJJ9Je5QQjct5YJfFRWiZ5CMQIDAQABAoIBAGBi/GhEgezcHIg1
8ltlHaFlLGuxsRbUnYwM9phVxnXk7GJlYe2/TjpERjPkIqOC6hBwwadZjJORP3FCc
9Mtc8PKRhjuZ377O7vU0915x2nnyLOGL1IE2AJ3iLi0ZFzTea0FPgg+5lWHM00s9F
10YI6qPcGtS41M+xtMWwZiYE3TBBRibHiY8ugGyaNAhiMKehyW05uApjlIF55wwCGx
11BkyESJpGRR/6853iHke6Ge+xVcMa9QmQdoH0QqL/8kT28PL568mJJr0Ow/83t4+d
12Pe70YPzKAxgUnaDsHJqO+b8qH69AEs8rTI5h2Mon6pH+bJT66KUoiXhn+Kf+4LSs
13henRP10CgYEA1QJSfuFOWVRjrg3N/rAIc/Ak84BTZavbyrkqBSuoTs9i/nMI/hOz
14VxpDntg7Bx2Tctl6sZO3GioTxKdc/YYaTKci1TKBbeginpsqEQVgwkMCy8HpvUmR
15fyAMqLwZC4h9+j+NiZtuoFJDTCgv+WYbasX+kWYEUM21bnSYuO7yEQsCgYEAyIdP
16r9uzqPgzN34Tmx+CNTa16VjhBh+zkBtXRLDLhWBeIYxoYNJARD98Pb1XZdvpkZZW
17Sk7MfaKo2/DomzyyyB/MbHWwAdFi3yb4y7uMJfyC1MzdUSNN3Vp579hJxHkJ+nN4
18Ys76yfcEeVOLnvUT1Z0KKCdIWRdT1Lgi+X1itzMCgYBJUXlPzwGG4fNFj97d0X23
19Wmt9nSgXkOYgi0eZbAOMzPmIF9R6kBFk49dur4Lx2g5Ms+r1gKC/0sfnIqxxX11i
20EQ1+UNoYGJUB/uql3TIG68XkmKR50P7RwRhaZBRC0gJ6xrFTMjsL2ATuC88niyvY
21vrn3FiRaI9RVZrDCxwxvLQKBgEXW4okEAqGBuAzGqztmkOnJoTehDdYdKmOxMgap
22cGiGdKJIjX3THDDoz3ONQyglnEZpTqpYoV3MTfU0BT8zt6x9bqwDnQY1D7NalmIW
23cqw0Mri8lQQSQKcsQLWo5aA466G/n5kCL1Qx5OwAjesRvhOyuvvbGpZ0ymyWqQ+t
24fLkDAoGATcul1L8y5D/wNVP1GXbXMZfBsFP3bbqy8c+Ashm6g8OLm2mGNntd5Z6h
251KkID7Yksh+dZ6t7XaPBtGACXX5Eryr537JVvdX8hAVCp5HVtaN/9VBVP8Ka2e4s
26VS/xeNgOMQ7uzhRPBJ8HiTmdI1nHhDnYQpGiBgQn0Z5RAkSvFMk=
27-----END RSA PRIVATE KEY-----
2. 构造签名串
我们希望商户的技术开发人员按照当前文档约定的规则构造签名串。微信支付会使用同样的方式构造签名串。如果商户构造签名串的方式错误,将导致签名验证不通过。下面先说明签名串的具体格式。
签名串一共有四行,每一行为一个参数。结尾以\n(换行符,ASCII编码值为0x0A)结束,包括最后一行。如果参数本身以\n结束,也需要附加一个\n。
1appId\n
2时间戳\n
3随机字符串\n
4prepay_id\n
JSAPI支付需要申请公众号,并获取对应的公众号的AppID,公众号的类型可以是服务号,也可以是订阅号(订阅号仅限于政府和媒体类型),可在公众号后台查看
1wx2421b1c4370ec43b
第二步,获取发起请求时的系统当前时间戳,即格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数,作为请求时间戳。微信支付会拒绝处理很久之前发起的请求,请商户保持自身系统的时间准确。
1$ date +%s
21554208460
第三步,生成一个请求随机串,我们推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串。这里,我们使用命令行直接生成一个。
1$ hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
2593BEC0C930BF1AFEB40B4A08C8FB242
1prepay_id=wx201410272009395522657a690389285100
1wx2421b1c4370ec43b\n
21554208460\n
3593BEC0C930BF1AFEB40B4A08C8FB242\n
4prepay_id=wx201410272009395522657a690389285100\n
3. 计算签名值
绝大多数编程语言提供的签名函数支持对签名数据进行签名。强烈建议商户调用该类函数,使用商户私钥对待签名串进行SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。
1$ echo -n -e \
2 "wx2421b1c4370ec43b\n1554208460\n593BEC0C930BF1AFEB40B4A08C8FB242\nprepay_id=wx201410272009395522657a690389285100\n" \
3 | openssl dgst -sha256 -sign apiclient_test_key.pem \
4 | openssl base64 -A
得出的签名值如下,你可以用一些校验工具校验你通过命令行或者你的代码得到的签名值是否和以下值一样,一样则表示计算过程无误,如果不一致则请检查签名的参数是否一致、签名串是否有严格换行等
1mI35pfNEQV6777ke/1T+LJLQDNTm7yeoUJH+j/adPGhmCCi0PbgkvYQTRcXH0uibcLVtvFLdGLpmoYO9FV6lBBsTAjuhh5YOvQi0e2g3e0yytitiNET9FEuqM0pjnKfRW4K6LIZDdbWJv9KhZUx3DrJa5TL7OJ7VdADVivxVySIlPVKjGwuCXzuXSJes0UcILgWQUMyha5/3nYofuHtS7r+KYyMuxD+oJ9VM1Qdxk4UIG59CP5Y3wtYIFybyF3bdu1caHTRRX+DLyMXyYA/IrTmiW01c4RPjpHBX5Dk1sZyY1zVsWNsvMHr2e1NTWtBxKJ+qk5N61J7caYoepHFaxw==
4. 请求示例
| 注意: signType参数不参与签名,但需要传递,默认值为RSA,生成的签名需要通过字段paySign传递 |
|
1function onBridgeReady() {
2 WeixinJSBridge.invoke('getBrandWCPayRequest', {
3 "appId": "wx2421b1c4370ec43b", //公众号appID,由商户传入
4 "timeStamp": "1554208460", //时间戳,自1970年以来的秒数
5 "nonceStr": "593BEC0C930BF1AFEB40B4A08C8FB242", //随机串
6 "package": "prepay_id=wx201410272009395522657a690389285100",
7 "signType": "RSA", //微信签名方式:
8 "paySign": "mI35pfNEQV6777ke/1T+LJLQDNTm7yeoUJH+j/adPGhmCCi0PbgkvYQTRcXH0uibcLVtvFLdGLpmoYO9FV6lBBsTAjuhh5YOvQi0e2g3e0yytitiNET9FEuqM0pjnKfRW4K6LIZDdbWJv9KhZUx3DrJa5TL7OJ7VdADVivxVySIlPVKjGwuCXzuXSJes0UcILgWQUMyha5/3nYofuHtS7r+KYyMuxD+oJ9VM1Qdxk4UIG59CP5Y3wtYIFybyF3bdu1caHTRRX+DLyMXyYA/IrTmiW01c4RPjpHBX5Dk1sZyY1zVsWNsvMHr2e1NTWtBxKJ+qk5N61J7caYoepHFaxw==%" //微信签名
9 },
10 function(res) {
11 if (res.err_msg == "get_brand_wcpay_request:ok") {
12 // 使用以上方式判断前端返回,微信团队郑重提示:
13 //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
14 }
15 });
16}
17if (typeof WeixinJSBridge == "undefined") {
18 if (document.addEventListener) {
19 document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
20 } else if (document.attachEvent) {
21 document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
22 document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
23 }
24} else {
25 onBridgeReady();
26}