获取token
请求官方API的地址将获取到的数据存到数据库,除此之外还有很多与微信服务器之间的交互场景,最好是把token和其他异步请求封装到一个文件里,就可以把这个文件统一看做微信请求的构造函数,一切与微信交互的功能都放到这个文件里,把它当做一个入口。
新建server/wechat-lib/index.js作为整个微信异步场景的入口文件,统一管理微信API地址。
server/wechat-lib/index.js
|
|
定义api地址,request方法,所有的异步函数都通过它统一管理,获取access_token,更新access_token。
新建server/wechat/index.js对微信异步场景函数做初始化。传递配置参数及方法,生成wechat实例。
server/wechat/index.js
|
|
在server/middlewares/router.js引入
|
|
引入这个文件就会去通过执行getWechat()
创建Wechat实例new Wechat(wechatConfig.wechat)
,然后调用fetchAccessToken()
方法获取access_token。在控制台成功打印出access_token,如图:
保存access_token
获取access_token后判断access_token是否过期,后期的话重启获取一次,再次保存access_token,修改代码:
server/wechat-lib/index.js
|
|
server/wechat/index.js
|
|
server/database/schema/token.js
|
|
等数据库连接成功之后再做微信初始化,require('../wechat')
的时间应该是整个项目跑起来对外提供服务的时候
server/middlewares/router.js
|
|
保存新增access_token成功,如图:
微信消息中间件
通过access_token和消息中间件结合就可以给用户回复了。无论http是get或post请求都要对query里的参数进行排序加密比对,比对正确的话进行数据分析。这里直接改成router.all()
,无论是get、post还是delete都可以拿到请求。写个中间件wechatMiddle(opts, reply)
- opts:配置参数。描述了微信公众号对access_token的外部获取方式
- reply:回复策略。
server/middlewares/router.js
|
|
消息中间件函数,server/wechat-lib/middleware.js
|
|
因为前面用的是router.all
所以在使用时要对请求方法做个判断,方法匹配成功后先拿到请求过来的数据,然后把它解析成xml util.parseXML(data)
,再对它转换成json或者对象格式util.formatMessage(content,xml)
,这样就能拿到对应的key和value。解析后的数据挂到context.weixin
上,在后面的代码单元就能访问到context.weixin
,转义上下文reply.apply(ctx, [ctx, next])
。在router.js引入middleware.js
server/middlewares/router.js
|
|
回复策略server/wechat/reply.js
|
|
重启项目,微信扫公众测试号二维码
扫码之后在会出现与测试号的对话窗口,随便打个字会看到自动回复内容,如图:
同时我也在控制台打印出回复内容,如图:
问题
如果键入内容没有自动回复消息而是出现“该公众号提供的服务出现故障请稍后再试”这样的提示,可能是你的接口配置url无法启用,就需要你再次修改url。我之前用Sunny-Ngrok配置的url但是突然不能用了,于是就是换了ngrok,可以从这里下载客户端,解压即可。
在命令(cmd)行下进入到ngrok客户端目录下,执行 ngrok -config=ngrok.cfg -subdomain xxx 80 (xxx 是你自定义的域名前缀),建议批处理
如果连接成功,会提示如下信息:
微信消息解析
把xml格式的数据转成Object。先判断如果数据是object的话进行遍历,得到一个key对应的一条数据item,接着遍历某一条数据的key。判断item是否是数组或者item的长度为0,继续执行,如果item的长度为1,取出值判断如果类型是object进行深层的遍历。
server/wechat-lib/util.js
|
|
将xml格式的数据转化为Object,挂在ctx.weixin,再将回复内容解析出来,得到解析后的微信消息,修改middleware.js
|
|
通过套模板渲染出xml的数据。
封装回复消息模板
回复用户消息类型包括回复文本消息、回复图片消息、回复语音消息、回复视频消息、回复音乐消息、回复图文消息,这里使用ejs模板。
server/wechat-lib/tpi.js
|
|
把所有的消息类型放到一个模板中,根据msgType的值匹配相应的模板。
重启服务,在手机上发送消息1,控制台打印消息的类型、内容以及消息id,如图:
七种微信普通消息的接收
先对消息类型进行筛选。修改reply.js
|
|
微信对测试号发送消息回复成功,如图:
关注/取消关注事件
关注和取消关注事件是根据MsgType区分的,但event不一样,修改server/wechat/reply.js
|
|
多媒体与图文素材处理
项目中可能会用到图片上传图片处理,所以要把图像素材管理的相关接口获取到。
上传素材
增加素材系列相关的请求地址,修改server/wechat-lib/index.js
|
|
上传参数:token,类型type,素材路径material,标识永久素材还是临时素材permanent。上传素材其实就是构建表单,声明对象form,拿到上传地址url,默认是临时素材地址api.temporary.upload
。如果指定是永久素材就改成永久素材地址api.permanent.upload
,通过loadsh继承permanent数据,如果类型是pic修改成上传图片的地址api.permanent.uploadNewsPic
,如果类型是news修改成上传图文地址api.permanent.uploadNews
,,同时form修改成material。;反之,如果不是图文类型素材的话可能是图片或者视频,这时就需要构建表单了。通过formsteam()
生成表单对象,声明statFile()函数读取文件大小,拿到图片的大小通过form.file()
增加字段media。如果不是永久类型, uploadUrl后面追加type,反之,把access_token加到表单里。
|
|
构建上传需要的对象,如果type是图文类型news的话,设置options.body为当前form,否则上传图片的表单域,最后返回options。也就是说uploadMaterial()
不会真正上传,只是配置好它要上传的参数。
封装上传动作:传进operation和参数args,拿到token和哪种类型的options,通过request()
获取数据。
|
|
测试上传视频临时素材,修改router.js
|
|
测试上传视频永久素材,修改router.js
|
|
测试上传图片永久素材,修改router.js
|
|
测试上传图片临时素材,修改router.js
|
|
每次修改router.js后重启项目,输入localhost:8080,看到控制台打印信息,如图:
图文创建
图文素材必须是永久素材
|
|
获取永久素材
获取素材要区分是临时素材还是永久素材
|
|
删除永久素材
|
|
修改永久图文素材
|
|
获取素材总数
|
|
获取素材列表
|
|