想在公司微信裡用上 AI,先別急著寫程式——三種方案的資料邊界、開發量和適用場景完全不同,選錯後面全是返工
| 維度 | 方案 A:自建應用 + 回調 | 方案 B:群機器人 Webhook | 方案 C:第三方 SaaS 託管 |
|---|---|---|---|
| 收訊息 | ✅ 應用內單聊可收可發 | ❌ 只能往群裡發 | ✅ 平台代收代發 |
| 資料邊界 | 訊息和回覆都在自己的伺服器 | 推送內容經企微伺服器 | 對話內容經第三方平台 |
| 上線耗時 | 1–3 天(主要是回調除錯) | 約 10 分鐘 | 半天到 1 天(設定為主) |
| 開發量 | 中:回調加解密 + token 管理 + AI 對接 | 極低:一個 HTTP 請求 | 低:網頁設定 + 少量介面 |
| 適合場景 | 正式 AI 助手、客服答疑、流程查詢 | 通知播報、警報推送、日報 | 快速驗證價值、無開發人力 |
一句話:做對話助手選 A,做通知播報選 B,先驗證價值選 C。最常見的錯誤是拿方案 B 做對話(收不到訊息,做不了),或者沒評估資料邊界就直接上方案 C。
這是企微官方支援的完整通路:員工在應用裡發訊息 → 企微推到你指定的回調 URL → 你的服務調 AI 生成回覆 → 透過應用訊息介面發回給員工。資料全程在自己伺服器,權限、日誌、稽核都可控。
管理後台 →「應用管理」→「自建」→「建立應用」,可見範圍先選一個小部門做灰度。記下三個值:
corpid:「我的企業」頁 → 企業 IDAgentId:應用詳情頁Secret:應用詳情頁(只顯示一次,立即存入金鑰管理,不要進程式庫)應用詳情 →「接收訊息」→「設定 API 接收」,填三項:URL(你伺服器的 HTTPS 位址)、Token、EncodingAESKey(可隨機產生)。點儲存時,企微會向你的 URL 發一個 GET 驗證請求,要求驗簽通過並原樣返回解密後的 echostr。
# callback_verify.py —— 回調 URL 驗證(GET)
# 驗簽規則:對 token、timestamp、nonce、密文四者排序拼接後取 sha1
import hashlib
def check_signature(token, timestamp, nonce, encrypt_msg):
items = sorted([token, timestamp, nonce, encrypt_msg])
return hashlib.sha1("".join(items).encode()).hexdigest()
@app.route("/wecom/callback", methods=["GET"])
def verify():
encrypt = request.args["echostr"]
expect = request.args["msg_signature"]
actual = check_signature(TOKEN, request.args["timestamp"],
request.args["nonce"], encrypt)
if actual != expect:
return "bad signature", 403
# 用官方加解密庫(WXBizMsgCrypt)做 AES 解密,拿到明文後原樣返回
return decrypt_echostr(encrypt, AES_KEY)
驗簽失敗的三大原因:Token 填錯、伺服器時間漂移(做 NTP 對時)、只寫了 POST 沒寫 GET。除錯期把「排序後參與計算的四個字串」打進日誌,一眼就能看出差在哪。
員工在應用裡發訊息後,企微會 POST 一段加密 XML 到你的回調 URL。兩個硬約束:5 秒內必須響應(逾時企微會重試,最多三次),重試的訊息內容一模一樣(不去重就會重複回覆)。所以標準寫法是:收到立即去重並返回,AI 處理放異步,算完再主動推給員工。
# wecom_bot.py —— 收訊息:MsgId 去重 + 異步處理
import threading
replying = set() # 生產環境換 Redis,防多實例重複處理
@app.route("/wecom/callback", methods=["POST"])
def on_message():
xml = decrypt_msg(request.data, request.args) # 官方加解密庫解開 XML
msg_id = xml.get("MsgId")
if msg_id in replying:
return "success" # 重試的重複訊息,直接吞掉
replying.add(msg_id)
threading.Thread(target=handle, args=(xml["FromUserName"],
xml["Content"], msg_id)).start()
return "success" # 立即響應,不等 AI
def handle(user, question, msg_id):
try:
answer = ask_ai(question) # 你自己的 AI 服務/知識庫
send_text(user, answer) # 用應用訊息介面主動回覆
except Exception:
send_text(user, "抱歉,剛才處理逾時了,請再問一次。")
finally:
replying.discard(msg_id)
access_token 用 corpid + Secret 換取,有效期 7200 秒,且有獲取頻率限制——每個地方都現取是典型反模式,必須集中快取、單點刷新。另外:呼叫發送介面的伺服器 IP 必須先加入應用的「企業可信 IP」,否則報錯 60020。
# wecom_client.py —— token 集中快取 + 發送文字訊息
import time, requests
_token, _ts = "", 0
def get_token():
global _token, _ts
if _token and time.time() - _ts < 7000: # 留 200 秒餘量
return _token
r = requests.get("https://qyapi.weixin.qq.com/cgi-bin/gettoken",
params={"corpid": CORP_ID, "corpsecret": SECRET},
timeout=5).json()
_token, _ts = r["access_token"], time.time()
return _token
def send_text(user, content):
requests.post(
"https://qyapi.weixin.qq.com/cgi-bin/message/send",
params={"access_token": get_token()},
json={"touser": user, "msgtype": "text", "agentid": AGENT_ID,
"text": {"content": content[:2000]}}, # 超長先截斷/分段
timeout=5)
到這裡方案 A 就通了。把 ask_ai() 換成你的 RAG 知識庫或大模型服務,就是一個能用的企業 AI 助手。
群聊設定 →「群機器人」→「加入機器人」,拿到一個 webhook 位址,之後往這個位址 POST JSON 就能往群裡發訊息:
curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的KEY' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"部署完成:訂單服務 v2.3 已上線"}}'
它的定位是單向通知:CI/CD 建置結果、監控警報、每日播報。兩個硬限制:收不到群裡的訊息(做不了對話),每個機器人有發送頻率限制(高頻警報要做聚合)。支援 text、markdown、圖文等訊息類型,適合「把系統裡的事件告訴人」,不適合「人問系統答」。
市面上有不少託管平台:授權企微後網頁設定知識庫和話術,不用自己寫回調程式,半天就能上線。適合兩種情況:沒有開發人力、想先小成本驗證 AI 助手有沒有價值。
但要在簽約前問清四件事,不然日後很難受:
現象:設定接收訊息時永遠儲存失敗,或者線上收不到推送。
根因:Token 兩邊不一致、伺服器時間漂移、只實現了 POST 忘了 GET 驗證。
現象:偶發取得 token 失敗,或新 token 一發舊 token 立刻不能用。
根因:多處程式各自刷新 token,互相把快取頂掉;或中心快取沒做併發鎖。
現象:AI 處理慢時,員工同一條問題收到重複回答。
根因:同步等 AI 超過 5 秒,企微重試,服務端沒按 MsgId 去重。
現象:本機除錯一切正常,部署到伺服器後發訊息報 60020。
根因:呼叫介面的出網 IP 不在應用的「企業可信 IP」名單裡。
現象:AI 回答長一點,員工端收不到或只有前半截。
根因:text 訊息內容超過長度上限,介面直接報錯或截斷。
三種方案沒有絕對優劣,選擇取決於三件事:資料邊界要求多高、有多少開發人力、要解決什麼場景。通知播報別上方案 A 浪費人力;正式對話助手別用方案 B(收不到訊息);上方案 C 之前把資料邊界四問問清楚。多數團隊的真實路徑是:先用 C 或 B 快速驗證,驗證成功後遷到方案 A 做長期自營。
如果只需要一個結論:做對話選 A,做通知選 B,做驗證選 C——別混用。