先看下面的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;
}