程序猿阵线联盟-汇总各类技术干货

Node开发微信公众号(3)——微信菜单

2018-05-05  本文已影响42人  Mr绍君

开始之前照例说一下实现思路。

要实现微信菜单,我们需要向微信服务器发送一个post请求,并把我们的菜单配置发送给微信服务器。


从上图的请求地址我们可以看到,我们可以分为两步来实现,第一步获得access_token这个参数,第二步发送post请求创建菜单。


1.获取access_token

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。所以说这个access_token是很重要的,而且这个票据只能保存2个小时,2个小时后就失效了,需要重新获取。

我们先将请求地址配置到config上,因为微信上的请求接口他们的前缀都是一样的,所以我们可以把前缀提取出来。

{
    "appID": "wxd27649727105b6d2",
    "appsecret": "a3f2eb9f5819b0bf4b2a92a81f99baf4",
    "token": "wechat",
    "prefix": "https://api.weixin.qq.com/",
    "diyApi": {
        "getAccessToken": "%scgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
        "createMenu": "%scgi-bin/menu/create?access_token=%s"
    }
}

代码中的%s是一个占位符,用于后面字符替换。然后我们给WeChat加个get请求方法和post请求方法,因为后面会经常用到。

// 获取全局票据
WeChat.prototype.getAccessToken =function() {
    var that = this;
    return new Promise(function(resolve,reject){
        var currentTime = new Date().getTime();
        //格式化请求地址,把刚才的%s按顺序替换
        var url = util.format(that.diyApi.getAccessToken, that.prefix, that.appID, that.appScrect);      
        //判断本地存储的 access_token 是否有效
        if(accessTokenJson.access_token === "" || accessTokenJson.expires_time < currentTime){
            that.requestGet(url).then(function(data){
                var result = JSON.parse(data); 
                if(data.indexOf("errcode") < 0){
                    accessTokenJson.access_token = result.access_token;
                    accessTokenJson.expires_time = new Date().getTime() + (parseInt(result.expires_in) - 200) * 1000;
                    //更新本地存储的
                    fs.writeFile('./wechat/access_token.json',JSON.stringify(accessTokenJson));
                    resolve(accessTokenJson.access_token);
                }else{
                    resolve(result);
                } 
            });
        }else{
            //将本地存储的 access_token 返回
            resolve(accessTokenJson.access_token);  
        }
    }); 
}

// 封装一个get请求方法
WeChat.prototype.requestGet = function(url) {
    return new Promise (function(resolve, reject) {
        request(url, (error, response, body)=> {
            resolve(body);
        })
    })
}

node原生的请求需要些一些请求头之类的东西,所以这里用了一个新的模块,叫做request。用法也很比较简单,直接上npm上看下一就行。这里的票据是存在本地的access_token.json文件中,当然也可以存数据库,这个看个人需求。

还有一个需要说明的是ES6的Promise用法,简单的说明一下:js的程序执行是单线程的,所以遇到O/I操作会发生阻塞,所以node使用了大量的回调函数。但是回调函数不是特别直观,所以es6提供了Promise用法,也是一种异步调用。

想要深入了解,可以看一下阮一峰的ECMAScript 6 入门,这是一本免费的电子书http://es6.ruanyifeng.com/#docs/intro

2.创建菜单

微信开发文档提供了几种类型,我们照着写就行。


{
    "button":[
       {    
         "type":"view",
         "name":"个人博客",
          "url":"http://xiaoxiagroup.top"
       },
       {    
         "type":"click",
         "name":"听歌",
         "key":"music"
       },
       {    
         "name":"小工具",
         "sub_button":[{
              "type": "scancode_waitmsg", 
              "name": "扫一扫",
              "key": "scancode"
         },{
              "type": "pic_sysphoto", 
              "name": "系统拍照发图",
               "key": "take_photo"
         },{
           "type": "location_select", 
           "name": "发送位置",
           "key": "send_location"
       }]
       }
    ]
}

封装一个post请求方法。

// 封装一个post请求方法
WeChat.prototype.requestPost = function(url, data) {
    return new Promise (function(resolve, reject) {
        request.post({url: url, form:data}, function(err,httpResponse,body){
            resolve(body);
        })
    })
}

至此,微信菜单也完成了。


源码地址:https://github.com/yeshaojun/wechatBase
如果喜欢就给我点个小星星吧!

上一篇 下一篇

猜你喜欢

热点阅读