4、消息推送机制:消息类型概述(文本、图片、文件、图文等)、主动推送消息、被动回复消息、消息加解密方案
消息推送,说白了就是企业微信跟你的OA系统之间怎么「说话」。
我刚开始接触这个模块时,觉得不就是发个消息嘛,能有多复杂?结果真上手才发现,这里面的门道还真不少。消息类型、推送方式、加解密方案,每一个环节踩过的坑,都够我写一本小册子了。
今天咱们就把这块彻底捋清楚。
4.1 消息类型概述
企业微信支持的消息类型,我数了数,大概有十几种。但咱们做OA集成,最常用的就这四种:文本、图片、文件、图文。
| 消息类型 | MsgType值 | 典型场景 |
|---|---|---|
| 文本 | text | 审批通知、待办提醒 |
| 图片 | image | 工单现场照片、签名截图 |
| 文件 | file | 报表导出、合同附件 |
| 图文 | news | 公告详情、跳转链接 |
每种消息的XML结构都不一样。我习惯把它们的模板存成常量,用的时候直接套。举个例子,文本消息长这样:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你的请假申请已通过]]></Content>
</xml>
图片和文件消息呢,需要先上传素材,拿到media_id才能发。我记得有个项目,同事直接传了文件路径就发,结果接口一直报错。嗯,这里要注意:media_id是有有效期的,一般是3天。
核心要点:图文消息(news)支持跳转链接,适合做OA待办的快捷入口。我一般会在图文消息里带上审批单号,用户点一下就能直达详情页。
4.2 主动推送消息
主动推送,就是你的OA系统主动给企业微信发消息。比如:员工提交请假单,系统自动通知审批人。
调用方式很简单,POST请求到 https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN。
但这里有个坑——频率限制。企业微信对主动推送有严格的频率控制:
- 每个应用,每分钟最多发600条
- 每个企业,每分钟最多发30000条
我曾经在一个大促项目里,OA系统同时推送上千条审批通知,结果直接触发了限流。后来我加了个消息队列,把推送任务排队处理,才解决了这个问题。
我的习惯:主动推送时,一定要做重试机制。网络抖动是常态,一次失败就丢弃消息,用户会投诉的。我一般会重试3次,间隔2秒、4秒、8秒。
另外,主动推送支持按成员、按部门、按标签发送。我个人建议:能用标签就别用成员列表。标签维护起来方便,而且推送效率更高。
4.3 被动回复消息
被动回复,跟主动推送正好相反。是用户在企业微信里发了消息,你的OA系统需要回复他。
举个例子:员工在企业微信里输入「查询年假」,你的系统需要回复他剩余年假天数。
被动回复的流程是这样的:
- 用户发消息给企业微信
- 企业微信把消息推送到你的回调URL
- 你的系统解析消息,构造回复内容
- 在5秒内返回XML给企业微信
注意:5秒超时限制!如果超过5秒没回复,企业微信会认为你的系统挂了,直接返回「服务不可用」。我见过有团队在回复逻辑里查数据库、调外部API,结果经常超时。
怎么解决?我的做法是:先返回一个「正在处理」的文本消息,然后异步去处理业务逻辑。等处理完了,再用主动推送把结果发给用户。
被动回复的消息格式跟主动推送一样,只是多了个加密层。嗯,说到加密,咱们接着聊。
4.4 消息加解密方案
消息加解密,说白了就是防止别人偷看你的消息内容。企业微信用的是AES加密,密钥长度256位。
我刚开始做这个的时候,被加解密折腾得够呛。各种填充、各种校验,一个字节不对就解密失败。后来我总结了一套标准流程:
- 从请求中拿到密文
- 用AES密钥解密
- 去掉PKCS7填充
- 解析出XML明文
解密后的XML结构是这样的:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
<MsgId>1234567890123456</MsgId>
<AgentID>1</AgentID>
</xml>
加密方案有三种模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 明文模式 | 不加密,直接传XML | 开发测试环境 |
| 兼容模式 | 同时包含明文和密文 | 过渡期使用 |
| 安全模式 | 只传密文 | 生产环境 |
我的建议:生产环境一定要用安全模式。明文模式虽然方便调试,但消息内容在传输过程中是裸奔的。万一被截获,用户的审批信息、个人数据就全暴露了。
加解密这块,企业微信官方提供了各种语言的SDK。我建议直接用SDK,别自己造轮子。我自己就吃过这个亏——自己写的解密代码,在某个特殊字符上出了问题,排查了两天才发现是填充算法实现有bug。
最后说一个容易忽略的点:消息去重。企业微信为了保证消息送达,可能会重复推送同一条消息。你的系统需要根据MsgId做去重处理。我一般会在Redis里存一个已处理的消息ID集合,有效期设成5分钟,这样既保证去重,又不会占用太多内存。
避坑指南:我曾经在生产环境遇到过一个问题——消息解密偶尔失败,但重试一次就好了。后来发现是AES密钥在服务器间同步时出现了短暂的不一致。解决办法:把密钥放到配置中心,所有服务器实时拉取,保证一致性。
好了,消息推送机制的核心内容就这些。文本、图片、文件、图文四种消息类型,主动推送和被动回复两种方式,再加上AES加解密方案,基本上覆盖了OA系统集成企业微信的常见场景。下一章咱们聊聊更高级的话题——如何设计一个高可用的消息推送架构。