微信公众号分享
微信官方文档:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
要想调用微信的接口,首先要调用配置接口
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ”, // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: ”, // 必填,生成签名的随机串
signature: ”,// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
公众号有appid和appsecret,那么首先要获取时间戳、随机串和签名
附录1:JS-SDK使用权限签名算法
要获取签名,就要获取唯一票据,要获取票据,就要获取access_token。
获取签名的过程:获取access_token —— 获取唯一票据jsapi_ticket —– 签名算法
一、获取签名进行初步配置
1、获取access_token:
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数:grant_type:获取access_token填写client_credential
appid:第三方用户唯一凭证
secret:第三方用户唯一凭证密钥,即appsecret
返回结果:正常:{“access_token”:”ACCESS_TOKEN”,”expires_in”:7200},错误时:{“errcode”:40013,”errmsg”:”invalid appid”}
获取access_token的java代码如下:
//获取access_token
protected static final String WX_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token";
public static String getAccessToken(String appid, String appsecret) {
// 凭证获取(GET)
String token_url = WX_ACCESS_TOKEN+"?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//将appid和appsecret参数传到url
String requestUrl = token_url.replace("APPID", appid).replace(
"APPSECRET", appsecret);
// 发起GET请求获取凭证
//底层封装的发送get请求的方法
String str = SimpleHttpUtils.httpGet(requestUrl, null);
System.out.println(str);
//从json格式的结果中获取access_token
JSONObject jsonObject = JSONObject.fromObject(str);
String access_token = null;
if (null != jsonObject) {
access_token = jsonObject.getString("access_token");
}
return access_token;
}
2、通过http请求获取调用微信js接口的临时票据
请求url为:
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功时返回:
{
“errcode”:0,
“errmsg”:”ok”,
“ticket”:”bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA”,
“expires_in”:7200
}
java代码如下:
public static String getJsApiTicket(String accessToken) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
String requestUrl = url.replace("ACCESS_TOKEN", accessToken);
// 发起GET请求获取凭证,此处为封装的get请求方法
String str = SimpleHttpUtils.httpGet(requestUrl, null);
JSONObject jsonObject = JSONObject.fromObject(str);
String ticket = null;
if (null != jsonObject) {
ticket = jsonObject.getString("ticket");
}
return ticket;
}
获取jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
3、获取签名:签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
按照ASCII码将参数排序为:jsapi_ticket、noncestr、timestamp、url。
用sha-1加密:
java代码为:
public static String sha1Encrypt(String str) {
String signature = null;
try {
//安全散列算法
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
//重置摘要
crypt.reset();
//使用“UTF-8”编码的字符串的byte数组更新摘要
crypt.update(str.getBytes("UTF-8"));
//crypt.digest()完成哈希计算
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
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;
}
4、最终获取所有config需要的参数
public static Map getParam(String appid, String appsecret, String url) {
Map<String,Object> map = new HashMap<String, Object>();
long now = System.currentTimeMillis();
String randomStr = UUID.randomUUID().toString();
if (time < 0 || now - time > 3600000) {
time = now;
access_token = getAccessToken(appid, appsecret);
jsapi_ticket = getJsApiTicket(access_token);
}
String str = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + randomStr
+ "×tamp=" + time + "&url=" + url;
//加密
String signature = sha1Encrypt(str);
map.put("time", time);
map.put("randomStr", randomStr);
map.put("signature", signature);
map.put("accessToken", access_token);
return map;
}
将生成的几个值用于config初始化配置
注意事项:
签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
签名用的url必须是调用JS接口页面的完整URL。
出于安全考虑,开发者必须在服务器端实现签名的逻辑。
二、js代码:
<%
String url = "";//该页面的相对url
if(request.getQueryString() != null){//url所带的参数
url = url+"?"+request.getQueryString();
}
Map params = WXAPIUtils.getParam(RequestParam.APP_ID,RequestParam.APP_SECRET, request.getScheme()+":"+basePath+url);
%>
wx.config({
debug: false,
appId: '<%=RequestParam.APP_ID%>',
timestamp: '<%=params.get("time") %>', //生成签名的时间戳
nonceStr: '<%=params.get("randomStr") %>', //生成签名的随机串
signature: '<%=params.get("signature") %>', //签名
jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
wx.ready(function(){
//分享到朋友圈
wx.onMenuShareTimeline({
title: '', // 分享标题
desc : '',
link: shareUrl, // 分享链接
imgUrl: '', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//分享给朋友
wx.onMenuShareAppMessage({
title : '', // 分享标题
desc : '',
link: shareUrl,
imgUrl : '',
type : '',
dataUrl : '',
success : function() {
},
cancel : function() {
}
});
//分享至手机QQ
wx.onMenuShareQQ({
title: '', // 分享标题
desc: '', // 分享描述
link: shareUrl, // 分享链接
imgUrl: '', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//分享至QQ空间
wx.onMenuShareWeibo({
title: '', // 分享标题
desc: '', // 分享描述
link: shareUrl, // 分享链接
imgUrl: '', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});