微信js分享接口的一些使用心得例子

然微信官方开放了js-sdk,但是在某些老版本的微信上存在兼容性问题,比如在安卓微信6.0.1版本上分享接口就无法使用,官方给出的解决方案就是升级微信。这不坑爹呢!我又不能强制我的用户去升级微信版本,总不能就抛弃他们吧?所以我们需要:

破解版js接口
点击查看项目 该接口为一大牛 @Alienfe 所做,当时在微信屏蔽私有接口的情况下,这个js库帮了大忙,破解了微信的限制,使得我们能够继续使用私有接口。但是在最新微信6.1版本,该库已经失效。

官方sdk
既然官方提供了接口,我们以后肯定是切换到上面的,代码重构少不了的,该接口的开发文档在这里:  官方js-sdk文档 说实话,该文档虽然功能强大,但是配置麻烦,需要请求授权后拿到授权码放到前端js里,简直蛋疼无比,而且不知道未认证的公众号能否使用。

这里就不详细介绍两个接口的使用方法了,这里主要说明一下如何合理使用两个接口,前面说过了,破解版js接口在6.1以上无效,而官方接口在低版本上存在兼容性问题,所以这里我们需要同时使用两个接口,以保证所有微信用户都能够正常分享。

那么,我的策略是:

1.微信版本<6.0.2 使用破解版接口 2.微信版本>=6.0.2 使用官方sdk

就以我的PHP项目为例,在后端,我通过 userAgent 提取微信版本号:

    //判断微信版本是否高于6.0.2,低版本用旧接口,高版本用jssdk
    preg_match('/MicroMessenger\/(.*?)[^\d\.]/',$_SERVER['HTTP_USER_AGENT'],$m);
    if (version_compare($m[1], '6.0.2') == 1) {
        $this->assign('wxHighVersion',true);
    } else {
        $this->assign('wxHighVersion',false);
    }
wxHighVersion 是绑定到视图模板的变量名,以便我们在模板决定用哪个接口。模板部分:

<script>
    //自定义分享参数
    var wxData = {
        "imgUrl": "",//图片
        "link": "",//分享链接
        "title": "",//定义分享标题
        "desc":""
    };
</script>
<?php if(!$wxHighVersion): ?>
<script src="/js/WeixinApi.js"></script>
<script>
    //使用破解版接口
</script>
<?php else: ?>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
    //使用官方接口
</script>
<?php endif; ?>

这样,我就实现了全版本兼容,只是重构代码需要细心+耐心。

我们要扩展thinkphp的微信类库(注这个是自己扩展改进来用于TP上用)。其实这个主要是继承高级接口类,分别写上缓存方法与以前调用其他接口时一样。代码中,我把官方的sample的PHP代码的方法复制过来用。
该例子中我用库表,实际中推荐你用memcached
缓存表一览:
data
<?php
namespace Wx;
class WechatJSAPI extends WechatJSON{
    //缓存access token
    public function cache($key, $value = null, $timeout = 7000) {
        $cache = M('access_token');
        $token = $cache->where(array('uid'=> 0))->find();
        if (empty($value)) {
            if ($token && $token['expires_time'] > time()) {
                return $token['access_token'];
            }
            return false;
        }
        $data = array(
            'uid' => 0,
            'access_token' => $value,
            'expires_time' => time() + $timeout,
        );
        if($token) {
            $cache->where('uid=0')->save($data);
        } else {
            $cache->data($data)->add();
        }
        return false;
    }
 
