微信官方 iLink 协议全解析:Java 手把手接入微信个人号 Bot
前言
2026 年,腾讯通过 OpenClaw 平台正式开放了微信个人号 Bot API——即 iLink(智联)协议。与之前逆向 iPad 协议、PC Hook 等灰色方案不同,这是微信官方首次合法开放个人号机器人能力,接入域名 ilinkai.weixin.qq.com,无封号风险。
本文将带你从零开始,用 Java + Spring Boot 搭建一个支持 AI 智能回复的微信机器人。
完整项目代码已开源,文末附 GitHub 地址。
一、iLink 协议是什么
iLink 是腾讯官方的微信个人号 Bot 接入标准,基于纯 HTTP/JSON 协议,核心流程只有三步:
扫码登录 → 长轮询收消息 → 回复消息
核心能力一览:
| 能力 | 支持 |
|---|---|
| 1v1 私聊 | ✅ |
| 文本/图片/语音/文件/视频 | ✅ |
| 群聊 | ❌ |
| 主动发消息 | ❌(只能回复) |
| Markdown | ✅ |
协议限制:
- Bot 只能回复用户先发来的消息,不能主动发起对话
- 用户超 24 小时未发消息,context_token 过期,无法回复
- iLink Bot 账号无法加入微信群
二、SDK 选型
当前主流的 Java SDK 有两款:
| SDK | Maven 坐标 | 特点 |
|---|---|---|
| wechat-ilink-sdk-java | io.github.lith0924:wechat-ilink-sdk:2.3.3 |
功能全面,Maven 中央仓库,Builder 模式 |
| ilink-wechat-sdk | io.github.pig-mesh.ai:ilink-wechat-sdk:1.0.0 |
零依赖,API 极简 |
本文选用 wechat-ilink-sdk-java(⭐ 推荐),它自动管理了 context_token 缓存、cursor 游标、心跳保活、重连退避等。
Maven 依赖
<dependency>
<groupId>io.github.lith0924</groupId>
<artifactId>wechat-ilink-sdk</artifactId>
<version>2.3.3</version>
</dependency>
三、消息类型详解
iLink 定义了 5 种消息类型,通过 MessageItem.type 区分:
| type | 含义 | 对应字段 |
|---|---|---|
| 1 | 文本 | item.getText_item().getText() |
| 2 | 图片 | item.getImage_item() → CDN + AES 解密 |
| 3 | 语音 | item.getVoice_item() → silk 格式 |
| 4 | 文件 | item.getFile_item() |
| 5 | 视频 | item.getVideo_item() |
// 消息处理示例
for (MessageItem item : msg.getItem_list()) {
if (item.getText_item() != null) {
// 文本消息
String text = item.getText_item().getText();
} else if (item.getImage_item() != null) {
// 图片消息 → 可下载解密
byte[] image = client.downloadImageFromMessageItem(item);
}
}
四、建立联系的凭证:QR 码 + Bot Token
iLink 有两层凭证:
| 凭证 | 来源 | 用途 | 生命周期 |
|---|---|---|---|
| QR Code | get_bot_qrcode 接口 |
绑定 Bot-微信账号 | 一次性,扫码后失效 |
| Bot Token | 扫码后微信下发 | 所有 API 请求鉴权 | 长期有效 |
完整鉴权流程:
① GET /ilink/bot/get_bot_qrcode?bot_type=3
→ 返回二维码 URL
② 微信扫描 → 手机确认
③ 轮询 GET /ilink/bot/get_qrcode_status
→ { status: "confirmed", bot_token: "xxx", bot_id: "xxx@im.bot" }
④ 后续所有请求携带:
Authorization: Bearer <bot_token>
SDK 将这 4 步封装为两句代码:
String qrCode = client.executeLogin(); // 获取二维码
LoginContext ctx = client.getLoginFuture().get(); // 阻塞等待扫码
五、会话关联的核心:context_token
这是 iLink 协议最重要的概念。
为什么需要 context_token
微信 Bot 不能随意给用户发消息。必须由用户先发起对话,消息中会携带 context_token,Bot 回复时原样回传,微信才知道这条回复应该路由到哪个聊天窗口。
用户发消息 → 消息含 context_token
↓
Bot 回复时必须带上同一个 context_token
↓
没有 → 消息无法投递到用户窗口
SDK 自动管理
SDK 内部维护了 (botId, userId) → contextToken 的缓存映射:
// SDK 内部逻辑(开发者无需手动处理)
getUpdates() → 提取每个消息的 context_token → 缓存
sendText(userId, text) → 从缓存取 context_token → 带上去请求
WeixinMessage 完整字段
public class WeixinMessage {
Long getMessage_id(); // 消息唯一 ID
String getFrom_user_id(); // 发送者: "xxx@im.wechat"
String getTo_user_id(); // 接收者: "xxx@im.bot"
String getContext_token(); // ⭐ 会话令牌
Long getCreate_time_ms(); // 时间戳(毫秒)
List<MessageItem> getItem_list(); // 消息内容
}
ID 命名规则:
xxx@im.wechat→ 普通微信用户xxx@im.bot→ Bot 账号
六、完整消息收发流程
用户发 "你好"
│
▼
微信服务器缓存消息
│
▼
Bot 长轮询 getUpdates() → 返回消息(含 context_token)
│
▼
Bot 业务逻辑处理 → 生成回复
│
▼
Bot sendMessage(回复内容 + 相同的 context_token)
│
▼
微信服务器路由到正确的聊天窗口
│
▼
用户在微信收到回复
七、项目架构设计
src/main/java/com/example/bot/
├── IlinkApplication.java # Spring Boot 启动入口
├── config/
│ └── ILinkConfigProperties.java # 配置类(yaml → Java)
├── service/
│ ├── ILinkBotService.java # Bot 核心:登录/轮询/回复
│ └── AiChatService.java # AI API 调用
└── controller/
└── BotController.java # REST 管理接口
设计要点:
- Bot 跑在虚拟线程(
Thread.startVirtualThread)里,不阻塞主线程 - 消息轮询用 长轮询模式(
getUpdates()最长 hold 35 秒),比定时轮询更实时、更省资源 - 回复采用 AI 优先 + 固定模板降级 策略,保证可用性
- AI 接口兼容 OpenAI 格式,可接任意平台(MiMo、SiliconFlow、DeepSeek、OpenAI)
八、核心代码实现
8.1 配置类
@Data
@Component
@ConfigurationProperties(prefix = "ilink.bot")
public class ILinkConfigProperties {
private int connectTimeoutMs = 35000;
private boolean aiEnabled = true;
private String aiApiKey = "";
private String aiBaseUrl = "https://api.xiaomimimo.com/v1";
private String aiModel = "mimo-v2.5-pro";
private String aiSystemPrompt = "你是一个友好的微信助手...";
private String replyTemplate = "收到你的消息啦!...";
}
8.2 Bot 核心服务(关键代码)
@Slf4j
@Service
public class ILinkBotService {
private volatile ILinkClient client;
private final AtomicBoolean running = new AtomicBoolean(false);
// 启动:虚拟线程中执行,不阻塞主线程
public void start() {
running.set(true);
Thread.startVirtualThread(() -> {
// 获取二维码
String qrCode = client.executeLogin();
log.info("请扫码: {}", qrCode);
// 等待扫码
LoginContext ctx = client.getLoginFuture().get();
log.info("登录成功! botId={}", ctx.getBotId());
// 消息轮询
while (running.get()) {
List<WeixinMessage> msgs = client.getUpdates(); // 35s 长轮询
for (WeixinMessage msg : msgs) {
String reply = buildReply(msg); // 生成回复
client.sendText(msg.getFrom_user_id(), reply);
}
}
});
}
// 回复策略:AI 优先,失败降级
private String buildReply(WeixinMessage msg) {
String userText = msg.getText();
if (aiEnabled) {
String aiReply = aiChatService.chat(userText);
if (aiReply != null) return aiReply;
}
return template.replace("{text}", userText)
.replace("{time}", LocalDateTime.now());
}
}
8.3 AI 服务
@Slf4j
@Service
public class AiChatService {
private final HttpClient httpClient = HttpClient.newHttpClient();
private final ObjectMapper mapper = new ObjectMapper();
public String chat(String userMessage) {
var body = Map.of(
"model", config.getAiModel(),
"messages", List.of(
Map.of("role", "system", "content", config.getAiSystemPrompt()),
Map.of("role", "user", "content", userMessage)
),
"max_tokens", 1024
);
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(config.getAiBaseUrl() + "/chat/completions"))
.header("Authorization", "Bearer " + config.getAiApiKey())
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(body)))
.build();
var resp = httpClient.send(req, HttpResponse.BodyHandlers.ofString());
return mapper.readTree(resp.body()).path("choices").get(0)
.path("message").path("content").asText();
}
}
8.4 管理 API
@RestController
@RequestMapping("/bot")
public class BotController {
@GetMapping("/status") // 查看运行状态
public Map<String, Object> status() { ... }
@GetMapping("/qrcode") // 获取登录二维码
public Map<String, Object> qrCode() { ... }
@PostMapping("/restart") // 重启 Bot
public Map<String, Object> restart() { ... }
}
8.5 application.yaml
ilink:
bot:
connect-timeout-ms: 35000
reply-template: "收到:「{text}」\n⏰ {time}\n🌤 {weather}"
weather-city: Beijing
ai-enabled: true
ai-api-key: your-api-key
ai-base-url: https://api.xiaomimimo.com/v1
ai-model: mimo-v2.5-pro
九、运行效果
启动后控制台输出二维码链接:
📱 QR 码已获取,请使用微信扫描二维码登录 https://liteapp.weixin.qq.com/q/7GiQu1?qrcode=xxx&bot_type=3
微信扫码后,Bot 登录成功。给 Bot 发消息:
用户: 你好 Bot: 你好!我是基于 MiMo-V2.5-Pro 的 AI 助手,有什么可以帮你的吗? 用户: 今天天气怎么样 Bot: 我来帮你查一下...(AI 结合实时数据回复)
如果 AI API 挂了,自动降级:
用户: 你好 Bot: 收到你的消息啦! 你说:「你好」 ⏰ 现在时间:2026-07-16 16:51:15 星期四 🌤 今日天气:晴 +32°C 🤖 这是 iLink Bot 的自动回复~
十、常见问题
Q: 为什么回复重复两条? A: SDK 的 OnMessageListener 回调和 getUpdates() 返回值都会触发消息处理,只保留一个即可。推荐只用 getUpdates() 返回值。
Q: 重启后要重新扫码吗? A: 目前需要。Bot Token 没有持久化,重启后 token 丢失需重新扫码。可以改造 LoginContext 持久化来避免。
Q: 怎么切换 AI 模型? A: 修改 application.yaml 中 ai-base-url 和 ai-model,支持任何 OpenAI 兼容接口。
Q: 支持群聊吗? A: 不支持。iLink Bot 账号被微信限制,无法加入微信群。
十一、总结
iLink 协议让微信个人号机器人开发从灰色地带正式进入合规时代。配合开源 Java SDK,只需几百行代码就能搭建一个支持 AI 智能回复的微信 Bot。
关键要点回顾:
- QR 码 + Bot Token 双重鉴权
- context_token 是会话关联的核心,SDK 已自动管理
- 长轮询比定时轮询更实时高效
- AI 优先 + 降级策略保证可用性
- 只能 1v1 私聊,不能群聊
本文使用的开源项目:wechat-ilink-sdk-java
作者:Cxx0709 | 日期:2026-07-16
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)