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