     //获取签名包数据
    public function getSignPackage() {
        $jsapiTicket = $this->getJsApiTicket();
        if( ! $jsapiTicket) return false;
        $url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        $timestamp = time();
        $nonceStr = $this->createNonceStr();
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
        $signature = sha1($string);
        $signPackage = array(
            "appId"     => $this->_APPID,
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }
 
    //生成随机字符串
    private function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
 
    //获取ticket
    private function getJsApiTicket() {
        $t = M('access_token');
        $cache = $t->where(array('uid'=> 0))->find();
        if ($cache && $cache['ticket_expires_time'] > time() && $cache['ticket']) {
            return $cache['ticket'];
        }
        $res = $this->call('/ticket/getticket', array('type' => self::API_TYPE_JS), self::GET, self::API_TYPE_CGI);
        if($res) {
            $data = array(
                'ticket' => $res['ticket'],
                'ticket_expires_time' => time() + 7200,
            );
            $t->where('uid=0')->save($data);
            return $res['ticket'];
        }
        return false;
    }
 
    //AJAX时刷新ticket
    public function refreshTicket() {
        $res = $this->call('/ticket/getticket', array('type' => self::API_TYPE_JS), self::GET, self::API_TYPE_CGI);
        if($res) {
            $t = M('access_token');
            $cache = $t->where(array('uid'=> 0))->find();
            if($res['ticket'] !== $cache['ticket']) {
                $data = array(
                    'ticket' => $res['ticket'],
                    'ticket_expires_time' => time() + 7200,
                );
                $t->where('uid=0')->save($data);
                return true;
            }
        }
        return false;
    }
}
然后在TP里的view新建一个layout(我以最基本要的HTML为例)
Layout/jsapi.phtml:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
{__CONTENT__}
</body>
<script type="text/javascript">
    window.jQuery || document.write("<script src='__PUBLIC__/js/jquery-1.10.2.min.js'>"+"<"+"/script>");
</script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
    wx.config({
        debug: false,
        appId: '{$signPackage["appId"]}',
        timestamp: {$signPackage["timestamp"]},
        nonceStr: '{$signPackage["nonceStr"]}',
        signature: '{$signPackage["signature"]}',
        jsApiList: [
            'checkJsApi',
            'onMenuShareTimeline',
            'onMenuShareAppMessage'
        ]
    });
    wx.ready(function () {
        wx.checkJsApi({
            jsApiList: [
                'getNetworkType',
                'previewImage'
            ],
            success: function (res) {
                //alert(JSON.stringify(res));
            }
        });
 
        var shareObj = {
            title: '{$shapeObje.title}',
            desc: '{$shapeObje.desc}',
            link: '{$shapeObje.link}',
            imgUrl: '{$shapeObje.imgUrl}',
            trigger: function (res) {
                alert('用户点击发送给朋友');
            },
            success: function (res) {
                alert('已分享');
            },
            cancel: function (res) {
                alert('已取消');
            },
            fail: function (res) {
                alert(JSON.stringify(res));
            }
        };
        //分享朋友
        wx.onMenuShareAppMessage(shareObj);
        //分享朋友圈
        wx.onMenuShareTimeline(shareObj);
    });
    jQuery.getJSON('index/ticket', function(data) {
        alert(data);
        if(data) {
            alert('ticket update');
        }
    });
 
    wx.error(function(res){
        var str = res.errMsg;
        var reg = /invalid signature$/;
        var r = str.match(reg);
        //当提示签名有误时就AJAX方式更新ticket后再刷新当前页
        if(r !== null) {
            jQuery(function(){
                $.getJSON('http://www.demo.com/home/index/ticket', function(data) {
                    if(data) {
                        alert('ticket update');
                        location = location;
                        window.navigate(location);
                    }
                });
            });
        }
    });
</script>
</html>

TP中的控制器,初化设置相关数据替换模板和远程更新ticket方法
<?php
namespace Home\Controller;
use Think\Controller;
use Wx\WechatJSAPI;
 
class IndexController extends Controller {
    protected $api;
    public function _initialize() {
        $package = $this->getJsPackage();
        $this->assign('signPackage',$package);
        $this->assign('shapeObje',array(
            'title' => '测试标题',
            'desc' => '测试描述',
            'link' => "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]",
            'imgUrl' => "yun_qi_img/No-Event.php",
        ));
    }
 
    public function indexAction(){
        $this->display();
    }
 
    protected function getJsPackage() {
        $config = C('WECHAT_CONF');
        $this->api = WechatJSAPI::getInstance(array(
            WechatJSAPI::APP_ID => $config[WechatJSAPI::APP_ID],
            WechatJSAPI::APP_SECRET => $config[WechatJSAPI::APP_SECRET]
        ));
        return $this->api->getSignPackage();
    }
 
