這幾天心血來潮怠肋,想玩下微信公眾平臺洁奈,看看它是如何對接到個人服務器的伍茄。這里簡單記錄下栋盹。
環(huán)境:
node v7.7.1
koa v2.0.1
流程
1.在微信公眾平臺的 開發(fā) -> 基本配置 那填寫服務器信息;
2.點擊啟用后敷矫,微信會發(fā) Get 請求到填寫的服務器例获,檢查服務器是否有效;
3.服務器驗證通過后曹仗,公眾號每次接收到新消息榨汤,都會發(fā) POST 請求到服務器,然后我們就可以在服務器里進行各種處理怎茫。
驗證服務器
微信開發(fā)文檔里有寫驗證的規(guī)則(這不是廢話么):
verify.png
上面的文字已經(jīng)寫的很直白了收壕,不多說,代碼實現(xiàn)如下:
// 驗證消息來自微信服務器
const crypto = require('crypto')
module.exports = (ctx) => {
const token = 'xxxx', // 自定義轨蛤,與公眾號設置的一致
signature = ctx.query.signature,
timestamp = ctx.query.timestamp,
nonce = ctx.query.nonce
// 字典排序
const arr = [token, timestamp, nonce].sort()
const sha1 = crypto.createHash('sha1')
sha1.update(arr.join(''))
const result = sha1.digest('hex')
if (result === signature) {
ctx.body = ctx.query.echostr
} else {
ctx.body = { code: -1, msg: "fail"}
}
}
處理 POST 請求
下面要處理接收消息的 POST 請求蜜宪。因為消息的格式都是 XML ,所以這里需要引入 xml2js 祥山。
接收 XML 數(shù)據(jù)
koa2 沒有對 XML 格式的參數(shù)進行處理圃验,這里需要我們自己來處理下,寫的中間件如下:
// xmlTool.js
const xml2js = require('xml2js')
exports.xmlToJson = (str) => {
return new Promise((resolve, reject) => {
const parseString = xml2js.parseString
parseString(str, (err, result) => {
if (err) {
reject(err)
} else {
resolve(result)
}
})
})
}
exports.jsonToXml = (obj) => {
const builder = new xml2js.Builder()
return builder.buildObject(obj)
}
// xmlParse.js
const xml = require('./xmlTool')
module.exports = () => {
return async (ctx, next) => {
if (ctx.method == 'POST' && ctx.is('text/xml')) {
let promise = new Promise(function (resolve, reject) {
let buf = ''
ctx.req.setEncoding('utf8')
ctx.req.on('data', (chunk) => {
buf += chunk
})
ctx.req.on('end', () => {
xml.xmlToJson(buf)
.then(resolve)
.catch(reject)
})
})
await promise.then((result) => {
ctx.req.body = result
})
.catch((e) => {
e.status = 400
})
next()
} else {
await next()
}
}
}
加上了這個中間件缝呕,我們就可以正確接收到 XML 格式的參數(shù)了澳窑。接收到的參數(shù)如下:
// console.log(buf)
<xml>\n<ToUserName><![CDATA[toUser]]></ToUserName>\n<FromUserName><![CDATA[fromUser]]></FromUserName>\n<C
reateTime>12345678</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[你好]]></Content>\n</x
ml>\n\n
// 轉為JSON后
{ ToUserName: [ 'toUser' ],
FromUserName: [ 'fromUser' ],
CreateTime: [ '12345678' ],
MsgType: [ 'text' ],
Content: [ '你好' ] }
發(fā)送消息
接收到消息后,服務器需要在5s內返回消息供常,如果沒內容返回摊聋,可以返回 success 或空字符串。下面是返回文本信息的例子:
// wx.js
exports.message = {
text (msg, content) {
return xml.jsonToXml({
xml: {
ToUserName: msg.FromUserName,
FromUserName: msg.ToUserName,
CreateTime: Date.now(),
MsgType: msg.MsgType,
Content: content
}
})
}
}
// index.js
const wx = require('./wx')
exports.postHandle = (ctx, next) => {
let msg,
MsgType,
result
msg = ctx.req.body ? ctx.req.body.xml : ''
if (!msg) {
ctx.body = 'error request.'
return;
}
MsgType = msg.MsgType[0]
switch (MsgType) {
case 'text':
result = wx.message.text(msg, msg.Content)
break;
default:
result = 'success'
}
ctx.res.setHeader('Content-Type', 'application/xml')
ctx.res.end(result)
}
這樣子就可以返回文本信息啦~到這里已經(jīng)把基本的流程走完话侧。其他更多的操作可以看官方文檔栗精,加以修改就好。
公眾號例子如下瞻鹏,目前只是實現(xiàn)了回復相同的文本內容:
qrcode_430.jpg
上面的代碼已開源到https://github.com/cirplan/koa2-wechat 上,歡迎圍觀鹿寨。