微信公众号-先撸一个自动回复

1,537 阅读3分钟

上篇把nodejs代码全部写在了app.js里面,现在把代码封装一下。

--------开始:抽离加密验证中间件-------------

第一步:在wechat目录下建立wechat/g.js,作为一个中间件

第二步:在g.js文件中写验证加密中间件

var sha1 = require('sha1')

module.exports = function(opts){
    return async (ctx) =>{
        console.log('aa',ctx.query)
        var token =opts.token;
        var signature = ctx.request.query.signature;
        var nonce = ctx.request.query.nonce;
        var timestamp = ctx.request.query.timestamp;
        var echostr = ctx.request.query.echostr;
        var str = [token,timestamp,nonce].sort().join('')
        var sha = sha1(str)
        console.log('sha',sha)
        console.log('signature',signature)
        if(sha === signature){
            ctx.body = echostr + '';
        }else{
            ctx.body = 'err'
        }
    }
}

第三步:在app.js中引入中间件g.js

    /*
 * @Description: In User Settings Edit
 * @Author: your name
 * @Date: 2019-08-24 16:30:18
 * @LastEditTime: 2019-08-24 18:41:12
 * @LastEditors: Please set LastEditors
 */
var Koa = require('koa')

var wechat = require('./wechat/g')

var config = {
    wechat:{
        appID:'你的appid',
        appSecret:'你的appsecret',
        token:'你的token'
    }
}

var app  = new Koa()
app.use(wechat(config.wechat))

app.listen(1234)
console.log('listen 1234')

-------结束:以上抽离了加密验证中间件------------

-------开始:access_token------------

access_token

  • 每2个小时自动失效,需要重新获取。让系统每个2个小时启动去刷新,保持始终最新。
  • 新建config和libs目录,此时结构是这样

  • wechat/g.js
    /*
     * @Description: In User Settings Edit
     * @Author: your name
     * @Date: 2019-08-24 18:37:34
     * @LastEditTime: 2019-08-26 10:14:16
     * @LastEditors: Please set LastEditors
     */
    var sha1 = require('sha1')
    var Promise = require('bluebird')
    var request = Promise.promisify(require('request'))
    var prefix = 'https://api.weixin.qq.com/cgi-bin/'
    var api = {
        accessToken:prefix+'token?grant_type=client_credential'
    }
    
    function Wechat(opts){
        var that = this;
        this.appID = opts.appID;
        this.appSecret = opts.appSecret;
        this.getAccessToken = opts.getAccessToken;
        this.saveAccessToken = opts.saveAccessToken;
    
    
        this.getAccessToken()
        .then(function(data){
            try{
                data = JSON.parse(data)
            }catch(e){
                return that.updateAccessToken()
            }
    
            if(that.isValidAccessToken(data)){
                Promise.resolve(data)
            }else{
                return that.updateAccessToken()
            }
        })
        .then(function(data){
            console.log('data',data)
            that.access_token = data.access_token;
            that.expires_in = data.expires_in;
    
            that.saveAccessToken(data)
        })
    }
    
    Wechat.prototype.isValidAccessToken = function(data){
        if(!data || !data.access_token || !data.expires_in){
            return false;
        }
    
        var access_token = data.access_token;
        var expires_in = data.expires_in;
        var now = (new Date().getTime())
        if(now<expires_in){
            return true;
        }else{
            return false;
        }
    }
    Wechat.prototype.updateAccessToken = function(){
        var appID = this.appID;
        var appSecret = this.appSecret;
    
        var url = api.accessToken + '&appid=' + appID + '&secret=' + appSecret
    
        return new Promise(function(resolve,reject){
            request({url:url,json:true}).then(function(response){
                var data = response.body
                var now = (new Date().getTime())
                var expires_in = now + (data.expires_in - 20) * 1000
        
                data.expires_in = expires_in
        
                resolve(data)
            })
    
        })
    
        
    }
    module.exports = function(opts){
        var wechat = new Wechat(opts)
        
        return async (ctx) =>{
            console.log('aa',ctx.query)
            var token =opts.token;
            var signature = ctx.request.query.signature;
            var nonce = ctx.request.query.nonce;
            var timestamp = ctx.request.query.timestamp;
            var echostr = ctx.request.query.echostr;
            var str = [token,timestamp,nonce].sort().join('')
            var sha = sha1(str)
            console.log('sha',sha)
            console.log('signature',signature)
            if(sha === signature){
                ctx.body = echostr + '';
            }else{
                ctx.body = 'err'
            }
        }
    }
  • app.js
    /*
     * @Description: In User Settings Edit
     * @Author: your name
     * @Date: 2019-08-24 16:30:18
     * @LastEditTime: 2019-08-26 10:11:55
     * @LastEditors: Please set LastEditors
     */
    var Koa = require('koa')
    var path = require('path')
    var wechat = require('./wechat/g')
    var util = require('./libs/util')
    var wechat_file = path.join(__dirname,'./config/wechat.txt')
    var config = {
        wechat:{
            appID:'你的appid',
            appSecret:'你的appsecret',
            token:'你的token',
            getAccessToken:function(){
                return util.readFileAsync(wechat_file)
            },
            saveAccessToken:function(data){
                data = JSON.stringify(data)
                return util.writeFileAsync(wechat_file,data)
            }
            
        }
    }
    
    var app  = new Koa()
    app.use(wechat(config.wechat))
    
    app.listen(1234)
    console.log('listen 1234')
  • libs/util.js
    /*
     * @Description: In User Settings Edit
     * @Author: your name
     * @Date: 2019-08-26 09:33:56
     * @LastEditTime: 2019-08-26 10:15:19
     * @LastEditors: Please set LastEditors
     */
    var fs = require('fs')
    var Promise = require('bluebird')
    
    
    exports.readFileAsync = function(fpath,encoding){
        return new Promise(function(resolve,reject){
            fs.readFile(fpath,encoding,function(err,content){
                if(err){
                    reject(err)
                }else{
                    resolve(content)
                }
            })
        })
    }
    
    exports.writeFileAsync = function(fpath,content){
        return new Promise(function(resolve,reject){
            fs.writeFile(fpath,content,function(err){
                if(err){
                    reject(err)
                }else{
                    resolve()
                }
            })
        })
    }

-------结束:access_token------------

-------开始:自动回复------------

五个步骤

  • 1.处理POST类型的控制逻辑,接受这个XML的数据包
  • 2.解析这个数据包(获得数据包的消息类型或者是事件类型)
  • 3.拼装我们定义好的消息
  • 4.包装成xml的格式
  • 5.在5s内返回回去

自动回复代码放到了 github