微信js sdk invalid signature簽名錯誤問題的解決方法分析
本文實例講述了微信js sdk invalid signature簽名錯誤問題的解決方法。分享給大家供大家參考,具體如下:
/**最近在做微信js sdk 接口調(diào)用說明*/
***相信很多人都遇見像我這樣的問題,再加上自己只能算是半個程序員,所以苦苦摸索了好久終于搞懂了。
****下面就把自己所遇見的各種問題和大家分享一下,都是自己親手實驗過的********/
一、問題說明
如果出現(xiàn) invalid signature,首先可以確定的是你的簽名算法有問題。
建議:首先查看微信官方網(wǎng)站給出的解決方案,鏈接為 http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
invalid signature簽名錯誤。建議按如下順序檢查:
2. 確認(rèn)簽名算法正確,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 頁面工具進行校驗。也就是你自己后臺生成簽名要和微信校驗算法生成的簽名一致才可以(可能大小寫不同)。
3. 注意:
簽名生成規(guī)則如下:
參與簽名的字段包括有效的 jsapi_ticket(獲取方式詳見微信 JSSDK 文檔), noncestr (隨機字符串,由開發(fā)者隨機生成),timestamp (由開發(fā)者生成的當(dāng)前時間戳), url(當(dāng)前網(wǎng)頁的URL,不包含#及其后面部分。注意:對于沒有只有域名沒有 path 的 URL ,瀏覽器會自動加上 / 作為 path,如打開 http://qq.com 則獲取到的 URL 為 http://qq.com/)。
特別注意:你在利用參數(shù)生成簽名的時候,要對所有待簽名參數(shù)按照字段名的 ASCII 碼從小到大排序(字典序)后,使用 URL 鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串 string1。這里需要注意的是所有參數(shù)名均為小寫字符。
我的最開始的錯誤就是沒有注意到生成簽名的那幾個參數(shù)要按照key=value的樣式連接成一個字符串,然后在sha1加密生成。
/****Java寫的參數(shù)拼接算法***/ String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl }; Arrays.sort(paramArr); // 將排序后的結(jié)果拼接成一個字符串 String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2]) .concat("&"+paramArr[3]); System.out.println("拼接之后的content為:"+content);
4. 確認(rèn)config中nonceStr(js中駝峰標(biāo)準(zhǔn)大寫S), timestamp與用以簽名中的對應(yīng)noncestr, timestamp一致。
5. 確認(rèn)url是頁面完整的url(請在當(dāng)前頁面alert(location.href.split('#')[0])確認(rèn)),包括'http(s)://'部分,以及'?'后面的GET參數(shù)部分,但不包括'#'hash后面的部分。
6. 確認(rèn) config 中的 appid 與用來獲取 jsapi_ticket 的 appid 一致。
7. 確保一定緩存access_token和jsapi_ticket。
8. 確保你獲取用來簽名的url是動態(tài)生成的,動態(tài)頁面可參見實例代碼中php的實現(xiàn)方式。如果是html的靜態(tài)頁面在前端通過ajax將url傳到后臺簽名,前端需要用js獲取當(dāng)前頁面除去'#'hash部分的鏈接(可用location.href.split('#')[0]獲?。?,因為頁面一旦分享,微信客戶端會在你的鏈接末尾加入其它參數(shù),如果不是動態(tài)獲取當(dāng)前鏈接,將導(dǎo)致分享后的頁面簽名失敗。
錯誤2、每次后臺網(wǎng)頁更新之后,微信訪問效果沒有出來。
問題:手機端,網(wǎng)頁緩沖導(dǎo)致。
解決方案:重啟手機,再試一下。
錯誤3、微信分享接口,可以在自己的網(wǎng)頁上面自定義一個按鈕,當(dāng)用戶點擊的時候完成分享。
問題:我最開始也是這樣想的,后來發(fā)現(xiàn),原來不是這樣的,只有當(dāng)你用微信客戶端打開,在最上面右邊的 “分享到朋友圈”按鈕按的時候效果才會出來。
錯誤4、微信圖像接口 permission denied
首先查看微信給出的錯誤說明:該公眾號沒有權(quán)限使用這個JSAPI(部分接口需要認(rèn)證之后才能使用)。
說明:只要通過了公眾號認(rèn)證,都不會有問題。
檢查對象:如果出現(xiàn)這個說明程序上基本上不會有問題 微信后臺已經(jīng)返回了數(shù)據(jù)。
第一、要檢查 你的config 文件中相應(yīng)的 jsapilist 是否包含了該接口喲。
/***用戶打開頁面的時候就加載**/ $(document).ready(function(){ initPage(); }); function initPage() { //alert(window.location.href);/***用于獲得當(dāng)前連接url用**/ /***用戶點擊分享到微信圈后加載接口接口*******/ $.post("http://******",{"url":window.location.href},function(data,status){ data=eval("("+data+")"); wx.config({ debug: false, appId: 'wxa7a1ad4cc5116437', timestamp:data.timestamp, nonceStr:data.noncestr, signature:data.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'hideOptionMenu', ] }); wx.ready(function(){ wx.hideOptionMenu();/***隱藏分享菜單****/ }); }); };
說明:這一塊我是通過寫一個方法,然后用戶用AJax 的post 獲得這樣的請求,然后參數(shù)是URL。
二、實例說明
獲得jsticket
public static String getjsTicket(String accesstoken) { String appid = "XXXXXXX"; String appsecret = "XXXX"; String result = ""; String url = js_ticketurl.replace("ACCESS_TOKEN", accesstoken); System.out.println("查看js_url:" + url); // 調(diào)用接口返回json字符串 JSONObject jsonObject = httpRequest(url, "GET", ""); System.out.println("查看紅的js_ticket:" + jsonObject.toString()); if (null != jsonObject) { result = jsonObject.getString("ticket");// 獲得ticket System.out.println("ticket為:" + result); } return result; }
獲得signature
// 獲得js signature public static String getSignature(String jsapi_ticket, String timestamp, String nonce, String jsurl) throws IOException { /**** * 對 jsapi_ticket、 timestamp 和 nonce 按字典排序 對所有待簽名參數(shù)按照字段名的 ASCII * 碼從小到大排序(字典序)后,使用 URL 鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串 * string1。這里需要注意的是所有參數(shù)名均為小寫字符。 接下來對 string1 作 sha1 加密,字段名和字段值都采用原始值,不進行 * URL 轉(zhuǎn)義。即 signature=sha1(string1)。 * **如果沒有按照生成的key1=value&key2=value拼接的話會報錯 */ String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl }; Arrays.sort(paramArr); // 將排序后的結(jié)果拼接成一個字符串 String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2]) .concat("&"+paramArr[3]); System.out.println("拼接之后的content為:"+content); String gensignature = null; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); // 對拼接后的字符串進行 sha1 加密 byte[] digest = md.digest(content.toString().getBytes()); gensignature = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 將 sha1 加密后的字符串與 signature 進行對比 if (gensignature != null) { return gensignature;// 返回signature } else { return "false"; } // return (String) (ciphertext != null ? ciphertext: false); } /** * 將字節(jié)數(shù)組轉(zhuǎn)換為十六進制字符串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 將字節(jié)轉(zhuǎn)換為十六進制字符串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; }
希望本文所述對大家微信程序設(shè)計有所幫助。
相關(guān)文章
有關(guān)IntelliJ IDEA中LeetCode插件配置問題
這篇文章主要介紹了關(guān)于IntelliJ IDEA中LeetCode插件配置問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08Java中BigDecimal類與int、Integer使用總結(jié)
這篇文章主要給大家介紹了關(guān)于Java中BigDecimal類與int、Integer使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07關(guān)于Java項目讀取resources資源文件路徑的那點事
這篇文章主要介紹了關(guān)于Java項目讀取resources資源文件路徑的那點事,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07Java使用JDBC實現(xiàn)Oracle用戶認(rèn)證的方法詳解
這篇文章主要介紹了Java使用JDBC實現(xiàn)Oracle用戶認(rèn)證的方法,結(jié)合實例形式分析了java使用jdbc實現(xiàn)數(shù)據(jù)庫連接、建表、添加用戶、用戶認(rèn)證等操作流程與相關(guān)注意事項,需要的朋友可以參考下2017-08-08詳解Spring Security中獲取當(dāng)前登錄用戶的詳細(xì)信息的幾種方法
本文主要介紹了詳解Spring Security中獲取當(dāng)前登錄用戶的詳細(xì)信息的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05SpringBoot使用Feign進行服務(wù)間通信的實現(xiàn)示例代碼
Feign是一個開源的Java HTTP客戶端,可以幫助我們在SpringBoot應(yīng)用中快速構(gòu)建和使用HTTP客戶端,方便實現(xiàn)服務(wù)間的通信,本文就來介紹一下SpringBoot使用Feign進行服務(wù)間通信的實現(xiàn)示例代碼,感興趣的可以了解一下2024-01-01