微信公众号本地开发环境搭建

670 阅读1分钟
  1. 进入ngrok官网 (ngrok.com/),注册ngrok账号…
  2. 根据官网运行命令
  • ./ngrok authtoken 1joIjHUJ2sQroatUKIWWhpKR94A_54HcKBHWJyzgTdiq5wDwZ
  • ./ngrok http 3000 3000是端口号 可以换成自己想要的端口号

运行成功如图

Forwarding,第一个是http协议对应的外网地址,第二个是https协议对应的外网地址。这样,凡是访问e45968c45c8b.ngrok.io的请求都将发送到localhost:3000。

  1. 微信公众号测试号配置

  2. 本地服务器配置 (koa2) 接口认证

router.get('/', async ctx => {
    console.log(ctx.query);
    const { signature, timestamp, nonce, echostr } = ctx.query 
    const token = 'wzm';
    ctx.body = echostr;
})
  1. 微信公众号自动信息回复案例
const Koa = require('koa');
const app = new Koa();
let Router = require('koa-router');
let router = new Router();
const getRawBody = require('raw-body');
const crypto = require('crypto');
// 解析xml数据为json格式
function parseXML(xml) {
    return new Promise((resolve, reject) => {
        xml2js.parseString(xml, { trim: true, explicitArray: false, ignoreAttrs: true }, function (err, result) {
            if (err) {
                return reject(err)
            }
            resolve(result.xml)
        })
    })
}
// 判断是否为微信服务器信息
function getSignature(timestamp, nonce, token) {
    let hash = crypto.createHash('sha1')
    const arr = [token, timestamp, nonce].sort()
    hash.update(arr.join(''))
    return hash.digest('hex')
}
app.use(async ctx => {
    const { signature, timestamp, nonce, echostr } = ctx.query
    const TOKEN = 'wzm';
    console.log(ctx.method)
    if (ctx.method === 'GET') {
        if (signature === getSignature(timestamp, nonce, TOKEN)) {
            const xml = await getRawBody(ctx.req, {
                length: ctx.request.length,
                limit: '1mb',
                encoding: ctx.request.charset || 'utf-8'
            });
            console.log(xml)
            const formatted = await parseXML(xml)
            console.log(formatted)
        }
    } else if (ctx.method === 'POST') {
        let data = ctx.request.body
        if (signature === getSignature(timestamp, nonce, TOKEN)) {
            console.log(data);
            const formatted = await parseXML(data)
            console.log(formatted)
            // 回复微信公众号信息
            ctx.type = 'application/xml';
            return ctx.body = `<xml> 
                                <ToUserName><![CDATA[${formatted.FromUserName}]]></ToUserName> 
                                <FromUserName><![CDATA[${formatted.ToUserName}]]></FromUserName> 
                                <CreateTime>${new Date().getTime()}</CreateTime> 
                                <MsgType><![CDATA[text]]></MsgType> 
                                <Content><![CDATA[这儿是JavaScript之禅]]></Content> 
                            </xml>`
        }
    }
});
app.use(router.routes()).use(router.allowedMethods())