业务消息自动通知的需求很常见:订单发货了、工单派单了、审批通过了,想让对应的人第一时间知道。但真做起来,卡点往往不在接口,而在"业务系统怎么和企微对话"这一层。这篇从业务侧视角讲清整条通知链路。
通知接口的三个要素
message/sendText 发起通知,只需要三个参数:
{"appid": "we_xxx", "conversationId": 1234567890123456, "content": "订单已发货"}
-
appid:实例标识,we_xxx格式 -
conversationId:会话 id,int64,必须传 JSON number -
content:通知内容
conversationId 是最容易踩坑的地方------它指向具体某个会话,不是成员 id。业务系统里的"通知张三"必须先转成张三的会话 id。
业务侧怎么设计通知模块
不要在业务代码里到处散落 POST 请求。先抽一个通知模块,业务代码只管说"通知谁、说什么":
python
class Notifier:
def __init__(self, client):
self.client = client
def to_member(self, uin, text):
conv_id = self._resolve(uin)
return self.client.call("message", "sendText", {
"conversationId": conv_id,
"content": text,
})
def _resolve(self, uin):
conv = redis.get(f"conv:{uin}")
if conv:
return int(conv)
raise RuntimeError(f"成员 {uin} 的会话未缓存")
业务侧调用就变成了 notifier.to_member(uin, "订单已发货"),换接口、加限流都只动 Notifier。
会话映射怎么预热
_resolve 里的会话缓存不能凭空有。预热的方式有两种:
一是从历史消息里捞。 调 message/getHistoryMessageList 传 uin,返回里挑 messageType=0(单聊)的记录,把 conversationId 存进缓存。
二是首次通知时创建。 有些场景第一次发就已经能建立会话,成功后把返回的 conversationId 落缓存,后续就直接命中。
一个简单的预热实现:
python
def warmup(uins):
for uin in uins:
resp = call("message", "getHistoryMessageList", {"uin": uin})
for item in resp["data"]["list"]:
if item["messageType"] == 0:
redis.set(f"conv:{uin}", item["conversationId"])
break
通知失败怎么处理
业务通知失败最忌讳静默丢失。做两层处理:
-
限流退避:返回 -301002 时按 2^n 秒重试,封顶后入重试队列
-
发送回执 :调
message/getMessageReceipt核对送达状态,失败补发
python
def notify_with_retry(notifier, uin, text, retries=3):
for i in range(retries):
try:
return notifier.to_member(uin, text)
except RateLimitError:
time.sleep(min(2 ** i, 32))
queue.push({"uin": uin, "text": text, "status": "retry"})
应用场景速览
| 业务 | 触发时机 | 通知对象 |
|---|---|---|
| 订单发货 | 订单状态变更 | 下单客户 |
| 工单派单 | 新工单创建 | 处理人 |
| 审批结果 | 审批流程结束 | 申请人 |
| 监控告警 | 指标超阈值 | 运维群 |
这些都是同一套模式:触发源 → 解析会话 → sendText → 回执核对。
业务消息自动通知看起来是"调个接口",实际上的工作量在于会话映射的维护和失败兜底。接口本身只有一行,配套的东西才是稳定运行的关键。凭证和接口路径在 Eyun 平台开通实例时拿到,字段和事件类型可以对照开发文档。