前置条件
- 1已注册腾讯云账号,有一台云服务器(2C4G 起步)
- 2有一个企业微信账号,且是该企业的管理员(或有权限创建自建应用)
- 3一个已备案的域名(企业微信回调要求公网 HTTPS 地址)
- 4服务器上已跑起大模型服务(Ollama)或已准备云端模型 API Key
读完想动手?新用户首单 8 折上云
服务器 + 大模型 API + 对象存储,新用户首购享 20% 补贴
企业微信 AI 助理腾讯云搭建完整指南
先说一个前提:不要用第三方协议登录个人微信做业务机器人。个人微信的用户协议不允许第三方客户端登录,实测中群发、异地登录最容易触发风控甚至限制登录。正式业务请走官方方案——企业微信自建应用。
这篇教你搭一个合规的企业级 AI 助理:同事在企业微信里 @ 它或者直接给它发消息,它用你们自己的大模型和知识库回答。
整体架构
先看清楚数据流向,后面每一步才不会迷路:
1同事在企业微信发消息
2 │
3 ▼
4企业微信服务器 ──HTTPS 回调──> 你的云服务器(助理服务)
5 │ │
6 │ ├─> 本地大模型(Ollama / GLM / InternLM)
7 │ └─> 内部知识库(RAGFlow / MaxKB)
8 │ │
9 ▼ ▼
10 同事收到回复 <──调用发消息接口──┘三个关键环节:
- 接收:企业微信把消息 POST 到你的回调 URL(加密的)
- 处理:你的服务解密 → 调模型或知识库 → 得到答案
- 回复:调用企业微信的消息发送接口回给用户
第一步:准备工作清单
开始之前确认这几样都齐了,缺一样都会卡住:
| 项目 | 用途 | 获取方式 |
|---|---|---|
| CorpID | 企业标识 | 企业微信管理后台「我的企业 → 企业信息」 |
| AgentID | 应用标识 | 创建自建应用后获得 |
| Secret | 应用密钥 | 创建自建应用后获得 |
| Token | 回调校验 | 回调配置页随机生成 |
| EncodingAESKey | 消息加解密 | 回调配置页随机生成 |
| 已备案域名 | 回调地址 | 腾讯云购买并备案 |
| 公网 HTTPS | 回调要求 | 用 Nginx 反代 + SSL |
警告
⚠️ 域名备案是最大的时间成本,通常需要几个工作日。建议第一步就去提交备案,同时并行做服务器上的模型部署。
前往 腾讯云轻量应用服务器 选购页准备服务器,2C4G 起步(要同时跑本地模型就按 GLM 腾讯云部署教程 的建议上 4C8G 以上)。
第二步:创建企业微信自建应用
2.1 创建应用
企业微信管理后台 →「应用管理 → 应用 → 自建 → 创建应用」:
- 应用名称:如「AI 助理」
- 应用 logo:上传一个图标
- 可见范围:选择允许使用的人员/部门
创建完成后,在应用详情页能看到 AgentId 和 Secret。
警告
⚠️ Secret 只显示一次(或需要管理员扫码才能查看),立刻复制保存。丢了要重新生成,且旧的会失效。
2.2 获取 CorpID
「我的企业 → 企业信息 → 企业ID」,就是 CorpID。
2.3 设置可信 IP
应用详情页 →「企业微信授权登录 / 可信IP」里,填入你云服务器的公网 IP。
警告
⚠️ 这一步漏了,调接口会返回 invalid ip 错误。服务器换 IP 后要回来改。
2.4 配置接收消息的服务器回调
应用详情页 →「接收消息 → 设置API接收」:
| 字段 | 填写 |
|---|---|
| URL | https://你的域名/wecom/callback |
| Token | 点「随机获取」,保存下来 |
| EncodingAESKey | 点「随机获取」,保存下来 |
警告
⚠️ 点了保存之后,企业微信会立刻发一个 GET 验证请求到你的 URL。你的服务必须能正确响应这个验证(解密 echostr 并原样返回),否则保存会失败。所以要先把服务部署好并跑起来,再回来点保存。
配置顺序:先部署服务(第四、五步)→ 再回来配回调。别搞反了。
第三步:服务器端准备
3.1 域名与 HTTPS
用 Nginx 反代你的助理服务:
1server {
2 listen 443 ssl;
3 server_name 你的域名;
4
5 ssl_certificate /path/to/fullchain.pem;
6 ssl_certificate_key /path/to/privkey.pem;
7
8 location /wecom/ {
9 proxy_pass http://127.0.0.1:5000;
10 proxy_set_header Host $host;
11 proxy_set_header X-Real-IP $remote_addr;
12 }
13}如果你已按 1Panel 腾讯云部署教程 或 宝塔面板教程 装了面板,直接用面板的反代功能配,不用手写。
3.2 放行端口
腾讯云控制台「防火墙」放行 443,助理服务端口(示例里 5000)不要对外放行,只监听本机。
3.3 准备大模型
方案一:本地模型(数据不出网)
按 GLM 腾讯云部署教程 或 InternLM 腾讯云部署教程 跑起 Ollama:
1curl http://127.0.0.1:11434/v1/models方案二:云端 API(省事)
准备 DeepSeek / 通义千问等国产模型的 API Key。
方案三:接知识库(推荐,最有价值)
按 RAGFlow 腾讯云部署教程 或 MaxKB 腾讯云部署教程 搭好知识库,助理就能回答只有你们内部才知道的问题。
第四步:写助理服务
下面是一个可直接跑的 Python 服务,包含回调验证、消息解密、调用模型、回复消息。
4.1 安装依赖
1mkdir -p /opt/wecom-bot && cd /opt/wecom-bot
2python3 -m venv venv
3source venv/bin/activate
4pip install flask requests PyCryptodome警告
⚠️ 消息加解密需要 AES 库,用 PyCryptodome(包名是 Crypto,注意大小写)。装 pycryptodome 时如果报冲突,先卸载 crypto 和 pycrypto。
4.2 配置文件
1cat > config.py <<'EOF'
2CORP_ID = "你的CorpID"
3AGENT_ID = "你的AgentID"
4SECRET = "你的Secret"
5TOKEN = "回调配置里的Token"
6AES_KEY = "回调配置里的EncodingAESKey"
7
8# 本地 Ollama(按你的实际标签改)
9LLM_BASE_URL = "http://127.0.0.1:11434/v1"
10LLM_MODEL = "glm4:9b"
11LLM_API_KEY = "ollama"
12EOF4.3 回调处理核心代码
1# app.py
2import base64, hashlib, json, struct, time, xml.etree.ElementTree as ET
3import requests
4from flask import Flask, request, abort
5from Crypto.Cipher import AES
6import config
7
8app = Flask(__name__)
9
10# ---------- 加解密 ----------
11def decrypt_msg(encrypted_b64):
12 aes_key = base64.b64decode(config.AES_KEY + "=")
13 cipher = AES.new(aes_key, AES.MODE_CBC, aes_key[:16])
14 raw = cipher.decrypt(base64.b64decode(encrypted_b64))
15 # 去掉补位
16 pad_len = raw[-1]
17 content = raw[:-pad_len]
18 # 前 16 字节是随机串,接下来 4 字节是消息长度(网络字节序)
19 msg_len = struct.unpack("!I", content[16:20])[0]
20 return content[20:20 + msg_len].decode("utf-8")
21
22def encrypt_msg(reply_xml):
23 aes_key = base64.b64decode(config.AES_KEY + "=")
24 rand = b"1234567890abcdef" # 16 字节随机串,示例写死,生产请随机生成
25 body = rand + struct.pack("!I", len(reply_xml.encode())) + reply_xml.encode()
26 pad = 32 - len(body) % 32
27 body += bytes([pad]) * pad
28 cipher = AES.new(aes_key, AES.MODE_CBC, aes_key[:16])
29 return base64.b64encode(cipher.encrypt(body)).decode()
30
31def get_access_token():
32 url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
33 r = requests.get(url, params={"corpid": config.CORP_ID,
34 "corpsecret": config.SECRET}, timeout=10)
35 return r.json().get("access_token")
36
37# ---------- 调模型 ----------
38def ask_llm(question):
39 r = requests.post(
40 config.LLM_BASE_URL + "/chat/completions",
41 headers={"Authorization": "Bearer " + config.LLM_API_KEY},
42 json={"model": config.LLM_MODEL,
43 "messages": [{"role": "user", "content": question}]},
44 timeout=120,
45 )
46 return r.json()["choices"][0]["message"]["content"]
47
48# ---------- 发消息 ----------
49def send_text(user_id, text):
50 token = get_access_token()
51 url = "https://qyapi.weixin.qq.com/cgi-bin/message/send"
52 requests.post(url, params={"access_token": token}, json={
53 "touser": user_id,
54 "msgtype": "text",
55 "agentid": config.AGENT_ID,
56 "text": {"content": text},
57 }, timeout=10)
58
59# ---------- 回调 ----------
60@app.get("/wecom/callback")
61def verify():
62 """企业微信配置回调时的 GET 验证"""
63 msg_signature = request.args.get("msg_signature")
64 timestamp = request.args.get("timestamp")
65 nonce = request.args.get("nonce")
66 echostr = request.args.get("echostr")
67
68 # 校验签名:token / timestamp / nonce / echostr 排序后 sha1
69 sign = hashlib.sha1("".join(sorted([config.TOKEN, timestamp, nonce, echostr]))
70 .encode()).hexdigest()
71 if sign != msg_signature:
72 abort(403)
73
74 return decrypt_msg(echostr) # 原样返回解密后的 echostr
75
76@app.post("/wecom/callback")
77def receive():
78 """接收用户消息"""
79 root = ET.fromstring(request.data)
80 encrypted = root.find("Encrypt").text
81
82 xml = decrypt_msg(encrypted)
83 msg = ET.fromstring(xml)
84
85 from_user = msg.find("FromUserName").text
86 content = (msg.findtext("Content") or "").strip()
87
88 if not content:
89 return "success"
90
91 try:
92 answer = ask_llm(content)
93 except Exception as e:
94 answer = f"抱歉,处理出错了:{str(e)[:100]}"
95
96 send_text(from_user, answer)
97 return "success"
98
99if __name__ == "__main__":
100 app.run(host="127.0.0.1", port=5000)4.4 用 systemd 常驻
1sudo tee /etc/systemd/system/wecom-bot.service <<'EOF'
2[Unit]
3Description=WeCom AI Assistant
4After=network.target
5
6[Service]
7Type=simple
8User=ubuntu
9WorkingDirectory=/opt/wecom-bot
10ExecStart=/opt/wecom-bot/venv/bin/python app.py
11Restart=on-failure
12RestartSec=5
13
14[Install]
15WantedBy=multi-user.target
16EOF
17
18sudo systemctl daemon-reload
19sudo systemctl enable wecom-bot
20sudo systemctl start wecom-bot
21sudo journalctl -u wecom-bot -f4.5 验证服务可访问
1curl -I http://127.0.0.1:5000/wecom/callback再从公网访问 https://你的域名/wecom/callback(GET 不带参数会返回 400/403,属正常——只要不是连接失败就行)。
第五步:回到企业微信配置回调
服务跑起来之后,回到第二步 2.4,填 URL / Token / EncodingAESKey,点保存。
企业微信会发 GET 验证请求。如果我们的服务正确返回了解密后的 echostr,就提示保存成功。
警告
⚠️ 保存失败最常见的原因是签名校验不匹配。检查 config.py 里的 TOKEN 是否与页面上生成的完全一致(区分大小写)。
第六步:接知识库(让它回答内部问题)
通用模型谁都能用。接了你们自己的文档,助理才有不可替代的价值。
6.1 接 RAGFlow / MaxKB
把 ask_llm 换成调知识库接口即可。以 MaxKB 为例:
1def ask_llm(question):
2 """改为:先查知识库,查不到再走通用模型"""
3 r = requests.post(
4 "http://127.0.0.1:8080/api/application/chat/completions",
5 headers={"Authorization": "Bearer 你的MaxKB应用Key"},
6 json={"message": question, "re_chat": False, "stream": False},
7 timeout=120,
8 )
9 data = r.json()
10 answer = data.get("data", {}).get("content") or ""
11 if not answer.strip():
12 # 知识库没命中,退回通用模型
13 return ask_general(question)
14 return answer警告
⚠️ 接口路径与字段以你部署的 MaxKB 版本为准,先 curl 通再写代码,别猜字段。
6.2 验收
问一个只有你们文档里才有答案的问题,比如「年假上限是多少天」。检查:
- 答案是否正确
- 是否带引用来源
- 答不上来时是否优雅降级(而不是报错或瞎编)
答不上来要老实说「没找到」,不要让模型编一个制度出来——这在企业场景里是事故。
第七步:安全与合规
7.1 内容过滤
AI 回复加一层敏感词过滤;涉及人事、财务、法务的问题,建议只返回知识库内容,不走通用模型自由发挥。
7.2 权限控制
企业微信应用有「可见范围」,把它限制在需要的部门。助理服务本身也要限制:
- 服务只监听
127.0.0.1:5000 - 公网只暴露 443
- 腾讯云防火墙只放行 22 / 443
7.3 日志与审计
记录每条提问与回答,出问题能追溯。生产环境建议落盘并定期归档。
7.4 别让它自动执行高危操作
助理可以做查询与生成,不要给它删库、批量发消息、改配置的权限。AI 会犯错,权限给大了就是事故。
18 条故障排查
| # | 现象 | 原因 | 解决 |
|---|---|---|---|
| 1 | 回调保存失败 | 签名不匹配 | 核对 TOKEN 是否与页面完全一致 |
| 2 | 回调保存失败(URL 不通) | 服务没起来或域名没解析 | curl 公网地址确认可访问 |
| 3 | 提示 invalid ip | 没配可信 IP | 应用详情页填服务器公网 IP |
| 4 | access_token 获取失败 | CorpID 或 Secret 错 | 核对配置;Secret 是否重新生成过 |
| 5 | access_token 频繁失效 | 多处服务在刷新 | token 有调用频率限制,做缓存复用 |
| 6 | 消息发不出去 | AgentID 错或用户不在可见范围 | 核对 AgentID 与应用可见范围 |
| 7 | 收到消息但不回复 | 解密失败或异常未捕获 | 看 journalctl -u wecom-bot |
| 8 | 解密报错 | EncodingAESKey 不对 | 重新生成并同步到配置文件 |
| 9 | 装 pycryptodome 报冲突 | 存在旧 crypto 包 | 先卸载 crypto / pycrypto 再装 |
| 10 | 模型超时 | 本地模型推理慢 | 调大 timeout;换更快模型;上 GPU |
| 11 | 回复很慢 | 模型推理耗时 | 异步处理 + 先回「正在思考」;或换小模型 |
| 12 | 知识库答非所问 | 检索没命中 | 检查文档解析;调整切分与提问方式 |
| 13 | 服务重启后不工作 | systemd 配置问题 | journalctl 看具体报错 |
| 14 | 公网能访问但企业微信不通 | 证书问题 | 确认证书有效且是完整链 |
| 15 | 中文乱码 | 编码问题 | 确认解密后按 UTF-8 解码 |
| 16 | 消息重复处理 | 没做去重 | 企业微信会重试,按 msgid 去重 |
| 17 | 日志报 40058 | 请求参数格式错 | 核对接口文档字段名 |
| 18 | 账号被限制 | 用了第三方协议 | ⚠️ 本文走官方接口不会触发;别混用第三方方案 |
落地建议
- 域名备案先启动 —— 这是唯一无法加速的环节,早提交早省心。
- 先部署服务,再配回调 —— 顺序反了必然保存失败。
- 接知识库才有价值 —— 通用问答谁都能做,能查到你们自己的制度才是护城河。
- 答不上来要老实说 —— 企业场景里编造制度比答不上来严重得多。
- 权限给最小 —— 助理只做查询与生成,不给写权限。
常见问题
Q和个人微信机器人比,企业微信自建应用有什么优缺点?
优点:**官方合规**,不存在封号风险;有完整的用户体系与权限控制;支持应用消息、群聊、通讯录等丰富能力。缺点:配置比第三方协议繁琐(要处理回调、加解密、可信 IP);需要企业微信管理员权限;回调要求公网 HTTPS 地址(国内节点域名需备案)。如果是正式业务,企业微信是唯一稳妥选择,可以看 chatgpt-on-wechat + NoneBot 腾讯云部署教程 了解第三方方案的风险边界。
Q回调一定要 HTTPS 和备案域名吗?
要。企业微信的回调 URL 必须是公网可访问的 HTTPS 地址,国内服务器还要求域名已备案。这是硬要求,无法绕过。如果你还没有域名,先去腾讯云买并备案(备案通常需要几个工作日),同时可以用服务器先把模型服务跑起来,域名下来后再配回调。
QAI 助理的回答能接我们自己的知识库吗?
能,而且这才是它真正的价值——让同事在群里直接问制度、问流程,答案来自你们自己的文档。本文会给出对接 RAGFlow 腾讯云部署教程 与 MaxKB 腾讯云部署教程 的两种方式。通用大模型谁都能用,接了内部知识库才是别人复制不了的东西。