美文网首页nodejs进行微信公众号全栈开发
5、获取jssdk,进行微信内置网页开发

5、获取jssdk,进行微信内置网页开发

作者: 伯纳乌的追风少年 | 来源:发表于2017-10-17 18:07 被阅读0次

    正常情况下,js是不可以直接操作原生App的,但微信作为一款原生App,它提供了一套接口,允许前端工程师通过js来调用原生App的一些功能,我们只需要按照约定好的方式使用js调用的话,就可以使用微信原生的一些功能,如:拍照、相册、语音、分享、地理位置、扫一扫等功能。
    但是在使用jssdk之前,还需要按照JS-SDK使用权限签名算法进行校验,只有校验通过,才可以使用jssdk提供的接口。

    一、JS-SDK后台接口的开发

    在开发JS-SDK接口之前,我们先要在后台配置一个JS接口安全域名:



    测试号的话,在此配置。



    注意,这里是域名,而不是url地址,如果带了“http://”的话,就会配置不成功。

    配置好JS安全域名后,我们便可以进行JS-SDK接口的开发了。
    js-sdk的接口需要返回以下数据:

    {
      appId:appId,
      noncestr:noncestr,
      timestamp:timestamp,
      signature:signature
    }
    

    其中appId是我们已经在可以在后台知道的,而其他三个参数需要我们根据已有的信息进行生成。
    首先, 创建noncestr参数:

    function createNonceStr(){
      const chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
      const length=chars.length;
      let str='';
      for (let i = 0; i < length; i++) {
        str += chars.substr(Math.round(Math.random()*length),1)
      };
      return str;
    }
    

    然后创建timestamp

    const timestamp = Math.round(Date.now() / 1000)
    

    还剩一个参数就是 signature了。
    这个 signature获得起来比较复杂了,要想获得signature的话,先要获得jsapi_ticket、noncestr、timestamp、url。
    noncestr、timestamp这两个参数我们可以自己生成,url在前端调用的时候会传进来,而jsapi_ticket则需要我们调用接口生成。
    调用jsapi_ticket的接口地址为:https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=${accessToken}
    jsapi_ticket接口和accessToken接口一样,都有2000次的调用限制,因此也需要和accessToken一样做7200秒的缓存。
    而jsapi_ticket的接口调用还需要传入accessToken作为参数,所以还需要调用获取accessToken的接口。
    所以我们的流程是:
    1、获取accessToken
    2、获取jsapi_ticket
    3、获取noncestr、timestamp、url
    4、生成signature
    5、返回js-sdk接口数据
    我们把这些封装成一个jssdk对象:

    var crypto = require('crypto');
    var request= require('request');
    var fs = require('fs');
    
    function JSSDK(appId,appSecret){
        this.appId=appId;
        this.appSecret=appSecret;
    }
    
    JSSDK.prototype={
        getSignPackage:function(url,done){
            const instance=this
            this.getJsApiTicket(function(err,jsApiTicket){
                if(err){
                    return done(err)
                }
    
                const timestamp = Math.round(Date.now() / 1000)
                const noncestr = instance.createNonceStr()
                const rawString = `jsapi_ticket=${jsApiTicket}&noncestr=${noncestr}&timestamp=${timestamp}&url=${url}`
                const hash = crypto.createHash('sha1');
                const signature = hash.update(rawString).digest('hex');
    
                done(null,{
                    appId:instance.appId,
                    noncestr:noncestr,
                    timestamp:timestamp,
                    url:url,
                    signature:signature
                })
            })
        },
        getJsApiTicket:function(done){
            const cacheFile='.jsApiTicket.json'
            const data=this.readCacheFile(cacheFile);
            const time=Math.round(Date.now() / 1000);
            const instance =this;
            if(typeof data.expireTime === 'undefined' || data.expireTime < time){
                instance.getAccessToken(function(error,accessToken){
                    if(error){
                        return done(error,null)
                    }
                    const url=`https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=${accessToken}`
                    request.get(url,function(err,res,body){
                        if (err) {
                            return done(err,null)
                        };
    
                        try {
                            const data =JSON.parse(body);
                            instance.writeCacheFile(cacheFile,{
                                expireTime: Math.round(Date.now() / 1000) +7200,
                                jsApiTicket: data.ticket
                            })
    
                            done(null,data.ticket)
                        }catch(e){
                            done(e,null)
                        }
    
                    })
                })
            }else{
                done(null,data.jsApiTicket)
            }
    
        },
        createNonceStr:function(){
            // return Math.random().toString(36).substr(2, 15);
            const chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            const length=chars.length;
            let str='';
            for (let i = 0; i < length; i++) {
                str += chars.substr(Math.round(Math.random()*length),1)
            };
            return str;
        },
        getAccessToken:function(done){
            const cacheFile = '.accesstoken.json';
        const instance = this;
        const data = instance.readCacheFile(cacheFile);
        const time = Math.round(Date.now() / 1000);
    
        if (typeof data.expireTime === 'undefined' || data.expireTime < time) {
            const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`;
            request.get(url, function (err, res, body) {
                if (err) {
                    return done(err, null);
                }
                try {
                    const data = JSON.parse(body);
                    instance.writeCacheFile(cacheFile, {
                        expireTime: Math.round(Date.now() / 1000) + 7200,
                        accessToken: data.access_token,
                    });
    
                    done(null, data.access_token);
                } catch (e) {
                    done(e, null);
                }
            });
        } else {
            done(null, data.accessToken);
        }
        },
        readCacheFile:function(filename){
            try {
                return JSON.parse(fs.readFileSync(filename));
            } catch (e){
                console.log("read file %s failed: %s",filename,e)
            }
            return {}
        },
        writeCacheFile:function(filename,data){
            return fs.writeFileSync(filename,JSON.stringify(data));
        },
    }
    
    const jssdk=new JSSDK('wxeee44dbd49e6139a','daad8a1466f76f6c6e98601d6179ec3b')
    
    
    module.exports=jssdk
    
    

    其中readCacheFile和writeCacheFile是读取和写入缓存文件时封装的方法。
    我们在调用js-jdk接口的时候,需要引入这个模块:

    var express = require('express');
    var router = express.Router();
    const jsSdk = require('../libs/jssdk')
    router.get('/getJsSdk', function (req, res) {
        jsSdk.getSignPackage(req.query.url,function(err,signPackage){
            res.send(signPackage)
        })
    });
    



    二、调用JS-SDK接口的前端开发

    后台将js-sdk接口开发完成后,将会提供给前端一个接口的地址,前端可以传入相应的参数进行调用,调用后用拿到的数据进行验证。
    1、引入script标签:<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    2、调用开发好的sdk接口,需要传入url作为参数,这个url是需要先截取“#”前面的部分才行
    3、拿到数据后,进行wx.config进行配置:

    wx.config({
                        debug: false,
                        appId: data.appId, 
                        timestamp: data.timestamp,
                        nonceStr: data.noncestr,
                        signature: data.signature,
                        jsApiList: ['showMenuItems','onMenuShareTimeline',   'onMenuShareAppMessage','onMenuShareQQ'] //功能列表,我们要使用JS-SDK的什么功能
    });
    

    4、配置成功,则我们可以拿到jsApiList中列出的所有js-sdk原生功能调用权限

    具体代码如下:
    我们新建一个文件index.html
    文件内容为:

    <html>
    <head>
        <title>js-sdk</title>
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    </head>
    <body>
    <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    <script type="text/javascript">
        ;(function($){
            $.ajax({
                type:'get',
                url:"http://wxnode.xiaoxiekeke.com/verify/getJsSdk",
          data: {
            url: '' + window.location.href.split('#')[0]
          },
                contentType: "application/json",
                success:function(data){
                    wx.config({
                        debug: false,
                        appId: data.appId, 
                        timestamp: data.timestamp,
                        nonceStr: data.noncestr,
                        signature: data.signature,
                        jsApiList: ['showMenuItems','onMenuShareTimeline', 'onMenuShareAppMessage','onMenuShareQQ'] //功能列表,我们要使用JS-SDK的什么功能
                    });
                    wx.ready(function() {
                        wx.showMenuItems({
                          menuList: ['menuItem:share:appMessage' , 'menuItem:share:timeline' ,'menuItem:share:qq'] // 要显示的菜单项,所有menu项见附录3
                      });
                    })
                },
                error:function(err){
            console.log(err);
          }
            })
        })(jQuery);
    </script>
    </body>
    
    </html>
    

    如何查看是否成功?我们可以使用微信开发者工具进行调试,打开微信开发者工具,输入index.html页面所在所在的地址:



    当我们看到:“config:ok”的时候证明配置验证成功了,此时,我们前端工程师便可以在网页中通过jssdk的文档进行公共号内嵌网页的开发了。

    另附上:jssdk说明文档

    相关文章

      网友评论

        本文标题:5、获取jssdk,进行微信内置网页开发

        本文链接:https://www.haomeiwen.com/subject/pulluxtx.html