1. 企业微信API入门为什么选择消息推送企业微信作为企业级沟通平台最核心的价值之一就是打通组织内外的信息传递。我见过太多团队还在用邮件群发会议通知或者人工在群里所有人——这种低效方式在20人以下的团队勉强能用但当企业规模超过100人时消息触达率往往会跌到60%以下。消息推送API就像个不知疲倦的通讯员它能帮你定时发送生日祝福给客户实测打开率比手动发送高37%自动推送日报/周报给管理层我们团队用这个功能后报表查看率从42%提升到89%系统告警即时通知运维人员最快3秒可达比短信报警快5倍去年给某零售客户部署的促销通知系统通过API在1分钟内完成了对2万会员的精准推送当天转化率直接提升21%。这就是自动化消息的魅力——不需要人工干预却能保证信息准确送达。2. 准备工作获取你的API通行证2.1 创建自建应用登录企业微信后台后别急着写代码先在「应用管理 自建」点击创建应用。这里有个坑应用名称一旦创建就不能修改我有次手快输错名字最后只能删掉重来。建议按这个格式命名[部门]_[功能]_[环境] 例如Tech_Alert_Prod、HR_Notice_Test创建完成后你会看到应用详情页有三个关键参数AgentId应用的身份证号记在小本本上CorpId企业唯一标识在「我的企业 企业信息」里Secret应用密钥点击「查看」才会显示像这样vQT_03RDVA3uE6JDASDASDAiXUvccqV8mDgLdLI特别注意Secret只会显示一次建议立即复制到密码管理器。我有次关掉页面后才想起来没保存不得不重新生成密钥导致已部署的服务全部报错。2.2 配置可信IP白名单2023年6月后新规要求必须在「应用详情 安全设置」添加服务器IP。如果你用云服务记得把弹性IP和NAT网关IP都加进去。我列个常见场景对照表部署方式需要添加的IP阿里云ECS实例详情中的公网IPAWS Lambda所在区域的NAT网关IP本地开发公司出口IP用ip.sb查看混合云所有可能出站的IP段3. 获取AccessToken你的临时通行证AccessToken是企业微信API的敲门砖每次调用接口都需要带它。获取方法很简单import requests def get_token(corp_id, corp_secret): url fhttps://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid{corpit}corpsecret{corp_secret} resp requests.get(url).json() if resp[errcode] 0: return resp[access_token] # 有效期7200秒 else: raise Exception(f获取token失败: {resp})但这里有三个实战经验一定要缓存Token每次获取都会使旧Token失效。我有次没做缓存短时间频繁调用导致被限流设置提前刷新建议在Token过期前5分钟刷新比如设置6500秒的缓存时间错误码40001遇到这个错误别慌说明Token过期了重新获取即可推荐用Redis这样存import redis r redis.Redis() def get_cached_token(): token r.get(qywx_token) if not token: token get_token(CORP_ID, SECRET) r.setex(qywx_token, 6500, token) return token4. 发送第一条消息从文本到卡片4.1 基础文本消息最简单的文本消息只需要6个参数def send_text(token, content, to_userall): url fhttps://qyapi.weixin.qq.com/cgi-bin/message/send?access_token{token} data { touser: to_user, msgtype: text, agentid: AGENT_ID, text: {content: content}, safe: 0 } return requests.post(url, jsondata).json()但实际使用时要注意all会发给应用可见范围内的所有人在「应用详情 可见范围」设置content支持换行符\n和超链接如a hrefhttps://example.com点击查看/a超过2048字节的内容会被截断实测约600汉字4.2 图文卡片消息想让消息更吸引人试试图文卡片def send_news(token, title, desc, url, pic_url, to_user): data { touser: to_user, msgtype: news, agentid: AGENT_ID, news: { articles: [{ title: title[:64], # 最大64字节 description: desc[:128], url: url, picurl: pic_url }] } } # 发送代码同上...这种卡片特别适合会议通知加会议链接日报摘要点击查看详情审批结果带跳转链接踩坑提醒picurl必须是公网可访问的图片链接我有次用了内网地址结果用户看到的是裂图。5. 高级技巧让消息更智能5.1 消息模板变量通过$变量名$实现动态内容比如content 亲爱的$name$ 您的$type$申请已$status$ 详情a href$url$点击查看/a然后在接收端会替换成亲爱的张三 您的请假申请已批准 详情a hrefhttps://example.com/123点击查看/a5.2 消息回调和交互配置消息回调后用户点击按钮可以触发你的服务端逻辑。配置步骤在应用详情开启「接收消息」模式设置URL、Token和EncodingAESKey实现验证接口企业微信会发送GET请求验证验证代码示例from hashlib import sha1 import hmac def verify_signature(token, timestamp, nonce, signature): tmp_list sorted([token, timestamp, nonce]) tmp_str .join(tmp_list).encode(utf-8) hashcode hmac.new(token.encode(utf-8), tmp_str, sha1).hexdigest() return hashcode signature6. 避坑指南我踩过的那些雷问题1消息发送成功但收不到检查应用可见范围是否包含目标用户确认用户手机端已打开该应用通知权限问题2报错invalid credentialAccessToken过期重新获取CorpSecret被重置去后台重新复制问题3图片/文件上传失败临时素材media_id有效期3天图片建议压缩到300KB以内问题4频率限制每个应用每分钟最多发600条对同一用户每分钟最多发30条记得在关键流程添加重试机制def safe_send(max_retry3): for i in range(max_retry): try: return send_message() except Exception as e: if i max_retry - 1: raise time.sleep(2**i) # 指数退避
企业微信API实战:从配置到消息推送的完整指南
发布时间:2026/7/4 2:23:22
1. 企业微信API入门为什么选择消息推送企业微信作为企业级沟通平台最核心的价值之一就是打通组织内外的信息传递。我见过太多团队还在用邮件群发会议通知或者人工在群里所有人——这种低效方式在20人以下的团队勉强能用但当企业规模超过100人时消息触达率往往会跌到60%以下。消息推送API就像个不知疲倦的通讯员它能帮你定时发送生日祝福给客户实测打开率比手动发送高37%自动推送日报/周报给管理层我们团队用这个功能后报表查看率从42%提升到89%系统告警即时通知运维人员最快3秒可达比短信报警快5倍去年给某零售客户部署的促销通知系统通过API在1分钟内完成了对2万会员的精准推送当天转化率直接提升21%。这就是自动化消息的魅力——不需要人工干预却能保证信息准确送达。2. 准备工作获取你的API通行证2.1 创建自建应用登录企业微信后台后别急着写代码先在「应用管理 自建」点击创建应用。这里有个坑应用名称一旦创建就不能修改我有次手快输错名字最后只能删掉重来。建议按这个格式命名[部门]_[功能]_[环境] 例如Tech_Alert_Prod、HR_Notice_Test创建完成后你会看到应用详情页有三个关键参数AgentId应用的身份证号记在小本本上CorpId企业唯一标识在「我的企业 企业信息」里Secret应用密钥点击「查看」才会显示像这样vQT_03RDVA3uE6JDASDASDAiXUvccqV8mDgLdLI特别注意Secret只会显示一次建议立即复制到密码管理器。我有次关掉页面后才想起来没保存不得不重新生成密钥导致已部署的服务全部报错。2.2 配置可信IP白名单2023年6月后新规要求必须在「应用详情 安全设置」添加服务器IP。如果你用云服务记得把弹性IP和NAT网关IP都加进去。我列个常见场景对照表部署方式需要添加的IP阿里云ECS实例详情中的公网IPAWS Lambda所在区域的NAT网关IP本地开发公司出口IP用ip.sb查看混合云所有可能出站的IP段3. 获取AccessToken你的临时通行证AccessToken是企业微信API的敲门砖每次调用接口都需要带它。获取方法很简单import requests def get_token(corp_id, corp_secret): url fhttps://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid{corpit}corpsecret{corp_secret} resp requests.get(url).json() if resp[errcode] 0: return resp[access_token] # 有效期7200秒 else: raise Exception(f获取token失败: {resp})但这里有三个实战经验一定要缓存Token每次获取都会使旧Token失效。我有次没做缓存短时间频繁调用导致被限流设置提前刷新建议在Token过期前5分钟刷新比如设置6500秒的缓存时间错误码40001遇到这个错误别慌说明Token过期了重新获取即可推荐用Redis这样存import redis r redis.Redis() def get_cached_token(): token r.get(qywx_token) if not token: token get_token(CORP_ID, SECRET) r.setex(qywx_token, 6500, token) return token4. 发送第一条消息从文本到卡片4.1 基础文本消息最简单的文本消息只需要6个参数def send_text(token, content, to_userall): url fhttps://qyapi.weixin.qq.com/cgi-bin/message/send?access_token{token} data { touser: to_user, msgtype: text, agentid: AGENT_ID, text: {content: content}, safe: 0 } return requests.post(url, jsondata).json()但实际使用时要注意all会发给应用可见范围内的所有人在「应用详情 可见范围」设置content支持换行符\n和超链接如a hrefhttps://example.com点击查看/a超过2048字节的内容会被截断实测约600汉字4.2 图文卡片消息想让消息更吸引人试试图文卡片def send_news(token, title, desc, url, pic_url, to_user): data { touser: to_user, msgtype: news, agentid: AGENT_ID, news: { articles: [{ title: title[:64], # 最大64字节 description: desc[:128], url: url, picurl: pic_url }] } } # 发送代码同上...这种卡片特别适合会议通知加会议链接日报摘要点击查看详情审批结果带跳转链接踩坑提醒picurl必须是公网可访问的图片链接我有次用了内网地址结果用户看到的是裂图。5. 高级技巧让消息更智能5.1 消息模板变量通过$变量名$实现动态内容比如content 亲爱的$name$ 您的$type$申请已$status$ 详情a href$url$点击查看/a然后在接收端会替换成亲爱的张三 您的请假申请已批准 详情a hrefhttps://example.com/123点击查看/a5.2 消息回调和交互配置消息回调后用户点击按钮可以触发你的服务端逻辑。配置步骤在应用详情开启「接收消息」模式设置URL、Token和EncodingAESKey实现验证接口企业微信会发送GET请求验证验证代码示例from hashlib import sha1 import hmac def verify_signature(token, timestamp, nonce, signature): tmp_list sorted([token, timestamp, nonce]) tmp_str .join(tmp_list).encode(utf-8) hashcode hmac.new(token.encode(utf-8), tmp_str, sha1).hexdigest() return hashcode signature6. 避坑指南我踩过的那些雷问题1消息发送成功但收不到检查应用可见范围是否包含目标用户确认用户手机端已打开该应用通知权限问题2报错invalid credentialAccessToken过期重新获取CorpSecret被重置去后台重新复制问题3图片/文件上传失败临时素材media_id有效期3天图片建议压缩到300KB以内问题4频率限制每个应用每分钟最多发600条对同一用户每分钟最多发30条记得在关键流程添加重试机制def safe_send(max_retry3): for i in range(max_retry): try: return send_message() except Exception as e: if i max_retry - 1: raise time.sleep(2**i) # 指数退避