Weixin (WeChat)
Kết nối Hermes với WeChat (微信), nền tảng nhắn tin cá nhân của Tencent. Bộ điều hợp sử dụng iLink Bot API của Tencent cho tài khoản WeChat cá nhân — điều này khác với WeCom (Enterprise WeChat). Tin nhắn được gửi thông qua kiểm tra vòng dài, do đó không yêu cầu điểm cuối công khai hoặc webhook.
Bộ chuyển đổi này dành cho tài khoản WeChat cá nhân (微信). Nếu bạn cần WeChat dành cho doanh nghiệp/công ty, thay vào đó hãy xem WeCom adapter.
Điều kiện tiên quyết
- Tài khoản WeChat cá nhân
- Gói Python:
aiohttpvàcryptography - Gói
qrcodelà tùy chọn (để hiển thị QR đầu cuối trong khi thiết lập)
Cài đặt các phụ thuộc cần thiết:
pip install aiohttp cryptography
# Optional: for terminal QR code display
pip install qrcode
Thiết lập
1. Chạy Trình hướng dẫn cài đặt
Cách dễ nhất để kết nối tài khoản WeChat của bạn là thông qua thiết lập tương tác:
Hermes gateway setup
Chọn Weixin khi được nhắc. Trình hướng dẫn sẽ:
- Yêu cầu mã QR từ API iLink Bot
- Hiển thị mã QR trong thiết bị đầu cuối của bạn (hoặc cung cấp URL)
- Đợi bạn quét mã QR bằng ứng dụng di động WeChat
- Nhắc bạn xác nhận đăng nhập trên điện thoại
- Tự động lưu thông tin đăng nhập tài khoản vào
~/.Hermes/weixin/accounts/
Sau khi xác nhận, bạn sẽ thấy thông báo như:
微信连接成功,account_id=your-account-id
Trình hướng dẫn lưu trữ account_id, token và base_url nên bạn không cần phải định cấu hình chúng theo cách thủ công.
2. Cấu hình biến môi trường
Sau lần đăng nhập QR đầu tiên, hãy đặt ID tài khoản tối thiểu trong ~/.Hermes/.env:
WEIXIN_ACCOUNT_ID=your-account-id
# Optional: override the token (normally auto-saved from QR login)
# WEIXIN_TOKEN=your-bot-token
# Optional: restrict access
WEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
# Optional: restore legacy multiline splitting behavior
# WEIXIN_SPLIT_MULTILINE_MESSAGES=true
# Optional: home channel for cron/notifications
WEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home
3. Khởi động Gateway
Hermes gateway
Bộ điều hợp sẽ khôi phục thông tin đăng nhập đã lưu, kết nối với API iLink và bắt đầu kiểm tra lâu dài các tin nhắn.
Tính năng
- Vận chuyển thăm dò ý kiến dài — không cần điểm cuối công khai, webhook hoặc WebSocket
- Đăng nhập bằng mã QR — thiết lập quét để kết nối qua
Hermes gateway setup - DM và nhắn tin nhóm — chính sách truy cập có thể định cấu hình
- Hỗ trợ đa phương tiện — hình ảnh, video, tệp và tin nhắn thoại
- CDN được mã hóa AES-128-ECB — mã hóa/giải mã tự động cho tất cả hoạt động truyền tải phương tiện
- Tính bền vững của mã thông báo bối cảnh — tính liên tục của phản hồi được hỗ trợ bằng đĩa trong các lần khởi động lại
- Định dạng đánh dấu — tiêu đề, bảng và khối mã được định dạng lại để WeChat có thể đọc được
- Phân chia tin nhắn thông minh — tin nhắn vẫn ở dạng một bong bóng duy nhất khi ở dưới giới hạn; chỉ các tải trọng quá khổ mới được phân chia ở ranh giới logic
- Chỉ báo đang gõ — hiển thị trạng thái "đang gõ..." trong ứng dụng khách WeChat trong khi nhân viên xử lý
- Bảo vệ SSRF — URL phương tiện gửi đi được xác thực trước khi tải xuống
- Loại bỏ tin nhắn — Cửa sổ trượt 5 phút ngăn chặn việc xử lý kép
- Tự động thử lại với backoff — khôi phục từ các lỗi API tạm thời
Tùy chọn cấu hình
Đặt những thứ này trong config.yaml trong platforms.weixin.extra:
| Chìa khóa | Mặc định | Mô tả |
|---|---|---|
account_id | — | ID tài khoản iLink Bot (bắt buộc) |
token | — | Mã thông báo iLink Bot (bắt buộc, được lưu tự động khi đăng nhập QR) |
base_url | https://ilinkai.weixin.qq.com | URL cơ sở API iLink |
cdn_base_url | https://novac2c.cdn.weixin.qq.com/c2c | URL cơ sở CDN để truyền phương tiện |
dm_policy | open | Truy cập DM: open, allowlist, disabled, pairing |
group_policy | disabled | Truy cập nhóm: open, allowlist, disabled |
allow_from | [] | ID người dùng được phép cho DM (khi dm_policy=allowlist) |
group_allow_from | [] | ID nhóm được phép (khi group_policy=allowlist) |
split_multiline_messages | false | Khi true, chia các câu trả lời nhiều dòng thành nhiều tin nhắn trò chuyện (hành vi cũ). Khi false, hãy giữ các câu trả lời nhiều dòng dưới dạng một tin nhắn trừ khi chúng vượt quá giới hạn độ dài. |
Chính sách truy cập
Chính sách DM
Kiểm soát ai có thể gửi tin nhắn trực tiếp tới bot:
| Giá trị | Hành vi |
|---|---|
open | Bất cứ ai cũng có thể DM bot (mặc định) |
allowlist | Chỉ ID người dùng trong allow_from mới có thể DM |
disabled | Tất cả DM đều bị bỏ qua |
pairing | Chế độ ghép nối (để thiết lập ban đầu) |
WEIXIN_DM_POLICY=allowlist
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
Chính sách nhóm
Kiểm soát những nhóm bot phản hồi trong:| Giá trị | Hành vi |
|-------|----------|
| open | Bot phản hồi trong tất cả các nhóm |
| allowlist | Bot chỉ phản hồi trong ID nhóm được liệt kê trong group_allow_from |
| disabled | Tất cả tin nhắn nhóm đều bị bỏ qua (mặc định) |
WEIXIN_GROUP_POLICY=allowlist
WEIXIN_GROUP_ALLOWED_USERS=group_id_1,group_id_2
Chính sách nhóm mặc định là disabled cho Weixin (không giống như WeCom có mặc định là open). Điều này là có chủ ý vì tài khoản WeChat cá nhân có thể thuộc nhiều nhóm.
Hỗ trợ truyền thông
Inbound (đang nhận)
Bộ điều hợp nhận các tệp đính kèm phương tiện từ người dùng, tải chúng xuống từ WeChat CDN, giải mã chúng và lưu vào bộ nhớ đệm cục bộ để xử lý tác nhân:
| Loại | Cách xử lý |
|---|---|
| Hình ảnh | Đã tải xuống, giải mã AES và lưu vào bộ nhớ đệm dưới dạng JPEG. |
| Video | Đã tải xuống, giải mã AES và lưu vào bộ nhớ đệm dưới dạng MP4. |
| Tệp | Đã tải xuống, giải mã AES và lưu vào bộ nhớ đệm. Tên tập tin gốc được giữ nguyên. |
| Giọng nói | Nếu có sẵn bản chép lại văn bản, nó sẽ được trích xuất dưới dạng văn bản. Nếu không, âm thanh (định dạng SILK) sẽ được tải xuống và lưu vào bộ nhớ đệm. |
Tin nhắn được trích dẫn: Phương tiện từ các tin nhắn được trích dẫn (đã trả lời) cũng được trích xuất, do đó, tổng đài viên có ngữ cảnh về nội dung người dùng đang trả lời.
CDN được mã hóa AES-128-ECB
Các tệp phương tiện WeChat được truyền qua CDN được mã hóa. Bộ điều hợp xử lý việc này một cách minh bạch:
- Inbound: Phương tiện đã mã hóa được tải xuống từ CDN bằng URL
encrypted_query_param, sau đó được giải mã bằng AES-128-ECB bằng khóa mỗi tệp được cung cấp trong tải trọng tin nhắn. - Gửi đi: Các tệp được mã hóa cục bộ bằng khóa AES-128-ECB ngẫu nhiên, được tải lên CDN và tham chiếu được mã hóa sẽ được bao gồm trong thư gửi đi.
- Khóa AES là 16 byte (128-bit). Khóa có thể đến dưới dạng base64 thô hoặc mã hóa hex — bộ điều hợp xử lý cả hai định dạng.
- Điều này yêu cầu gói Python
cryptography.
Không cần cấu hình - quá trình mã hóa và giải mã diễn ra tự động.
Gửi đi (gửi)
| Phương pháp | Nó gửi gì |
|---|---|
send | Tin nhắn văn bản có định dạng Markdown |
send_image / send_image_file | Tin nhắn hình ảnh gốc (thông qua tải lên CDN) |
send_document | Tệp đính kèm (thông qua tải lên CDN) |
send_video | Tin nhắn video (thông qua tải lên CDN) |
Tất cả phương tiện gửi đi đều đi qua luồng tải lên CDN được mã hóa:
- Tạo khóa AES-128 ngẫu nhiên
- Mã hóa tệp bằng phần đệm AES-128-ECB + PKCS#7
- Yêu cầu URL tải lên từ API iLink (
getuploadurl) - Tải bản mã lên CDN
- Gửi tin nhắn có tham chiếu phương tiện được mã hóa
Sự tồn tại của mã thông báo bối cảnh
API iLink Bot yêu cầu context_token được phản hồi lại với mỗi tin nhắn gửi đi cho một thiết bị ngang hàng nhất định. Bộ điều hợp duy trì kho lưu trữ mã thông báo ngữ cảnh được hỗ trợ bằng đĩa:
- Mã thông báo được lưu trên mỗi tài khoản+ngang hàng với
~/.Hermes/weixin/accounts/<account_id>.context-tokens.JSON - Khi khởi động, mã thông báo đã lưu trước đó sẽ được khôi phục
- Mỗi tin nhắn gửi đến sẽ cập nhật mã thông báo được lưu trữ cho người gửi đó
- Tin nhắn gửi đi tự động bao gồm mã thông báo ngữ cảnh mới nhất
Điều này đảm bảo tính liên tục của phản hồi ngay cả sau khi cổng khởi động lại.
Định dạng đánh dấu
Trò chuyện cá nhân của WeChat về cơ bản không hiển thị đầy đủ Markdown. Bộ chuyển đổi định dạng lại nội dung để dễ đọc hơn:
- Tiêu đề (
# Title) → được chuyển đổi thành【Title】(cấp 1) hoặc**Title**(cấp 2+) - Bảng → được định dạng lại dưới dạng danh sách khóa-giá trị được gắn nhãn (ví dụ:
- Column: Value) - Hàng rào mã → được giữ nguyên (WeChat hiển thị đầy đủ các hàng rào này)
- Quá nhiều dòng trống → thu gọn thành hai dòng mới
Phân đoạn tin nhắn
Tin nhắn được gửi dưới dạng một tin nhắn trò chuyện bất cứ khi nào chúng vừa với giới hạn của nền tảng. Chỉ những trọng tải quá khổ mới được phân chia để phân phối:
- Độ dài tin nhắn tối đa: 4000 ký tự
- Tin nhắn dưới giới hạn vẫn nguyên vẹn ngay cả khi chúng chứa nhiều đoạn văn hoặc ngắt dòng
- Tin nhắn quá khổ được phân chia theo ranh giới logic (đoạn văn, dòng trống, hàng rào mã)
- Hàng rào mã được giữ nguyên bất cứ khi nào có thể (không bao giờ tách ra giữa khối trừ khi hàng rào vượt quá giới hạn)
- Các khối riêng lẻ quá khổ sẽ quay trở lại logic cắt ngắn của bộ điều hợp cơ sở
- Độ trễ giữa các đoạn 0,3 giây sẽ ngăn chặn việc giảm giới hạn tốc độ của WeChat khi nhiều đoạn được gửi
Chỉ báo gõ
Bộ điều hợp hiển thị trạng thái nhập trong ứng dụng khách WeChat:1. Khi có tin nhắn đến, bộ điều hợp sẽ tìm nạp typing_ticket thông qua API getconfig
2. Phiếu đánh máy được lưu vào bộ nhớ đệm trong 10 phút cho mỗi người dùng
3. send_typing gửi Signal bắt đầu gõ; stop_typing gửi Signal dừng gõ
4. Cổng tự động kích hoạt các chỉ báo nhập trong khi tác nhân xử lý tin nhắn
Kết nối thăm dò dài
Bộ điều hợp sử dụng tính năng bỏ phiếu dài HTTP (không phải WebSocket) để nhận tin nhắn:
Cách thức hoạt động
- Kết nối: Xác thực thông tin xác thực và bắt đầu vòng thăm dò ý kiến
- Thăm dò ý kiến: Gọi
getupdatesvới thời gian chờ là 35 giây; máy chủ giữ yêu cầu cho đến khi có tin nhắn đến hoặc hết thời gian chờ - Điều phối: Tin nhắn gửi đến được gửi đồng thời qua
asyncio.create_task - Bộ đệm đồng bộ hóa: Một con trỏ đồng bộ hóa liên tục (
get_updates_buf) được lưu vào đĩa để bộ điều hợp tiếp tục hoạt động từ vị trí chính xác sau khi khởi động lại
Thử lại hành vi
Đối với các lỗi API, bộ điều hợp sử dụng chiến lược thử lại đơn giản:
| Tình trạng | Hành vi |
|----------||----------|
| Lỗi thoáng qua (thứ 1–thứ 2) | Thử lại sau 2 giây |
| Lỗi lặp lại (3+) | Lùi lại trong 30 giây rồi đặt lại bộ đếm |
| Phiên đã hết hạn (errcode=-14) | Tạm dừng trong 10 phút (có thể cần đăng nhập lại) |
| Hết giờ | Thăm dò lại ngay lập tức (hành vi thăm dò ý kiến kéo dài thông thường) |
Chống trùng lặp
Tin nhắn gửi đến sẽ được loại bỏ trùng lặp bằng cách sử dụng ID tin nhắn có thời hạn 5 phút. Điều này ngăn chặn việc xử lý kép khi mạng gặp trục trặc hoặc các phản hồi thăm dò chồng chéo.
Khóa mã thông báo
Mỗi lần chỉ có một phiên bản cổng Weixin có thể sử dụng một mã thông báo nhất định. Bộ điều hợp nhận được khóa có phạm vi khi khởi động và mở khóa khi tắt máy. Nếu một cổng khác đang sử dụng cùng một mã thông báo thì quá trình khởi động sẽ không thành công kèm theo thông báo lỗi đầy thông tin.
Tất cả các biến môi trường
| Biến | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|
WEIXIN_ACCOUNT_ID | ✅ | — | ID tài khoản iLink Bot (từ đăng nhập QR) |
WEIXIN_TOKEN | ✅ | — | Mã thông báo iLink Bot (được lưu tự động khi đăng nhập QR) |
WEIXIN_BASE_URL | — | https://ilinkai.weixin.qq.com | URL cơ sở API iLink |
WEIXIN_CDN_BASE_URL | — | https://novac2c.cdn.weixin.qq.com/c2c | URL cơ sở CDN để truyền phương tiện |
WEIXIN_DM_POLICY | — | open | Chính sách truy cập DM: open, allowlist, disabled, pairing |
WEIXIN_GROUP_POLICY | — | disabled | Chính sách truy cập nhóm: open, allowlist, disabled |
WEIXIN_ALLOWED_USERS | — | (trống) | ID người dùng được phân tách bằng dấu phẩy cho danh sách cho phép DM |
WEIXIN_GROUP_ALLOWED_USERS | — | (trống) | ID nhóm được phân tách bằng dấu phẩy cho danh sách cho phép của nhóm |
WEIXIN_HOME_CHANNEL | — | — | ID trò chuyện cho đầu ra cron/thông báo |
WEIXIN_HOME_CHANNEL_NAME | — | Home | Tên hiển thị cho kênh chủ |
WEIXIN_ALLOW_ALL_USERS | — | — | Cờ cấp cổng để cho phép tất cả người dùng (được sử dụng bởi trình hướng dẫn thiết lập) |
Khắc phục sự cố| Vấn đề | Sửa chữa |
|----------|------|
| Weixin startup failed: aiohttp and cryptography are required | Cài đặt cả hai: pip install aiohttp cryptography |
| Weixin startup failed: WEIXIN_TOKEN is required | Chạy Hermes gateway setup để hoàn tất đăng nhập QR hoặc đặt WEIXIN_TOKEN theo cách thủ công |
| Weixin startup failed: WEIXIN_ACCOUNT_ID is required | Đặt WEIXIN_ACCOUNT_ID trong .env của bạn hoặc chạy Hermes gateway setup |
| Another local Hermes gateway is already using this Weixin token | Trước tiên hãy dừng phiên bản cổng khác - chỉ cho phép một người thăm dò cho mỗi mã thông báo |
| Phiên đã hết hạn (errcode=-14) | Phiên đăng nhập của bạn đã hết hạn. Chạy lại Hermes gateway setup để quét mã QR mới |
| Mã QR đã hết hạn trong quá trình thiết lập | QR tự động làm mới tối đa 3 lần. Nếu nó hết hạn, hãy kiểm tra kết nối mạng của bạn |
| Bot không phản hồi DM | Kiểm tra WEIXIN_DM_POLICY - nếu được đặt thành allowlist, người gửi phải ở WEIXIN_ALLOWED_USERS |
| Bot bỏ qua tin nhắn nhóm | Chính sách nhóm mặc định là disabled. Đặt WEIXIN_GROUP_POLICY=open hoặc allowlist |
| Tải xuống/tải lên phương tiện không thành công | Đảm bảo cryptography được cài đặt. Kiểm tra quyền truy cập mạng vào novac2c.cdn.weixin.qq.com |
| Blocked unsafe URL (SSRF protection) | URL phương tiện gửi đi trỏ đến địa chỉ riêng tư/nội bộ. Chỉ cho phép các URL công khai |
| Tin nhắn thoại hiển thị dưới dạng văn bản | Nếu WeChat cung cấp bản phiên âm thì bộ chuyển đổi sẽ sử dụng văn bản đó. Đây là hành vi được mong đợi |
| Tin nhắn xuất hiện trùng lặp | Bộ điều hợp sẽ loại bỏ trùng lặp theo ID tin nhắn. Nếu bạn thấy các bản sao, hãy kiểm tra xem có nhiều phiên bản cổng đang chạy hay không |
| iLink POST ... HTTP 4xx/5xx | Lỗi API từ dịch vụ iLink. Kiểm tra tính hợp lệ của mã thông báo và kết nối mạng |
| Mã QR đầu cuối không hiển thị | Cài đặt qrcode: pip install qrcode. Ngoài ra, hãy mở URL được in phía trên QR |