搭建公众号自动回复功能

749 阅读6分钟

程序员爱炫技,写个公众号文章,都想拿点技术整整【自动回复】;程序员爱偷懒,什么都想做个【自动化】,最好所有事情系统都给做了,点点手指头就能达到目标。

今天的主角是如何搭建一个公众号自动回复功能。整个流程如下:

  1. 利用 hapi 开发 web 程序,对接微信公众号后台;

  2. 利用 LeanCloud SDK 将文章存储于 LeanCloud 后端;

  3. 接收用户发送的消息,获取关键词,查询文章,并回复给用户;

  4. 将 web 程序代码托管于 coding.net;

  5. 使用 LeanEngine 部署 hapi 程序。

1. hapi

A rich framework for building applications and services

hapi enables developers to focus on writing reusable application logic instead of spending time building infrastructure.

选择 hapi,主要被它的 logo 和读音(与 happy 同音)吸引,也主要因为自己爱折腾,老想着用不同的框架写写,重点是看看区别,你也可以看看 stackoverflow 上的帖子

https://stackoverflow.com/questions/30469767/how-do-express-and-hapi-compare-to-each-other

在用 hapi 写代码时,有种代码既文档的感觉,更重点的是 hapi 提供了一套 Plugins 方案,所有代码都可以以这种方式进行扩展和分离组织,可读性更高,如我将对接微信公众后台的 API 独立为 Plugin 形式:

server.register([{
  register: require('./api/Books'),
  options: {}
}, {
  register: require('./api/Articles'),
  options: {}
},{
  register: require('./api/Blogs'),
  options: {}
}, {
    register: require('./api/User'),
    options: {}
}, {
    register: require('./api/Comments'),
    options: {}
}], {routes: {prefix: '/api'}}, (err) => {
    if (err) {
        throw err;
    }
});

// wechat
server.register([{
  register: require('./wechat/weixin'),
  options: {}
}], (err) => {
    if (err) {
        throw err;
    }
});

这样就可以将微信公众号后台功能相关的代码独立到wechat/weixin.js中:

const wechat = require('./wechatserver');
const AV = require('leanengine');

const ModelBlog = require('../model/Blogs');
const config = {
  token: '***',
  appid: '***',
  encodingAESKey: '***'
};

exports.register = function (server, options, next) {
    server.route({
        method: ['POST', 'GET'],
        path: '/wechat',
        handler: function (request, reply) {
          wechat(config, request, reply, next, function (req, res, next) {
            // 微信输入信息都在req.weixin上
            var message = req.weixin;
            // 具体逻辑处理 和 自动回复
          });
        }
    });
    return next();
};

exports.register.attributes = {
    name: 'wechat-weixin'
};

具体如何配置开发 hapi 可以参考官网和 github
https://hapijs.com/
https://github.com/hapijs/hapi/

具体和微信后台路由配置就好说了,直接上图:

2. LeanCloud

LeanCloud 领先的 BaaS 提供商,为移动开发提供强有力的后端支持

包括云存储、数据分析、用户关系、消息推送、即时通信等现代应用基础模块,满足移动开发所有需求

https://leancloud.cn/

为什么选择 LeanCloud

  • 云存储。 主要方便自动回复,不需要存储大量数据,完全没必要购买一台【云服务器】或者【云数据库服务器】,而且 LeanCloud 提供 10 GB 免费空间,足够前期使用;

  • 数据。支持任意类型的 JSON 对象,以及对象之间的关联映射,同时提供完整的增删改查操作接口,方便开发;

  • 统计。提供开箱即用的移动统计,没准哪天粉丝数量增多了,也可以做一些统计分析,如分析分析哪个关键词是大家关注的,哪个话题是大家乐于传播分享的,等等。

  • 全平台 SDK 。搭建公众号后台功能,主要也是折腾折腾,这回用 Javascipt SDK 写写接口,没准哪天想换换口味,也可以重新试试用 PHP SDK 来重构复写。满足折腾需求。

JavaScript SDK

使用 SDK 主要三个作用:

  • 存储公众号文章基本信息,便于查询

根据微信公众号文档接口需要,主要存储 title, description, picurl, url 四要素;如果为了结合搜索功能,还需要存储这篇文章的关键词。

