最近做项目要用到微信分享功能,由于之前微信公众号的功能没怎么接触过,所以相对陌生。
以至于到前台页面调用jsapi时老是报各种错误,包括:invalid signature,updateAppMessageShareData Permission Denied这些错误。
故作此备忘:
官方开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
A.需要公众号开发信息中的 AppID,AppSecret。
1.获取token,每次请求时生成的token有效期为7200秒,注意每天有限制该接口调用次数,所以要做好缓存。
后台使用接口https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $weixin['AppID'] . "&secret=" . $weixin['AppSecret']
1 //使用get 请求,从微信服务器获取 token
2 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $weixin['AppID'] . "&secret=" . $weixin['AppSecret'];
3 //返回的是json格式
4 $access_token = json_decode(curlGet($url),true);
5
6 if($access_token['access_token']==''||$access_token['access_token']==null){
7 return array('success'=>0,'error'=>'获取token的配置参数有误');
8 }else{
9 //将token 传入缓存中(保存时间为3600秒=一小时)
10 S('Wxzj_Access_Token',$access_token['access_token'],array('expire'=>3600*1.5));
11 return array('success'=>$access_token['access_token']);
12 }
View Code
2.根据token获取ticket
1 if($token=S('Wxzj_Access_Token')){
2 $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$token}&type=jsapi";
3 $res = curlGet($url);
4 $res = json_decode($res, true);
5 if($res['errcode']!=0) {
6 return null;
7 } else {
8 S('Wxzj_jssdk_ticket', $res['ticket'], 3600);
9 }
10 return S('Wxzj_jssdk_ticket');
11 }else{
12 return null;
13 }
View Code
3.前台通过ajax传递url(处理过的url)到后台方法,通过方法拼装签名后,再返回结果。需要注意的是url所在域名必须添加在 微信公众平台-》公众号设置-》功能设置-》JS接口安全域名。且 微信公众平台-》开发-》基本配置-》IP白名单 需要添加url所在域名的ip地址
a).前台js代码
1 <script src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
2
3 <script>
4 /*
5 * url 目标url
6 * arg 需要替换的参数名称
7 * arg_val 替换后的参数的值
8 * return url 参数替换后的url
9 */
10 function changeURLArg(url,arg,arg_val){
11 var pattern=arg+'=([^&]*)';
12 var replaceText=arg+'='+arg_val;
13 if(url.match(pattern)){
14 var tmp='/('+ arg+'=)([^&]*)/gi';
15 tmp=url.replace(eval(tmp),replaceText);
16 return tmp;
17 }else{
18 if(url.match('[\?]')){
19 return url+'&'+replaceText;
20 }else{
21 return url+'?'+replaceText;
22 }
23 }
24 }
25
26 /**
27 * 获取url参数值
28 * @param name 参数名
29 * @returns
30 * @author Donlyn
31 * <li>created at 2018-02-12</li>
32 */
33 function GetQueryString(name) {
34 var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i");
35 var r = window.location.search.substr(1).match(reg);
36 if (r!=null) return unescape(r[2]); return null;
37 }
38
39 var url = '';
40 // 通过后台生成签名,因为之前都是直接在微信打开页面加载时就直接获取签名,导致老是报invalid signature的错误,后来查文档才发现这样不行。
41 //附录5-常见错误及解决方法 11.invalid signature签名失败(后台生成签名的链接为使用jssdk的当前链接,也就是跳转后的b链接,请不要用微信登录的授权链接进行签名计算,后台签名的url一定是使用jssdk的当前页面的完整url除去'#'部分)
42 $.ajax({
43 url : 'initJsapi',
44 type : 'post',
45 data : {url:(window.location.href).split('#')[0]},
46 success :function(res){
47 //alert(res);
48 var params = JSON.parse(res);
49 url = params.url;
50
51 // =============这里我重新拼装了url,以修改要分享出去的链接============
52 var share_mid = $('#MemberID').val();
53 if(share_mid!=0){
54 var id_val = GetQueryString('id');
55 var url_params_id_tmp = id_val.split('.');
56 if(url_params_id_tmp.length==2 || (url_params_id_tmp.length>2 && (url_params_id_tmp[2]==0))){
57 id_val += '.'+share_mid;
58 url = changeURLArg(url,'id', id_val);
59 }else if(url_params_id_tmp.length>2 && url_params_id_tmp[2]!=share_mid){
60 url_params_id_tmp[2] = share_mid;
61 id_val = url_params_id_tmp.join(".");
62 url = changeURLArg(url, 'id', id_val);
63 }
64 }
65 //=========修改url到这里结束==========
66
67 /*配置 wx.config 参数*/
68 wx.config({
69 debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
70 appId: params.appId, // 必填,企业号的唯一标识,此处填写企业号corpid
71 timestamp: params.timestamp, // 必填,生成签名的时间戳
72 nonceStr: params.nonceStr, // 必填,生成签名的随机串
73 signature: params.signature,// 必填,签名,见附录1
74 jsApiList: [
75 'checkJsApi',
76 'updateAppMessageShareData',
77 'hideMenuItems',
78 'onMenuShareAppMessage'
79 ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
80 });
81 }
82 });
83 wx.ready(function(){
84
85 // 这里禁用掉右上角菜单中的一些按钮
86 wx.hideMenuItems({
87 menuList: [
88 "menuItem:share:qq",
89 "menuItem:share:weiboApp",
90 "menuItem:share:facebook",
91 "menuItem:share:timeline",
92 "menuItem:share:QZone",
93
94 "menuItem:editTag",
95 "menuItem:delete",
96 //"menuItem:copyUrl",
97 "menuItem:originPage",
98 "menuItem:readMode",
99 "menuItem:openWithQQBrowser",
100 "menuItem:openWithSafari",
101 "menuItem:share:email",
102 ] // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
103 });
104 wx.error(function(res) {
105 alert(JSON.stringify(res));
106 });
107 wx.checkJsApi({
108 jsApiList: ['updateAppMessageShareData','onMenuShareAppMessage'/* 'onMenuShareAppMessage' */], // 需要检测的JS接口列表,所有JS接口列表见附录2,
109 success: function(res) {
110 // 以键值对的形式返回,可用的api值true,不可用为false
111 // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
112 //alert(JSON.stringify(res));
113 }
114 });
115 // 这个接口是旧版本接口,分享给好友,此接口即将失效,但是因为要用到判断“是否分享成功”,所以暂时使用着。1.4.0版本接口为updateAppMessageShareData,不能判断是否分享成功
116 wx.onMenuShareAppMessage({
117 "imgUrl" : "imgUrl", // 分享显示的缩略图地址
118 "link" : url, // 分享地址
119 "desc" : "desc", // 分享描述
120 "title" : "Title", // 分享标题
121 success : function(){
122 // 分享成功可以做相应的数据处理
123 /* alert("分享成功");
124 return; */
125
126 }
127 });
128 //wx.onMenuShareAppMessage(shareData);
129 });
130 </script>
View Code
这里要注意拼接签名字符串 $str 的参数的先后顺序
1 function initJsapi(){
2 if(IS_POST) {
3 $url = $_POST['url'];
4 $res = array();
5 // ======================== Start at 2017/05/27 1015 ======================== //
6 $jsapi_ticket = S('Wxzj_jssdk_ticket');
7 if($jsapi_ticket){
8 $noncestr = rand_string(16);//16位长度随机字符串
9 $timestamp = time();
10 // 拼接签名字符串
11 $str = 'jsapi_ticket='.$jsapi_ticket.'&noncestr='.$noncestr.'×tamp='.$timestamp.'&url='.$url;
12 $this->str_test = $str;
13 // sha1()加密方式
14 $signature = sha1($str);
15
16 // 这个是微信公众号的AppID
17 if($zjwx = $weixin['AppID']) {
18 $appID = $zjwx;
19 } else {
20 $appID = '';
21 }
22
23 $res = array(
24 'str_test' => $str,
25 'url'=>$url,
26 'signature'=>$signature,
27 'nonceStr'=>$noncestr,
28 'timestamp'=>$timestamp,
29 'jsapi_ticket'=>$jsapi_ticket,
30 'appId' => $appID
31 );
32 }
33 exit(json_encode($res));
34 }
35 }
View Code