微信JSSDK分享介面中wx.config 出現invalid signature問題的解決辦法
先看下面的JSP程式碼:
String rand = StringUtil.getUUID(); //隨機字串
//String timestamp = Long.toString(new Date().getTime());
String timestamp = Long.toString(System.currentTimeMillis() / 1000);// Long.toString(new Date().getTime());
String url = "http://m.kuaixuetuan.com/portal/apps/wd/vip/product.jsp?rowId="+proRowId;
String sign = CommonUtil.createShareSign( "jiacheng",rand,timestamp,url);
wx.config({
debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
appId: '<%=appId%>', // 必填,公眾號的唯一標識
nonceStr: '<%=rand%>', // 必填,生成簽名的隨機串
signature: '<%=sign%>',// 必填,簽名,見附錄1
timestamp: <%=Long.parseLong(timestamp)%>, // 必填,生成簽名的時間戳
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'hideMenuItems',
'showMenuItems',
'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem',
'translateVoice',
'startRecord',
'stopRecord',
'onRecordEnd',
'playVoice',
'pauseVoice',
'stopVoice',
'uploadVoice',
'downloadVoice',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getNetworkType',
'openLocation',
'getLocation',
'hideOptionMenu',
'showOptionMenu',
'closeWindow',
'scanQRCode',
'chooseWXPay',
'openProductSpecificView',
'addCard',
'chooseCard',
'openCard'
]
});
其中時間戳timestamp可以用 Long.toString(System.currentTimeMillis() / 1000); 獲取,timestamp的長度是10位數字;
url是當前網頁的url地址。
我今天從上午除錯到傍晚,呼叫wx.config一直出現invalid signature的問題,最後發現問題還是出現在計算簽名的演算法上。仔細閱讀了微信文件,發現自己誤將token當做jsapi_ticket了,實際上要做兩次微信介面呼叫,第一次呼叫獲取access_token,第二次呼叫根據access_token計算jsapi_ticket,下面是自己寫的CommonUtil類中關於計算簽名的演算法:
public static String createShareSign(String accountId,String rand,String timestamp,String url) throws Exception
{
//首先獲得一個accessToken
String token = WeixinAccessTokenUtil.getAccessToken(accountId);//自己寫的獲取快取access_token,大家可按自己的方式獲取accessToken
//根據token獲取jsapi
String jsapiUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
jsapiUrl = jsapiUrl.replace("ACCESS_TOKEN", token);
//
JSONObject jsonObject = httpsRequest(jsapiUrl, "GET", null);//呼叫jsapi介面獲取jsapi_ticket
String jsapiTicket = jsonObject.getString("ticket");
log.info("返回的jsapiticket::"+jsapiTicket);
log.info(jsonObject.toString());
String string1="";
String signature="";
//System.out.println("SHA1簽名 :"+str);
string1 = "jsapi_ticket=" + jsapiTicket +
"&noncestr=" + rand +
"×tamp=" + timestamp +
"&url=" + url;
System.out.println(string1);
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
System.out.println("簽名1:"+signature);
// System.out.println("簽名2:"+ SHA1Util.encode(string1) );
return signature;
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}