不一樣。
V2版本接口的簽名方式為MD5或HMAC-SHA256。
V3版本接口的簽名方式為非對稱密鑰SHA256-RSA。
微信支付的回調(diào),在HTTP頭部包含了以下四個HTTP頭:
1、Wechatpay-Timestamp
2、Wechatpay-Nonce
3、Wechatpay-Singature
4、Wechatpay-Serial某些代理服務器或CDN服務提供商,轉(zhuǎn)發(fā)時會“過濾“微信支付擴展的HTTP頭,會導致驗簽的應用層無法取到微信支付的簽名信息。遇到這種情況時,建議商戶調(diào)整代理服務器配置,或者通過直連的方式接受微信支付的回調(diào)。
該報錯是因為基礎規(guī)則設置錯誤導致,Accept和User-Agent都必須設置,缺一不可。
1、Accept的設置參考以下設置:
Content-Type: application/json
Accept: application/json
2、User-Agent的設置參考如下:
HTTP協(xié)議要求發(fā)起請求的客戶端在每一次請求中都使用HTTP頭? User-Agent來標識自己。微信支付建議調(diào)用方選用以下兩種方式的一種:
A、使用HTTP客戶端默認的 User-Agent。
B、遵循HTTP協(xié)議,使用自身系統(tǒng)和應用的名稱和版本等信息,組成自己獨有的User-Agent。
注意:
1、該報錯內(nèi)容只存在于V3接口
2、微信支付API V3很可能會拒絕處理無User-Agent 的請求。
推薦使用微信支付提供的SDK。你也可以查看下列編程語言的示例代碼。
/**
* 獲取私鑰。
*
* @param filename 私鑰文件路徑 (required)
* @return 私鑰對象
*/
public static PrivateKey getPrivateKey(String filename) throws IOException {
String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
try {
String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s+", "");
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(
new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("當前Java環(huán)境不支持RSA", e);
} catch (InvalidKeySpecException e) {
throw new RuntimeException("無效的密鑰格式");
}
}
請根據(jù)報文中的message信息,在下表中找到錯誤的原因和對應的解決方案。
錯誤描述 | 原因 | 解決方案 |
---|---|---|
商戶未設置APIv3密鑰。 | 商戶未設置APIv3密鑰 | 請登錄商戶平臺設置APIv3密鑰 |
商戶未申請過證書。 | 商戶未申請過API證書 | 請參考商戶API證書說明 |
商戶證書序列號有誤。 | 使用了錯誤的商戶證書,或者使用了已經(jīng)失效的歷史的商戶證書,或者獲取的商戶證書序列號有誤 | 請檢查商戶證書,可登錄商戶平臺查看正確的證書序列號。 |
商戶證書已過期。 | 使用了已經(jīng)過期的商戶證書和私鑰 | 請到商戶平臺進行續(xù)期,使用續(xù)期后的新證書 |
商戶證書已作廢。 | 使用了商戶主動作廢的商戶證書和私鑰 | 請到商戶平臺重新申請證書后,使用新申請的證書 |
錯誤的簽名,導致驗簽失敗。 | 使用了錯誤的商戶私鑰,或簽名串構(gòu)造不正確 | 請見下一問題 |
Http頭Authorization值格式錯誤 | 缺少 Authorization頭,或其格式不正確 | 請檢查上送的 Authorization |
Http頭Authorization認證類型不正確 | 不支持 Authorization中聲明的簽名算法 | 請檢查上送的 Authorization,目前僅支持WECHATPAY2-SHA256-RSA2048 |
Http頭Authorization中的timestamp與發(fā)起請求的時間不得超過5分鐘 | Authorization頭中的時間戳timestamp所示時間距離當前時間超過5分鐘 | 請檢查系統(tǒng)時間是否準確,或者獲取時間的邏輯是否正確 |
已更換證書,請使用新證書 | 商戶主動重新申請了商戶API證書 | 請使用新申請的商戶API證書 |
為了方便開發(fā)者定位,我們對于驗簽失敗,會在應答的錯誤詳情detail中加入驗簽信息。驗簽信息是我們根據(jù)商戶的HTTP請求構(gòu)造簽名串的各種信息。
1. method,HTTP請求方法
2. url,請求的URL
3. truncated_sign_message,微信支付驗簽時使用的簽名串(換行符顯示成\n)。為了方便查看,我們對最后的請求報文主體做了截斷
4. sign_message_length,微信支付驗簽時使用的簽名串的字節(jié)長度
{
"code": "SIGN_ERROR",
"message": "錯誤的簽名,驗簽失敗",
"detail": {
"field": "signature",
"issue": "sign not match",
"location": "authorization",
"sign_information": {
"method": "GET",
"url": "/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ",
"truncated_sign_message": "GET\n/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ\n1559194069\n18a427e78d2344e1a71156a2690cc4d6\n\n",
"sign_message_length": 157
}
}
}
建議開發(fā)者在程序中將自己組裝的簽名串以及簽名串的字節(jié)長度在調(diào)試信息中輸出,跟微信支付返回的驗簽信息進行仔細對比,排查以下幾種常見的錯誤:
簽名串的最后一行沒有附加換行符
如果請求報文主體為空(如GET請求),最后一行應為一個換行符。
簽名串中的參數(shù),跟實際請求的參數(shù)不一致
手工拼接的URL,和實際請求發(fā)送的不一致。我們建議的實現(xiàn)是,使用HTTP庫構(gòu)造請求對象或者URL對象,再使用相應的方法取得URL。
簽名和設置Authorization頭時,使用了前后生成的兩個時間戳
簽名和設置Authorization頭時,使用了前后生成的兩個不同的隨機串。
簽名和請求時,使用了前后兩次序列化的JSON串作為請求主體。
文本的編碼不一致
生成簽名串使用了非UTF-8編碼或者未設置具體編碼。
構(gòu)建簽名串順序不對
構(gòu)建簽名串沒有按照文檔要求的順序進行構(gòu)建。
使用了錯誤的商戶私鑰
開發(fā)者可以使用如下的openssl命令檢查私鑰和商戶證書中的modulus(p、q兩個大素數(shù)的乘積)是否一致。如果兩者一致,那么私鑰和證書是成對的。
$ openssl x509 -noout -modulus -in 1900009191_20180326_cert.pem
Modulus=C6D43C87B991...
$ openssl rsa -noout -modulus -in 1900009191_20180326_key.pem
Modulus=C6D43C87B991...
微信支付的回調(diào),在HTTP頭部包含了以下四個HTTP頭:
1. Wechatpay-Timestamp
2. Wechatpay-Nonce
3. Wechatpay-Signature
4. Wechatpay-Serial
某些代理服務器或CDN服務提供商,轉(zhuǎn)發(fā)時會“過濾”微信支付擴展的HTTP頭,會導致驗簽的應用層無法取到微信支付的簽名信息。遇到這種情況時,建議商戶調(diào)整代理服務器配置,或者通過直連的方式接受微信支付的回調(diào)。
Customer Service Tel
Business Development
9:00-18:00
Monday-Friday GMT+8
Technical Support
WeChat Pay Global
ICP證