- 上一篇传送门——微信公众号服务器(1)
- 本次工程项目在 https://gitee.com/ayachensiyuan/wechat_server 代码仓库中更新
本篇的主题
- git代码仓库的创建和常用的操作
- 微信公众号申请
- 微信服务器连接验证
- 服务器收发消息
本篇就涉及到重头戏,就是文章的主题,如何把这个普通的服务器变成微信服务器。在此之前,先把git仓库给配置好。
git真的好用吗?
对于初学者来说,git代码仓库并不是一开始就需要涉及到的知识,但我建议如果小伙伴是初学的话,一定先要把这块给了解。这里的了解也就是你会简单配置能上传能下载仅此而已。我认为git对于初学者的意义是以下几点:
- 整理每天学习的知识点
- 任何地点随时继续写代码
- 任何时期的代码不丢失
- “同性”交流平台
不要局限性认为git平台是用来放代码的,其实你可以放任何的数字化资产,如写日记、博客、放照片、记事、音乐甚至视频等等。通常一提到git总会想到github全世界最大的“同性”交流平台。
当你体验了它时好时坏的“本地”网络环境后,和看到它最近“站边”的行为后,拥有本土的平台是多么美妙的体验。我推荐两个选择,一是使用gitlab把代码仓库放入自己的云端服务器,二是使用本土的gitee。出于交友,所以我用gitee。
配置git仓库
- 在你本地电脑上安装git总是第一步,这里自行查看文档 https://git-scm.com/book/zh/v2
- 其次是gitee平台注册,你的用户名和密码是远程连接的条件之一。https://gitee.com/
- 在gitee的“我的工作台”中点击“新建仓库”,同时记住仓库地址。(只需填写名字即可创建。)
-
仓库新建完成后会有如下的代码提示
-
打开本地的vscode,并输入密码连接到上一篇配置好的云服务器
-
首先修改.gitignore文件,这个文件是添加git忽略文件,通常库文件和个人敏感的配置信息就不应该放在仓库中,敏感信息尤其要注意。
node_modules
config.js
yarn.lock
.htaccess
token.txt
-
config.js未来会放入微信服务器信息和机密;yarn.lock和.htaccess文件是宝塔项目自建不用上传;token.txt用来保存未来微信api需用的access_token信息。目前暂时就这些,切记一定不要把敏感信息传上云仓。
-
在“源代码管理器”选项卡中选择“初始化储存库”,如此就在项目文件夹中初始化好了git。
-
在项目中打开命令行,连接远程仓库,输入之前的代码提示,选用已有仓库的代码,稍微修改下代码
git config --global user.name <yourName>
git config --global user.email <yourEmail>
git add .
git commit -m 'init'
git remote add origin <yourAddress>
git push -u origin master
git命令解释
- 查看文档是好习惯 https://git-scm.com/book/zh/v2
- git add . 此命令会把添加工程文件夹下所有文件加入代码的监控(忽略文件标注的除外)。如果需要指定某一个就直接把.换成某个文件名如:
git add file.js *.txt
- git commit -m 'commit' 此命令是确认刚才add的文件,-m是写下提交的原因
- git push origin master 把提交更改的文件推送到远程仓库中。
- git init 初始化工程目录git
- git pull < remoteGitRepository > 拉取远程代码仓库代码
- git remote add origin < yourAddress > 把本地仓库链接到远程仓库
- 如果你要把本地的代码上传就按步骤使用2-4。
- 如果你换了一台电脑或环境要把远程代码下载到本地就使用5-6来拉取。完成编写修改后先使用7来添加远程仓库,再按照2-4来上传。
- 切记养成每次结束工程后就提交代码。
微信公众号申请
微信公众平台 https://mp.weixin.qq.com/
按照提示来注册平台账号,选择什么样的平台可以参考我的上一篇文章。
- 注册的邮箱必须是没有在微信任何开发平台上注册过的,也就是一号一邮箱。
- 注册完成后进入“设置与开发”选项中的“开发者工具”,找到开发者文档,这里也给出它的链接可以记录下。
https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
- 微信的开发者文档说实在的,能看得懂那说明你已经不是初级开发水平了,很多的坑需要自己去探索。核心的api还是要借助文档的帮助然后就看你造化了。
自建服务器验证
接下来就到核心环节,如何去验证自建的微信服务器。根据微信提供的文档,以下网址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html
开发平台设置
-
在“设置与开发”选项中选择“基本配置”,首先生成“开发者密码(AppSecret)”,需要自行记住生成的密码,同时也记下“开发者ID(AppID)”
-
在“白名单”中添加你当前的ip地址,微信使用白名单策略,只有在白名单中的地址才能访问设置服务。添加云服务器的ip地址就行了。
-
如果需要使用本地环境测试的话推荐使用ngrok,https://ngrok.com/
ngrok的作用是内网穿透,把你本地的ip暴露在互联网上可供外部访问。这里的“白名单”就可以使用ngrok提供的本地ip,具体方法自行查看文档,其实基本上就是下载运行就能用的操作。因为我们直接使用vscode远程链接云服务器远程开发,这一步不是必要选择。
服务器代码
- 验证逻辑(明文模式)
微信服务器的验证,需要GET请求访问'/wx',微信验证端会发送4个字段,分别是signature, timestamp, nonce和echostr。
- token 是自己在公众号平台设置的,稍后有介绍。
- signature签名也是随机生成,验证就是和它比对。
- timestamp是微信发送的时间戳
- nonce是随机字符串
- echostr是返还给验证端的字符串,如果验证没问题就返还这个字段。验证需要自己设置
验证的方式是使用sha1加密,把token, timestamp, nonce按照字母顺序排序后拼接,然后加密。
在node中我们直接使用sha1的npm包来实现。我们写个验证函数代码如下:
npm install sha1
//verifyServer.js
module.exports = verifyServer = (query)=> {
const sha1 = require('sha1')
const {token, timestamp, nonce, signature} = query
return sha1([token, timestamp, nonce].sort().join('')) == signature? true: false
}
- 服务器设置
当处理GET ’/wx'时需要注意以下几点:
- 只有是验证服务器访问这个路由才响应,其余返回‘error’
- token保存在config.js配置文件中,不要直接保存在app.js中。同时不要忘记在.gitignore文件中添加config.js文件
- 返回代码只要返回echostr的字符串形式即可
//config.js
module.exports= {
token: 'yourToken'
}
//app.js
//...
//验证服务器
app.get('/wx', (req, res)=> {
const {token} = require('./config')
const data = req.query
//如果收到的数据没有echostr字段就直接返回error
if(!data.echostr) res.end('error!')
else {
//把token保存在data中传入验证函数
data.token = token
const status = verifyServer(data)
//验证正确才返回echostr
if (status) res.end(data.echostr)
else res.end('error')
}
})
//...
- 启动服务器
确保在宝塔面板的服务停止,在vscode中打开终端,直接在编辑器中运行代码测试。
这里也可以在本地下载全局安装nodemon包,好处就是每次代码更改后自动重启服务器,免去自己重启的繁琐。
npm install -g nodemon
安装完成后运行
nodemon app.js
- 公众号平台设置
进入“设置与开发”选项中选择“基本配置”,点击“启用”来配置服务器。在跳出的界面中设置:
- URL: http(s)://yourServerIP/wx
- token: 就是验证用的token,在这里设置,同时在config.js中不要忘了设置相同的。
- EncodingAESKey: 随机生成即可
- 开发使用明文模式
确保服务器是在vscode启动状态,然后就可以点击提交即可成功。
服务器收发用户消息
- 基本信息
收消息还是在'/wx'路径,但使用POST协议。文档链接: https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html - 数据简介
消息的数据形式是xml,就普通文字消息而言,字段解释如下:
- ToUserName: 接收方的APPID
- FromUserName: 发送方的APPID
- CreateTime: 创建时间
- MsgType: 消息类型
- Content: 消息内容
- MsgId: 消息id
- 消息接收
我们需要新建一个接收消息的代码叫getUserMessage.js。xml数据以流数据形式传输到服务器,我们需要监视‘end’事件来完成收消息的程序。由于js没有办法原生处理xml,所以需要转成字符串来接收。因为是异步的请求,这个函数封装成promise方便在外层后期处理。
//getUserMessage.js
module.exports = getUserMessage = (req)=>{
return new Promise((reslove, reject)=> {
let xmlData = ''
req.on('data', data => {
//console.log(data.toString())
xmlData += data.toString()
})
.on('end', ()=>{
reslove(xmlData)
})
})
}
- 消息解析
xml字符串在js里很麻烦提取信息,这里还需要借助npm的xml2js包来把数据转换成js对象,所以再新建一个parseMsg.js函数来解析数据。这里需要安装xml2js包
npm install xml2js
//parseMsg.js
const xml2js = require('xml2js')
const xmlParser = new xml2js.Parser()
module.exports = parseMsg = (xmlmsg)=>{
return new Promise((reslove,reject)=>{
xmlParser.parseString(xmlmsg,(err,res)=>{
const callbackData = {
ToUserName: res.xml.ToUserName[0],
FromUserName: res.xml.FromUserName[0],
MsgType: res.xml.MsgType[0],
CreateTime: res.xml.CreateTime[0],
Content: res.xml.Content[0],
MsgId: res.xml.MsgId[0]
}
reslove(callbackData)
})
})
}
- 数据转回xml
微信xml数据有固定的模式,所以我们可以提前预备好这个模板,替换关键的数据来做到。
module.exports= sendMsg = (to, from, msg)=>{
//xml模板
const xmlSendData = `<xml><ToUserName><![CDATA[${to}]]></ToUserName><FromUserName><![CDATA[${from}]]></FromUserName><CreateTime>${Date.now()}</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[${msg}]]></Content></xml>`
return xmlSendData
}
- 主函数处理和发送消息
使用async函数来获取异步数据,同时这里做一个小任务就是把收到的消息翻转发回给用户。
//app.js
//...
//接受消息并做出反应
app.post('/wx', async(req,res) => {
//第一步收消息
const xmlMsg = await require('./getUserMessage')(req)
//第二步解析消息
const jsonData = await require('./paresMsg')(xmlMsg)
//做出反应,以下是倒转文字返回例子,交换发送和接收方
const xmlSendData = require('./sendMsg')(jsonData.FromUserName,jsonData.ToUserName,jsonData.Content.split('').reverse().join(''))
//返回处理好的数据
res.send(xmlSendData)
})
//...
- 测试效果
结语
本次教程使用了最简单的代码实现服务器的验证和收发消息,至此就可以使用自己的服务器来处理所有的公众号工作。之后可以在消息的层面上操作的譬如:
- 保存、查询用户聊天记录
- 新建会话层面,可以持续性智能聊天
- 用户使用对应文字输入来激发特定的api
- 操作服务器
- 查看新闻、天气等
- 获取公众号最新文章
- 闹钟提醒等等
这里需要注意的是,如果启用了自己的服务器,原先微信服务器设置的菜单等功能立即失效,需要在之后你的服务器中自行配置。所以谨慎上线。
下一篇: 微信公众号 | API连接篇