# 如何在程序中加載私鑰
推薦使用微信支付提供的SDK。你也可以查看下列編程語言的示例代碼。
示例代碼
# 1. 為什么請求返回401 Unauthorized?
請根據(jù)報文中的message信息,在下表中找到錯誤的原因和對應(yīng)的解決方案。
錯誤描述 | 原因 | 解決方案 |
---|---|---|
商戶未設(shè)置APIv3密鑰。 | 商戶未設(shè)置APIv3密鑰 | 請登錄商戶平臺設(shè)置APIv3密鑰 |
商戶未申請過證書。 | 商戶未申請過API證書 | 請參考什么是商戶API證書?如何獲取商戶API證書? (opens new window) |
商戶證書序列號有誤。 | 使用了錯誤的商戶證書,或者使用了已經(jīng)失效的歷史的商戶證書,或者獲取的商戶證書序列號有誤 | 請檢查商戶證書序列號,登錄商戶平臺【API安全】->【API證書】->【查看證書】,可查看商戶API證書序列號。 |
商戶證書已過期。 | 使用了已經(jīng)過期的商戶證書和私鑰 | 請到商戶平臺重新申請證書后,使用新申請的證書 |
商戶證書已作廢。 | 使用了商戶主動作廢的商戶證書和私鑰 | 請到商戶平臺重新申請證書后,使用新申請的證書 |
錯誤的簽名,導(dǎo)致驗簽失敗。 | 使用了錯誤的商戶私鑰,或簽名串構(gòu)造不正確 | 請見下一問題 |
HTTP頭Authorization值格式錯誤 | 缺少 Authorization頭,或其格式不正確 | 請檢查上送的 Authorization |
HTTP頭Authorization認(rèn)證類型不正確 | 不支持 Authorization中聲明的簽名算法 | 請檢查上送的 Authorization,目前僅支持WECHATPAY2-SHA256-RSA2048 |
HTTP頭Authorization中的timestamp與發(fā)起請求的時間不得超過5分鐘 | Authorization頭中的時間戳timestamp所示時間距離當(dāng)前時間超過5分鐘 | 請檢查系統(tǒng)時間是否準(zhǔn)確,或者獲取時間的邏輯是否正確 |
已更換證書,請使用新證書 | 商戶主動重新申請了商戶API證書 | 請使用新申請的商戶API證書 |
# 2. 如何定位“錯誤的簽名,導(dǎo)致驗簽失敗”的錯誤?
為了方便商戶定位簽名問題,微信支付對于驗簽失敗的請求,會在應(yīng)答的錯誤詳情detail中加入驗簽信息。
- method,HTTP請求方法
url
,請求的URL- truncated_sign_message,微信支付驗簽時使用的簽名串(換行符顯示成\n)。為了方便查看,我們對最后的請求報文主體做了截斷
- sign_message_length,微信支付驗簽時使用的簽名串的字節(jié)長度
1{2"code": "SIGN_ERROR",3"message": "錯誤的簽名,驗簽失敗",4"detail": {5 "field": "signature",6 "issue": "sign not match",7 "location": "authorization",8 "sign_information": {9 "method": "GET",10 "url": "/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ",11 "truncated_sign_message": "GET\n/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ\n1559194069\n18a427e78d2344e1a71156a2690cc4d6\n\n",12 "sign_message_length": 15713 }14}15}
建議商戶開發(fā)者在程序中輸出自行組裝的簽名串及其字節(jié)長度,并將其與微信支付返回的驗簽信息進(jìn)行詳細(xì)對比。以下是一些常見的錯誤:
# 簽名串的最后一行沒有附加換行符
- 如果請求報文主體為空(如GET請求),最后一行應(yīng)為一個換行符。
# 簽名串中的參數(shù),跟實際請求的參數(shù)不一致
- 手工拼接的URL,和實際請求發(fā)送的不一致。我們建議的實現(xiàn)是,使用HTTP庫構(gòu)造請求對象或者URL對象,再使用相應(yīng)的方法取得URL。
- 簽名和設(shè)置Authorization頭時,使用了前后生成的兩個時間戳。
- 簽名和設(shè)置Authorization頭時,使用了前后生成的兩個不同的隨機(jī)串。
- 簽名和請求時,使用了前后兩次序列化的JSON串作為請求主體。
注意
商戶的開發(fā)者可以將關(guān)鍵參數(shù)生成并保存在變量中,簽名和發(fā)送請求時統(tǒng)一使用,避免前后生成的信息不一致。
# 文本的編碼不一致
生成簽名串使用了非UTF-8編碼或者未設(shè)置具體編碼。
# 構(gòu)建簽名串順序不對
構(gòu)建簽名串沒有按照文檔要求的順序進(jìn)行構(gòu)建。
# 使用了錯誤的商戶私鑰
開發(fā)者可以使用如下的openssl命令檢查私鑰和商戶證書中的modulus(p、q兩個大素數(shù)的乘積)是否一致。如果兩者一致,那么私鑰和證書是成對的。
1$ openssl x509 -noout -modulus -in 1900009191_20180326_cert.pem2Modulus=C6D43C87B991...3$ openssl rsa -noout -modulus -in 1900009191_20180326_key.pem4Modulus=C6D43C87B991...
注意
- modulus長度為2048位,輸出為512個字節(jié)。
- 檢查密鑰匹配前,請先查看證書序列號,檢查是否是正確的商戶證書。
# 3. 為什么微信支付的回調(diào)缺少簽名的幾個HTTP頭?
微信支付的回調(diào),在HTTP頭部包含了以下四個HTTP頭:
- Wechatpay-Timestamp
- Wechatpay-Nonce
- Wechatpay-Signature
- Wechatpay-Serial
某些代理服務(wù)器或CDN服務(wù)提供商,轉(zhuǎn)發(fā)時會“過濾”微信支付擴(kuò)展的HTTP頭,會導(dǎo)致驗簽的應(yīng)用層無法取到微信支付的簽名信息。遇到這種情況時,建議商戶調(diào)整代理服務(wù)器配置,或者通過直連的方式接受微信支付的回調(diào)。