OpenILink.SDK
1.0.0
.NET 8.0
This package targets .NET 8.0. The package is compatible with this framework or higher.
.NET Standard 2.0
This package targets .NET Standard 2.0. The package is compatible with this framework or higher.
.NET Framework 4.6.2
This package targets .NET Framework 4.6.2. The package is compatible with this framework or higher.
dotnet add package OpenILink.SDK --version 1.0.0
NuGet\Install-Package OpenILink.SDK -Version 1.0.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="OpenILink.SDK" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenILink.SDK" Version="1.0.0" />
<PackageReference Include="OpenILink.SDK" />
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 OpenILink.SDK --version 1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: OpenILink.SDK, 1.0.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 OpenILink.SDK@1.0.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=OpenILink.SDK&version=1.0.0
#tool nuget:?package=OpenILink.SDK&version=1.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
OpenILink.SDK
微信 iLink Bot API 的 C# / .NET SDK。
这版文档默认按现代 C# 写示例:
using varvar- 顶层语句
- 局部函数 / 方法组优先
完整可运行示例见 examples/OpenILink.ConsoleEchoBot。
安装
dotnet add package OpenILink.SDK
兼容性
net462netstandard2.0net8.0
同一个 NuGet 包可以同时用于老的 .NET Framework、.NET Core
和现代 .NET。
快速开始
using OpenILink.SDK;
var tokenPath = "bot_token.txt";
var bufferPath = "get_updates_buf.txt";
using var client = OpenILinkClient.Create(ReadText(tokenPath));
if (string.IsNullOrWhiteSpace(client.Token))
{
var login = await client.LoginWithQrAsync(ShowQrCode, OnScanned);
if (!login.Connected)
{
Console.Error.WriteLine($"登录失败: {login.Message}");
return;
}
File.WriteAllText(tokenPath, login.BotToken ?? string.Empty);
}
await client.MonitorAsync(HandleMessageAsync, new MonitorOptions
{
InitialBuffer = ReadText(bufferPath),
OnBufferUpdated = SaveBuffer,
OnError = ReportError,
OnSessionExpired = ReportSessionExpired
});
Task HandleMessageAsync(WeixinMessage message)
{
var text = message.ExtractText();
if (string.IsNullOrWhiteSpace(text))
{
return Task.CompletedTask;
}
Console.WriteLine($"[{message.FromUserId}] {text}");
return client.ReplyTextAsync(message, $"echo: {text}");
}
void ShowQrCode(string qrCodeImage)
{
Console.WriteLine(qrCodeImage);
}
void OnScanned()
{
Console.WriteLine("已扫码,请在微信端确认。");
}
void SaveBuffer(string buffer)
{
File.WriteAllText(bufferPath, buffer);
}
void ReportError(Exception exception)
{
Console.Error.WriteLine(exception.Message);
}
void ReportSessionExpired()
{
Console.Error.WriteLine("会话过期,请重新登录。");
}
static string ReadText(string path)
{
return File.Exists(path) ? File.ReadAllText(path).Trim() : string.Empty;
}
创建客户端
最常用的三种写法:
using var client = OpenILinkClient.Create(token);
using var client = new OpenILinkClient(token);
using var httpClient = new HttpClient();
using var client = OpenILinkClient.Builder()
.Token(token)
.BaseUri("https://ilinkai.weixin.qq.com/")
.CdnBaseUri("https://novac2c.cdn.weixin.qq.com/c2c/")
.RouteTag("gray-route")
.HttpClient(httpClient)
.ApiTimeout(TimeSpan.FromSeconds(15))
.LongPollingTimeout(TimeSpan.FromSeconds(35))
.Build();
如果你是从配置系统里读参数,直接用 OpenILinkClientOptions:
var options = new OpenILinkClientOptions(token)
{
BaseUri = new Uri("https://ilinkai.weixin.qq.com/"),
CdnBaseUri = new Uri("https://novac2c.cdn.weixin.qq.com/c2c/"),
RouteTag = "gray-route",
LoginTimeout = TimeSpan.FromMinutes(8)
};
using var client = new OpenILinkClient(options);
登录
首次启动通常没有 bot_token,直接扫码:
var login = await client.LoginWithQrAsync(ShowQrCode, OnScanned, OnExpired);
if (login.Connected)
{
File.WriteAllText("bot_token.txt", login.BotToken ?? string.Empty);
}
void ShowQrCode(string qrCodeImage)
{
Console.WriteLine(qrCodeImage);
}
void OnScanned()
{
Console.WriteLine("已扫码,请确认。");
}
void OnExpired(int attempt, int maxAttempt)
{
Console.WriteLine($"二维码过期,正在刷新 ({attempt}/{maxAttempt})");
}
登录成功后 SDK 会自动更新:
client.Tokenclient.BaseUri
下次启动时直接复用 bot_token 即可。
接收消息
await client.MonitorAsync(HandleMessageAsync, new MonitorOptions
{
InitialBuffer = ReadText("get_updates_buf.txt"),
OnBufferUpdated = buffer => File.WriteAllText("get_updates_buf.txt", buffer),
OnError = exception => Console.Error.WriteLine(exception.Message),
OnSessionExpired = () => Console.Error.WriteLine("会话过期")
});
Task HandleMessageAsync(WeixinMessage message)
{
var text = message.ExtractText();
if (string.IsNullOrWhiteSpace(text))
{
return Task.CompletedTask;
}
return client.ReplyTextAsync(message, $"收到: {text}");
}
MonitorAsync 会自动:
- 重试和退避
- 跟进服务端返回的
longpolling_timeout_ms - 缓存每个用户的
contextToken - 推进
get_updates_buf
回复和主动推送
收到消息后,优先直接回复:
await client.ReplyTextAsync(message, "你好");
需要主动推送时:
if (client.CanPushTo(userId))
{
await client.PushTextAsync(userId, "这是一条主动消息");
}
也可以显式读取缓存的上下文:
var contextToken = client.GetContextToken(userId);
输入状态和 Bot 配置
var config = await client.GetConfigAsync(userId, contextToken);
await client.SendTypingAsync(userId, config.TypingTicket ?? string.Empty, TypingStatus.Typing);
媒体上传和发送
最省心的写法:
var bytes = File.ReadAllBytes("photo.jpg");
await client.SendMediaFileAsync(toUserId, contextToken, bytes, "photo.jpg", "看看这张图");
需要手动控制上传和发送时:
var bytes = File.ReadAllBytes("photo.jpg");
var upload = await client.UploadFileAsync(bytes, toUserId, UploadMediaType.Image);
await client.SendImageAsync(toUserId, contextToken, upload);
同理也可以调用:
SendVideoAsyncSendFileAttachmentAsync
下载文件和语音
下载文件:
var plaintext = await client.DownloadFileAsync(
media.EncryptQueryParam ?? string.Empty,
media.AesKey ?? string.Empty);
下载语音前,需要先注入 ISilkDecoder:
public sealed class MySilkDecoder : ISilkDecoder
{
public Task<byte[]> DecodeAsync(byte[] silkData, int sampleRate, CancellationToken cancellationToken)
{
return Task.FromResult(Array.Empty<byte>());
}
}
using var client = OpenILinkClient.Builder()
.Token(token)
.SilkDecoder(new MySilkDecoder())
.Build();
var wav = await client.DownloadVoiceAsync(voiceItem);
工具方法
var text = message.ExtractText();
var isMedia = MessageUtilities.IsMediaItem(item);
var mime = MimeUtilities.MimeFromFilename("photo.jpg");
var extension = MimeUtilities.ExtensionFromMime("video/mp4");
var isImage = MimeUtilities.IsImageMime("image/png");
var isVideo = MimeUtilities.IsVideoMime("video/mp4");
异常处理
try
{
await client.PushTextAsync(userId, "hello");
}
catch (MissingContextTokenException)
{
Console.WriteLine("该用户还没有可用的 contextToken。");
}
catch (OpenILinkApiException exception) when (exception.IsSessionExpired())
{
Console.WriteLine("会话过期,请重新登录。");
}
catch (OpenILinkHttpException exception)
{
Console.WriteLine($"HTTP 状态码: {exception.StatusCode}");
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETFramework 4.6.2
- Newtonsoft.Json (>= 13.0.3)
- System.Net.Http (>= 4.3.4)
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on OpenILink.SDK:
| Repository | Stars |
|---|---|
|
lindexi/lindexi_gd
博客用到的代码
|
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 276 | 3/23/2026 |