WeixinBotSdk 1.3.0

dotnet add package WeixinBotSdk --version 1.3.0
                    
NuGet\Install-Package WeixinBotSdk -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WeixinBotSdk" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WeixinBotSdk" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="WeixinBotSdk" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WeixinBotSdk --version 1.3.0
                    
#r "nuget: WeixinBotSdk, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WeixinBotSdk@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WeixinBotSdk&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=WeixinBotSdk&version=1.3.0
                    
Install as a Cake Tool

WeixinBotSdk

微信 ilink bot 的 C# 客户端 SDK,支持 .NET 8、.NET 9、.NET 10。围绕「扫码登录 → 长轮询收消息 → 事件 → 回复/推送」提供统一门面 WeixinBotClient。

源码:Gitee

安装

dotnet add package WeixinBotSdk

或直接在 .csproj 中添加引用:

<PackageReference Include="WeixinBotSdk" Version="1.3.0" />

快速开始

完整示例参见 samples/。

首次运行(需扫码)

using WeixinBotSdk;
using WeixinBotSdk.Models;
using Microsoft.Extensions.Logging;

// 创建客户端并接入日志
var bot = new WeixinBotClient();

// 首次启动无保存的 token,进入登录流程
if (!bot.IsLoggedIn)
{
    // 1. 获取二维码 URL
    var qr = await bot.StartLoginAsync();
    Console.WriteLine($"请用微信扫描:{qr.QrCodeUrl}");

    // 2. 等待扫码确认(最长 8 分钟超时)
    var result = await bot.FinishLoginAsync(qr.QrCode, TimeSpan.FromMinutes(8));

    if (!result.Connected && !result.AlreadyConnected)
    {
        Console.WriteLine("登录失败。");
        return;
    }
}

// 3. 启动长轮询,后台收消息
await bot.StartAsync();

// 4. 订阅消息事件(含媒体类型解析)
bot.MessageReceivedAsync += async e =>
{
    if (e.ContentType == (int)MessageItemType.File)
    {
        await CdnDownloader.DownloadToFileAsync(
            bot.GetEffectiveCdnBaseUrl(), e.DownloadEncryptedQueryParam!, e.AesKeyHex!,
            Path.Combine("/tmp", e.FileName!));
    }
    else
    {
        Console.WriteLine($"[{e.From}] {e.Body}");
    }
};

// ... 程序保持运行 ...

// 5. 退出前释放资源
await bot.StopAsync();
await bot.DisposeAsync();

后续运行(已有 token)

var bot = new WeixinBotClient();
bot.CdnBaseUrl = "https://your-cdn-domain.com"; // 设置 CDN 地址用于下载收到的媒体文件
await bot.StartAsync(); // 自动加载已保存的凭据,直接启动

bot.MessageReceived += (_, e) => Console.WriteLine(e.Body);

发送消息

以下调用通常在 MessageReceived 事件处理器(上文第 4 步的 e)中执行:

// 回复收到的用户(context_token 已由 SDK 自动缓存并自动回传)
await bot.SendTextAsync(e.From, "你好,我是机器人!");

// 文件附件(自动 AES-128-ECB 加密 → CDN 上传 → 发送)
await bot.SendFileAsync(e.From, "/path/to/report.pdf", fileName: "report.pdf");

// 图片 / 视频
await bot.SendImageAsync(e.From, "/path/to/photo.jpg");
await bot.SendVideoAsync(e.From, "/path/to/video.mp4");

context_token 全自动管理:用户发来消息时 SDK 自动提取并缓存 context_token,发送回复时无需传入,SDK 会自动附带。SeedContextToken 仅用于测试或无历史对话的特殊场景。

关键 API

方法 说明
StartLoginAsync() 获取二维码 URL
FinishLoginAsync(qrcode, timeout) 等待扫码确认并登录
StartAsync() 加载保存的 token 并启动长轮询
StopAsync() 停止长轮询
SendTextAsync(to, content, contextToken?) 发送文本消息
SendImageAsync(to, filePath, contextToken?) 发送图片(自动上传 CDN)
SendVideoAsync(to, filePath, contextToken?) 发送视频(自动上传 CDN)
SendFileAsync(to, filePath, fileName?, contextToken?) 发送文件附件(自动上传 CDN)
SendTypingAsync(to, status) 输入中状态(1=输入中,2=取消)
SeedContextToken(to, token) 预置用户会话 token(用于主动推送无历史对话的用户)

事件

事件 说明
MessageReceived 收到新消息时同步触发
MessageReceivedAsync 收到新消息时异步触发(轮询循环内 await,适合回复/下载)
StateChanged 监控循环状态变化(Stopped/Running/Paused/Reconnecting)

Token 过期

长轮询收到 errcode / ret = -14 时,SDK 进入 MonitorState.Paused,暂停 120s 后再试,不会自动重新扫码。token 仍无效会再次暂停。

订阅 StateChanged,在 Paused 时停轮询并重新登录。不要在事件处理函数里直接 await StopAsync()(会与轮询线程死锁),先让事件返回:

bot.StateChanged += (_, state) =>
{
    if (state == MonitorState.Paused)
        _ = ReloginAsync();
};

