企业微信自建应用消息
企业自建应用适合按组织身份向成员、部门或标签发送工作通知。它比群消息推送的配置更多,但接收范围和权限更可控。本文依据企业微信官方资料整理,核验日期为 2026-09-08;未使用真实企业执行发送验证。
本页介绍的是 message/send 应用消息:接收目标是企业内部的成员、部门或标签,消息显示在成员的应用会话中。它不能直接向任意已有内部群或外部客户群发送消息。
- 若要向固定内部群实时通知,使用消息推送(原群机器人)。
- 若要向由应用管理的内部群聊会话发送消息,应另行评估官方应用发送消息到群聊会话接口。
- 若要触达外部客户群,评估创建企业群发,但该能力需要成员确认,不是实时机器人推送。
- 企业微信企业已经创建完成,操作者能登录企业管理后台。
- 操作者有自建应用管理权限,能创建应用或编辑目标应用。
- 已确定最小可见范围,并准备一名处于该范围内的测试成员。
- 服务端有稳定的公网出口 IP。新创建的自建应用调用接口前需要配置企业可信 IP。
- 服务端能够通过 HTTPS 访问
qyapi.weixin.qq.com,并能安全保存应用 Secret 和 Token。 - 已明确接收目标使用成员
userid、部门 ID 还是标签 ID;显示名和手机号不能直接替代userid。
如何判断自己有没有应用管理权限
Section titled “如何判断自己有没有应用管理权限”打开 企业微信管理后台的应用管理页,扫码登录后检查:
- 能进入应用管理 → 应用 → 自建并看到“创建应用”:可以创建自建应用。
- 能进入已有应用并修改可见范围、企业可信 IP:可以维护该应用的发送配置。
- 能查看 AgentId,并按页面安全流程取得 Secret:具备完成服务端接入所需的凭据权限。
- 只能看到应用列表,不能创建、编辑或取得 Secret:当前管理权限不足,应让超级管理员创建应用或授予对应应用管理权限。
不同企业的管理员分工可能不同,不要仅凭“我是群主”判断;群主权限与企业自建应用管理权限无关。
1. 在 Web 管理后台创建应用
Section titled “1. 在 Web 管理后台创建应用”- 打开 企业微信管理后台:应用管理 并由有权限的管理员登录。
- 进入应用管理 → 应用 → 自建,点击创建应用。
- 填写应用 Logo、名称和介绍。
- 配置可见范围。首次联调建议只选择测试成员或测试部门,不要直接开放到全企业。
- 完成创建后进入应用详情页,确认应用已启用。
企业微信官方简易教程同样给出了“管理端 → 应用与小程序 → 应用 → 自建 → 创建应用”的路径;后台菜单名称可能随版本略有调整。
2. 取得 CorpID、Secret 和 AgentId
Section titled “2. 取得 CorpID、Secret 和 AgentId”| 字段 | 获取位置 | 注意事项 |
|---|---|---|
CORP_ID | 管理后台的我的企业 → 企业信息 | 是企业标识,不是应用 ID |
APP_SECRET | 自建应用详情页的 Secret 区域 | 每个应用独立;不要使用通讯录 Secret 或其他应用 Secret |
AGENT_ID | 自建应用详情页 | 数值型应用 ID,发送请求时必须与 Secret 所属应用一致 |
Secret 通常需要按管理后台提示完成身份确认后查看。只把它交给服务端配置人员,不通过聊天、截图或前端代码传递。
3. 配置企业可信 IP
Section titled “3. 配置企业可信 IP”在自建应用详情页找到企业可信 IP,添加实际调用企业微信 API 的公网出口 IP。企业微信官方“开发前必读”说明:2022-06-20 20:00 后新创建的自建应用必须配置可信 IP,只有配置的 IP 能调用接口。
- 填写 NAT、网关或云函数对外访问时真正使用的出口 IP,不是容器内网 IP。
- 多节点部署时列出所有可能的稳定出口 IP。
- 出口 IP 会动态变化的开发电脑不适合长期直连;可通过固定出口的后端服务调用。
- 修改网络、NAT 或部署区域后,应重新核对可信 IP。
4. 核对可见范围和接收者
Section titled “4. 核对可见范围和接收者”应用只能向可见范围内的成员发送。先用一名明确可见、已激活企业微信且具备应用许可的成员 userid 做联调,再逐步扩大范围。
如果使用部门或标签作为目标,也要确保对应成员落在应用可见范围内。扩大可见范围属于权限变更,应由应用负责人确认。
5. 获取并缓存 access_token
Section titled “5. 获取并缓存 access_token”调用 gettoken,传入当前企业的 CorpID 和当前应用的 Secret。返回成功时会得到 access_token 和 expires_in;正常情况下有效期为 7200 秒。
- Token 只能供颁发它的应用使用,不同应用必须分开缓存。
- 不要频繁调用
gettoken,应按expires_in缓存并预留刷新余量。 - 企业微信可能提前使 Token 失效,调用方应在明确的失效返回码下刷新一次并重试。
- Token 和 Secret 不能返回给浏览器前端,所有 API 请求都应由后端发起。
6. 发送最小文本消息
Section titled “6. 发送最小文本消息”调用 message/send,同时提供接收目标、当前应用的 agentid 和消息内容。先向单个测试成员发送,确认成功后再启用部门或标签目标。
| 字段 | 必需 | 说明 |
|---|---|---|
CORP_ID | 是 | 企业 ID |
APP_SECRET | 是 | 当前自建应用的 Secret |
AGENT_ID | 是 | 当前自建应用的 AgentId |
ACCESS_TOKEN | 是 | 有有效期的服务端令牌,由 CorpID 和应用 Secret 换取 |
TO_USER | 按目标 | 成员 userid,多个值使用英文竖线分隔 |
TO_PARTY | 按目标 | 部门 ID,多个值使用英文竖线分隔 |
TO_TAG | 按目标 | 标签 ID,多个值使用英文竖线分隔 |
touser、toparty、totag 不能同时为空。发送应用消息的官方限制为:touser 最多 1000 个成员,toparty 最多 100 个部门,totag 最多 100 个标签。
JavaScript 示例需要 Node.js 20 或更新版本;Python 示例需要安装 requests。
curl 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=CORP_ID&corpsecret=APP_SECRET'
curl -X POST 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN' \ -H 'Content-Type: application/json' \ -d '{"touser":"USER_ID","msgtype":"text","agentid":AGENT_ID,"text":{"content":"通知渠道连通性测试"},"safe":0}'const tokenUrl = new URL('https://qyapi.weixin.qq.com/cgi-bin/gettoken');tokenUrl.searchParams.set('corpid', process.env.CORP_ID);tokenUrl.searchParams.set('corpsecret', process.env.APP_SECRET);const tokenResponse = await fetch(tokenUrl);if (!tokenResponse.ok) throw new Error(`Token HTTP ${tokenResponse.status}`);const tokenResult = await tokenResponse.json();if (tokenResult.errcode !== 0) throw new Error(JSON.stringify(tokenResult));
const sendUrl = new URL('https://qyapi.weixin.qq.com/cgi-bin/message/send');sendUrl.searchParams.set('access_token', tokenResult.access_token);const response = await fetch(sendUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ touser: process.env.USER_ID, msgtype: 'text', agentid: Number(process.env.AGENT_ID), text: { content: '通知渠道连通性测试' }, safe: 0, }),});if (!response.ok) throw new Error(`Send HTTP ${response.status}`);const result = await response.json();if (result.errcode !== 0) throw new Error(JSON.stringify(result));console.log(result);import osimport requests
token_response = requests.get( "https://qyapi.weixin.qq.com/cgi-bin/gettoken", params={"corpid": os.environ["CORP_ID"], "corpsecret": os.environ["APP_SECRET"]}, timeout=15,)token_response.raise_for_status()token_result = token_response.json()if token_result.get("errcode") != 0: raise RuntimeError(token_result)
response = requests.post( "https://qyapi.weixin.qq.com/cgi-bin/message/send", params={"access_token": token_result["access_token"]}, json={ "touser": os.environ["USER_ID"], "msgtype": "text", "agentid": int(os.environ["AGENT_ID"]), "text": {"content": "通知渠道连通性测试"}, "safe": 0, }, timeout=15,)response.raise_for_status()result = response.json()if result.get("errcode") != 0: raise RuntimeError(result)print(result)发送响应的 errcode 应为 0,目标成员应在对应应用会话中看到测试消息。还要检查成功响应中的部分失败字段:
invaliduser:成员不存在、不在可见范围内或没有权限。invalidparty:部门不存在、无权限或不在应用范围内。invalidtag:标签不存在或不可用。unlicenseduser:成员没有可用的企业微信应用许可。81013:所有接收人都无权限或不存在。
不要只记录 errmsg=ok;将上述字段做脱敏后写入调用日志和告警,才能发现“请求成功但部分成员没有收到”的情况。
调用限制与投递策略
Section titled “调用限制与投递策略”- 同一成员接收同一应用消息的限制为 30 次/分钟、1000 次/小时。
- 每个应用的每日发送上限按企业账号上限人数乘以 200 人次计算。
- 官方建议避免所有应用集中在每小时的 0 分和 30 分触发。
- 可按业务需要使用
enable_duplicate_check和重复检查间隔,减少重试产生的重复消息。
生产环境应对同一事件生成幂等键,并把平台业务错误、部分失败目标和 HTTP 错误分开处理。
- Secret 和 Token 只在服务端使用,按企业和应用隔离存储。
- 日志、监控、错误上报和链路追踪中都要对 Secret、Token 和成员标识脱敏。
- 不要为方便测试把可见范围扩大到全企业,先使用专门的测试成员或部门。
- 只配置必要的固定出口 IP;网络变更时同步更新可信 IP。
- Token 缓存要设置过期时间并避免多节点同时刷新,可使用共享缓存或刷新锁。
- 应用停用、负责人变更或 Secret 泄露时及时轮换 Secret,并清除旧 Token。
管理后台没有“创建应用”按钮:当前账号没有自建应用管理权限。请超级管理员创建应用或调整应用管理权限;群主身份不会赋予该权限。
无法获取 access_token:确认应用处于启用状态,CorpID 与应用 Secret 属于同一企业,并检查请求出口 IP 是否已加入企业可信 IP。
成员未收到但接口返回成功:检查 invaliduser、unlicenseduser 等部分失败字段,再核对 userid、应用可见范围、成员激活状态和许可。
返回 81013:所有接收目标均不存在或无权限。先用应用可见范围内的一名已知测试成员验证。
AgentId 不匹配:发送请求中的 agentid 必须与换取 Token 所用 Secret 的应用一致。
Token 频繁失效:按应用缓存 access_token,使用 expires_in 管理有效期;只在过期或明确的失效返回码下刷新。
想发送到已有群聊或客户群:message/send 不是任意群消息接口。内部固定群可使用消息推送;客户群只能评估企业群发等客户联系能力。