章節:訊息平台 · 網址:https://hermesbible.com/docs/user-guide/messaging/weixin
將 Hermes 連接到 微信(WeChat),這是騰訊的個人訊息平台。此適配器使用騰訊的 iLink Bot API 連接個人微信帳號——這與企業微信(WeCom)不同。訊息透過長輪詢(long-polling)傳送,因此無需公開端點或 webhook。
資訊
此適配器適用於個人微信帳號。如果你需要企業微信,請參閱 WeCom 適配器。
警告 — iLink 機器人身份——普通微信群組可能無法運作
QR 登入會將 Hermes 連接到一個 iLink 機器人身份(例如
a5ace6fd482e@im.bot),而不是一個可完全編程控制的普通個人微信帳號。影響如下:
- iLink 機器人身份通常無法像一般聯絡人那樣被邀請進入普通微信群組。
- iLink 通常不會將普通微信群組事件(包括對用於 QR 登入的個人帳號的
@提及)傳送到閘道。- 對用於掃描 QR code 的個人微信帳號進行
@提及,與對 iLink 機器人進行@提及不同——機器人是獨立的身份。- 下方的
WEIXIN_GROUP_POLICY/WEIXIN_GROUP_ALLOWED_USERS設定僅在 iLink 為你的帳號類型實際返回群組事件時才生效。如果它不返回,無論策略如何設定,群組訊息永遠不會到達 Hermes。實務上,大多數部署只能可靠地接收對 iLink 機器人的私訊。如果設定後群組訊息仍然無法運作,限制在 iLink 端,而非 Hermes。當
WEIXIN_GROUP_POLICY設定為非disabled的值時,閘道會在啟動時記錄WARNING。
前置需求
- 一個個人微信帳號
- Python 套件:
aiohttp和cryptography - 安裝帶有
messaging額外元件的 Hermes 時,已內建終端機 QR 繪製功能
安裝所需依賴:
pip install aiohttp cryptography
# 選用:用於終端機 QR code 顯示
pip install hermes-agent[messaging]
設定
1. 執行設定精靈
連接微信帳號最簡單的方式是透過互動式設定:
hermes gateway setup
在提示時選擇 Weixin。精靈將會:
- 從 iLink Bot API 請求一個 QR code
- 在終端機顯示 QR code(或提供一個 URL)
- 等待你用微信手機版掃描 QR code
- 提示你在手機上確認登入
- 自動將帳號憑證儲存到
~/.hermes/weixin/accounts/
確認後,你會看到類似以下的訊息:
微信连接成功,account_id=your-account-id
精靈會儲存 account_id、token 和 base_url,因此你不需要手動設定它們。
2. 設定環境變數
完成 QR 登入後,至少在 ~/.hermes/.env 中設定帳號 ID:
WEIXIN_ACCOUNT_ID=your-account-id
# 選用:覆蓋 token(通常從 QR 登入自動儲存)
# WEIXIN_TOKEN=your-bot-token
# 選用:限制存取權限
WEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
# 選用:恢復舊版多行分割行為
# WEIXIN_SPLIT_MULTILINE_MESSAGES=true
# 選用:用於排程/通知的主頻道
WEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home
3. 啟動閘道
hermes gateway
適配器會還原已儲存的憑證,連接到 iLink API,並開始長輪詢接收訊息。
功能
- 長輪詢傳輸 — 無需公開端點、webhook 或 WebSocket
- QR code 登入 — 透過
hermes gateway setup掃描連接 - 私訊 — 可設定的存取策略;群組訊息取決於 iLink 是否實際為連接的身份傳遞群組事件(iLink 機器人帳號通常無法接收——見上方警告)
- 媒體支援 — 圖片、影片、檔案和語音訊息
- AES-128-ECB 加密 CDN — 所有媒體傳輸自動加密/解密
- 上下文 token 持久化 — 磁碟支援的回覆連續性,重啟後仍可延續
- Markdown 格式 — 保留 Markdown,包括標題、表格和程式碼區塊,支援 Markdown 的微信客戶端可原生渲染
- 智慧訊息分塊 — 訊息在限制內保持為單一氣泡;只有過大的負載才會在邏輯邊界分割
- 輸入指示器 — 在代理程式處理時於微信客戶端顯示「正在輸入...」狀態
- SSRF 防護 — 出站媒體 URL 在下載前會進行驗證
- 訊息去重 — 5 分鐘滑動窗口防止重複處理
- 自動重試與退避 — 從暫時性 API 錯誤中恢復
設定選項
在 config.yaml 的 platforms.weixin.extra 下設定:
| 鍵值 | 預設值 | 說明 |
|---|---|---|
account_id | — | iLink Bot 帳號 ID(必填) |
token | — | iLink Bot token(必填,從 QR 登入自動儲存) |
base_url | https://ilinkai.weixin.qq.com | iLink API 基礎 URL |
cdn_base_url | https://novac2c.cdn.weixin.qq.com/c2c | 媒體傳輸的 CDN 基礎 URL |
dm_policy | open | 私訊存取:open、allowlist、disabled、pairing |
group_policy | disabled | 群組存取:open、allowlist、disabled |
allow_from | [] | 允許發送私訊的使用者 ID(當 dm_policy=allowlist 時) |
group_allow_from | [] | 允許的群組 ID(當 group_policy=allowlist 時) |
split_multiline_messages | false | 設為 true 時,將多行回覆分割為多條聊天訊息(舊版行為)。設為 false 時,多行回覆保持為單一訊息,除非超過長度限制。 |
text_batch_delay_seconds | 3.0 | 緩衝的快速文字訊息批次在合併為單一請求前的靜默期(秒)。iLink 逐條傳遞訊息,因此此防抖機制避免每個片段觸發一次代理程式呼叫。設為 0 可立即派發每條訊息。 |
text_batch_split_split_delay_seconds | 5.0 | 當最新片段接近分割閾值(iLink 可能已分割的長訊息)時使用的延伸刷新延遲。 |
存取策略
私訊策略
控制誰可以向機器人發送私人訊息:
| 值 | 行為 |
|---|---|
open | 任何人都可以私訊機器人(預設) |
allowlist | 只有 allow_from 中的使用者 ID 可以私訊 |
disabled | 所有私訊都會被忽略 |
pairing | 配對模式(用於初始設定) |
WEIXIN_DM_POLICY=allowlist
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
WEIXIN_ALLOWED_USERS 是入站過濾器,而非邀請系統。QR 登入將一個 iLink 機器人身份連接到 Hermes。其他人不會用自己的帳號掃描 Hermes 的 QR code;他們必須透過微信向已連接的 iLink 機器人/聯絡人發送訊息,而 Hermes 僅在傳送者的微信使用者 ID 存在於 WEIXIN_ALLOWED_USERS 時才會處理該私訊。
實際設定流程如下:
- 使用
hermes gateway setup配對一次 Hermes,並記下已連接的 iLink 機器人帳號。 - 讓每個被允許的使用者向該機器人/聯絡人發送一條私人訊息。
- 從閘道日誌或入站事件負載中讀取傳送者/使用者 ID。
- 將這些 ID 加入
WEIXIN_ALLOWED_USERS,然後重新啟動閘道。
如果只有掃描 QR code 的帳號可以與 Hermes 通訊,請確認其他使用者正在向 iLink 機器人身份本身發送訊息,而非進行 QR 登入的個人微信帳號。iLink 機器人是獨立的身份,普通的微信聯絡人/群組路由可能受到騰訊 iLink 行為的限制。
群組策略
控制機器人在哪些群組中回應——前提是 iLink 為連接的身份實際傳遞群組事件。對於 QR 登入的 iLink 機器人身份(例如 ...@im.bot),群組事件通常完全不會被傳遞,因此此策略可能無效——見頁面頂部的 iLink 機器人限制警告。
| 值 | 行為 |
|---|---|
open | 機器人在所有群組中回應(如果事件被傳遞) |
allowlist | 機器人只在 group_allow_from 列出的群組 ID 中回應(如果事件被傳遞) |
disabled | 所有群組訊息都會被忽略(預設) |
WEIXIN_GROUP_POLICY=allowlist
# 注意:這是群組聊天 ID 的逗號分隔列表,不是成員使用者 ID,
# 儘管變數名稱包含 "USERS"。設定時請注意這一點。
WEIXIN_GROUP_ALLOWED_USERS=group_id_1,group_id_2
備註
微信的群組策略預設為
disabled(與 WeCom 預設為open不同)。這是刻意的——個人微信帳號可能在許多群組中,而 iLink 機器人身份通常完全無法接收普通微信群組訊息。如果你將WEIXIN_GROUP_POLICY設定為非disabled的值,閘道會在啟動時記錄WARNING。
媒體支援
入站(接收)
適配器從使用者接收媒體附件,從微信 CDN 下載、解密,並在本地快取以供代理程式處理:
| 類型 | 處理方式 |
|---|---|
| 圖片 | 下載、AES 解密,並快取為 JPEG。 |
| 影片 | 下載、AES 解密,並快取為 MP4。 |
| 檔案 | 下載、AES 解密並快取。原始檔名會被保留。 |
| 語音 | 如果有文字逐字稿可用,會提取為文字。否則音訊(SILK 格式)會被下載並快取。 |
引用訊息: 引用(回覆)訊息中的媒體也會被提取,讓代理程式了解使用者正在回覆什麼內容。
AES-128-ECB 加密 CDN
微信媒體檔案透過加密的 CDN 傳輸。適配器會透明地處理:
- 入站: 使用
encrypted_query_paramURL 從 CDN 下載加密媒體,然後使用訊息負載中提供的每個檔案金鑰以 AES-128-ECB 解密。 - 出站: 使用隨機 AES-128-ECB 金鑰在本地加密檔案,上傳到 CDN,然後將加密的引用包含在出站訊息中。
- AES 金鑰為 16 位元組(128 位元)。金鑰可能以原始 base64 或十六進位編碼格式到達——適配器會處理兩種格式。
- 這需要
cryptographyPython 套件。
無需額外設定——加密和解密會自動發生。
出站(傳送)
| 方法 | 傳送內容 |
|---|---|
send | 帶有 Markdown 格式的文字訊息 |
send_image / send_image_file | 原生圖片訊息(透過 CDN 上傳) |
send_document | 檔案附件(透過 CDN 上傳) |
send_video | 影片訊息(透過 CDN 上傳) |
所有出站媒體都經過加密的 CDN 上傳流程:
- 產生隨機 AES-128 金鑰
- 使用 AES-128-ECB + PKCS#7 填充加密檔案
- 從 iLink API 請求上傳 URL(
getuploadurl) - 上傳密文到 CDN
- 使用加密的媒體引用傳送訊息
上下文 Token 持久化
iLink Bot API 要求每個出站訊息都必須回傳 context_token 給特定對端。適配器維護一個磁碟支援的上下文 token 儲存:
- Token 按帳號+對端儲存到
~/.hermes/weixin/accounts/<account_id>.context-tokens.json - 啟動時,先前儲存的 token 會被還原
- 每條入站訊息都會更新該傳送者的已儲存 token
- 出站訊息會自動包含最新的上下文 token
這確保了即使在閘道重啟後,回覆仍能保持連續性。
Markdown 格式
透過 iLink Bot API 連接的微信客戶端可以直接渲染 Markdown,因此適配器保留 Markdown 而非重寫:
- 標題 保持為 Markdown 標題格式(
#、##...) - 表格 保持為 Markdown 表格
- 程式碼區塊 保持為 fenced 程式碼區塊
- 多餘空行 在 fenced 程式碼區塊外被壓縮為雙換行
訊息分塊
訊息在符合平台限制時會作為單一聊天訊息傳送。只有過大的負載才會被分割:
- 最大訊息長度:4000 字元
- 低於限制的訊息即使包含多個段落或換行也會保持完整
- 過大的訊息在邏輯邊界分割(段落、空行、程式碼區塊)
- 程式碼區塊盡可能保持完整(除非區塊本身超過限制,否則永遠不在區塊中間分割)
- 過大的個別區塊退回到基礎適配器的截斷邏輯
- 0.3 秒的塊間延遲防止多個塊傳送時被微信速率限制丟棄
輸入指示器
適配器在微信客戶端顯示輸入狀態:
- 收到訊息時,適配器透過
getconfigAPI 取得typing_ticket - 輸入票證按使用者快取 10 分鐘
send_typing發送開始輸入訊號;stop_typing發送停止輸入訊號- 閘道在代理程式處理訊息時自動觸發輸入指示器
長輪詢連線
適配器使用 HTTP 長輪詢(非 WebSocket)接收訊息:
運作方式
- 連線: 驗證憑證並啟動輪詢迴圈
- 輪詢: 使用 35 秒逾時呼叫
getupdates;伺服器會保持請求直到訊息到達或逾時 - 派發: 入站訊息透過
asyncio.create_task並行派發 - 同步緩衝: 持久化的同步游標(
get_updates_buf)儲存到磁碟,使適配器在重啟後從正確位置恢復
重試行為
API 錯誤時,適配器使用簡單的重試策略:
| 條件 | 行為 |
|---|---|
| 暫時性錯誤(第 1-2 次) | 2 秒後重試 |
| 重複錯誤(第 3 次以上) | 後退 30 秒,然後重設計數器 |
Session 過期(errcode=-14) | 暫停 10 分鐘(可能需要重新登入) |
| 逾時 | 立即重新輪詢(正常的長輪詢行為) |
去重
入站訊息使用訊息 ID 進行去重,時間窗口為 5 分鐘。這可以防止在網路波動或重疊的輪詢回應期間重複處理。
Token 鎖定
同一時間只有一個微信閘道實例可以使用特定的 token。適配器在啟動時取得範圍鎖定,並在關閉時釋放。如果另一個閘道已經在使用相同的 token,啟動會失敗並顯示錯誤訊息。
所有環境變數
| 變數 | 必填 | 預設值 | 說明 |
|---|---|---|---|
WEIXIN_ACCOUNT_ID | ✅ | — | iLink Bot 帳號 ID(來自 QR 登入) |
WEIXIN_TOKEN | ✅ | — | iLink Bot token(從 QR 登入自動儲存) |
WEIXIN_BASE_URL | — | https://ilinkai.weixin.qq.com | iLink API 基礎 URL |
WEIXIN_CDN_BASE_URL | — | https://novac2c.cdn.weixin.qq.com/c2c | 媒體傳輸的 CDN 基礎 URL |
WEIXIN_DM_POLICY | — | open | 私訊存取策略:open、allowlist、disabled、pairing |
WEIXIN_GROUP_POLICY | — | disabled | 群組存取策略:open、allowlist、disabled |
WEIXIN_ALLOWED_USERS | — | (空) | 以逗號分隔的使用者 ID,用於私訊允許清單 |
WEIXIN_GROUP_ALLOWED_USERS | — | (空) | 以逗號分隔的群組聊天 ID(不是成員使用者 ID),用於群組允許清單。此變數名稱為舊版名稱——它期望的是群組 ID,而非使用者 ID。 |
WEIXIN_HOME_CHANNEL | — | — | 用於排程/通知輸出的聊天 ID |
WEIXIN_HOME_CHANNEL_NAME | — | Home | 主頻道的顯示名稱 |
WEIXIN_ALLOW_ALL_USERS | — | — | 閘道層級的全域允許所有使用者標誌(供設定精靈使用) |
疑難排解
| 問題 | 解決方案 |
|---|---|
Weixin startup failed: aiohttp and cryptography are required | 安裝兩者:pip install aiohttp cryptography |
Weixin startup failed: WEIXIN_TOKEN is required | 執行 hermes gateway setup 完成 QR 登入,或手動設定 WEIXIN_TOKEN |
Weixin startup failed: WEIXIN_ACCOUNT_ID is required | 在你的 .env 中設定 WEIXIN_ACCOUNT_ID,或執行 hermes gateway setup |
Another local Hermes gateway is already using this Weixin token | 先停止另一個閘道實例——每個 token 只允許一個輪詢器 |
Session 過期(errcode=-14) | 你的登入 session 已過期。重新執行 hermes gateway setup 掃描新的 QR code |
| 設定期間 QR code 過期 | QR code 最多自動重新整理 3 次。如果持續過期,請檢查網路連線 |
| 機器人不回應私訊 | 檢查 WEIXIN_DM_POLICY——如果設為 allowlist,傳送者必須在 WEIXIN_ALLOWED_USERS 中 |
| 機器人忽略群組訊息 | 群組策略預設為 disabled。設定 WEIXIN_GROUP_POLICY=open 或 allowlist——但請注意 QR 登入的 iLink 機器人身份(...@im.bot)通常完全無法接收普通微信群組訊息。如果閘道日誌中沒有顯示群組訊息的原始入站事件,限制在 iLink 端,而非 Hermes。 |
| 媒體下載/上傳失敗 | 確保已安裝 cryptography。檢查到 novac2c.cdn.weixin.qq.com 的網路存取 |
Blocked unsafe URL (SSRF protection) | 出站媒體 URL 指向私有/內部位址。只允許公開 URL |
| 語音訊息顯示為文字 | 如果微信提供逐字稿,適配器會使用文字。這是預期行為 |
| 訊息出現重複 | 適配器按訊息 ID 去重。如果看到重複,檢查是否有多個閘道實例在運行 |
iLink POST ... HTTP 4xx/5xx | 來自 iLink 服務的 API 錯誤。檢查你的 token 有效性和網路連線 |
| 終端機 QR code 無法繪製 | 使用 messaging 額外元件重新安裝:pip install hermes-agent[messaging]。或者,開啟 QR code 上方列印的 URL |