• 首页
  • nodejs
  • node.js 调用 wechat 开发微信公众号自定义接口及中间件简介

node.js 调用 wechat 开发微信公众号自定义接口及中间件简介

上一次给公众号做自定义接口已经是很久以前的事了.....以至于今天发现那个公众号的接口已经不能服务了.

访问公众号直接给出提示"该公众号暂时无法提供服务,请稍后再试"

我想难道是年久失修? 也不应该啊,这么牛x的公司绝对不会修改api,或者是更新api不兼容之类的.....看来问题还是出在我这边.

我甚至忘记了公众号登录密码.

进去后复制接口链接地址到浏览器地址栏,发现是可以访问的,那么问题出在哪里?

难道腾讯知道我好久没有维护此号了.所以暂时不提供服务了,想想以前网易邮箱经常被冻结,我竟然真的以为是这样的了.


所以:我尝试前后到编辑模式,然后再切换回来,依然不提供服务...

我试图改了token ,尝试还是不行....


最后,我终于发现了那个 www ,没错,之前我的站点主域是 www.yijiebuyi.com ,后来我折腾几次,改成了现在的样子 yijiebuyi.com

而且对于www开头的域名做了一个301跳转.去掉www就好了,接口不能跳转的.


使用:

npm install wechat
var wechat = require('wechat');

wechat 是一个中间件

exports.wechat_method=wechat('你定义的token', function (req,res) {
    var message=req.weixin;
    if (message && message.MsgType == 'text') {
        var text = '';
        var description = '';
        switch (message.Content) {
            case '关键词1':
                res.reply({
                    content: 'hello world!',
                    type: 'text'
                });
                break;
            case '关键词2':
                text = '关键词2';
                description = message.ToUserName + '----' + message.FromUserName;
                res.reply([
                    {
                        title: text,
                        description: description,
                        picurl: '图片绝对地址',
                        url: '' }
                ]);
                break;
            default:    //默认回复文本消息
                res.reply({
                    content: '消息已收到',
                    type: 'text'
                });
                break;
        }
    } else if (message && message.Event) {
        switch (message.Event) {
            case 'subscribe':
                res.reply({
                    content: '关注事件',
                    type: 'text'
                });
                break;
            case 'unsubscribe':    //取消关注
                break;
            default:
                res.reply({
                    content: 'O(∩_∩)O~',
                    type: 'text'
                });
                break;
        }
    }
});

看到上面的方法,你应该发现 req,res 非常奇怪.

因为他不再是你认为的req和res了.


req有了 weixin 的属性.

res 有了 reply  的方法.


因为上面调用 wechat 中间件,然后对req,res 做了包装.


wechat包括下面几种不同的调用方法.

1.

wechat(token, function (req, res, next) {});

我们上面用的就是这一种,把req,res 传入,next 指向下一个中间件队列需要处理的中间件


2.

wechat(token, wechat.text(function (message, req, res, next) {
    // 这里处理文本类消息
  }).location(function (message, req, res, next) {
    // 这里处理地理位置消息 (就是分享一个地理位置)
  })//后面还可以链式处理其他类型的消息
);

3.

wechat(token)
   .text(function (message, req, res, next) {
     // 处理文本类消息
   }).location(function (message, req, res, next) {
    // 处理地理位置消息
   }).middleware();//后面依然可以链式调用

一共支持下面几种类型的消息处理:

* - `text`,处理文字推送的回调函数,接受参数为(text, req, res, next)。

 * - `image`,处理图片推送的回调函数,接受参数为(image, req, res, next)。

 * - `voice`,处理声音推送的回调函数,接受参数为(voice, req, res, next)。

 * - `video`,处理视频推送的回调函数,接受参数为(video, req, res, next)。

 * - `location`,处理位置推送的回调函数,接受参数为(location, req, res, next)。

 * - `link`,处理链接推送的回调函数,接受参数为(link, req, res, next)。

 * - `event`,处理事件推送的回调函数,接受参数为(event, req, res, next)。


顺便我们了解一下node.js 中的中间件:

最出名的中间件模块非 Connect 莫属了.其中 express 就是在此模块上构建起来的.

它内部维护了一个中间件队列,队列中的每一个中间件都有一个next指针,指向下一个中间件.每一个中间件就像U盘,可以插拔一样.


我们实现一个最简单的中间件:

function (req, res, next) {
  // 中间件
}

一个非常简单的中间件实现过程,处理完请求,执行 next() --> 指向中间件队列里的下一个请求


我们之前写的关于判断登录,图片防盗链,301跳转等,其实都是一个中间件的实现.


中间件处理流程大致分为3种:

1. pre-request 用来改写 request 的原始数据.

2. request /response 我们常常写的一些处理,过滤等操作,就是类似这样的中间件

3. post-response 全局处理,改写 response 数据等.

像上面介绍的微信处理中间件这3个过程都经历了,因为它不仅修改了request ,而且还修改了 response .


我们用express 创建web项目的时候,常见的 use() 就是一个典型的中间件使用环境.

var app = connect();
// Middleware
app.use(connect.staticCache());
app.use(connect.cookieParser());
app.use(connect.session());
app.use(connect.bodyParser());
app.use(connect.csrf());
app.use(function (req, res, next) {
  // 自己实现一个中间件
});
app.listen(3001);

上面这类中间件是匹配所有路由,其实中间件接受2个参数,第一个就是指定一个路由,如果指定,就会针对此路由下的请求做出过滤.如下:

app.use('/public', connect.static(__dirname + '/public'));
app.use("/upload", connect.multipart({ uploadDir: path }));

指定静态服务器走 /public 目录, 上传文件走 /upload 目录,那么这2个中间件就不会在所有路由上过滤.

回到顶部