Appearance
回调字典
内容消息和联系人通知推送的请求体就是这条消息本身:按 contentType 在类型速查表里找到读法,messageType 用来分清单聊、群聊还是系统通知。事件名在 X-Eyun-Event 请求头中,见回调说明。样本来自生产环境真实推送(2026-09-10 至 09-12),已脱敏。
脱敏规则
fromUserId / toUserId / uin / roomId / corpId 等 int64 换成同格式占位(1688850000000001 本账号、7881300000000002 外部客户、10000000000002 群、1970320000000001 企业;系统号 10030 / 10014 / 10120 是协议常量,保留);md5 / aesKey 写作 <md5> / <aesKey>,下载 URL 里的临时凭证省略,长 id / hex 截断标注;姓名与企业名换成「示例客户」「示例网络科技」。字段名与结构保持真实。
一条推送长这样
json
{
"id": 1013420,
"messageType": 0,
"contentType": 0,
"roomId": 0,
"fromUserId": 7881300000000002,
"toUserId": 1688850000000001,
"senderName": "",
"summary": "您好",
"sendTime": 1789093735,
"syncKey": 12014383,
"flag": 16777216,
"appInfo": "<appInfo>",
"extraData": "",
"devInfo": 0,
"content": [{ "type": 0, "text": "您好" }]
}常用字段
| 字段 | 含义 |
|---|---|
id | 消息 id,同一账号内唯一,可用来去重;撤回消息时作为 serverMsgId |
messageType | 会话类型:0 好友(单聊)、1 群聊、3 系统通知 |
contentType | 内容类型,决定 content 怎么读,见类型速查表 |
roomId | 群 id;单聊与系统私发为 0,系统通知里可能是群 id 或系统号 |
fromUserId | 发送方 id(uin);群消息里是真实成员,系统通知里常是系统号(如 10030) |
toUserId | 接收方 id,通常是本账号;群消息与部分系统通知为 0 |
summary | 可直接展示的摘要,如 您好、[图片]、文章标题 |
sendTime | 发送时间,秒级时间戳 |
content | 消息内容,读法见下一节 |
id、syncKey、fromUserId、toUserId、roomId 是 int64 大整数,解析时不要转成 JS Number 或浮点数(前端用 json-bigint,或后端转字符串)。
其余字段(原样透传即可)
| 字段 | 含义 |
|---|---|
senderName | 发送方昵称,大多为空;要昵称请调通讯录接口 |
syncKey | 同步位置,递增,可作同步消息的位置标记 |
flag | 企微内部标志位 |
appInfo | 企微内部推送信息 |
extraData | 企微内部数据(base64 编码的 protobuf,含 @ 与引用),一般无需解析 |
devInfo | 设备信息标记 |
content 怎么读
看到的 content | 常见类型 | 怎么读 |
|---|---|---|
数组 [{ "type": 0, "text": "…" }] | 文本 | 各段 text 是明文,拼起来就是正文;type=0 纯文本、type=3 表情;type=5 带 userId 是 @某人,不带则是 @所有人 |
对象,带 id 与 aesKey | 图片、语音、视频、文件 | 媒体文件:用 id 与 aesKey 调 CDN 下载;单聊图片、视频还带可直接下载的 url |
对象 { "hex": "…", "msgType": … } | 多数系统通知、表情、图文 | hex 是十六进制编码的数据(不是 base64),msgType 与外层 contentType 相同;系统通知里常为空,只当作「有变化」的信号,去调对应接口刷新 |
| 对象,带明文字段 | 好友申请 2357、链接卡片 13 | 字段直接可用 |
和同步消息不一样
推送的文本是明文数组,媒体是带下载凭证的明文对象,系统类常为 {hex, msgType}。同步消息拉历史时的 content 基本是企微 protobuf,文本拿不到明文。推送和同步消息必须分开解析,不能共用同一套读法。发送接口的响应则回显你发送的内容或上传字段。
类型速查表
内容消息(多为 messageType 0 或 1,图文 31 的样本是 3)
| 类型 | contentType | 样本 | 收到后怎么做 |
|---|---|---|---|
| 文本 | 0,单聊变体 2 | 看样本 | 拼接 content[].text |
| 图片 | 14 群 / 101 单聊 | 看样本 | 调 CDN 下载;101 可直接用 url |
| 语音 | 16 | 看样本 | 调 CDN 下载,silk 格式 |
| 视频 | 23,单聊 103 | 看样本 | 调 CDN 下载;103 可直接用 url |
| 文件 | 15,群与转发 20 | 看样本 | 调 CDN 下载 |
| 动画表情 | 104 | 看样本 | 原样保存 |
| 图文、公众号文章卡片 | 31,系统图文 105 | 看样本 | 展示 summary(即标题) |
| 链接、视频号卡片 | 13 | 看样本 | 读 title、url 等明文字段 |
| 位置 | 6 | — | 读经纬度与地址 |
| 名片 | 41 | — | 读明文字段 |
| 小程序 | 78 | — | 读明文字段(两层结构) |
| 红包 | 26 | — | 原样保存 |
系统通知(多为 messageType 3,也有群事件;已读回执 2001 的样本是 0)
| 类型 | contentType | 样本 | 收到后怎么做 |
|---|---|---|---|
| 已读回执 | 2001 | 看样本 | 发消息后必收一条,可忽略 |
| 外部联系人信息变动或删除 | 2131 | 看样本 | 调同步外部数据(非企业) |
| 好友申请(带明文) | 2357 | 看样本 | 展示申请,调同意新客户 |
| 好友申请 | 2132 | 看样本 | 调同意新客户 |
| 群信息变动 | 2118 | 看样本 | 调获取群资料刷新 |
| 群成员变动、建群 | 1006 | 看样本 | 刷新群成员 |
| 联系人免打扰、置顶 | 2104 | 看样本 | 原样保存 |
| 个人标签变更 | 2186 | — | 调同步标签,syncType=2 |
| 企业标签变更 | 2185 | — | 调同步标签,syncType=1 |
| 内部联系人变动 | 2188 | — | 调通讯录同步 |
| 撤回消息 | 2063 | — | 按撤回处理 |
| 其它系统信号 | 2130 / 2180 / 2201 | 看样本 | 含义未确认,原样保存 |
— 表示还没抓到真实推送(经接口发送不会触发回调,只能等客户端真实操作),含义按协议整理,结构可能有出入;查不到的 contentType 原样保存,由业务判断。
内容消息
对应事件为 message.received,用于文本、图片、视频等内容类消息。
文本(0 / 2 单聊变体)
正文在 content[].text。单聊文本(2)结构相同,messageType 与 roomId 都是 0。
查看样本
json
{
"id": 1000554,
"messageType": 1,
"contentType": 0,
"roomId": 10000000000002,
"fromUserId": 1688850000000011,
"toUserId": 0,
"summary": "",
"sendTime": 1789106713,
"syncKey": 15993462,
"flag": 83886080,
"content": [{"type": 0, "text": "就仅仅"}]
}图片(14 群 / 101 单聊)
14(群):用id与aesKey调 CDN 下载。101(单聊):content还带url、中图wechatMidImage与wechatAuthKey;url带临时凭证,可直接下载;summary为[图片]。
查看样本
json
{
"id": 1013724,
"messageType": 1,
"contentType": 14,
"roomId": 10000000000002,
"fromUserId": 1688850000000001,
"sendTime": 1789183828,
"content": {
"id": "<下载凭证>",
"md5": "<md5>",
"aesKey": "<aesKey>",
"size": 1209017,
"width": 1080,
"height": 1920,
"thumbMd5": "<md5>",
"thumbWidth": 326,
"thumbHeight": 580,
"thumbFileSize": 25455,
"midImageFileSize": 25455
}
}语音(16)
voiceTime 是秒数;silk 格式,调 CDN 下载。
查看样本
json
{
"id": 1013637,
"messageType": 0,
"contentType": 16,
"summary": "[语音]",
"fromUserId": 7881300000000002,
"toUserId": 1688850000000001,
"sendTime": 1789112161,
"content": {
"id": "<下载凭证>",
"md5": "<md5>",
"aesKey": "<aesKey>",
"size": 2608,
"voiceTime": 2
}
}视频(23 / 单聊 103)
23:用id与aesKey调 CDN 下载;path与sourcePath是发送端本地路径,忽略即可。103(单聊):带url与封面previewImgUrl,都带临时凭证,可直接下载;另有videoWidth/videoHeight/videoDuration;summary为[视频]。
查看样本
json
{
"id": 1013739,
"messageType": 0,
"contentType": 23,
"summary": "",
"fromUserId": 1688850000000001,
"toUserId": 7881300000000002,
"sendTime": 1789184127,
"content": {
"id": "<下载凭证>",
"md5": "<md5>",
"aesKey": "<aesKey>",
"size": 2533630,
"width": 1920,
"height": 1080,
"duration": 2,
"thumbUrl": "https://wework.qpic.cn/wwpic3az/…(封面直链)",
"path": "<发送端本地路径>",
"sourcePath": "<发送端本地路径>"
}
}文件(15 / 群与转发 20)
用 id 与 aesKey 调 CDN 下载,文件名在 name。20 结构相同,summary 形如 发送人昵称 : [文件名]。
查看样本
json
{
"id": 1013745,
"messageType": 0,
"contentType": 15,
"summary": "",
"fromUserId": 1688850000000001,
"toUserId": 7881300000000002,
"sendTime": 1789184468,
"content": {
"id": "<下载凭证>",
"md5": "<md5>",
"aesKey": "<aesKey>",
"url": "",
"name": "示例文件.jpg",
"size": 1863186
}
}动画表情(104)
hex 是十六进制数据,内含表情的 CDN 地址与表情信息。
查看样本
json
{
"id": 1013605,
"messageType": 0,
"contentType": 104,
"summary": "[动画表情]",
"fromUserId": 7881300000000002,
"toUserId": 1688850000000001,
"sendTime": 1789111816,
"content": {
"hex":
"0a4768747470733a2f2f…(十六进制,内含 CDN url 与表情信息)",
"msgType": 104
}
}图文、公众号文章卡片(31 / 105)
summary 就是文章标题,可直接展示;标题、摘要、落地页与配图等明细在 hex 里。系统图文(105,如「一周小结」)结构相同。
查看样本
json
{
"id": 1013415,
"messageType": 3,
"contentType": 31,
"roomId": 10120,
"fromUserId": 10120,
"summary": "同事们在看《示例文章标题》",
"sendTime": 1789085330,
"content": {
"hex":
"0aeb020a…(十六进制,内含标题 / 摘要 / 落地页 / 配图 url)",
"msgType": 31
}
}链接、视频号卡片(13)
普通链接读 title、description、imageUrl、url 四个字段;视频号卡片在 sph_feed_h5_message 里,字段是 base64。
查看样本
json
{
"id": 1001089,
"messageType": 1,
"contentType": 13,
"roomId": 10000000000002,
"fromUserId": 1688850000000001,
"summary": "发送人昵称 : [视频号]的视频",
"sendTime": 1789191553,
"content": {
"title": "卡片标题",
"description": "卡片描述",
"imageUrl": "https://example.com/cover.jpg",
"sph_feed_h5_message": {"url": "<base64>"}
}
}系统通知
已读回执(2001)
发出任意消息后都会收到一条,hex 很短,一般可忽略。
查看样本
json
{
"id": 1013420,
"messageType": 0,
"contentType": 2001,
"roomId": 0,
"fromUserId": 1688850000000001,
"toUserId": 7881300000000002,
"sendTime": 1789089094,
"content": {"hex": "080210aba6dd052800", "msgType": 2001}
}外部联系人信息变动或删除(2131)
对应事件为 contact.modified;删除外部联系人还会产生 friend.deleted。不能只凭 2131 判断删除,需同步外部联系人后判断是增是删。
fromUserId 是系统号 10030,hex 为空,只当信号。收到后调同步外部数据(非企业)拉增量。
查看样本
json
{
"id": 1013407,
"messageType": 3,
"contentType": 2131,
"roomId": 10030,
"fromUserId": 10030,
"toUserId": 0,
"summary": "",
"sendTime": 1789047615,
"content": {"hex": "", "msgType": 2131}
}好友申请 · 带明文(2357)
对应事件为 friend.added。
少数直接给明文的系统通知:uin 是申请人,corpId 与 corpName 是其企业,customerName 是昵称,source 是来源。可直接展示,用同意新客户同意。
查看样本
json
{
"id": 1013589,
"messageType": 3,
"contentType": 2357,
"roomId": 10030,
"fromUserId": 10030,
"summary": "示例客户@微信申请添加你为联系人",
"sendTime": 1789111073,
"content": {
"uin": 7881300000000002,
"corpId": 1970320000000001,
"source": "微信",
"corpName": "示例网络科技",
"customerName": "示例客户"
}
}好友申请(2132)
对应事件为 friend.added。
同为好友申请,但 hex 为空,只当信号;同意同样用同意新客户。
查看样本
json
{
"id": 1013587,
"messageType": 3,
"contentType": 2132,
"roomId": 10030,
"fromUserId": 10030,
"summary": "",
"sendTime": 1789111073,
"content": {"hex": "", "msgType": 2132}
}群信息变动(2118)
对应事件为 contact.modified。
群设置一有变更就会推送若干条 2118 以及具体事件,是最频繁的群推送(hex 为空);按 roomId 调获取群资料刷新即可。
查看样本
json
{
"id": 1001024,
"messageType": 1,
"contentType": 2118,
"roomId": 10000000000002,
"fromUserId": 1688850000000012,
"summary": "",
"sendTime": 1789182975,
"content": {"hex": "", "msgType": 2118}
}群成员变动、建群(1006)
对应事件为 contact.modified。
hex 解出来是分号连接的成员 id 列表,收到后刷新群成员。
查看样本
json
{
"id": 1001020,
"messageType": 1,
"contentType": 1006,
"roomId": 10000000000002,
"fromUserId": 1688850000000012,
"summary": "",
"sendTime": 1789182974,
"content": {
"hex": "31363838…(十六进制,解出为分号连接的成员 uin 列表)",
"msgType": 1006
}
}其它系统信号(2104 / 2130 / 2180 / 2201 等)
结构都一样:messageType 为 3,发送方是系统号,content.hex 为空。除 2104(联系人免打扰、置顶)外,含义都未确认,原样保存。
查看样本
json
{
"id": 1013412,
"messageType": 3,
"contentType": 2180,
"roomId": 10014,
"fromUserId": 10014,
"summary": "",
"sendTime": 1789047766,
"content": {"hex": "", "msgType": 2180}
}连接事件
实例的企微连接建立时推送 instance.online,请求体为 {};断开时推送 instance.offline,请求体形如:
json
{ "code": 0, "message": "手动关闭长链", "time": "2026-09-11 16:50:12" }instance.offline 的 code 按下表处理:
| code | 含义 |
|---|---|
0 | 用户主动关闭 |
-1008 | 移动端主动退出 |
-11001 | 需要断线重连 |
-11002 | 已在其他设备登录 |
-2007 | 已下线 |
-1 | 连接异常,详情看 message |
-11001 和 -11002 都会推送 instance.offline。同时保留定期业务探测,见实例与代理 · 掉线检测与恢复。
只有 -11001 可以自动重连
-11002 不要自动重连,否则会和另一台设备互相顶号、反复掉线。应置为离线,提示「已在其他设备登录」,由用户决定是否重新登录。
断线重连返回 code=0 只代表已经开始恢复;之后的业务调用不再报 -11002 / -2007,才可继续判断在线状态。重连失败要间隔几十秒以上再试,连续失败就重新扫码。
大文件上传完成
上传大文件到 CDN是异步的:接口先返回 requestId,上传完成后系统推送一条大文件事件。事件名以可订阅事件列表接口返回为准。请求体如下(暂无真实样本,按协议整理):
json
{
"content": {
"id": "*1*<大文件 id,含下载凭证>",
"name": "文件名",
"url": "",
"size": 6342632,
"aesKey": "",
"md5": "<md5>"
},
"requestId": "<与同步响应一致>"
}requestId 与接口同步返回的一致;content.id(*1* 开头)可直接用来发送大文件。上传失败时推送的结构相同;源地址 404 时接口直接返回 code -1,不推送,只有「下载成功、上传失败」才推送失败通知。