企微内部应用发消息,和向客户发消息是两套逻辑。内部应用面向的是企业成员,消息类型更丰富,支持卡片、按钮、跳转链接。这篇讲清楚内部应用消息怎么发。
先分清内部应用和外部联系人
内部应用消息发给的是企业成员(员工),不是外部客户。成员的标识是uin(int64),和外部客户的 uin 范围不同。
发送接口还是message/sendText,但conversationId指向的是成员的单聊会话。关键问题变成:怎么从成员 uin 拿到单聊会话 id。
从成员到会话
没有"给 uin 返回会话 id"的直接接口。实际做法:
本地缓存:之前发过消息,会话 id 已存
历史消息捞:调
message/getHistoryMessageList传 uin,挑messageType=0的记录
def get_conv_id(uin): cached = redis.get(f"conv:{uin}") if cached: return int(cached) resp = call("message", "getHistoryMessageList", {"uin": uin}) for item in resp["data"]["list"]: if item["messageType"] == 0: redis.set(f"conv:{uin}", item["conversationId"]) return item["conversationId"] return None发文本消息
拿到会话 id 后发文本:
resp = requests.post( f"{BASE}/wx-api/api/message/sendText", headers=HEADERS, json={ "appid": APPID, "conversationId": conv_id, "content": "审批已通过,请查收", } )发卡片消息
企微的卡片消息比纯文本体验好得多。支持标题、摘要、封面图、跳转链接:
content = { "title": "新工单提醒", "description": "您有一条新工单待处理", "url": "https://your-system.com/ticket/123", "picurl": "https://cdn.example.com/cover.png", } resp = requests.post( f"{BASE}/wx-api/api/message/sendRichText", headers=HEADERS, json={"appid": APPID, "conversationId": conv_id, "content": content} )卡片消息的字段和企微后台的"应用消息"格式对应,url是点击跳转的地址。
批量发送
向多个成员发同一条消息,循环调单发接口:
def batch_send(uins, content): for uin in uins: conv_id = get_conv_id(uin) if conv_id: send_text(conv_id, content)注意限流。批量发送时加间隔,或提前预热好所有会话 id。
发送回执
消息发出去后,调message/getMessageReceipt查送达状态:
resp = call("message", "getMessageReceipt", {"msgId": msg_id}) # 返回里带 status 字段回执用于确认消息真的到了,重要通知建议核对。
内部应用消息的典型场景
场景 | 消息类型 | 说明 |
|---|---|---|
审批结果通知 | 卡片 | 带跳转链接,点进去看详情 |
工单派单 | 富文本 | 高亮工单号、优先级 |
日报提醒 | 文本 | 简单直接 |
系统告警 | 富文本 | 红色高亮关键指标 |
小结
内部应用消息的核心是"从成员到会话"这一步。会话 id 拿到后,文本、卡片、富文本都是同一个接口的不同参数。批量发送时注意限流,重要消息核对回执。
接口用的是Eyun 平台的企业微信 API,路径统一是/wx-api/api/<模块>/<动作>,鉴权Bearer eyk_xxxx。凭证在官网开通实例时拿到,消息类型和字段在开发文档里有完整说明。