公众号项目需要在页面中做分享控制,有的页面可以分享,有的不允许分享。具体的流程做个记录
基本原理是调用微信浏览器内置的对象进行控制。
步骤一:绑定域名
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
步骤二:引入JS文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
备注:支持使用 AMD/CMD 标准模块加载方法加载
步骤三:通过config接口注入权限验证配置
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
var list = [ 'onMenuShareTimeline' //分享到朋友圈
,'onMenuShareAppMessage' //发送给好友
, 'showMenuItems' //显示功能按钮
,'hideAllNonBaseMenuItem' //隐藏所有非基础功能按钮
];
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: param.appId, // 必填,公众号的唯一标识
timestamp: param.timestamp, // 必填,生成签名的时间戳
nonceStr: param.nonceStr, // 必填,生成签名的随机串
signature: param.signature,// 必填,签名,见附录1
jsApiList: list // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
代码中的param
由后台返回,appId,timestamp,nonceStr这三个参数容易获取,signature需要调用微信的接口拿到ticket,并按照微信规定的算法生成。(另:注意参数大小写)
signature的获取方法如下
- 获取access_token
https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
其中grant_type固定为client_credential,appid为公众号ID,secret为公众号密钥。
会返回JSON格式数据。
{"access_token":"ACCESS_TOKEN","expires_in":7200}
做好本地缓存,如果参数未过期,不需要访问接口来获取参数,直接本地获取。
2.拿到jsapi_token
http请求方式:GET
[https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi](https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi)
其中type固定为jsapi,access_token为上一步获取到的access_token
成功返回如下JSON:
{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}
同样ticket需要缓存到本地。
获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
3.签名算法
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
PHP代码示例如下
//获取sign
$link = $_SERVER["HTTP_REFERER"];
//1.获取ticket
$ticket = $this->get_ticket();
//2.按照ASCII码排序,生成字符串
$arr = [];
$arr["noncestr"] = $json["nonceStr"];
$arr["jsapi_ticket"] = $ticket;
$arr["timestamp"] = $now;
$arr["url"] = $link;
ksort($arr);
$str = "";
foreach($arr as $k=>$v) {
$str .= $k;
$str .= "=";
$str .= $v;
$str .= "&";
}
$str = rtrim($str, "&");
$signature = sha1($str);
其中noncestr为生成的随机字符串,url为需要做分享的页面地址
最终生成的$signature就是签名字符串。
(另,此处的foreach循环不建议改用http_build_query函数,因为http_build_query会对数据urlencode,可能会碰到坑)
到此,wx.ready配置信息已经完成。之后调用wx.ready来控制分享功能
wx.ready(function () {
//隐藏所有非功能按钮
wx.hideAllNonBaseMenuItem();
if(is_share) {
var obj = {
title : title, //分享标题
desc : desc, //分享描述信息
link : param.link, //进行分享的页面地址
imgUrl : imgUrl //分享的logo图片
};
//显示分享给朋友、分享到朋友圈按钮
wx.showMenuItems({
menuList: ['menuItem:share:appMessage', 'menuItem:share:timeline'] // 要显示的菜单项,所有menu项见附录3
});
// 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
wx.onMenuShareTimeline(obj);
//监听“分享到好友”
wx.onMenuShareAppMessage(obj);
}
});
此项目中只开启了分享给好友和分享到朋友圈。
参考微信JS-SDK说明文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
差点忘了,还有个坑,获取access_token的时候,需要在公众平台后台设置IP白名单,将你的服务器IP地址加进去,否则会报错。
欢迎批评指正,也欢迎大家留言交流。