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系统需要回复他。

举个例子:员工在企业微信里输入「查询年假」,你的系统需要回复他剩余年假天数。

被动回复的流程是这样的:

  1. 用户发消息给企业微信
  2. 企业微信把消息推送到你的回调URL
  3. 你的系统解析消息,构造回复内容
  4. 在5秒内返回XML给企业微信

注意:5秒超时限制!如果超过5秒没回复,企业微信会认为你的系统挂了,直接返回「服务不可用」。我见过有团队在回复逻辑里查数据库、调外部API,结果经常超时。

怎么解决?我的做法是:先返回一个「正在处理」的文本消息,然后异步去处理业务逻辑。等处理完了,再用主动推送把结果发给用户。

被动回复的消息格式跟主动推送一样,只是多了个加密层。嗯,说到加密,咱们接着聊。

4.4 消息加解密方案

消息加解密,说白了就是防止别人偷看你的消息内容。企业微信用的是AES加密,密钥长度256位。

我刚开始做这个的时候,被加解密折腾得够呛。各种填充、各种校验,一个字节不对就解密失败。后来我总结了一套标准流程:

  1. 从请求中拿到密文
  2. 用AES密钥解密
  3. 去掉PKCS7填充
  4. 解析出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系统集成企业微信的常见场景。下一章咱们聊聊更高级的话题——如何设计一个高可用的消息推送架构。