    public function ticketAction() {
        if(IS_AJAX) {
            $res = $this->api->refreshTicket();
            $this->ajaxReturn($res);
        }
    }
}
后记,测试出ticket的缓存时间,与access_token无关!也就是只要ticket还没过期,你更新了access_token再调/ticket/getticket接口,ticket值还是一样的。重点是怎么缓存ticket和更新ticket较为合理,我上面的方法就利用JS-SDK的wx.error(function(res){})来正则匹出是invalid signature时就AJAX一下更新ticket的URL,然后再刷新。
你如果有什么好建议欢迎一起探讨!

时间: 2024-09-18 05:13:54

微信js分享接口的一些使用心得例子的相关文章

同一个界面内取微信的OPENID和调用微信的分享接口

步骤如下,1:判断URL是否有CODE参数传入,没有则拼接那个微信跳转连接,然后redirect2:有CODE传入,调用微信接口,根据code获取openid和access_token,注意这一步取到的token是没用的,这里已经取到openid了,下面开始取微信JS SDK的接口注入配置3:调用微信接口根据appid和secrect取access_token4:用上一步得到的access_token再调用微信接口 根据access_token 取得tikect5:用上一步得到的tikect进行

php版微信数据统计接口用法示例_php技巧

本文实例讲述了php版微信数据统计接口用法.分享给大家供大家参考,具体如下: php版微信数据统计接口其实是非常的好用了在前版本还没有此功能是后面的版本增加上去了,下面来看一个php版微信数据统计接口的例子: 微信在1月6日时放出了新的数据分析接口传送门: 请注意: 1.接口侧的公众号数据的数据库中仅存储了2014年12月1日之后的数据,将查询不到在此之前的日期,即使有查到,也是不可信的脏数据: 2.请开发者在调用接口获取数据后,将数据保存在自身数据库中,即加快下次用户的访问速度,也降低了微信侧

JS版微信6.0分享接口用法分析_javascript技巧

本文实例讲述了JS版微信6.0分享接口用法.分享给大家供大家参考,具体如下: 为了净化网络,整顿诱导分享及诱导关注行为,微信于2014年12月30日发布了<微信公众平台关于整顿诱导分享及诱导关注行为的公告>,微信平台开发者发现,原有的微信分享功能不能用了.正在苦于微信分享该怎么解决时,微信于2015年1月10日即时发布了开放JS-SDK,为微信网站的开发提供了强大的js功能. 注: 1.微信JS-SDK,提供的分享接口仅是监听分享事件触发时,修改分享的标题.链接等.不能自定义触发分享事件 2.

微信JS接口

关键字:微信公众平台 JSSDK 发送给朋友 分享到朋友圈 onMenuShareTimeline onMenuShareAppMessage 作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/p/weixin-js.html    在这篇微信公众平台开发教程中,我们将介绍如何在网页中实现发送给朋友和分享到朋友圈时内容参数自定义的功能. 本文分为以下二个部分: 生成JS-SDK权限验证签名 实现发送给朋友和分享到朋友圈时内容参数自定义 我们提供本接口的付费购买

微信JS接口汇总及使用详解_javascript技巧

基本说明 使用说明 1.引入JS文件 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 备注:支持使用 AMD/CMD 标准模块加载方法加载 2.注入配置config接口 所有需要使用JSSDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用). 复制代码 代码如下: wx.config({  debug:

微信JS接口大全_javascript技巧

本文为大家分享了js微信接口详细版,供大家参考,具体内容如下 基本说明使用说明1.引入JS文件 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js  备注:支持使用 AMD/CMD 标准模块加载方法加载 2.注入配置config接口  所有需要使用JSSDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用).

解析微信JS-SDK配置授权,实现分享接口_javascript技巧

微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享.扫一扫.卡券.支付等微信特有的能力.7月份的时候,因为这个分享的证书获取问题深深的栽了一坑,后面看到"config:ok"的时候真的算是石头落地,瞬间感觉世界很美好.. 这篇文章是微信开发的很多前置条件,包括了服务端基于JAVA的获取和缓存全局的access_token,获取和缓存全局的jsapi_ticket,以及前端配置授权组件封装,调用分享组件封装. 配置授权思路:首先根据

java-调用微信分享接口后,微信会自动刷新页面,但session丢失

问题描述 调用微信分享接口后,微信会自动刷新页面,但session丢失 我在微信打开网页,网页调用微信分享接口,发现分享完后,页面自动刷新了一次,后台去取session做处理逻辑发现session丢失了! 问: 1.如何防止分享后自动刷新 2.有没有其他办法保存session,以至于session不丢失 解决方案 微信调用图片预览接口 解决方案二: 刷新后session是不应该丢失的.你仔细检查下你的处理逻辑,在哪里把他销毁了.

魅族手机调用微信分享接口无效,其他手机均正常

问题描述 魅族手机调用微信分享接口无效,其他手机均正常 有没人遇到魅族手机调用微信分享接口无效的情况,测试其他品牌的机器都是正常的,有没有什么解决办法? 解决方案 我用的是魅蓝,你用数据线连接到电脑试试,看下有输出日志没有...