微信js sdk invalid signature簽名錯誤 問題解決。

/**最近在作微信js sdk 接口調用說明*/
***相信不少人都碰見像我這樣的問題,再加上本身只能算是半個程序員,因此苦苦摸索了很久終於搞懂了。
****下面就把本身所碰見的各類問題和你們分享一下,都是本身親手實驗過的********/

1、問題說明

若是出現 invalid signature,首先能夠肯定的是你的簽名算法有問題。php

建議:首先查看微信官方網站給出的解決方案,連接爲 http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.htmlhtml

  1. invalid signature簽名錯誤。建議按以下順序檢查:前端

    1. 確認簽名算法正確,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 頁面工具進行校驗。也就是你本身後臺生成簽名要和微信校驗算法生成的簽名一致才能夠(可能大小寫不一樣)。java

      注意:git

      簽名生成規則以下:程序員

      參與簽名的字段包括有效的 jsapi_ticket(獲取方式詳見微信 JSSDK 文檔), noncestr (隨機字符串,由開發者隨機生成),timestamp (由開發者生成的當前時間戳), url(當前網頁的URL,不包含#及其後面部分。注意:對於沒有隻有域名沒有 path 的 URL ,瀏覽器會自動加上 / 做爲 path,如打開 http://qq.com 則獲取到的 URL 爲 http://qq.com/)。ajax

      特別注意:你在利用參數生成簽名的時候,全部待簽名參數按照字段名的 ASCII 碼從小到大排序(字典序)後,使用 URL 鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串 string1。這裏須要注意的是全部參數名均爲小寫字符。算法

      個人最開始的錯誤就是沒有注意到生成簽名的那幾個參數要按照key=value的樣式鏈接成一個字符串,而後在sha1加密生成。json

    2. /****Java寫的參數拼接算法***/
    3. String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
      				"timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
      Arrays.sort(paramArr);
      // 將排序後的結果拼接成一個字符串
      String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
      				.concat("&"+paramArr[3]);
      System.out.println("拼接以後的content爲:"+content);
    4. 確認config中nonceStr(js中駝峯標準大寫S), timestamp與用以簽名中的對應noncestr, timestamp一致。api

    5. 確認url是頁面完整的url(請在當前頁面alert(location.href.split('#')[0])確認),包括'http(s)://'部分,以及'?'後面的GET參數部分,但不包括'#'hash後面的部分。

    6. 確認 config 中的 appid 與用來獲取 jsapi_ticket 的 appid 一致。

    7. 確保必定緩存access_token和jsapi_ticket。

    8. 確保你獲取用來簽名的url是動態生成的,動態頁面可參見實例代碼中php的實現方式。若是是html的靜態頁面在前端經過ajax將url傳到後臺簽名,前端須要用js獲取當前頁面除去'#'hash部分的連接(可用location.href.split('#')[0]獲取),由於頁面一旦分享,微信客戶端會在你的連接末尾加入其它參數,若是不是動態獲取當前連接,將致使分享後的頁面簽名失敗

    錯誤二、每次後臺網頁更新以後,微信訪問效果沒有出來。

    問題:手機端,網頁緩衝致使。

    解決方案:重啓手機,再試一下。

    錯誤三、微信分享接口,能夠在本身的網頁上面自定義一個按鈕,當用戶點擊的時候完成分享。

    問題:我最開始也是這樣想的,後來發現,原來不是這樣的,只有當你用微信客戶端打開,在最上面右邊的 「分享到朋友圈」按鈕按的時候效果纔會出來。

    錯誤四、微信圖像接口 permission denied

    首先查看微信給出的錯誤說明:該公衆號沒有權限使用這個JSAPI(部分接口須要認證以後才能使用)。

    說明:只要經過了公衆號認證,都不會有問題。

    檢查對象:若是出現這個說明程序上基本上不會有問題 微信後臺已經返回了數據。

    第1、要檢查 你的config 文件中相應的 jsapilist  是否包含了該接口喲。

    /***用戶打開頁面的時候就加載**/
    $(document).ready(function(){
    initPage();
    });
    function initPage() {
    //alert(window.location.href);/***用於得到當前鏈接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 得到這樣的請求,而後參數是URL。

2、實例說明

得到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);
		// 調用接口返回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 按字典排序 對全部待簽名參數按照字段名的 ASCII
		 * 碼從小到大排序(字典序)後,使用 URL 鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串
		 * string1。這裏須要注意的是全部參數名均爲小寫字符。 接下來對 string1 做 sha1 加密,字段名和字段值都採用原始值,不進行
		 * URL 轉義。即 signature=sha1(string1)。
		 * **若是沒有按照生成的key1=value&key2=value拼接的話會報錯
		 */
		String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
				"timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
		Arrays.sort(paramArr);
		// 將排序後的結果拼接成一個字符串
		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);
	}

	/**
	 * 將字節數組轉換爲十六進制字符串
	 *
	 * @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;
	}

	/**
	 * 將字節轉換爲十六進制字符串
	 *
	 * @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;
	}
相關文章
相關標籤/搜索