Files
yunzerwebsiteallinone/go/docs/小程序订阅消息配置与使用.md
T
2026-10-31 19:17:37 +08:00

143 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 小程序订阅消息:配置与使用(怎么让用户收到提示)
## 一、先分清两条通道
| | 消息推送(服务器配置) | 订阅消息 |
| --- | --- | --- |
| 方向 | **用户 → 你**(用户发客服消息给你) | **你 → 用户**(你主动推提示给用户) |
| 触发 | 用户在小程序点「客服」发消息 | 业务事件发生(审批待办、日程提醒、站内信…) |
| 前置条件 | 无 | 用户必须在微信弹窗里点「允许」(一次性订阅:授权一次 = 1 次推送机会) |
| 微信后台位置 | 开发管理 → 开发设置 → 消息推送 | 功能 → 订阅消息 |
| 本工程实现 | `services/wechatmini/push.go` + `controllers/api_wechat_mini.go` | `services/wechatmini/subscribe.go` + `controllers/api_mini_subscribe.go` |
**结论**:想让用户「收到提示」,靠的是**订阅消息**,不是消息推送。消息推送只是接收端(顺带做客服自动回复)。
---
## 二、完整流程(4 步)
### 第 1 步:微信后台选一个订阅消息模板
小程序后台 → **功能 → 订阅消息 → 公共模板库 → 选用模板**(例如「审批进度通知」「待办提醒」)。
选完后记下两样东西:
- **模板 ID**(一串字母数字)
- **模板的字段名**(如 `thing1`、`phrase2`、`time3`、`character_string4`)
> 模板选错会导致推送报 40066 / 47003,字段名对不上则报「模板字段不匹配」。
### 第 2 步:平台端登记模板
平台后台 → **系统设置 → 小程序配置 → 编辑小程序 → 订阅消息模板 → 新增模板**
| 字段 | 填什么 |
| --- | --- |
| 场景码 | `notice`(站内通知/通用提醒;同一个小程序下唯一) |
| 场景名称 | 如「站内通知」 |
| 模板 ID | 第 1 步复制的模板 ID |
| 跳转页面 | 用户点击消息进入的小程序页面,如 `pages/index/index` |
| 字段映射 | JSON:`{"thing1":"title","phrase2":"content","time3":"time"}` |
**字段映射怎么读**:左边是微信模板的字段名,右边是平台这边的变量名。平台会提供三个变量:
- `title` —— 标题(如「您有新的审批待办」)
- `content` —— 内容
- `time` —— 推送时间(`2026-10-31 19:00`)
映射里写了哪个字段,就把对应变量填进去;模板有但没映射的字段会自动填 `-`。
### 第 3 步:小程序端让用户授权
已接入的位置:**小程序「我的 → 消息通知」**,点一下会拉起微信的订阅授权弹窗。
```js
import { requestSubscribeNotice } from '@/utils/subscribe.js'
await requestSubscribeNotice()
```
建议在**用户确实可能需要收到提醒**的时机也调用一次(比如进入工作台、提交完审批之后)——因为微信一次性订阅,授权一次只有一次推送机会,用完了要再授权。
小程序端也可以直接调接口:
- `GET /api/mini/subscribe/templates` 取模板列表
- `POST /api/mini/subscribe/authorize` 上报授权结果
- `POST /api/mini/subscribe/test` 给自己发一条测试消息
### 第 4 步:业务侧触发
已接入的触发点(业务照常发,订阅消息自动跟上,**不影响主流程**,失败只记日志):
| 业务 | 代码位置 |
| --- | --- |
| 站内信(平台端手动发通知) | `services/system_sitereminder.go` → `SendSiteReminder` |
| OA 日程提醒(定时任务) | `services/reminder_scheduler.go` → `SiteMsgSender.Send` |
| 审批待办(租户侧审批人生成待办) | `services/approval/engine.go` → `createTasks` |
自己接新场景时,直接调:
```go
wechatmini.PushTenantNotice(租户用户ID, "标题", "内容")
// 或指定场景码:
wechatmini.PushSubscribeToTenantUser(租户用户ID, "notice", "", map[string]string{
"title": "标题", "content": "内容", "time": "2026-10-31 19:00",
})
```
---
## 三、一次性订阅的规则(最容易踩坑)
- 用户点一次「允许」= **1 次**推送机会,服务器记在 `yz_platform_wechat_mini_subscribe.remain`
- 推送成功自动 `remain - 1`;用户拒绝或机会用尽(微信返回 43101)自动清零
- `remain = 0` 时不会调微信接口,直接跳过(不浪费配额)
- 微信一次弹窗最多 3 个模板,前端已自动分批
- 「长期订阅」只有部分类目能用,��务小程序基本用不了,所以要设计好**再次引导授权**的时机
---
## 四、常见错误码
| errcode | 含义 | 处理 |
| --- | --- | --- |
| 43101 | 用户未订阅 / 拒绝订阅 | 引导用户在小程序里重新点「消息通知」授权 |
| 40066 | 模板 ID 无效 | 检查是不是填了「功能 → 订阅消息」里真正的模板 ID |
| 47003 | 模板字段不匹配 | 检查字段映射与微信模板字段是否一致 |
| 40003 | openid 无效 | 该用户不是用这个小程序登录的,或 openid 与 AppID 不匹配 |
| 40001 | access_token 失效 | 工具会自动刷新,稍后重试 |
平台端「测试」按钮会直接返回中文排查建议。
---
## 五、接口清单
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/api/mini/subscribe/templates` | 小程序端:可订阅模板列表(含剩余次数) |
| POST | `/api/mini/subscribe/authorize` | 小程序端:上报授权结果 |
| POST | `/api/mini/subscribe/test` | 小程序端:给自己发一条测试消息 |
| GET | `/platform/wechatMini/templates` | 平台端:模板列表 |
| POST | `/platform/wechatMini/template/save` | 平台端:保存模板 |
| POST | `/platform/wechatMini/template/delete/:id` | 平台端:删除模板 |
| POST | `/platform/wechatMini/template/test` | 平台端:给指定租户用户发测试消息 |
## 六、相关文件
| 文件 | 作用 |
| --- | --- |
| `go/services/wechatmini/subscribe.go` | 订阅消息 / 客服消息发送、模板 CRUD、授权记录、推送编排 |
| `go/controllers/api_mini_subscribe.go` | 小程序端接口 |
| `go/controllers/platform_wechat_mini.go` | 平台端模板管理接口 |
| `go/models/wechat_mini.go` | `WechatMiniTemplate` / `WechatMiniSubscribe` 模型 |
| `go/docs/sql/create_wechat_mini_template.sql` | 建表脚本 |
| `uniapp/utils/subscribe.js` | 小程序端授权助手 |
| `uniapp/api/subscribe.js` | 小程序端接口封装 |
| `uniapp/pages/profile/profile.vue` | 「我的 → 消息通知」授权入口 |
建表脚本:
```bash
mysql -h <host> -P <port> -u <user> -p <db> < go/docs/sql/create_wechat_mini_template.sql
```