这个功能在几年前就做好了,近期又做了改动,顺便做个笔记。
开发步骤及所有可能遇到的问题,在官方文档中多数能找到答案,写这篇文章,是为了规避一些开发中可能遇到的坑,也方便了那些想快速开发却又不想一字一句读文档的人。
官方文档传送门:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
首先需要一个已认证的公众号,建议服务号,没测试过订阅号也可以,个人账号不可以。
本篇文章中,我将用测试号进行演示,后端语言采用PHP。
微信公众平台接口测试帐号申请:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
在公众号后台填写接口配置信息,url为服务器验证文件的网址,精确到.php,Token自己填写。
填写完成需要做验证,其中给出了说明,网址:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html, 打开后里面有部分代码,复制到php文件中即可,服务器的URL就是这个php文件的网站。
我把代码复制到下面,做个参考,比如Token我填写message,代码中的TOKEN也要一致。
define("TOKEN","message");
function checkSignature(){
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
$echoStr = $_GET["echostr"];
if (checkSignature()){
echo $echoStr;
}
若没什么问题,提交后会提示“配置成功”。
下面配置JS接口安全域名,这个配置很重要,文档中说明了支持80端口和443端口,但并未说明这里要不要加http或https,很多人容易在这里出错,经实际测试,这个位置仅添写域名,其它什么都不需要。
这个位置填错后,最常见的错误是:invalid url domain,如果出现这个提示,不妨查验一下公众号后台的JS接口安全域名。
接口配置信息和JS接口安全域名都保存完成后,开始代码工作。
首先后端请求微信,先拿到access_token,再通过access_token请求接口获取ticket,每次请求有效期7200秒。
注意access_token和ticket都有请求次数限制,如果使用较多,建议保存本地,access_token每次请求都会变化,ticket在一次有效期内值不会变,哪怕每次access_token不同,但ticket依然不变。
拿到ticket后,所需参数按照首字目正序拼接,得到的字符串,通过sha1加密生成最终所需要的签名signature。
public $appid = "wx852d1b8c7146h838";
public $secre = "cf88907d78da86906dd854523f34cb8d";
public $timestamp;
public $nonceStr = "Wm3WZYTP10wz1cnS"; //随机字符串
public $signature; //签名
public $url; //分享的地址
function __construct() {
$appid = $this->appid;
$secre = $this->secre;
$nonceStr = $this->nonceStr;
$this->timestamp = time();
//查询保存数据库的ticket,若请求较大,建议上缓存
$this->db->table_name = 'v9_weixin_ticket';
$res = $this->db->select("","*","1","id DESC");
$time = 0;
foreach($res as $key => $val) {
$jsapi_ticket = $val['ticket'];
$time = $val['create_time'];
}
//若本地ticket过期,再次请求微信
if($time+60*60*2 < $this->timestamp) {
//access_token
$token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secre;
$token_msg = file_get_contents($token_url);
$token = json_decode($token_msg,true);
$access_token = $token['access_token'];
//jsapi_ticket
$jsapi_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$access_token."&type=jsapi";
$jsapi_msg = file_get_contents($jsapi_url);
$jsapi = json_decode($jsapi_msg,true);
$jsapi_ticket = $jsapi['ticket'];
//insert
$this->db->insert(['create_time'=>$this->timestamp,'ticket'=>$jsapi_ticket]);
}
//要分享的URL地址(当前页面的URL),注意协议头必须和当前打开页面所用的一致(http或https)
$url = $this->url = $_SERVER['REQUEST_SCHEME']."://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$str = "jsapi_ticket=".$jsapi_ticket."&noncestr=".$nonceStr."×tamp=".$this->timestamp."&url=".$url;
//生成签名
$this->signature = sha1($str);
}
注意:生成签名所需要的url,也就是当前页面的url,协议头一定要和打开页面所用的一样,比如当前使用了https,而参数中是http,那么生成的签名将不能通过微信的验证,前端开启debug会提示类似“invalid signature ”的错误信息。
后端完成请求后,将所有数据传给前端,接下来需要按照文档给出的信息,在前端页面中配置分享接口。
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
通过config接口注入权限验证配置:
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
通过ready接口处理成功验证:
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
自定义“分享给朋友”及“分享到QQ”按钮的分享内容(1.4.0)
wx.ready(function () { //需在用户可能点击分享按钮前就先调用
wx.updateAppMessageShareData({
title: '', // 分享标题
desc: '', // 分享描述
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function () {
// 设置成功
}
})
});
自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容(1.4.0)
wx.ready(function () { //需在用户可能点击分享按钮前就先调用
wx.updateTimelineShareData({
title: '', // 分享标题
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function () {
// 设置成功
}
})
});
代码演示: