nodejs+express对微信公众号进行二次开发--接收消息,自动回复文本,图片以及代码优化

上篇说到微信开发配置,接下来着手开发,我们先来看看文本消息的接收与自动回复:
接收普通消息–当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上,当服务器接收到消息,服务器如果没有做出回应,会断开连接并重新发起请求,重复三次操作,若还未作出回应便回复xxx直接看图:
在这里插入图片描述
实现思路,通过构建构造函数,将实例方法绑定在原型对象上,然后将方法导出,微信返回和接收的数据格式都是xml,所以我们要对xml进行转换。所以在今天我们会引入几个新的模块。代码如下(wechat.js):

var sha1 = require("sha1");
var parseString = require('xml2js').parseString;
var msg = require("../common/msg");
var request = require("request");
var path = require("path");
var fs = require("fs");
var util = require("util");
var accessTokenJson = require("../config/access_token.json");
function Wechat(config) {
  this.config = config;
  this.token = config.wechat.token;
  this.appID = config.wechat.appID;
  this.appScrect = config.wechat.appSecret;
  this.prefix = config.wechat.prefix;
  this.diyApi = config.wechat.diyApi;
}
Wechat.prototype.autoMsg = function (req, res, next) {
  var buffer = [];
  var that = this;
  req.on('data', function (data) {
    buffer.push(data);
  });
  req.on('end', function () {
    var msgXml = Buffer.concat(buffer).toString('utf-8');
    parseString(msgXml, { explicitArray: false }, function (err, result) {
      if (err) throw err;
      result = result.xml;
      // console.log(result);
      var toUser = result.ToUserName;
      var fromUser = result.FromUserName;
      //回复普通消息
      if (result.MsgType === "text") {
        res.send(msg.textMsg(toUser, fromUser, msg.message(result.Content)));
      } else if (result.MsgType === "image") {//回复图片
      //在这里图片相当于素材,用户发送的素材只是临时素材,只能在微信服务器保存三天,回复思路:
        //先上传素材---先封装一个post请求,然后通过素材接口获取media_id来获取素材
        //上传素材就需要封装post get以及素材上传的api
        //注意在上传素材时需要access_token所以也需要封装获取access_token的api
        var urlPath = path.join(__dirname, "../material/timg.jpg");
        that.uploadFile(urlPath, "image").then(function (mdeia_id) {
          resultXml = msg.imgMsg(fromUser, toUser, mdeia_id);
          res.send(resultXml);
        })
      }
    })
  })
};
//获取access_token
//为什么要保存access_token,原因请查看文档
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);
        // console.log(result);
        if (data.indexOf("errcode") < 0) {
          accessTokenJson.access_token = result.access_token;
          accessTokenJson.expires_time = new Date().getTime() + (parseInt(result.expires_in) - 200) * 1000;
          // console.log(accessTokenJson);
          //更新本地存储的
          fs.writeFile('./../config/access_token.json', JSON.stringify(accessTokenJson),function(err){
             if(err){
              throw err;
            }else{
              console.log("access_token失效,重新写入成功!");
            }
          });
          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);
    })
  })
}
//封装一个post方法
Wechat.prototype.requestPost = function (url, data) {
  return new Promise(function (resolve, reject) {
    request.post({ url: url, formData: data }, function (err, httpResponse, body) {
      resolve(body);
    });
  });
}


//上传素材
Wechat.prototype.uploadFile = function (urlPath, type) {
  var that = this;
  return new Promise(function (resolve, reject) {
    that.getAccessToken().then(function (data) {
      //data=== access_token
      var form = { //构造表单
        media: fs.createReadStream(urlPath)
      }
      var url = util.format(that.diyApi.uploadFile, that.prefix, data, type);
      that.requestPost(url, form).then(function (result) {
        resolve(JSON.parse(result).media_id);
      })
    })
  })
}

代码优化部分:msg.js
将文字回复和图片恢复的api都抽出来放于一个新的js文件,代码如下:

//回复文字消息
exports.textMsg = function (toUser, fromUser, content) {
    var resultXml = "<xml><ToUserName><![CDATA[" + fromUser + "]]></ToUserName>";
    resultXml += "<FromUserName><![CDATA[" + toUser + "]]></FromUserName>";
    resultXml += "<CreateTime>" + new Date().getTime() + "</CreateTime>";
    resultXml += "<MsgType><![CDATA[text]]></MsgType>";
    resultXml += "<Content><![CDATA[" + content + "]]></Content></xml>";
    return resultXml;
}
//设置自动回复内容
exports.message = function (data) {
    console.log(data)
    var content;
    if (data === "你好" || data === "hello" || data === "hi") {
        content = "欢迎光临小许客栈!"
    } else {
        content = "公众号还在升级,敬请期待!";
    }
    return content;
}
//回复图片消息
exports.imgMsg = function(toUser, fromUser, media_id) {
    var xmlContent = "<xml><ToUserName><![CDATA["+ toUser +"]]></ToUserName>";
        xmlContent += "<FromUserName><![CDATA["+ fromUser +"]]></FromUserName>";
        xmlContent += "<CreateTime>"+ new Date().getTime() +"</CreateTime>";
        xmlContent += "<MsgType><![CDATA[image]]></MsgType>";
        xmlContent += "<Image><MediaId><![CDATA["+ media_id +"]]></MediaId></Image></xml>";
    return xmlContent; 
}

app.js

var Wechat = require('./routes/wechat');
var wechat = new Wechat(config); //实例化一个WeChat对象
app.get('/', (req,res,next)=>{
  wechat.auth(req,res,next);
});
app.post("/",(req,res,next)=>{
  wechat.autoMsg(req,res,next);
});

注意看代码注释,比较重要!!!
接下来看下效果:
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值