使用express实现微信公众号推送消息

339 阅读3分钟

准备工作

  1. 申请测试公众号或真实服务号
  2. 在线接口调试

搭建公众号后端服务

使用 express 进行搭建

验证微信接口配置信息

参考官方文档

const express = require('express');
const app = express();
const sha1 = require('node-sha1'); //加密模块

const config = {
  token: 'hellowechat', //对应测试号接口配置信息里填的token
  appid: 'wx5f58282ecb777790', //对应测试号信息里的appID
  secret: '4161005346b5ae9472dc9353ffdc6066', //对应测试号信息里的appsecret
  grant_type: 'client_credential' //默认
}

app.get('/', function (req, res) {
  const token = config.token; //获取配置的token
  const { signature, nonce, timestamp } = req.query
  const str = [token, timestamp, nonce].sort().join(''); //排序token、timestamp、nonce后转换为组合字符串
  const sha = sha1(str); //加密组合字符串

  //如果加密组合结果等于微信的请求参数signature,验证通过
  if (sha === signature) {
    const { echostr } = req.query; //获取微信请求参数echostr
    res.send(echostr + ''); //正常返回请求参数echostr
  } else {
    res.send('验证失败');
  }
});

填写接口配置信息

  • URL 处填写你校验服务的地址,地址必须在公网可访问,这里推荐内网穿透工具
  • Token 处随便写,必须要和后端服务中的保持一致 Pasted image 20230222114424.png

然后提交,会提示成功或失败

  • 如果配置失败,请检查服务是否按照规则返回内容
  • 配置成功则继续

编写发送模板消息的方法

首先,在后台新建模板,例如:

通知内容:
{{thing01.DATA}}

可用 postman 进行测试,access_token自行使用调试工具获取 或 直接调用/send接口,下面的获取 token 的方法都封装好了

模板参数可参考发送模板消息接口

app.get('/send', async function (req, res) {
  await getAccessToken(openid);
  res.send('结束,看控制台')
});

// 获取access_token
async function getAccessToken (openid) {
  const appid = config.appid;
  const secret = config.secret;
  const grant_type = config.grant_type;
  const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=${grant_type}&appid=${appid}&secret=${secret}`;
  const res = await fetch(url)
  if (res.status === 200) {
    const { access_token } = await res.json();
    sendTemplateMsg(access_token); //获取access_token成功后调用发送模板消息的方法
  } else {
    throw 'update access_token error';
  }
}

// 发送模板消息
async function sendTemplateMsg (access_token) {
  const url = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${access_token}`; //发送模板消息的接口
  const requestData = { //发送模板消息的数据
    "touser": "oMK9n6z-trWsXW25_prV3dDrMGRI",
    "template_id": "cYCEP-VzHdxXDFEx8iC5VyIdh2oYTM-1Ulo7U1O-i44",
    "url": "http://www.baidu.com", // url会跳转到普通的链接
    "miniprogram": {
      "appid": "wxb49aa4f53c9004d8",
      "pagepath": "index"
    }, // 如果要推送小程序链接,小程序必须关联公众号,测试号是不能推送小程序的
    "client_msg_id": "MSG_000001",
    "page": "index",
    "data": {
      "thing01": {
        "value": "asdf"
      }
    }
  };
  const res = await fetch(url, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json;charset=utf-8;'
    },
    body: JSON.stringify(requestData) // 注意这里一定要把json转成字符串,大坑!!
  })
  console.log(requestData)
  if (res.status === 200) {
    const { errcode, errmsg } = await res.json()
    if (!errcode) {
      console.log('模板消息推送成功')
    } else {
      throw errmsg
    }
  }
}

关注和取关事件

const xmlparser = require('express-xml-bodyparser'); // 解析xml
const template = require('./utils/template')
app.use(xmlparser());

app.post('/', function (req, res) {
  const { xml } = req.body
  console.log(xml)
  switch (xml.event?.[0]) {
    case 'subscribe':
      saveOpenId();
      break;
    case 'unsubscribe':
      delOpenId();
      break
  }
  res.send('')
})
function saveOpenId () {
  console.log('保存用户的openid')
}
function delOpenId () {
  console.log('删除用户的openid')
}

至此,公众号推送模板消息的功能开发完毕

如果需要推送小程序链接,需要参考上述的步骤 2,在参数中添加miniprogram,示例代码中也有写到 由于测试号无法推送小程序链接,只能推送普通的 url,这里就不在展示了

使用

在小程序中,调用后端接口/send,指定模板和接收人的 openid即可,如果需要发送小程序链接,则参数带上 miniprogram(公众号和小程序必须关联)