官网友情链接 wechatapi.net

微信二次开发做到一定阶段以后,很多企业都会提出一个需求:

在这里插入图片描述

微信里的事件,能不能直接通知自己的业务系统?

比如客户发来一条消息,希望通知 CRM;
客户在微信群里发送售后问题,希望通知工单系统;
收到某个关键词,希望触发内部流程;
客户发送文件,希望通知资料处理系统;
好友关系变化,希望同步客户管理后台。

这个时候,就会用到 Webhook。

从表面上看,Webhook 很简单:

微信事件发生以后,向指定地址 POST 一份数据。

但真正做生产系统以后,会发现 Webhook 不是“把 JSON 发出去”这么简单。

真正需要解决的是:

事件应该长什么样;
如何保证不重复;
失败怎么办;
目标系统超时怎么办;
能不能重放;
不同系统需要不同字段怎么办;
敏感数据能不能直接发送;
事件顺序错了怎么办。

所以 Webhook 本质上是一个事件系统。

WechatApi 可以作为微信API 和个人微信API 接入层,把微信私聊、微信群、文件、好友、消息事件接入业务系统。本地系统再把这些事件标准化,通过 Webhook 分发给 CRM、工单、数据平台和内部系统。

一、为什么不能把原始微信消息直接转发

最简单的做法是:

WechatApi 收到什么数据,就原样 POST 给业务系统。

这个方式短期很快。

但长期问题很多。

第一,外部系统会直接依赖底层微信数据结构。

以后字段变化或者接入方式调整,所有下游都要修改。

第二,不同事件格式可能完全不同。

文本消息、文件消息、好友事件、群消息结构不一样。

下游系统会写大量判断逻辑。

第三,原始数据里可能包含下游不需要的字段。

甚至包含敏感信息。

所以业务系统最好先建立统一事件模型。

二、什么是统一事件模型

可以定义一个标准事件结构。

例如每个事件都包含:

event_id;
event_type;
occurred_at;
tenant_id;
account_id;
conversation_id;
contact_id;
group_id;
payload;
trace_id;
schema_version。

不同事件的差异放在 payload 里。

这样 CRM、工单等下游系统可以先处理统一的事件头,再根据 event_type 处理具体内容。

这比直接转发底层原始数据更稳定。

三、事件类型应该标准化

例如可以抽象:

message.text.received;
message.image.received;
message.file.received;
contact.added;
contact.removed;
group.message.received;
group.member.changed;
account.status.changed。

这些名字只是示例,真正系统可以按业务定义。

关键是:

事件类型长期稳定。

即使底层微信API 返回格式变化,业务事件仍然保持稳定。

WechatApi 负责接入底层能力,本地事件层负责向业务系统提供统一语义。

四、Webhook 一定会失败

生产环境里,Webhook 失败非常正常。

目标系统可能:

超时;
宕机;
返回 500;
网络不可达;
限流;
正在维护。

所以系统不能发送一次失败后就丢掉。

每次 Webhook 调用都应该有投递记录。

状态可以包括:

待投递;
投递中;
成功;
失败;
等待重试;
已放弃;
人工处理。

这样 Webhook 才真正可靠。
在这里插入图片描述

五、重试为什么需要退避

如果目标系统已经故障,立即每秒重试会让问题更严重。

可以采用递增间隔。

第一次失败后 1 分钟;
第二次 5 分钟;
第三次 15 分钟;
后续更长。

具体策略按业务重要性配置。

对于实时性要求非常高的事件,可以同时触发告警。

六、Webhook 必须幂等

目标系统也要考虑重复投递。

假设某次 Webhook 已经成功处理,但响应因为网络中断没有返回。

发送方认为失败,于是重试。

目标系统就会收到两次同一个事件。

如果没有幂等,可能创建两条 CRM 跟进、两个工单或者两次通知。

所以 event_id 必须稳定。

下游系统可以使用 event_id 去重。

这也是统一事件模型的价值。

七、一个具体例子

客户通过微信发送:

“上传文件一直失败。”

随后发送一张截图。

WechatApi 将微信消息接入业务系统。

系统形成事件:

message.text.received;
message.image.received。

