Python 接入微信机器人 API:Webhook + 自动回复完整示例
给要在自己业务系统里接一个"收微信消息 → 自动回复"闭环的后端同学。本文以 WTAPI微信机器人开发平台的接口为例,演示从发消息到 Webhook 自动回复的最小闭环,复制改 Token 即可用,不讲协议原理。
一、接入架构
整体链路三段:凭证 → 登录 → 收发。
- 凭证:平台 Token(请求头
X-finder-TOKEN)+ Bearer 授权(部分环境必需,登录后拿到)。 - 登录:控制台「微信实例」页扫码拿
appId(实例标识);走 API 登录则调getLoginQrCode+checkLogin轮询。 - 收发:主动发消息走 HTTP
POST,收消息走 Webhook 回调。
Base URL 统一为 登录WTAPI查看,所有接口都是 POST,Content-Type 为 application/json。
二、发一条文本消息(最小验证)
先跑通"发",证明凭证和实例都 OK。WTAPI 的 postText 接口必传三个参数:appId(实例标识)、toWxid(接收方)、content(文本内容)。测试时把 toWxid 设为 filehelper(文件传输助手),避免打扰真实用户。
import requests, json
BASE = "https://wx.chuapi.com"
HEADERS = {
"X-finder-TOKEN": "<你的平台Token>", # WTAPI 控制台「Token回调」页获取
"Authorization": "Bearer <你的Bearer>",
"Content-Type": "application/json",
}
APP_ID = "<你的appId>" # 控制台「微信实例」页扫码后生成
def send_text(to_wxid, content):
url = f"{BASE}/finder/v2/api/message/postText"
payload = {"appId": APP_ID, "toWxid": to_wxid, "content": content}
resp = requests.post(url, headers=HEADERS, json=payload, timeout=10)
return resp.json()
if __name__ == "__main__":
print(send_text("filehelper", "Hello, 机器人已上线"))
返回 ret: 200 就算接入成功。鉴权失败先去控制台「Token回调」页核对 Token 和 Bearer 是否最新。
三、Webhook 收消息 + 自动回复
发消息是主动调接口,收消息要靠平台把消息推过来。WTAPI 回调统一报文结构如下(以文本消息为例):
{
"TypeName": "AddMsg",
"Appid": "wx_e2PiMSX8ySDV6tQGroCDc",
"Wxid": "wxid_msxcysdpcdf18",
"Data": {
"MsgId": 1040357364,
"FromUserName": {"string": "wxid_sender"},
"ToUserName": {"string": "wxid_receiver"},
"MsgType": 1,
"Content": {"string": "你好"},
"NewMsgId": 7353749793478223190,
"CreateTime": 1705041728
}
}
起一个公网可访问的 Flask 服务,在控制台「访问控制」→「配置回调地址」里填这个 URL,平台就会以 HTTP POST JSON 实时推送。
回调有两个硬约束(WTAPI 文档明确):
- 3 秒内必须响应(建议直接返回
""或 HTTP 200),业务逻辑要异步处理。 - 必须用
Appid + Data.NewMsgId做去重,否则同一条消息会被推两次。
from flask import Flask, request
app = Flask(__name__)
DEDUP = set() # 生产环境用 Redis,这里用集合演示
def send_text(to_wxid, content):
# 复用上面的 send_text 实现
pass
@app.route("/webhook", methods=["POST"])
def webhook():
data = request.json or {}
msg = data.get("Data", {})
appid = data.get("Appid", "")
new_msg_id = msg.get("NewMsgId", "")
# 去重:Appid + NewMsgId
dedup_key = f"{appid}:{new_msg_id}"
if dedup_key in DEDUP:
return ""
DEDUP.add(dedup_key)
# 只处理文本消息(MsgType=1)
if msg.get("MsgType") != 1:
return ""
from_wxid = msg.get("FromUserName", {}).get("string", "")
content = msg.get("Content", {}).get("string", "")
self_wxid = data.get("Wxid", "")
# 群消息判定:from_wxid 以 @chatroom 结尾
# 群内真实发送者在 content 里 "wxid_xxxx:\n" 前缀
is_group = from_wxid.endswith("@chatroom")
if is_group:
sender_wxid, _, real_content = content.partition(":\n")
else:
sender_wxid, real_content = from_wxid, content
# 跳过自己发的消息
if sender_wxid == self_wxid:
return ""
# 关键词自动回复
if "你好" in real_content:
send_text(sender_wxid, "你好呀,有什么可以帮你?")
elif "价格" in real_content:
send_text(sender_wxid, "报价单已发你,请查收。")
return ""
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
跑起来后,给登录的微信号发"你好",机器人秒回"你好呀"——收发闭环就通了。
四、常见报错与排查
- 回调收不到消息:先用 Apifox/Postman 手动向
/webhook发一条 POST,确认服务能收;能收但平台没推,检查控制台回调地址是否保存成功——保存时平台会发一条"验证回调地址是否可用"测试数据。 - 同一条消息回了两次:去重键没用对,必须用
Appid + Data.NewMsgId,不要用MsgId(稳定性差)。 - 3 秒超时:回调里别同步调外部 API,收到消息丢进队列(Celery/RQ),立即返回
""。 - 鉴权失败:确认
X-finder-TOKEN没拼错,Bearer 没过期;部分环境 Bearer 是必需的不是可选的。
五、扩展方向
跑通闭环后,把 send_text 换成发图片/文件/链接,或把关键词匹配换成接 LLM(GPT/Claude)生成回复,就是一个完整的 AI 客服底座。群管、朋友圈、标签分层都是在收发闭环上叠功能。
参考资料
WTAPI 开发文档(接口路径与字段以文档内容为准)weiti.apifox.cn
合规声明
本文示例仅用于技术学习与合规私域自动化场景,
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)