為了方便大家理解,我們將使用測試的一對公私鑰,通過命令行形式一步一步介紹如何生成"App調(diào)起支付 (opens new window)"的簽名,強烈建議你使用測試的公私鑰,按照本文實際操作一下,如果算出來的簽名和文檔的一致則說明計算無誤。實際業(yè)務(wù)中請?zhí)鎿Q為你的真實的參數(shù)。
# 1. 準(zhǔn)備
商戶需要擁有一個微信支付商戶號,并通過超級管理員賬號登錄商戶平臺,獲取商戶API證書,可以參考如何獲取商戶API證書 (opens new window)。 商戶申請商戶 API 證書時,證書工具會生成商戶私鑰,并保存在本地證書文件夾的文件apiclient_key.pem
中。私鑰也可通過工具從商戶的 p12 證書中導(dǎo)出。請妥善保管好商戶私鑰文件。請注意計算簽名需要用到的是商戶API證書而不是平臺證書,請不要搞混。
商戶號:123456789
API證書私鑰:你需要將以下文件保存為pem格式,為了避免大家和自己的真實的公私鑰混淆,此處將其保存為了apiclient_test_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAptpm+qvIDCh/9wjU26SQCK26ogYkBhDrYxnAaw2JbbBsp1oD
bHKk+1r381NeBUG2HEFAuU+Fr72u5ot3yKdzoF/FajAzQNKnm569/D3upKoi8mYB
aST15Uig8j8qoUW1U217LL0jEHlSnHV3lcaDTXqDpTRR4Bfz9IqOgJgFZ8/oTfEo
mSrjrLYef81Eyxr7ZIMQXEKKEK7V4UXKS0+/fDsiG/cXidhzt8UbTL9vqXqxM2+I
DImyO+FAc/tkBG55LmzxPto1Nq0WbnZzRM/wTzrd0I/8NlevxtFbphg4evlHjFNI
7+GrqR87ViEwuAJJ9Je5QQjct5YJfFRWiZ5CMQIDAQABAoIBAGBi/GhEgezcHIg1
ltlHaFlLGuxsRbUnYwM9phVxnXk7GJlYe2/TjpERjPkIqOC6hBwwadZjJORP3FCc
Mtc8PKRhjuZ377O7vU0915x2nnyLOGL1IE2AJ3iLi0ZFzTea0FPgg+5lWHM00s9F
YI6qPcGtS41M+xtMWwZiYE3TBBRibHiY8ugGyaNAhiMKehyW05uApjlIF55wwCGx
BkyESJpGRR/6853iHke6Ge+xVcMa9QmQdoH0QqL/8kT28PL568mJJr0Ow/83t4+d
Pe70YPzKAxgUnaDsHJqO+b8qH69AEs8rTI5h2Mon6pH+bJT66KUoiXhn+Kf+4LSs
henRP10CgYEA1QJSfuFOWVRjrg3N/rAIc/Ak84BTZavbyrkqBSuoTs9i/nMI/hOz
VxpDntg7Bx2Tctl6sZO3GioTxKdc/YYaTKci1TKBbeginpsqEQVgwkMCy8HpvUmR
fyAMqLwZC4h9+j+NiZtuoFJDTCgv+WYbasX+kWYEUM21bnSYuO7yEQsCgYEAyIdP
r9uzqPgzN34Tmx+CNTa16VjhBh+zkBtXRLDLhWBeIYxoYNJARD98Pb1XZdvpkZZW
Sk7MfaKo2/DomzyyyB/MbHWwAdFi3yb4y7uMJfyC1MzdUSNN3Vp579hJxHkJ+nN4
Ys76yfcEeVOLnvUT1Z0KKCdIWRdT1Lgi+X1itzMCgYBJUXlPzwGG4fNFj97d0X23
Wmt9nSgXkOYgi0eZbAOMzPmIF9R6kBFk49dur4Lx2g5Ms+r1gKC/0sfnIqxxX11i
EQ1+UNoYGJUB/uql3TIG68XkmKR50P7RwRhaZBRC0gJ6xrFTMjsL2ATuC88niyvY
vrn3FiRaI9RVZrDCxwxvLQKBgEXW4okEAqGBuAzGqztmkOnJoTehDdYdKmOxMgap
cGiGdKJIjX3THDDoz3ONQyglnEZpTqpYoV3MTfU0BT8zt6x9bqwDnQY1D7NalmIW
cqw0Mri8lQQSQKcsQLWo5aA466G/n5kCL1Qx5OwAjesRvhOyuvvbGpZ0ymyWqQ+t
fLkDAoGATcul1L8y5D/wNVP1GXbXMZfBsFP3bbqy8c+Ashm6g8OLm2mGNntd5Z6h
1KkID7Yksh+dZ6t7XaPBtGACXX5Eryr537JVvdX8hAVCp5HVtaN/9VBVP8Ka2e4s
VS/xeNgOMQ7uzhRPBJ8HiTmdI1nHhDnYQpGiBgQn0Z5RAkSvFMk=
-----END RSA PRIVATE KEY-----
# 2. 構(gòu)造簽名串
我們希望商戶的技術(shù)開發(fā)人員按照當(dāng)前文檔約定的規(guī)則構(gòu)造簽名串。微信支付會使用同樣的方式構(gòu)造簽名串。如果商戶構(gòu)造簽名串的方式錯誤,將導(dǎo)致簽名驗證不通過。下面先說明簽名串的具體格式。
簽名串一共有四行,每一行為一個參數(shù)。結(jié)尾以\n(換行符,ASCII編碼值為0x0A)結(jié)束,包括最后一行。如果參數(shù)本身以\n結(jié)束,也需要附加一個\n。
1appid\n2時間戳\n3隨機字符串\n4prepay_id\n
以App調(diào)起支付接口為例,
第一步,獲取AppID
App支付需要申請公眾號,并獲取對應(yīng)的公眾號的AppID,公眾號的類型可以是服務(wù)號,也可以是訂閱號(訂閱號僅限于政府和媒體類型),可在公眾號后臺 (opens new window)查看
1wx2421b1c4370ec43b
第二步,獲取發(fā)起請求時的系統(tǒng)當(dāng)前時間戳,即格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現(xiàn)在的總秒數(shù),作為請求時間戳。微信支付會拒絕處理很久之前發(fā)起的請求,請商戶保持自身系統(tǒng)的時間準(zhǔn)確
1$ date +%s 21554208460
第三步,生成一個請求隨機串,我們推薦生成隨機數(shù)算法如下:調(diào)用隨機數(shù)函數(shù)生成,將得到的值轉(zhuǎn)換為字符串。這里,我們使用命令行直接生成一個。
1$ hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random 2593BEC0C930BF1AFEB40B4A08C8FB242
第四步,獲取prepay_id。
調(diào)用下單接口 (opens new window)會返回prepay_id
1wx201410272009395522657a690389285100
第五步,按照前述規(guī)則,構(gòu)造的請求簽名串如下:
1wx2421b1c4370ec43b\n 21554208460\n 3593BEC0C930BF1AFEB40B4A08C8FB242\n 4wx201410272009395522657a690389285100\n
# 3. 計算簽名值
絕大多數(shù)編程語言提供的簽名函數(shù)支持對簽名數(shù)據(jù)進(jìn)行簽名。強烈建議商戶調(diào)用該類函數(shù),使用商戶私鑰對待簽名串進(jìn)行SHA256 with RSA簽名,并對簽名結(jié)果進(jìn)行Base64編碼得到簽名值。
1$ echo -n -e \2 "wx2421b1c4370ec43b\n1554208460\n593BEC0C930BF1AFEB40B4A08C8FB242\nwx201410272009395522657a690389285100\n" \3 | openssl dgst -sha256 -sign apiclient_test_key.pem \4 | openssl base64 -A
得出的簽名值如下,你可以用一些校驗工具校驗?zāi)阃ㄟ^命令行或者你的代碼得到的簽名值是否和以下值一樣,一樣則表示計算過程無誤,如果不一致則請檢查簽名的參數(shù)是否一致、簽名串是否有嚴(yán)格換行等
1gXx9KhTP6IooKV1SuG3OCGlBIgZbKtubCZvnau6khw1iffvNT28IzLbKmztq2xA/RCNbZa1XOsoiuVmAEeTZQicWfhv4P+O4oBRIrx0X9f3cnWFkMBU9alTWs0nyQ1N9fcILOTe0f4kxOhVh+/Xhn5hOiUK7Sz3XA1mcpa3R2NCWf/e+0ow/RDf15iTymOHgDrEkT/gedg/3E0iXfDX3mFicSZhrHESZDOTXcl9RzELREBUFznd/o2NQM99WcL86m23HY0cTy+QGWU4QDmNrbQ9ihmLW71qPb0Cx/d7EQvw/Kyx0A6s64ZQp3hHdcmiRcLnjVXrKCk7LShaCK+lS3Q==
# 4. 請求示例
ios請求示例
1PayReq *request = [[[PayReq alloc] init] autorelease];2request.appId = "wx2421b1c4370ec43b";3request.partnerId = "123456789";4request.prepayId= "wx201410272009395522657a690389285100",;5request.packageValue = "Sign=WXPay";6request.nonceStr= "593BEC0C930BF1AFEB40B4A08C8FB242";7request.timeStamp= "1554208460";8request.sign= "gXx9KhTP6IooKV1SuG3OCGlBIgZbKtubCZvnau6khw1iffvNT28IzLbKmztq2xA/RCNbZa1XOsoiuVmAEeTZQicWfhv4P+O4oBRIrx0X9f3cnWFkMBU9alTWs0nyQ1N9fcILOTe0f4kxOhVh+/Xhn5hOiUK7Sz3XA1mcpa3R2NCWf/e+0ow/RDf15iTymOHgDrEkT/gedg/3E0iXfDX3mFicSZhrHESZDOTXcl9RzELREBUFznd/o2NQM99WcL86m23HY0cTy+QGWU4QDmNrbQ9ihmLW71qPb0Cx/d7EQvw/Kyx0A6s64ZQp3hHdcmiRcLnjVXrKCk7LShaCK+lS3Q==%";9[WXApi sendReq:request];
Android請求示例
1IWXAPI api;2PayReq request = new PayReq();3request.appId = "wx2421b1c4370ec43b";4request.partnerId = "123456789";5request.prepayId= "wx201410272009395522657a690389285100",;6request.packageValue = "Sign=WXPay";7request.nonceStr= "593BEC0C930BF1AFEB40B4A08C8FB242";8request.timeStamp= "1554208460";9request.sign= "gXx9KhTP6IooKV1SuG3OCGlBIgZbKtubCZvnau6khw1iffvNT28IzLbKmztq2xA/RCNbZa1XOsoiuVmAEeTZQicWfhv4P+O4oBRIrx0X9f3cnWFkMBU9alTWs0nyQ1N9fcILOTe0f4kxOhVh+/Xhn5hOiUK7Sz3XA1mcpa3R2NCWf/e+0ow/RDf15iTymOHgDrEkT/gedg/3E0iXfDX3mFicSZhrHESZDOTXcl9RzELREBUFznd/o2NQM99WcL86m23HY0cTy+QGWU4QDmNrbQ9ihmLW71qPb0Cx/d7EQvw/Kyx0A6s64ZQp3hHdcmiRcLnjVXrKCk7LShaCK+lS3Q==%";10api.sendReq(request);