Yoyo.WeCom
10.5.10
dotnet add package Yoyo.WeCom --version 10.5.10
NuGet\Install-Package Yoyo.WeCom -Version 10.5.10
<PackageReference Include="Yoyo.WeCom" Version="10.5.10" />
<PackageVersion Include="Yoyo.WeCom" Version="10.5.10" />
<PackageReference Include="Yoyo.WeCom" />
paket add Yoyo.WeCom --version 10.5.10
#r "nuget: Yoyo.WeCom, 10.5.10"
#:package Yoyo.WeCom@10.5.10
#addin nuget:?package=Yoyo.WeCom&version=10.5.10
#tool nuget:?package=Yoyo.WeCom&version=10.5.10
Yoyo.WeCom
独立的 .NET 10 企业微信公共客户端。底层 SDK 精确锁定为 SKIT.FlurlHttpClient.Wechat.Work 3.17.0,不依赖 Yoyo Admin、ABP、EF 或登录会话。当前为源码及本地打包交付,尚未发布到 NuGet。
引用与接线
包名、程序集和命名空间均为 Yoyo.WeCom。产品包版本由仓库 common.props 的统一列车决定,不等于底层 SKIT 的 3.17.0。发布前从本地生成的 .nupkg 或项目引用消费;包中附带 XML API 文档,不能将本说明视为 nuget.org 已上架。
using Microsoft.Extensions.DependencyInjection;
using Yoyo.WeCom;
services.AddWeCom();
var client = provider.GetRequiredService<IWeComClient>();
var connection = new WeComConnection
{
ConnectionId = "tenant-a-app-a", // 宿主提供稳定且隔离的连接身份
CorpId = resolvedCorpId,
AgentId = resolvedAgentId,
Secret = resolvedSecret, // 从宿主安全配置解析,不写入日志
CredentialVersion = resolvedCredentialVersion // 轮换 Secret 时必须改变
};
var result = await client.ListDepartmentsAsync(connection);
if (!result.IsSuccess)
{
// Error 仅包含脱敏类别/远端错误码;不要无条件重试写请求。
HandleError(result.Error!);
}
同进程同 DI 容器共享 token。缓存键由 ConnectionId、CorpId、AgentId、CredentialVersion 组成;默认提前 2 分钟刷新(短有效期最多提前一半)、同连接 single-flight、最多 1024 个连接并淘汰空闲项。相同版本下更换 Secret 会被拒绝,要求宿主正确更新版本。失败刷新短时合并,不让并发请求逐个冲击 token 接口。跨实例共享缓存/锁不在首版保证范围。所有连接使用官方 HTTPS endpoint,不提供可将 Secret 送往任意地址的全局 endpoint 配置。
AddWeCom 支持 RequestTimeout、TokenRefreshSkew、MaxCachedConnections 与 MaxCallbackCiphertextLength。宿主可注册 TimeProvider;无须注册数据库、用户会话、ABP Module 或 Secret 持久化 provider。
首期能力与限制
| 公共 API | 对应企业微信原子能力 | 边界 |
|---|---|---|
ListDepartmentsAsync |
/cgi-bin/department/list |
返回应用可见目录,可指定部门;不创建本地组织 |
ListMembersAsync |
/cgi-bin/user/list |
读取一个部门,不隐式递归;字段与可见范围受通讯录政策约束 |
SendTextMessageAsync |
/cgi-bin/message/send |
显式成员接收者、UTF-8 文本不超过 2048 字节;不允许隐式 @all 广播 |
GetTodoAsync |
/cgi-bin/todo/get |
查询已有外部待办,不提供创建能力 |
UpdateTodoAsync |
/cgi-bin/todo/update |
修改已有待办整体/参与人状态,0=完成、1=进行中;最多 20 个参与人 |
VerifyCallback |
签名校验、AES-CBC 解密、CorpId 校验 | 同时适用于 URL 验证 echostr 和事件密文;宿主负责时间窗口/重放拒绝 |
待办查询/修改要求应用可见范围包含根部门,且只能操作当前应用创建的待办,已删除待办不能修改。消息返回的 MessageId 是提交回执,不等于所有成员已送达;调用方必须检查 InvalidUserIds 和 UnlicensedUserIds,不能把部分无效接收者当作全部成功。
目录列表接口无游标分页参数,本包忠实返回对应列表,不伪造分页。创建于较新时期的应用和第三方应用可能不能直接取得完整通讯录;权限不足返回 CapabilityUnavailable 或脱敏远端业务错误,不伪造目录同步成功。首版不支持创建外部待办、第三方 suite 授权、会话存档、所有媒体消息或全量上游接口。绩效任务可先使用站内任务及文本应用消息,不能以调用 UpdateTodo 代替创建外部待办。
官方来源:获取 token、部门列表、部门成员详情、应用消息、待办详情、修改待办、回调配置。SDK 模型与权限说明已核对,不代表某企业已获授权或真实远端投递已完成验证。
回调接线
连接补充 CallbackToken 与 43 字符 EncodingAesKey。宿主先按受控路由解析连接,再将 query 的 msg_signature/timestamp/nonce 与外层 XML/JSON 的 Encrypt 字段传给 WeComEncryptedCallback;URL 验证则使用 echostr 作为 Ciphertext。
var verified = client.VerifyCallback(connection,
new WeComEncryptedCallback(signature, timestamp, nonce, ciphertext));
if (!verified.IsSuccess) return RejectRequest();
// 此处仍须校验时间窗口和事件幂等,再反序列化 Plaintext 或返回 echo。
return HandleVerifiedPayload(verified.Value!);
SKIT 的公开解密方法丢弃 receiveId,不能独自保证跨企业隔离;本包通过 SDK 验签,再以 .NET AES 严格检查消息帧长度、32 字节 PKCS#7 填充、UTF-8 和接收者。默认限制密文 1 MiB;宿主仍须限制整个 HTTP 请求体,禁止未经校验的 XML DTD/外部实体解析,并检查外层目的地址、时间窗口与持久化重放键。已校验载荷仍可能包含个人数据,禁止记录完整载荷。连接、回调及结果的 ToString 不输出 Secret、密钥、token 或消息正文。
错误与重试
错误分为 Configuration、Authentication、RateLimited、CapabilityUnavailable、Protocol、RemoteBusiness、Transport、OutcomeUncertain,保留远端数字错误码,不透传 errMsg、请求 URL、token 或底层异常。CanRetry 表示调用方可按自身策略处理,客户端本身不自动重试任何业务写请求。远端 token 拒绝仅失效相应缓存,当前写操作不被自动重放。
响应丢失、HTTP 服务错误或无法确认提交结果时,写请求返回 OutcomeUncertain 且 CanRetry=false;宿主需结合该接口实际支持的查询/去重或转人工。网络层不保证恰好一次。租户解析、本地用户/部门映射、目录写入、业务 outbox、幂等记录和深链接授权均由宿主拥有。
从旧包迁移
旧 Yoyo.Pro.Wechat.Work 新接入不推荐,推荐使用 Yoyo.WeCom。旧 PackageId、公开接口和 Senparc 依赖保留,不下架、不加入编译级 Obsolete。
旧 UseYoyoProSenparcWorkAccount / RegisterWorkAccount 是 Senparc 全局注册接口;新包是普通 DI + 每次调用显式连接,不能仅替换包名就继续使用原 API。按宿主 Secret owner 解析新连接并更新 CredentialVersion,改为上述公共方法,再验证实际企业权限。原包的 ABP 模块启动、Senparc 原生模型或其他能力没有全部逐项迁移。
最小消费示例
仓库中的 samples/Standalone 默认仅验证加载和 DI,不执行外部调用:
dotnet run --project modules/integration/Yoyo.WeCom/samples/Standalone
dotnet test modules/integration/Yoyo.WeCom/tests/Yoyo.WeCom.Tests.csproj
dotnet restore modules/integration/Yoyo.WeCom/Yoyo.WeCom.csproj --locked-mode
需要真实只读目录验证时,安全设置 WECOM_CORP_ID、WECOM_AGENT_ID、WECOM_SECRET、WECOM_CREDENTIAL_VERSION 和 WECOM_CONNECTION_ID,再向示例传入 --departments。示例不发送消息或修改待办。包消费模式通过 -p:UsePackedWeCom=true 使用与统一产品版本一致的本地 feed 制品。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- SKIT.FlurlHttpClient.Wechat.Work (= 3.17.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.