async Task ReloginAsync()
{
    await bot.StopAsync();
    var qr = await bot.StartLoginAsync();
    Console.WriteLine($"Token 已过期,请重新扫码:{qr.QrCodeUrl}");
    var result = await bot.FinishLoginAsync(qr.QrCode, TimeSpan.FromMinutes(8));
    if (!result.Connected && !result.AlreadyConnected) return;
    await bot.StartAsync();
}

凭据存储(IAccountStore)

登录成功后 SDK 把 AccountData(Token / BaseUrl / UserId / AccountId)写入存储;StartAsync 从中读取。默认是 JsonAccountStore(~/.weixinbot/accounts.json)。

换路径:

var bot = new WeixinBotClient(store: new JsonAccountStore("/var/lib/mybot/accounts.json"));

自定义后端(内存 / 数据库 / 密钥保管库):

public sealed class MyAccountStore : IAccountStore
{
    public AccountData? Load() => LoadFromYourBackend(); // 无数据返回 null
    public void Save(AccountData data) => PersistToYourBackend(data); // 扫码确认后覆盖
}

var bot = new WeixinBotClient(store: new MyAccountStore());

Load / Save 是同步调用,实现里不要长时间阻塞。

注意事项

  • 网络失败:连续 3 次 getupdates 失败 → 退避 30s 后重试。
  • 事件订阅者:同步逻辑用 MessageReceived;异步回复/下载用 MessageReceivedAsync(轮询循环内 await)。
  • 媒体下载:收到图片、视频、文件等媒体消息时,SDK 自动解析 CDN 引用参数,通过 CdnDownloader.DownloadToFileAsync(bot.GetEffectiveCdnBaseUrl(), encryptedQueryParam, aesKeyHex, path) 流式解密落盘。文件类型为 MessageItemType.File(值为 4)。
  • 发送约束:from_user_id 必须为空串 ""(非空会导致 ret=-2 prepare failed,SDK 已统一处理);context_token 为 null 时发送仍可成功,回复时自动回传缓存值。
  • 媒体 aes_key 编码:SDK 内部使用 base64(hex 字符串)(与 openclaw-weixin 一致),请勿改为原始字节的 base64,否则对方无法解密媒体(显示「图片过期或被清理」)。

日志

SDK 各组件通过 ILogger 输出登录 / 轮询 / 收发 / 异常等日志:

using var loggerFactory = LoggerFactory.Create(b => b.AddConsole().SetMinimumLevel(LogLevel.Debug));
var bot = new WeixinBotClient(loggerFactory: loggerFactory);

日志前缀约定:

前缀 来源 说明
[AUTH] WeixinAuth 扫码登录流程
[MON] WeixinMonitor 长轮询启停、游标推进、令牌过期、失败退避
[HTTP] WeixinHttpClient HTTP 请求/响应、host 重定向
[REPLY] WeixinBotClient 消息发送及错误

更新日志

v1.3.0

  • 修复 媒体发送(图片/视频/文件)回传 context_token,与文本路径一致
  • 修复 CDN 上传 5xx 重试:每次重建 HttpContent,并正确设置 HTTP 状态码
  • 修复 默认 CDN 地址不再写入缓存,避免挡住后续 getconfig 的真实 cdn_base_url
  • 修复 StartAsync 改为 await getconfig,去掉 GetAwaiter().GetResult()
  • 新增 MessageItemType 枚举(FILE=4,VIDEO=5);文档与示例不再把 FILE 写成 5
  • 新增 MessageReceivedAsync:轮询循环内 await,适合异步回复/下载
  • 新增 长轮询启停调用 notifystart / notifystop(失败仅记日志)
  • 新增 门面 Send* / 登录方法支持 CancellationToken;暴露 State / StateChanged
  • 新增 媒体流式 AES 加解密(上传走临时密文文件,DownloadToFileAsync 边解密边写盘)
  • 变更 WeixinAuth / WeixinMonitor / WeixinClient / WeixinHttpClient 改为 internal,公开入口仅为 WeixinBotClient
  • 变更 未注入时由 SDK 创建的 HttpClient 在 DisposeAsync 中释放
  • 文档 Token 过期(-14 → Paused)处理方式、IAccountStore 用法示例

v1.2.1

  • 变更 samples/SendFilesDemo:移除硬编码的真实用户 ID 和本机文件路径,替换为占位值
  • 优化 NUGET_README.md:精简示例项目表格,保留 GitHub 目录链接

v1.2.0

  • 新增 媒体文件传输支持:SendImageAsync / SendVideoAsync / SendFileAsync,自动完成 AES-128-ECB 加密 → CDN 上传 → 消息构造全流程
  • 新增 CdnDownloader.DownloadAsync / DownloadToFileAsync:从 CDN 下载并解密收到的媒体文件
  • 新增 IWeixinClient 接口与 WeixinClient 实现类分离
  • 增强 MessageReceivedEventArgs 增加 ContentType、FileName、FileSize、DownloadEncryptedQueryParam、AesKeyHex 属性,方便订阅者处理 incoming 媒体消息
  • 新增 CdnBaseUrl 配置项,用于 CDN 地址全局配置

开源许可

MIT License

Star & Follow

如果觉得有用,来 Gitee Star 支持下,或 Follow 获取更新。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 109 8/20/2026
1.2.2 102 8/19/2026
1.2.0 101 8/19/2026
1.1.1 96 8/18/2026
1.1.0 104 8/18/2026