点击上方 蓝字 关注我们
引入微信 JS-SDK 后,我们的网站也会拥有和对应绑定公众号的全部权限,比如现在很流行的网页分享到微信好友或者朋友圈时,除了公众号会自己带上小 LOGO 和标题外,其它的外链页面都是一个灰色链接图标和一长串 url,通过接入 JS-SDK 后,我们可以让分享的链接带上我们自定义的小图标以及文章标题。
工具
IDE
微信开发者工具(调试模拟微信打开网页)
任意后端服务(我以 PHP 举例,Laravel 框架)
准备工作
AppID
,AppSecret
,IP白名单
,绑定安全域名
微信公众平台后台登录后,在公众号开发信息内获取。
其中IP白名单
内,需要填入你的后端服务器真实公网 IP 地址,这是为了接口调用安全考虑,除了白名单之外的终端,都没有权限调用接口。
绑定安全域名也是在此操作,具体是在设置
-公众号设置
-功能设置
-JS接口安全域名
中填入,填入规则请只保留你的域名,如 famio.cn,不需要 http/https 协议头和末尾的任何参数。
后端配置
在服务端,我们根据微信官方接口文档提示,需要进行三个前置数据
的获取工作,分别是access_token
,随机字符串nonce
以及jsapi_ticket
。
access_token 获取
请求接口地址
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$ACCESS_TOKEN&type=jsapi
将之前准备好的AppID
和AppSecret
的值,代替掉上述请求接口地址中的APPID
和SECRET
。
请求方式
GET
返回结果
如果返回的结果(Json Object)中包含access_token
字段,则表示请求成功,我们取它对应的值即可。
如果没有,则说明请求失败,会返回errMessage
字段的错误信息,具体返回体说明可参照官方微信开发文档:
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
随机字符串 nonce 获取
这个很简单,从a-z
,A-Z
和0-9
之间取随机数,拼成一个长度为 16 的随机字符串。
/** * 生成nonce * @paramint $length * @returnstring */static function createNonceString($length = 16){ $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $string = ""; for ($i = 0; $i < $length; $i++) { $string .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $string;}
jsapi_ticket 获取
前提条件:获取到了access_token
。
请求接口地址
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$ACCESS_TOKEN&type=jsapi
将之前获取的access_token
的值,代替掉上述请求接口地址中的ACCESS_TOKEN
。
请求方式
POST
返回结果
如果返回的结果(Json Object)中包含ticket
字段,则表示请求成功,我们取它对应的值即可。
如果没有,则说明请求失败,会返回errMessage
字段的错误信息。
jsapi_ticket
有请求频次限制,每次请求到的jsapi_ticket
都可以在一定的生命周期内被重复使用,官方默认有效时间为7200
秒,因此,强烈建议将jsapi_ticket
的值存放到缓存中,并赋予7200
秒的 TTL,取值前优先从缓存中获取,如果缓存中没有值,则请求接口获取jsapi_ticket
,并将其值存放进缓存供下次调用。
构造签名请求控制器&路由
当我们获取到了以上三个参数后,我们需要构造签名控制器和路由了,假设:
/api/wechat/mp/sign
通过GET
绑定到了WeChatController
控制器的getSignPackage
方法。
在getSignPackage
方法中,我们首先要获取接入JS-SDK
站点的当前url
,这个可以通过传入参数。
其次结合之前的工作,得到以下这些参数:
$appid //对应之前取得的AppID$ticket //对应之前取得的jsapi_ticket$nonceStr //对应之前取得的nonce$timestamp //直接通过time()全局方法获取
然后将以上参数通过字符串拼接的方式,形成以下一个字符串:
$string = "jsapi_ticket=$ticket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
接着,将这个$string
通过sha1
签名:
$signature = sha1($string);
最后,我们构建并返回这样一个数组:
$signPackage = array( "appId" => $appid, "nonceStr" => $nonceStr, "timestamp" => $timestamp, "url" => $url, "signature" => $signature, "rawString" => $string, "ticket" => $ticket, );
将上述数组以 Json Object 形式返回,此控制器就完成了。
前端
以最传统的原生JavaScript
为例,因为只要掌握了原生处理的办法,针对其他前端框架,也是很容易就理解了。
引用 JS 库
在你的网站中引入以下 JS 文件:
https://res.wx.qq.com/open/js/jweixin-1.6.0.js
接入
然后在需要分享的页面上构建以下JavaScript
代码:
$.ajax({ type: "get", url: "这里填你之前写的后端签名控制器对应的路由?url=" + window.location.href, success: function (res, textStatus, request) { //初始化配置 wx.config({ // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 debug: false, // 必填,公众号的唯一标识 appId: res.data.appId, // 必填,生成签名的时间戳 timestamp: res.data.timestamp, // 必填,生成签名的随机串 nonceStr: res.data.nonceStr, // 必填,签名 signature: res.data.signature, // 必填,需要使用的JS接口列表 jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage"], }); //这里写你自己的逻辑执行代码,比如你要写分享到朋友圈或者发送给好友的时候,链接带上小图和标题说明文字,那么就在这里写上以下代码 //需在用户可能点击分享按钮前就先调用 wx.ready(function () { //分享到朋友圈 wx.onMenuShareTimeline({ // 分享标题,可以指定,也可以像我一样动态获取当前页面标题 title: document.title, // 分享描述 desc: "时刻保持冷静,沸腾只会更快蒸发", // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 link: window.location.href, // 分享图标,图标地址可以是相对路径或者是绝对路径,格式为图片文件 imgUrl: "", success: function () { // 设置成功 }, }); //分享给好友(发送消息) wx.onMenuShareAppMessage({ title: "", desc: "", link: window.location.href, imgUrl: "", success: function () { // 设置成功 }, }); }); }, error: function (res) { console.log; },});
到这里,JS-SDK
引入完成,并且你的网站也拥有了公众号的全部权限。
坑
如果在
wx.onMenuShareTimeline
这样的接口方法中写死link
的值,务必保证这样的格式https://famio.cn/
,而不是https://famio.cn
,最后一个/
是需要保留的,这样微小的差异会给签名时的sha1
结果带来翻天覆地的改变,结果自然会是错误的。wx.onMenuShareTimeline
这样的接口方法已经即将被废弃,具体参考官方微信开发文档描述。看仔细
noncestr
和nonceStr
的字段名。timestamp
是一个10
位长度的数字,必须是10
位。我想到了再补充。