业务层识别这两条消息属于同一个售后问题。

生成业务事件:

service.issue.candidate.created。

这个事件通过 Webhook 发送给工单系统。

工单系统不需要理解底层微信消息结构,只需要处理“售后候选问题”事件。

这就是事件抽象带来的解耦。

八、不同下游需要不同事件

同一条微信消息可能要给多个系统。

CRM 关心:

客户是谁;
说了什么业务需求。

工单系统关心:

是否属于故障;
有没有截图。

数据平台关心:

消息类型;
发生时间;
所属账号。

不应该要求所有系统消费完全相同的数据。

系统可以支持不同订阅。

例如:

CRM 订阅 customer.;
工单订阅 service.
;
数据平台订阅所有审计事件。

这样 Webhook 更像事件总线。

九、Webhook 配置也需要版本

下游地址会变化。

密钥会变化。

订阅事件会调整。

所以 Webhook 配置也应该有:

创建时间;
修改记录;
启停状态;
订阅范围;
签名密钥版本。

高风险修改最好有操作审计。

否则某个地址什么时候被换掉很难追踪。

十、安全问题不能忽略

Webhook 可能携带客户消息和文件信息。

必须考虑:

HTTPS;
签名验证;
重放防护;
时间戳;
敏感字段脱敏;
访问白名单;
密钥轮换。

不能因为是内部系统就完全信任网络环境。

特别是微信客户数据,越需要谨慎。

十一、事件 Schema 也要有版本

统一事件结构未来也会变化。

例如 V1 没有 customer_id。

V2 增加 customer_id。

如果直接改变格式,下游系统可能崩溃。

所以事件中可以包含 schema_version。

下游可以逐步升级。

这就是事件契约管理。

十二、失败事件需要重放

Webhook 系统非常实用的能力是“事件重放”。

比如 CRM 上午故障 2 小时。

恢复以后,管理员可以选择失败事件重新投递。

而不是要求客户重新发消息。

重放必须保证:

event_id 不变;
原始事件不变;
只增加新的投递记录。

这样下游仍然可以正确幂等。

十三、死信和人工处理

某些事件重试很多次仍然失败。

不能无限重试。

可以进入死信列表。

管理员可以看到:

事件类型;
目标系统;
失败次数;
最后错误;
首次失败时间;
最后重试时间。

然后选择:

重新投递;
修改目标后投递;
忽略;
人工处理。

这和任务异常中心类似。

十四、WechatApi 和 Webhook 层的边界

WechatApi 负责:

微信消息接入;
微信群消息;
文件;
好友;
账号事件。

事件系统负责:

事件标准化;
业务事件抽象;
Webhook 投递;
签名;
重试;
幂等;
重放;
失败管理。

两层分开以后,微信机器人不再和每个内部系统直接耦合。

十五、为什么这对 AI 微信机器人也重要

AI 微信机器人处理完消息以后,也可以产生业务事件。

例如:

ai.reply.generated;
human.handoff.required;
service.issue.detected;
customer.intent.detected。

这些事件可以通过 Webhook 通知其他系统。

这样 AI 不只是“回复客户”,还可以参与业务流程。

十六、日志应该怎么做

每次 Webhook 投递记录:

event_id;
目标;
请求时间;
响应状态;
耗时;
重试次数;
响应摘要;
trace_id。

出现问题时,可以从微信消息一路追到下游系统处理结果。

这就是完整链路追踪。

十七、总结

微信机器人接入 Webhook,不应该只是简单把消息 POST 出去。

真正可长期运行的 Webhook 系统,需要:

统一事件模型;
稳定事件类型;
Schema 版本;
投递状态;
失败重试;
幂等;
签名验证;
事件重放;
死信处理;
链路日志。

WechatApi 可以作为个人微信API 接入层,把微信消息、微信群、文件和关系变化稳定接入业务系统。

事件模型则把这些底层微信能力转换成企业内部可以长期消费的业务事件。

只有这一层建立以后,微信二次开发才能真正和 CRM、工单、数据平台、AI 系统、内部业务流程解耦。

微信API 负责连接微信,事件系统负责连接企业自己的业务世界。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