Files
yunzerwebsiteallinone/go/docs/微信小程序消息推送配置.md
2026-10-31 19:17:37 +08:00

6.4 KiB
Raw Permalink Blame History

微信小程序「消息推送」配置指引

对应小程序后台:开发管理 → 开发设置 → 消息推送(就是你截图里的那个表单)。


0. 先搞清楚这个配置是干什么的

微信后台的「消息推送」= 你的服务器接收微信主动推送的入口。

场景 是否走这个配置
用户给小程序「客服」发消息、进入客服会话 ✅ 走(微信 POST 到你的 URL)
扫普通链接二维码打开小程序等事件 ✅ 走
订阅消息(wx.requestSubscribeMessage) ❌ 不走,用服务端 API 主动发
模板消息 ❌ 已下线,改用订阅消息

1. 前置条件(不满足会一直「配置失败」)

  1. 域名已 ICP 备案(微信后台会校验)。
  2. 只用 80 / 443 端口:https://xxx.com(443)或 http://xxx.com(80),其它端口微信不接受。
  3. 微信服务器能直连:公网可达,不能是 127.0.0.1、内网 IP 或本机端口。
  4. HTTPS 证书链完整:只部署 .crt 不带中间证书,微信侧会握手失败(自签证书不行)。
  5. 5 秒内返回:接口要在 5 秒内响应,否则微信断开并重试。

本项目的回调地址在 go/conf/app.conf 里配置: wechat_mini_callback_base = https://api.yunzer.cn(留空则退化为相对路径 /api/wechat/mini/callback,需由网关补域名)。


2. 第一步:在本平台生成参数

平台端:系统设置 → 小程序配置 → 编辑某个小程序 → 消息推送

字段 操作 说明
回调地址 自动生成,点「复制」 即 https://你的域名/api/wechat/mini/callback
Token 点「随机生成」 3-32 位字母数字
EncodingAESKey 点「随机生成」 43 位字母数字,后台也有「随机生成」按钮,两边值必须一致
加解密方式 明文 / 兼容 / 安全 与微信后台选择保持一致
数据格式 XML / JSON 与微信后台选择保持一致
自动回复文案 选填 留空 = 只接收不回复

填完点 「保存消息推送配置」(注意:这一步只存平台端,不会自动同步到微信后台)。


3. 第二步:在微信后台把值抄过去

小程序后台 → 开发管理 → 开发设置 → 消息推送,逐项对应:

后台字段 填什么
URL(服务器地址) 平台端「回调地址」整条复制,如 https://api.yunzer.cn/api/wechat/mini/callback
Token(令牌) 平台端「Token」
EncodingAESKey(消息加密密钥) 平台端「EncodingAESKey」(43 位)
消息加密方式 与平台端一致(明文 / 兼容 / 安全)
数据格式 与平台端一致(XML / JSON)

填完点「提交」,微信会立刻发一个 GET 请求到你的 URL 做校验,通过就提示配置成功。

⚠️ 配置提交后立即生效,切换加密方式或数据格式前,务必先把平台端改成同样的值,否则消息会被验签/解密失败直接丢弃。


4. 提交时微信做了什么(校验逻辑)

微信 GET 你的 URL,参数:signature timestamp nonce echostr。

  • 明文 / 兼容模式:服务端算 sha1(sort(token, timestamp, nonce) 拼接) 与 signature 比对,通过后原样返回 echostr。
  • 安全模式:echostr 是密文,额外带 msg_signature = sha1(sort(token, timestamp, nonce, echostr));服务端验签后解密,再返回解密结果。

对应实现:

  • go/services/wechatmini/push.go —— 签名校验、AES 加解密、XML/JSON 解析、被动回复构造
  • go/controllers/api_wechat_mini.go —— GET /api/wechat/mini/callback 校验 + POST 收消息

多小程序:每个小程序在自己的后台单独配置,本平台按 AppID 分别维护 Token / AESKey; 回调接口不携带 appid,服务端会逐个应用匹配签名,命中哪个就按哪个的密钥解密。


5. 收到消息后的行为

  • 微信 5 秒内没收到响应会断开并重试,总共重试 3 次(间隔 15s / 5s / 5s)。
  • 返回空串或 success = 已处理,微信不再重试(我们的实现返回空串)。
  • 平台端配了「自动回复文案」时,5 秒内以被动回复形式把文案回给用户。
  • 复杂业务(例如按关键字回复、转发人工)可接管钩子: services/wechatmini/push.go 中的 PushHandler。

6. 常见报错排查

现象 常见原因 处理
后台一直「配置失败」 域名未备案 / 端口不是 80、443 / 证书链不完整 / 返回内容不是 echostr 逐条对照第 1 节
后台提示超时 接口处理超过 5 秒 先只回 echostr,业务逻辑异步做
后台提示 Token 校验失败 平台端 Token 与后台填的不一致 两边都复制一遍核对(区分大小写)
配置成功但收不到消息 加解密方式或数据格式两边不一致 平台端与后台改成一致
小程序会话提示「客服暂时无法提供服务」 5 秒内没回复 配「自动回复文案」,或让接口先返回空串
明文模式正常,切安全模式收不到 EncodingAESKey 两边不一致 重新复制 43 位密钥

自测命令(明文模式)

# signature = sha1(sort(token, timestamp, nonce) 拼接),用与平台端相同的 token
curl "https://api.yunzer.cn/api/wechat/mini/callback?signature=<签名>&timestamp=1700000000&nonce=abc123&echostr=hello"
# 期望输出:hello(等于传入的 echostr)

服务端日志会打印 [wechat-mini] 收到推送: ...,看不到这行说明微信请求没到服务端(先查域名 / 端口 / 证书)。


7. 相关接口

方法 路径 说明
GET/POST /api/wechat/mini/callback 微信回调(无需鉴权,内部验签)
GET /platform/wechatMini/app/push?app_id=xxx 读取推送配置(含回调地址)
POST /platform/wechatMini/app/push/save 保存推送配置
POST /platform/wechatMini/app/push/generate 生成随机 Token / EncodingAESKey

8. 数据库

新增字段(token / aes_key / encrypt_mode / data_format / push_reply):

mysql -h <host> -P <port> -u <user> -p <db> < go/docs/sql/alter_wechat_mini_app_push.sql

aes_key 以 AES-256-GCM 加密入库(复用公众号的 wechat_mp_secret_key),接口只回显掩码。