Multi-language SDK for WeChat messaging via the OpenClaw channel protocol
Go · Python · Rust · PHP
A set of lightweight, zero-framework SDKs that let you send and receive WeChat messages programmatically through the OpenClaw iLink channel protocol.
- Scan a QR code to bind a WeChat account
- Receive messages from WeChat users via long-polling
- Send text, image, video, and file messages back
- All media transferred via CDN with AES-128-ECB encryption
Disclaimer: This is an independent community project. Not affiliated with Tencent or WeChat.
Intended for educational and research purposes. See DISCLAIMER.md for full details.
HTTP JSON API
┌──────────┐ ◄─────────────────────► ┌────────────────────────┐
│ Your │ │ ilinkai.weixin.qq.com │
│ App │ │ (iLink Gateway) │
│ + SDK │ CDN Upload / Download ├────────────────────────┤
│ │ ◄─────────────────────► │ novac2c.cdn.weixin.qq │
└──────────┘ AES-128-ECB │ (Media CDN) │
└────────────────────────┘
Step 1. QR Login → get bot_token + user_id
Step 2. Start long-polling → getUpdates loop
Step 3. User sends a msg → you receive context_token ← REQUIRED
Step 4. Now you can reply → sendMessage with context_token
context_token is mandatory for message delivery. Without it the API accepts your request (HTTP 200) but the message will never reach the WeChat client. The token is only available after the user sends their first message from WeChat.
import "github.com/qingchencloud/wxchat-sdk/go/wxchatoc"
// 1. QR Login
session, _ := wxchatoc.StartQRLogin(ctx, wxchatoc.DefaultBaseURL)
fmt.Println("Scan:", session.QRCodeURL)
result, _ := session.WaitForLogin(ctx, func(s string) { fmt.Println(s) })
// 2. Create client + start polling
client := wxchatoc.NewClient(result.BotToken)
tokens := wxchatoc.NewContextTokenStore()
poller := wxchatoc.NewPoller(client, func(msg *wxchatoc.WeixinMessage) {
// 3. Save context_token from first message
if msg.ContextToken != "" {
tokens.Set("default", msg.FromUserID, msg.ContextToken)
}
fmt.Printf("From %s: %s\n", msg.FromUserID, msg.ItemList[0].TextItem.Text)
// 4. Reply
ct := tokens.Get("default", msg.FromUserID)
client.SendText(ctx, msg.FromUserID, "Got it!", ct)
})
poller.Run(ctx)Deps: Go 1.21+, zero third-party dependencies
from wxchatoc import WxChatClient, start_qr_login, Poller, ContextTokenStore
# 1. QR Login
session = start_qr_login()
print("Scan:", session.qrcode_url)
result = session.wait_for_login(on_status=print)
# 2. Client + polling
client = WxChatClient(token=result.bot_token)
tokens = ContextTokenStore()
def on_message(msg):
if msg.context_token:
tokens.set("default", msg.from_user_id, msg.context_token)
print(f"From {msg.from_user_id}: {msg.item_list[0].text_item.text}")
ct = tokens.get("default", msg.from_user_id)
client.send_text(msg.from_user_id, "Got it!", ct)
Poller(client, on_message=on_message).run()Deps: Python 3.9+, httpx, cryptography
use wxchatoc::{WxChatClient, auth};
#[tokio::main]
async fn main() {
let mut session = auth::start_qr_login(
"https://ilinkai.weixin.qq.com", None, None
).await.unwrap();
println!("Scan: {}", session.qrcode_url);
let result = session.wait_for_login(
Some(|s: &str| println!("{}", s))
).await.unwrap();
let client = WxChatClient::new(&result.bot_token);
// ... start polling, collect context_token, then send
client.send_text("user@im.wechat", "Hello!", "ctx-token").await.unwrap();
}Deps: reqwest, aes, serde, tokio
use WxChatOC\{Client, Auth, Poller, ContextTokenStore};
$session = Auth::startQRLogin();
echo "Scan: " . $session->qrcodeUrl . "\n";
$result = $session->waitForLogin(fn($s) => print("$s\n"));
$client = new Client($result->botToken);
$tokens = new ContextTokenStore();
$poller = new Poller($client, function($msg) use ($client, $tokens) {
if ($msg->context_token) {
$tokens->set('default', $msg->from_user_id, $msg->context_token);
}
$ct = $tokens->get('default', $msg->from_user_id);
$client->sendText($msg->from_user_id, 'Got it!', $ct);
});
$poller->run();Deps: PHP 8.1+, guzzlehttp/guzzle, ext-openssl
A browser-based chat interface for quick testing:
cd examples/testui
pip install httpx
python server.py # opens http://localhost:8199Open browser → Scan QR to bind → Send a message from WeChat to establish channel → Chat
wxchat-sdk/
├── go/wxchatoc/ # Go SDK (zero deps)
│ ├── client.go # API client
│ ├── auth.go # QR login
│ ├── cdn.go # CDN upload/download
│ ├── poller.go # Long-poll + token store
│ ├── crypto.go # AES-128-ECB
│ └── types.go # Type definitions
├── python/wxchatoc/ # Python SDK
├── rust/wxchatoc/ # Rust SDK
├── php/wxchatoc/ # PHP SDK
├── examples/testui/ # Browser test UI
└── docs/PROTOCOL.md # Full protocol documentation
| Endpoint | Method | Description |
|---|---|---|
ilink/bot/get_bot_qrcode |
GET | Fetch QR code for login |
ilink/bot/get_qrcode_status |
GET | Poll QR scan status (long-poll) |
ilink/bot/getupdates |
POST | Long-poll for new messages |
ilink/bot/sendmessage |
POST | Send message (text/image/video/file) |
ilink/bot/getuploadurl |
POST | Get CDN upload pre-signed URL |
ilink/bot/getconfig |
POST | Get account config (typing ticket) |
ilink/bot/sendtyping |
POST | Send typing indicator |
Full protocol documentation: docs/PROTOCOL.md
Contributions are welcome! Please open an issue or PR.
一套多语言 SDK,通过 OpenClaw iLink 通道协议实现与微信的消息收发。
- 扫码绑定 -- 获取 bot_token 和用户 ID
- 启动长轮询 -- getUpdates 循环接收消息
- 用户从微信发一条消息 -- 获取 context_token(必需)
- 开始双向聊天 -- sendMessage 必须携带 context_token
context_token是消息投递的必要条件,没有它消息不会到达微信客户端- 每次收到新消息都应更新 context_token
get_updates_buf同步游标需要持久化保存- errcode=-14 表示会话过期,SDK 会自动暂停 1 小时
cd examples/testui
pip install httpx
python server.py浏览器打开 http://localhost:8199 ,扫码绑定后在微信发一条消息建立通道,即可双向聊天。
本项目是独立的社区开源项目,与腾讯/微信无任何关联。仅供教育和研究用途。详见 DISCLAIMER.md。