官方解決方案:
可參考以下指引:
https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay7_1.shtml#part-2
當(dāng)使用V3接口報(bào)簽名類錯(cuò)誤,還有在對(duì)返回的信息做驗(yàn)簽,如:回調(diào)通知驗(yàn)簽,驗(yàn)簽失敗的錯(cuò)誤,都可以使用驗(yàn)簽工具驗(yàn)簽,本文主要介紹如何正確使用簽名工具,以及簽名工具能排查出的幾種原因。
工具下載、使用:
1.首先先下載官方提供的驗(yàn)簽工具:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml#part-1
2.下載解壓后打開(kāi)文件夾,里面有我們的驗(yàn)簽工具、錯(cuò)誤碼對(duì)照表和使用說(shuō)明書(shū),TenpayCertUtil.exe就是驗(yàn)簽工具了,雙擊打開(kāi)
3.工具界面:
一共三個(gè)部分:
1、選擇文件:
校驗(yàn)自己請(qǐng)求接口生成的簽名,使用在商戶平臺(tái)下載的商戶證書(shū)文件,建議使用其中具體的商戶私鑰文件,apiclient_key.pem文件(這個(gè)是默認(rèn)的文件名,如果有下載后自己改過(guò),就按自己改的選,只要是正確的商戶私鑰文件就行),因?yàn)槭褂眠@個(gè)文件,既可以用工具驗(yàn)簽自己的簽名,又可以用工具直接生成簽名值。商戶證書(shū)獲?。?a target="_blank">https://kf.qq.com/faq/161222NneAJf161222U7fARv.html
校驗(yàn)接口應(yīng)答的簽名值,如:回調(diào)通知的驗(yàn)簽,就要使用平臺(tái)證書(shū)驗(yàn)簽,所以要先獲取平臺(tái)證書(shū):https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
2、明文:
這里要填放的是生成簽名或驗(yàn)簽時(shí)構(gòu)造的簽名串/驗(yàn)簽串,注意不是已經(jīng)生成好的簽名值
簽名串:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml#part-1
驗(yàn)簽串:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml#part-2
3、簽名
這里要填放的就是要校驗(yàn)的簽名值,如果是要直接對(duì)簽名串進(jìn)行簽名,而不是要校驗(yàn)簽名,可以不填寫(xiě)此處,然后點(diǎn)擊下方的簽名按鈕,工具會(huì)將生成的簽名值顯示在此處,可以用工具生成的簽名值和自己代碼中生成的簽名值進(jìn)行對(duì)比,看是否一致。
驗(yàn)簽排查思路:
了解了驗(yàn)簽工具要填寫(xiě)的三個(gè)部分后,就可以開(kāi)始驗(yàn)簽了,下面我會(huì)舉例幾種工具可以排查出來(lái)的情況,或配合工具可以排查出來(lái)的情況,為了不泄露信息,我會(huì)用官網(wǎng)示例這樣的中文代替實(shí)際數(shù)值
先放三個(gè)正確驗(yàn)簽的明文示例,點(diǎn)擊驗(yàn)簽,后面的示例圖主要放的是對(duì)自己生成的簽名值校驗(yàn)的示例圖:
此處注意應(yīng)答簽名的驗(yàn)簽使用的是平臺(tái)證書(shū)驗(yàn)簽,而不是使用商戶證書(shū),所以第一步選擇的文件要選擇平臺(tái)證書(shū)文件
平臺(tái)證書(shū)的獲取:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
情景一:如果按正確驗(yàn)簽示例填寫(xiě)的方式:驗(yàn)簽不通過(guò),說(shuō)明這個(gè)簽名值與這個(gè)簽名串是不匹配的,建議按文章開(kāi)頭提供的官方解決方案檢查下,也可以嘗試下面情景二、三的明文方式,看看是否碰巧:驗(yàn)簽通過(guò)
情景二:
如上方式填寫(xiě)明文:驗(yàn)簽通過(guò),說(shuō)明程序中,在構(gòu)造簽名串時(shí),最后一行沒(méi)有加上換行
情景三:
如上方式填寫(xiě)明文:驗(yàn)簽通過(guò),說(shuō)明程序中,在構(gòu)造簽名串時(shí),將換行符 \n 作為字符串"\n"去構(gòu)造簽名串/驗(yàn)簽串的,而不是作為轉(zhuǎn)義字符 \n 去構(gòu)造簽名串/驗(yàn)簽串的
情景四:如果按正確驗(yàn)簽示例填寫(xiě)的方式:驗(yàn)簽通過(guò),就需要更加仔細(xì)的檢查下自己的代碼:
1.可能使用錯(cuò)了一個(gè)商戶私鑰/平臺(tái)證書(shū)
這個(gè)不是指代碼里用的和工具用的不是同一個(gè),而是指比如本來(lái)要使用A商戶的商戶私鑰/平臺(tái)證書(shū),但實(shí)際使用的是B商戶的
2.可能代碼中實(shí)際編碼存在問(wèn)題
將所有中文部分換成英文,如果這時(shí)請(qǐng)求通過(guò),說(shuō)明是編碼問(wèn)題
3.可能簽名串中的參數(shù),和實(shí)際請(qǐng)求的參數(shù)不一致,不能增加或缺少參數(shù),參數(shù)大小寫(xiě)要與文檔一致(可通過(guò)打印簽名原串進(jìn)行排查)
如請(qǐng)求頭中的時(shí)間戳、隨機(jī)字符串和簽名串的不一致,具體請(qǐng)參考文章開(kāi)頭提供的官方解決方案
4.可能簽名串/驗(yàn)簽串、簽名值在數(shù)值傳遞過(guò)程中,發(fā)生了改變
在代碼實(shí)際填寫(xiě)簽名值時(shí),可能在各種方法傳遞中去除了'=',或?qū)⒁恍┓?hào)做了其他轉(zhuǎn)換,如'+'被替換成' '(空格),然后被添加到請(qǐng)求頭,或用來(lái)應(yīng)答驗(yàn)簽,所以工具通過(guò),代碼報(bào)錯(cuò)。'+'替換成' '在網(wǎng)絡(luò)上有相應(yīng)的解決方案,可自行查找下。
注:如果不確定簽名值是否在傳值過(guò)程中被處理修改,可以在工具中不填寫(xiě)簽名值,點(diǎn)擊簽名按鈕,將生成好的簽名值直接放進(jìn)請(qǐng)求頭,時(shí)間戳、隨機(jī)字符串也是,都寫(xiě)成固定值,如果通過(guò)請(qǐng)求,則說(shuō)明在之前傳值過(guò)程中,數(shù)據(jù)有被修改,須仔細(xì)排查
情景五:如果是下單成功,調(diào)起支付時(shí)報(bào)錯(cuò),按正確驗(yàn)簽示例填寫(xiě)的方式:驗(yàn)簽通過(guò),則需要前后端同學(xué)一起配合檢查
1.傳給前端接收到的調(diào)起時(shí)所用的數(shù)據(jù),是否和后端生成的簽名值所使用的簽名串中數(shù)據(jù)一致
例如:時(shí)間戳、隨機(jī)字符串等,可以由前端打印出調(diào)起支付時(shí)實(shí)際使用數(shù)據(jù),組成簽名串,進(jìn)行驗(yàn)簽,看看驗(yàn)簽是否通過(guò),如果后端驗(yàn)簽通過(guò),而前端使用調(diào)起支付的數(shù)據(jù)做簽名串驗(yàn)簽不通過(guò),則說(shuō)明前端調(diào)起使用的數(shù)據(jù)與后端生成簽名值使用的數(shù)據(jù)不一致
2.前端調(diào)起支付時(shí)填寫(xiě)的參數(shù)是否有一一對(duì)應(yīng)
例如:timeStamp的值錯(cuò)填了隨機(jī)字符串,nonceStr的值錯(cuò)填了時(shí)間戳
3.前端調(diào)起支付時(shí)填寫(xiě)的參數(shù)名、參數(shù)值是否正確,要注意參數(shù)名的大小寫(xiě),參數(shù)值一定要正確填寫(xiě)
例如:signType的值為'RSA',不要錯(cuò)填'RAS',package的值不要忘記加上'prepay_id='
4.調(diào)起支付時(shí)生成簽名使用的商戶私鑰和下單時(shí)生成簽名使用的不是同一個(gè)商戶私鑰
這個(gè)可以用下單時(shí)的簽名串、簽名值和這個(gè)調(diào)起支付簽名使用的私鑰文件驗(yàn)簽一下,如果通過(guò)則說(shuō)明下單和調(diào)起的簽名用的是同一個(gè)私鑰文件,沒(méi)有使用錯(cuò)誤,如果不通過(guò),說(shuō)明調(diào)起支付時(shí)使用的商戶私鑰是錯(cuò)誤的,需要檢查
情景六:校驗(yàn)應(yīng)答簽名時(shí),校驗(yàn)總是報(bào)錯(cuò),比如回調(diào)通知驗(yàn)簽,建議檢查下應(yīng)答報(bào)文主體中,各個(gè)參數(shù)的順序,一定要原樣按照通知的順序去構(gòu)造驗(yàn)簽串
如微信通知的是{C,B,A},就要按{C,B,A}原樣填寫(xiě),注意不要在轉(zhuǎn)JSON格式時(shí),或其他傳值過(guò)程中進(jìn)行排序,變成了{(lán)A,B,C},這樣構(gòu)造的驗(yàn)簽串是肯定驗(yàn)簽不通過(guò)的
明文中{C,B,A}要寫(xiě)成一行的形式,不要按JSON去換行寫(xiě)成:
正確示例:
以上是我個(gè)人總結(jié)的一些V3校驗(yàn)簽名工具的使用,和排除查思路,如果有需要補(bǔ)充或修改的地方,歡迎留言反饋
另補(bǔ)充下:判斷商戶私鑰、商戶號(hào)、商戶證書(shū)序列號(hào)是否匹配,可以用官方提供的postman腳本去校驗(yàn)下的,如果postman腳本也是報(bào)簽名錯(cuò)誤,說(shuō)明這三個(gè)是不匹配的,要檢查,還有就是官方的postman腳本是V3的簽名規(guī)則來(lái)的,V3的簽名規(guī)則和V2的簽名規(guī)則是不一樣的
postman腳本:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml#part-1