# WeixinBotSdk-java **Repository Path**: wufengsheng/weixinbot-sdk-java ## Basic Information - **Project Name**: WeixinBotSdk-java - **Description**: 微信「智能机器人 / ilink bot」协议客户端 SDK(Java 21)。支持扫码登录、getUpdates 长轮询收消息、sendMessage 发消息。 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-08-17 - **Last Updated**: 2026-08-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: weixin, weixinbot, ilinkai, ilink ## README # weixinbot-sdk 微信「智能机器人 / ilink bot」协议客户端 SDK(Java 21)。支持扫码登录、`getUpdates` 长轮询收消息、`sendMessage` 发消息。纯托管实现,唯一第三方运行时依赖为 Jackson(JSON),HTTP 用 JDK 原生 `java.net.http.HttpClient`。 本协议接口与字段命名(snake_case)参考 [openclaw-weixin 微信插件](https://github.com/Tencent/openclaw-weixin/),在此基础上用 Java 重新实现。 ## 快速开始 ```java try (WeixinBotClient client = new WeixinBotClient()) { // 订阅消息:收到 "ping" 回复 "pong" client.onMessageReceived(ev -> { System.out.println("[" + ev.from() + "] " + ev.body()); if ("ping".equals(ev.body())) { client.sendText(ev.from(), "pong").join(); } }); // 可选:监听状态变化(RUNNING → PAUSED → RECONNECTING …) client.onStateChanged(ev -> System.out.println("[state] " + ev.state())); try { client.start(); // 已有 token 直接启动长轮询 } catch (IllegalStateException e) { // 未登录:扫码 LoginStartResult start = client.startLogin().join(); System.out.println("请微信扫码:"); System.out.println(start.qrcodeImgContent()); client.finishLogin(start.qrcode(), Duration.ofMinutes(8), null).join(); client.start(); } new CountDownLatch(1).await(); // 阻塞到 Ctrl+C } ``` 完整示例见 [`ManualDemo.java`](src/test/java/com/weixinbot/sdk/example/ManualDemo.java),可连接真实网关测试。 ## 架构 SDK 按职责分四层,单向依赖不回流: ```mermaid flowchart LR subgraph FACADE["📦 门面层"] WB["WeixinBotClient\n(AutoCloseable)"] end subgraph DOMAIN["⚙️ 业务逻辑层"] AUTH["WeixinAuth\nQR 扫码登录"] MONITOR["WeixinMonitor\n长轮询收消息"] end subgraph HTTP["🌐 HTTP 传输层"] HC["WeixinHttpClient\n统一请求头 + base_info"] end subgraph ABSTRACT["🔌 传输抽象层"] HT["HttpTransport\nsend → CompletableFuture"] end FACADE --> DOMAIN DOMAIN --> HTTP HTTP --> ABSTRACT subgraph SUPPORT["🧩 支撑组件"] STORE["JsonAccountStore\nToken 持久化"] CTX["ContextTokenStore\n会话 Token 缓存"] EVENT["Event\n进程内多播分发"] end WB -.-> STORE WB -.-> CTX WB -.-> EVENT MONITOR -.-> EVENT AUTH -.-> STORE classDef layer fill:#1a2332,stroke:#2d4059,color:#e0e0e0; classDef comp fill:#263547,stroke:#3b5570,color:#c8dce8,rx:6,ry:6; classDef infra fill:#1e2a3a,stroke:#2d4059,color:#9ab0c0; class FACADE,DOMAIN,HTTP,ABSTRACT,SUPPORT layer; class WB,AUTH,MONITOR,HC,HT,STORE,CTX,EVENT comp; ``` | 组件 | 职责 | 关键 API | |------|------|----------| | **`WeixinBotClient`** · 门面 | 唯一公共入口,构造函数内聚装配所有组件;对外暴露登录、启动、收发、事件订阅 | `startLogin()` → `finishLogin()` → `start()` → `sendText()` | | **`WeixinAuth`** · 认证 | QR 扫码登录状态机:取码 → 轮询状态 → confirmed 后持久化 Token;自动处理重定向、配对码 | `CompletableFuture` | | **`WeixinMonitor`** · 监控 | 虚拟线程后台长轮询:`getupdates` → 游标续传 → 派发 `MessageReceivedEvent`;内置过期暂停、失败退避 | `start()` / `stop()` / `onStateChanged()` | | **`WeixinHttpClient`** · HTTP | 统一请求头(AuthorizationType / X-WECHAT-UIN / Bearer)、包裹 `base_info`、支持 baseUrl 切换 | 继承 `WeixinClient` 接口 | | **`JsonAccountStore`** · 存储 | `IAccountStore` 默认实现:Token + baseUrl 存本地 JSON 文件 | `~/.weixinbot/accounts-java.json` | | **`ContextTokenStore`** · 会话 | 线程安全内存缓存:`from_user_id` → `context_token`,发消息时自动回传 | `get(to)` / `put(from, token)` | | **`Event`** · 事件 | 进程内同步多播分发器:`add(Consumer)` 返回退订句柄;订阅者异常被隔离 | `messageReceived.add(listener)` | **方法返回类型**:全部公开方法返回 `CompletableFuture`;`start()` / `stop()` / `close()` 为同步控制方法。 ## 项目结构 ``` src/ ├── main/java/com/weixinbot/sdk/ │ ├── WeixinBotClient.java # 门面(唯一公共入口) │ ├── WeixinConstants.java # 协议常量与工具方法 │ ├── WeixinSdkException.java # 运行时异常基类 │ ├── auth/ # 扫码登录状态机(WeixinAuth) │ ├── monitor/ # 长轮询循环(WeixinMonitor) │ ├── http/ # 协议接口 + HTTP 实现 + 传输抽象(HttpTransport) │ ├── model/ # 消息 / 响应模型(immutable record) │ ├── store/ # 账号持久化 & 上下文 Token 缓存 │ ├── event/ # 事件分发器与事件类型 │ └── util/ # 全局 Jackson ObjectMapper └── test/java/com/weixinbot/sdk/ ├── example/ManualDemo.java # 可运行示例(echo bot,连真实网关) └── ... # 单元测试 + 测试替身(FakeTransport / InMemoryStore) ``` 构建与测试: ```bash mvn test # 运行全部 JUnit 5 测试 mvn verify # 构建 + 测试 ``` ## 注意事项 ### 幂等与会话 - **游标仅内存、不落盘**:进程重启后从空游标重新拉取,可能重复投递消息 → 应用侧应按幂等处理。 - **主动推送**需目标用户已建过会话,或先调用 `seedContextToken(to, token)` 预置。 ### 可靠性 - **过期 Token**(`errcode/ret = -14`)→ 暂停 120s 后重试;连续 3 次失败 → 退避 30s。 - **超时策略**:长轮询 35s 超时会话按成功路径处理(返回空响应)。不要使用 `.orTimeout()`,改用 `HttpRequest.timeout()`。 ### 使用限制 - **X-WECHAT-UIN** 每次请求随机生成,不可缓存复用;HTTP 强制 HTTP/1.1 并禁用系统代理。 - **事件订阅者勿做阻塞操作**(在 monitor 线程同步派发)。 - 媒体上传未实现(`getUploadUrl` 抛 `UnsupportedOperationException`)。 ### 日志 每个 POST body 自动附加 `base_info`(含 `channel_version`、`bot_agent`)。日志前缀 `[MON]` / `[HTTP]` / `[AUTH]` / `[BOT]` / `[EVENT]` 便于过滤。