结合 LeanCloud SDK,存储代码就很简单了:

    var blog = new Blog();
    blog.set('title', request.payload.title);
    blog.set('url', request.payload.url);
    blog.set('desc', request.payload.desc);
    blog.set('picurl', request.payload.picurl);
    blog.set('tags', request.payload.tags);
    blog.save().then(function (blog) {
        // 成功保存之后,执行其他逻辑.
        console.log('成功保存:New object created with objectId: ' + blog.id);
        reply(blog);
    }, function (error) {
        // 失败之后执行其他逻辑
        console.log('Failed to create new object, with error message: ' + error.message);
        return reply(Boom.wrap(error, 'error'));
    });
  • 获取最新的一篇文章; 当一个新粉丝首次进入公众号,或者发了一些暂时没处理的信息时,可以直接回复最新的一篇文章:

    const query = new AV.Query(Blog);
    query.descending('createdAt');
    
    query.first().then(function (data) {
      res.reply([
          {
              title: data.get('title'),
              description: data.get('desc'),
              picurl: data.get('picurl'),
              url: data.get('url')
          }
      ]);
    }, function (error) {
    });
  • 通过【关键词】查询相关文章。

搜索【关键词】,主要搜索 title, description, tags等:

    const titleQuery = new AV.Query(Blog)
    titleQuery.contains('title', words);
    
    const descQuery = new AV.Query(Blog)
    descQuery.contains('desc', words);
    
    const tagsQuery = new AV.Query(Blog)
    tagsQuery.contains('tags', words);
    
    const wordsQuery = AV.Query.or(titleQuery, descQuery, tagsQuery);
    
    wordsQuery.descending('createdAt');
    wordsQuery.limit(5);
    wordsQuery.find().then(function (results) {
        res(results);
    }, function (error) {
        res([]);
    });

最后可以将查询结果转成【图文信息】回复

ModelBlog.search(message.Content, results => {
    if (results.length === 0) {
        res.reply({
            content: message.Content,
            type: 'text'
        });
    } else {
        let data = [];
        results.forEach(function(v) {
            let wrap = {};

            wrap.title = v.get('title');
            wrap.description = v.get('desc');
            wrap.picurl = v.get('picurl');
            wrap.url = v.get('url');

            data.push(wrap);
        });
        res.reply(data);
    }
});

当然,根据情况需要,如果在找不到查询结果时,我们可以内建一些【智能聊天】、【生活信息查询】等等。

3. LeanEngine

云引擎(LeanEngine)是 LeanCloud 推出的服务端托管平台。提供了多种运行环境(Node.js, Python 等)来运行服务端程序。你只需要提供服务端的业务逻辑(网站或云函数等),而服务端的多实例负载均衡,不中断服务的平滑升级等都由云引擎提供支持。

当写了服务端代码后,总要有个地方托管。对于大网站或者项目来说,找一家如阿里云、腾讯云等云服务平台, 但对于个人只是想简单的搭建一个公众号管理——自动回复功能,终究有些大材小用了;LeanEngine 结合 LeanCloud 使用相得映彰,而且 LeanEngine 可以根据需要升级扩展。

部署

部署主要有两种途径:命令行部署和 Git 部署

  • 命令行部署

只要在项目的根目录运行:

lean deploy

使用命令行工具可以方便的部署、发布应用,查看应用状态,查看日志,甚至进行多应用部署。具体可参考网站文档:
https://leancloud.cn/docs/leanengine_cli.html#使用

  • Git 部署

代码都有一个版本控制,为了配合 LeanEngine 使用,我将代码托管到 https://coding.net/ 进行源码的版本管理,只要在 LeanCloud 后台一键部署即可,具体可参考网站文档:

https://leancloud.cn/docs/leanengine_webhosting_guide-node.html#Git_部署

总结

写代码太无聊了,偶尔折腾折腾挺好,如何将不同的技术和工具,以及第三方服务结合在一起,做一些事情也挺好的。

  • LeanCloud 负责后台数据存储;

  • LeanEngine 负责服务端托管平台,来运行服务端程序;

  • hapi 负责服务端 web 程序开发;

  • coding.net 负责源码的版本控制管理;

下一步要做:

  1. 搭建一个录入微信文章的后台;

  2. 如何解析和加解密微信的消息体;


coding01 期待您关注