# 消息推送

微信云托管支持接收微信消息推送,走内网链路,无需加解密和签名。

当微信云托管消息推送开启时,消息不会推送到开发者服务器上,而是会推送到开发者指定的云托管服务中。

# 配置方式

前往微信云托管控制台 - 设置 - 全局设置 - 消息推送中配置

配置消息

配置时需要的信息解释如下:

  • 环境ID:选择微信云托管的哪个环境接收消息推送
  • 服务名称:选择接收消息推送的服务,只需配置1个服务即可接收所有类型消息;
  • path:服务下哪个接口接收即写该接口在服务内的路径即可,比如根路径填写 /
  • 推送模式:支持 JSONXML 两种模式,根据自己的项目实际情况选择,一般是 JSON

# 资源复用配置

如果当前环境有配置资源复用给其他小程序/公众号,则配置窗口会变成如下:

配置消息

你可以选择其他已复用的小程序/公众号,配置推送路径。

需要注意的是:配置确认的扫码,需要是目标「小程序/公众号」的管理员,而不是环境的管理员或者环境所属的账号管理员。

# 配置解绑

当想要取消消息推送时,直接在控制台列表选择操作解绑。

如果你的公众号/小程序,之前配置过服务器路径接收消息,配置消息推送后,将会覆盖服务器路径。

但解绑后,原有的服务器路径不会生效,需要先在开发者后台停用,再启用,就可以恢复正常了。

# 配置测试

配置消息推送时,微信后台会向配置的服务发起一个检测请求。

当配置格式为 JSON 时,请求体为:

{ 
  "action": "CheckContainerPath"
}

当配置格式为 XML 时,请求体为:

<xml>
  <action>CheckContainerPath</action>
</xml>

开发者回复 success 或回复空即可完成测试。

需要注意,路径返回的 Status 需要为200,如果是非200将会导致路径配置检查失败

# 确认消息来源

若云托管未开启公网访问,则可以信任所有消息推送。

若云托管开启了公网访问,需要验证消息推送的请求头,带 x-wx-source 的请求才是微信侧发起的推送。

消息推送如果是 JSON 形式,则收到的信息格式如下:

{
  "ToUserName": "gh_919b00572d95", // 小程序/公众号的原始ID,资源复用配置多个时可以区别消息是给谁的
  "FromUserName": "oVneZ57wJnV-ObtCiGv26PRrOz2g", // 该小程序/公众号的用户身份openid
  "CreateTime": 1651049934, // 消息时间
  "MsgType": "text", // 消息类型
  "Content": "回复文本", // 消息内容
  "MsgId": 23637352235060880 // 唯一消息ID,可能发送多个重复消息,需要注意用此 ID 去重
}

# 消息回复

消息推送有两种,被动回复和主动回复。

# 1. 被动回复

原理可以参考此文档,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。

需要注意,被动回复只支持公众号,小程序需要使用主动回复。公众号具体的回复格式可参考开发指引

# 2. 主动回复

小程序,以及公众号无法即时回复场景,可以使用 API 异步发送来完成,这也是微信团队推荐的做法。

比如接收到了「小程序/公众号」的客服消息,可以在请求体中得到发送者openid,unionid,以及发送的内容。

接下来就可以通过开放接口服务方式,发送客服消息来完成回复操作。

详细的主动回复例子请参考开发指引

代码如下:

const request = require('request')
return new Promise((resolve, reject) => {
  request({
    method: 'POST',
    url: 'http://api.weixin.qq.com/cgi-bin/message/custom/send',
    // 资源复用情况下,参数from_appid应写明发起方appid
    // url: 'http://api.weixin.qq.com/cgi-bin/message/custom/send?from_appid=wxxxxx'
    body: JSON.stringify({
      touser: "OPENID", // 一般是消息推送 body 的FromUserName值,为用户的openid
      msgtype: "text",
      text: {
        content: "Hello World"
      }
    })
  },function (error, response) {
    console.log('接口返回内容', response.body)
    resolve(JSON.parse(response.body))
  })
})

在使用前请开启「开放接口服务」,并配置 cgi-bin/message/custom/send 到云调用白名单接口,具体参考文档

# 代码示例

以下演示使用 node.js 来构建接收消息的服务,共三个文件。详细的包含回复的代码示例可以参考开发指引

index.js 文件

const express = require('express')

const app = express()

app.use(express.json())

app.post('/', async (req, res) => {
  console.log('消息推送', req.body)
  res.send('success') // 不进行任何回复,直接返回success,告知微信服务器已经正常收到。
});

app.listen(80, function(){
  console.log('服务启动成功!')
})

Dockerfile 文件

FROM node:12-slim

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . ./

CMD [ "node", "index.js"]

package.json 文件

{
  "name": "cloudbase-push",
  "version": "1.0.0",
  "description": "call push server",
  "main": "index.js",
  "scripts": {},
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}

将3个文件组成文件夹,版本创建上传,端口填写 80,创建版本成功后,部署发布。

在消息推送配置填写对应的服务,路径填写 /

填写后在控制台 - 日志中可以看到如下