• 微信JSSDK分享--挖坑填坑之小结


      最近参与微信服务号小项目的开发,关于微信分享,我是只知其功能,并没深入了解其中的弯弯道道。虽然项目中不是我负责微信分享这一块(因为我也不太会),但是团队在这个功能上,那可是说多了都是泪,耗费了超级多的时间:一句话就是加班加点的挖坑,制造解决不了的bug,然后加班加点的找问题所在,去解决。主要是我们对于微信分享这块的了解并不深入,没想到的太多。

      当时一直分享不成功,我们前端一直以为是我们的js代码写的有问题,谁知道最大的问题是配置问题:

      一、不再同一个服务号。

      因为微信端,为了识别用户,每个用户针对每个公众号会产生一个安全的OpenID,如果需要在多公众号、移动应用之间做用户共通,则需前往微信开放平台,将这些公众号和应用绑定到一个开放平台账号下,绑定后,一个用户虽然对多个公众号和应用有多个不同的OpenID,但他对所有这些同一开放平台账号下的公众号和应用,只有一个UnionID,可以在用户管理-获取用户基本信息(UnionID机制)文档了解详情。

      二、分享的链接有&符,我们没有做处理

      三、JS接口安全域名设置,没有设置白名单。

      今天团队的大神,特别针对微信分享这个功能,对于其中会遇到的问题进行了总结和讲解,我这才对微信分享,有了更深入的认识和了解。记性不好,听完怕忘,得来个听后记录啊。

      虽然微信提供了JSSDK,但是这不意味着你可以用自定义的按钮来直接打开微信的分享界面,这套JSSDK只是把微信分享接口的内容定义好了,实际还是需要用户点击右上角的菜单按钮进行主动的分享,用户点开分享界面之后,出现的内容就会是你定义的分享标题、图片和链接

      JSSDK使用步骤:

      1.步骤一:绑定域名

      2.步骤二:引入js

      

      3.步骤三:通过config接口注入权限验证配置

      

      4.步骤四:通过ready接口处理成功验证

      

      5. 步骤五:通过error接口处理失败问题  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。

      

      写到这里,其实已经跟前端没多大事了,剩下的就是关于公众号的配置。但是当时我们前端还一直以为是自己js的错误。。(js详见最后)

      配置大纲:

      

      详细步骤:  

      1.设置JS接口安全域名。

      这里填写的是一级域名,不带www和http。最多可以设置三个域名。设置完后点击确定。(多说一句,相比以前的分享没有任何域名限制,这里设置安全域名,目的是为了当发现此公众平台发现诱导分享行为时,可以根据此域名追溯到所有分享出去的链接,以及通过这些链接增加的粉丝。这样,微信就可以牢牢控制了你的微信平台,一旦发现违规,让分享链接失效,删除掉诱导行为增加的粉丝,是瞬间就可以完成的。因此,微信平台的开发者,一定要合理来使用分享功能,不要因小失大。等到你的微信平台被封,估计哭都来不及)

      

      2.在开发者中心中获取你的AppID和AppSecret,接下来在获取令牌时,需要这两个信息。

      

      3.获取令牌

    unction wx_get_token() {
        $token = S('access_token');
        if (!$token) {
            $res = file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='            .'你的AppID'.'&secret='            .'你的AppSecret');
            $res = json_decode($res, true);
            $token = $res['access_token'];
            // 注意:这里需要将获取到的token缓存起来(或写到数据库中)
            // 不能频繁的访问https://api.weixin.qq.com/cgi-bin/token,每日有次数限制
            // 通过此接口返回的token的有效期目前为2小时。令牌失效后,JS-SDK也就不能用了。
            // 因此,这里将token值缓存1小时,比2小时小。缓存失效后,再从接口获取新的token,这样
            // 就可以避免token失效。
            // S()是ThinkPhp的缓存函数,如果使用的是不ThinkPhp框架,可以使用你的缓存函数,或使用数据库来保存。
            S('access_token', $token, 3600);
        }
        return $token;
    }
    注意:返回的access_token长度至少要留够512字节。接口返回值:
    {"access_token":"ACCESS_TOKEN","expires_in":7200}
    {"access_token":"vdlThyTfyB0N5eMoi3n_aMFMKPuwkE0MgyGf_0h0fpzL8p_hsdUX8VGxz5oSXuq5dM69lxP9wBwN9Yzg-0kVHY33BykRC0YXZZZ-WdxEic4","expires_in":7200}
    

      4.获取jsapi的ticket。jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。

    function wx_get_jsapi_ticket(){
        $ticket = "";
        do{
            $ticket = S('wx_ticket');
            if (!empty($ticket)) {
                break;
            }
            $token = S('access_token');
            if (empty($token)){
                wx_get_token();
            }
            $token = S('access_token');
            if (empty($token)) {
                logErr("get access token error.");
                break;
            }
            $url2 = sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",
                $token);
            $res = file_get_contents($url2);
            $res = json_decode($res, true);
            $ticket = $res['ticket'];
            // 注意:这里需要将获取到的ticket缓存起来(或写到数据库中)
            // ticket和token一样,不能频繁的访问接口来获取,在每次获取后,我们把它保存起来。
            S('wx_ticket', $ticket, 3600);
        }while(0);
        return $ticket;
    }
    接口返回值:
    {"errcode":0,"errmsg":"ok","ticket":"sM4AOVdWfPE4DxkXGEs8VMKv7FMCPm-I98-klC6SO3Q3AwzxqljYWtzTCxIH9hDOXZCo9cgfHI6kwbe_YWtOQg","expires_in":7200}
    

      5.签名,将jsapi_ticket、noncestr、timestamp、分享的url按字母顺序连接起来,进行sha1签名。    noncestr是你设置的任意字符串。     timestamp为时间戳。

    $timestamp = time();
    $wxnonceStr = "任意字符串";
    $wxticket = wx_get_jsapi_ticket();
    $wxOri = sprintf("jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s",
    $wxticket, $wxnonceStr, $timestamp,
           '要分享的url(从http开始,如果有参数,包含参数)'
    );
    $wxSha1 = sha1($wxOri);
    

      

      js代码:

    var shareData = {
        shareTitle:"",
        shareContent:"",
        shareUrl:location.href,
        imgUrl:"",
        success:function(){
            alert('分享成功!');
        }
    };
    function wxConfig () {
        $.ajax({
         // 此处的location.href必须做处理,一个大坑,因为如果url中有&这个特殊符号,微信端分享就不会成功。
    url: "http://***?url=" + encodeURIComponent(location.href), method: 'get', success: function (data) { var wxdataObj = {}; if(typeof data == "string" && data.indexOf("{")!=-1){ wxdataObj = JSON.parse(data); }else{ wxdataObj = data; } wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: wxdataObj.AppId||wxdataObj.appId, // 必填,公众号的唯一标识 timestamp: wxdataObj.Timestamp||wxdataObj.timestamp, // 必填,生成签名的时间戳 nonceStr: wxdataObj.NonceStr||wxdataObj.nonceStr, // 必填,生成签名的随机串 signature: wxdataObj.Signature||wxdataObj.signature, // 必填,签名,见附录1 jsApiList: ['chooseImage', 'uploadImage','onMenuShareTimeline', 'onMenuShareAppMessage',"hideAllNonBaseMenuItem","showAllNonBaseMenuItem"], // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.error(function (res) { //console.log('res', res); }); }, error: function (data) { //console.log('error', data); } }); wx.ready(function () { wx.onMenuShareTimeline({ title: shareData.shareTitle, // 分享标题 link: shareData.shareUrl, // 分享链接 imgUrl: shareData.shareIcon, // 分享图标 success: shareData.success// 用户确认分享后执行的回调函数 }); wx.onMenuShareAppMessage({ title: shareData.shareTitle, // 分享标题 desc: shareData.shareContent, // 分享描述 link: shareData.shareUrl, // 分享链接 imgUrl: shareData.shareIcon, // 分享图标 success: shareData.success// 用户确认分享后执行的回调函数 });
         // 此处是微信禁用 if(location.href.indexOf("tinysite.html")==(-1)){ wx.hideAllNonBaseMenuItem(); } }); }; function isWeiXin(){ var ua = navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i)=="micromessenger") { return true; } else { return false; } }//判断是否在微信打开 //若果是微信就拉取微信权限 if(isWeiXin()){ wxConfig (); } //从url里取值var urlData = getUrlData(["userId","fromSource"]); //使用 urlData.userId,urlData.fromSource function getUrlData (arr){ var dataArr = {}; for(var i = 0; i < arr.length; i++){ var urlList = decodeURIComponent(location.href).split("&"); for(var j = 0; j < urlList.length; j++){ if(urlList[j].indexOf(arr[i]+"=") != (-1)){ var data = urlList[j].slice(urlList[j].indexOf(arr[i]+"=")+arr[i].length+1); dataArr[arr[i]] = data; } } } return dataArr; }

      如果是多个页面都分享自定义的标题和描述:

    var share = {
                title: document.title,
                discription: document.discription,
                imgurl: "",
                url: location.href,
                success: function () {
                    alert('分享成功!');
                }
            };
            if (data) {
                for (v in data) {
                    share[v] = data[v] || share[v];
                }
            }   
    

      

      

  • 相关阅读:
    创建或者连接管道+++检查管道空间是否够写入本消息++++删除管道
    从instr中截取第一个delimiter之前的内容放到outstr中,返回第一个delimiter之后的位置
    把数字按网络顺序或主机顺序存放到字符串中++++把字符串按网络顺序转换成数字++++把字符串按主机顺序转换成数字
    压缩空格的函数以及BCD码与ASCII相互转换函数
    判断文件是否存在
    把指定长度字符串转换成数字
    找到特定串在源字符串中的位置
    FTP命令详解
    docker 学习路线
    云原生技术的了解
  • 原文地址:https://www.cnblogs.com/wxiaoying/p/7486790.html
Copyright © 2020-2023  润新知