Skip to content

Mud.Feishu ​

📖 简介 ​

Mud.Feishu 是飞书服务端 SDK 的 .NET 适配版,提供完整的 HTTP API 客户端能力,支持 .NET Standard 2.0、.NET 6.0、.NET 8.0 和 .NET 10.0 平台。通过类型安全的 API 封装,让开发者能够在 .NET 应用程序中便捷、高效地集成飞书服务端功能。

✨ 核心特性 ​

  • 类型安全 - 强类型接口定义,编译时类型检查
  • 模块化设计 - 按需注册 API 模块,减少不必要的依赖
  • 自动令牌管理 - 智能缓存和刷新,无需手动维护
  • 智能重试机制 - 内置重试策略,提高调用成功率
  • 多应用支持 - 统一管理多个飞书应用
  • 弹性策略 - Polly 重试 + 熔断,参数可按应用配置
  • 配置热更新 - BaseUrl / TimeOut 等运行期生效,凭据变更即清库
  • 原生 AOT 支持 - net8.0+ 一等公民支持 Native AOT 发布
  • 完整 API 覆盖 - 支持组织架构、消息、群聊、审批、任务、云文档、画板、电子表格、多维表格、日历日程、视频会议、邮箱、AI、搜索、服务台等全部飞书核心功能

🏗️ 架构概览 ​

mermaid
graph TD
    subgraph Mud_Feishu[Mud.Feishu]
        direction TB

        HTTP_API[HTTP API Client<br/>源生成客户端]
        Token_Management[Token Management<br/>Smart Cache & Auto Refresh]
        Module_Registry[Module Registry<br/>AddXxxApi / FeishuModule]
        App_Manager[IFeishuAppManager<br/>多应用上下文]

        HTTP_API --> Module_Registry
        HTTP_API --> Token_Management
        Module_Registry --> App_Manager
    end

    DataModels[Mud.Feishu.DataModels] --> HTTP_API
    Abstractions[Mud.Feishu.Abstractions] --> Token_Management
    HttpUtils[Mud.HttpUtils<br/>HTTP 客户端与弹性策略] --> HTTP_API

    style Mud_Feishu fill:#e1f5ff
    style HTTP_API fill:#4caf50,color:#fff
    style Token_Management fill:#00bcd4,color:#fff
    style Module_Registry fill:#9c27b0,color:#fff
    style App_Manager fill:#ff9800,color:#fff

🚀 快速开始 ​

安装 ​

bash
dotnet add package Mud.Feishu

💡 Mud.Feishu.Abstractions 与 Mud.Feishu.DataModels 会作为依赖自动引入,通常无需单独安装。

服务注册 ​

csharp
using Mud.Feishu;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// 注册飞书应用配置
builder.Services.AddFeishuApp(builder.Configuration);

// 方式一:懒人模式 - 注册所有 API 服务
builder.Services.CreateFeishuServicesBuilder()
    .AddAllApis()
    .Build();

// 方式二:建造者模式 - 按需注册
builder.Services.CreateFeishuServicesBuilder()
    .AddOrganizationApi()
    .AddMessageApi()
    .AddChatGroupApi()
    .AddApprovalApi()
    .AddTaskApi()
    .AddCardApi()
    .AddAttendanceApi()
    .AddDriveApi()
    .AddWikiApi()
    .AddDocxApi()
    .AddSpreadsheetsApi()
    .AddBiTableApi()
    .AddCalendarApi()
    .AddVideoConferencingApi()
    .AddMailApi()
    .AddAIApi()
    .AddSearchApi()
    .AddHelpDeskApi()
    .Build();

// 方式三:模块枚举模式
builder.Services.AddFeishuServices(
    FeishuModule.Organization,
    FeishuModule.Message,
    FeishuModule.ChatGroup,
    FeishuModule.Spreadsheets,
    FeishuModule.Bitable,
    FeishuModule.Calendar,
    FeishuModule.VideoConferencing,
    FeishuModule.Mail,
    FeishuModule.AI,
    FeishuModule.Search,
    FeishuModule.HelpDesk
);

var app = builder.Build();
app.Run();

建造者方法清单 ​

方法模块方法模块
AddOrganizationApi()组织架构AddDocxApi()文档
AddMessageApi()消息服务AddSpreadsheetsApi()电子表格
AddChatGroupApi()群聊管理AddBiTableApi()多维表格
AddApprovalApi()审批流程AddCalendarApi()日历日程
AddTaskApi()任务管理AddVideoConferencingApi()视频会议
AddCardApi()卡片管理AddMailApi()邮箱管理
AddAttendanceApi()考勤管理AddAIApi()AI 能力
AddDriveApi()云盘管理AddSearchApi()搜索
AddWikiApi()知识库AddHelpDeskApi()服务台

配置文件 ​

json
{
  "FeishuApps": [
    {
      "AppKey": "default",
      "AppId": "your_feishu_app_id",
      "AppSecret": "your_feishu_app_secret",
      "BaseUrl": "https://open.feishu.cn",
      "TimeOut": 30,
      "RetryCount": 3,
      "RetryDelayMs": 1000,
      "EnableLogging": true,
      "IsDefault": true
    }
  ]
}

使用 API 服务 ​

csharp
using Mud.Feishu;
using Mud.Feishu.DataModels;
using Mud.Feishu.DataModels.Organization;

public class UserService
{
    private readonly IFeishuTenantV3User _userApi;

    public UserService(IFeishuTenantV3User userApi)
    {
        _userApi = userApi;
    }

    public async Task<FeishuApiResult<GetUserInfoResult>?> GetUserAsync(string userId)
    {
        return await _userApi.GetUserInfoByIdAsync(userId);
    }

    public async Task<FeishuApiResult<CreateOrUpdateUserResult>?> CreateUserAsync(CreateUserRequest request)
    {
        return await _userApi.CreateUserAsync(request);
    }
}

⚙️ 配置选项 ​

FeishuAppConfig 配置项 ​

配置项类型默认值说明
AppKeystring-应用唯一标识(必需)
AppIdstring-飞书应用 ID(必需)
AppSecretstring-飞书应用密钥(必需)
BaseUrlstringhttps://open.feishu.cnAPI 基础地址
AllowCustomBaseUrlboolfalse是否允许自定义基础 URL(存在 SSRF 风险,仅特殊场景启用)
TimeOutint30HTTP 请求超时时间(秒)
RetryCountint3失败重试次数
RetryDelayMsint1000重试延迟时间(毫秒)
CircuitBreakerEnabledbooltrue是否启用熔断策略
CircuitBreakerFailureThresholdint20熔断失败率阈值(百分比)
CircuitBreakerSamplingDurationSecondsint60熔断采样窗口时间(秒)
CircuitBreakerBreakDurationSecondsint60熔断持续时间(秒)
CircuitBreakerMinimumThroughputint10熔断最小吞吐量
TokenRefreshThresholdint300令牌刷新阈值(秒)
EnableLoggingbooltrue是否启用日志记录
IsDefaultboolfalse是否为默认应用

⚠️ 多应用模式下,弹性策略为全局共享,仅默认应用(IsDefault=true)的配置生效。

配置验证 ​

FeishuAppConfig 提供 Validate() 方法校验配置项有效性:

  • TimeOut 必须在 1-300 秒之间
  • RetryCount 必须在 0-10 次之间
  • RetryDelayMs 必须在 100-60000 毫秒之间
  • TokenRefreshThreshold 必须在 60-3600 秒之间
  • AppId 必须以 cli_ 或 app_ 开头,且长度至少为 20 字符
  • AppSecret 长度至少为 16 字符
  • BaseUrl 必须是有效的 HTTP/HTTPS URL 格式

ℹ️ 自 3.0.0 起,为适配 AOT 源生成配置绑定,FeishuAppConfig 已移除 required 修饰,必填校验统一由 Validate() 承担(源生成绑定器通过 new T() 构造)。

安全建议 ​

  • AppId 和 AppSecret 是飞书应用的身份凭证,请妥善保管
  • 建议使用环境变量或安全的配置管理系统来存储敏感信息
  • 非必要不要开启 AllowCustomBaseUrl(存在 SSRF 风险)
  • 生产环境必须启用签名验证和时间戳验证(详见 Webhook 文档)

📋 API 模块总览 ​

模块分类API 版本接口(典型)主要功能
组织管理V3IFeishuTenantV3User、IFeishuTenantV3Departments用户、部门、职级、职务、职务族、用户组、角色、单位、工作城市、人员类型
消息服务V1IFeishuTenantV1Message、IFeishuTenantV1BatchMessage消息发送/回复/编辑/转发、表情回复、Pin、加急、消息内资源、上传下载
群聊管理V1IFeishuTenantV1ChatGroup、IFeishuTenantV1ChatGroupMember群信息、群成员、群公告、群标签页、群菜单
审批流程V4 / V2IFeishuTenantV4Approval、IFeishuTenantV4ApprovalTask审批定义与实例、审批任务、评论、第三方审批、审批文件、查询、订阅
任务管理V2IFeishuTenantV2Task、IFeishuTenantV2TaskCustomFields任务、子任务、成员、清单、提醒、依赖、自定义字段、评论、附件、分组、活动订阅
卡片管理V1IFeishuTenantV1Card、IFeishuTenantV1CardElements卡片实体创建/更新/局部更新、卡片元素
考勤管理V1IFeishuTenantV1AttendanceUserFlows、IFeishuTenantV1AttendanceGroups打卡流水、考勤组、考勤统计、班次、考勤档案
云盘管理V1IFeishuTenantV1DriveFiles、IFeishuTenantV1DrivePermissions文件元数据/复制/移动/删除、快捷方式、上传下载(含分片)、导入导出、点赞、文件夹、版本、媒体、权限、事件订阅、评论
知识库V2IFeishuTenantV2Wiki、IFeishuTenantV2WikiNodes知识空间、空间成员、空间设置、知识节点
文档管理V1IFeishuTenantV1Docx、IFeishuTenantV1DocxBlocks文档创建获取、文档块读写、批量操作、内容转换
画板管理V1IFeishuTenantV1Board画板主题、缩略图、PlantUML/Mermaid 解析、节点创建与读取
电子表格V3 / V2IFeishuTenantV3Spreadsheets、IFeishuV3SpreadsheetRange表格、区域、数据、单元格、筛选、筛选视图、浮动图片、保护范围、数据验证、条件格式
多维表格V1 / V2IFeishuTenantV1Bitable、IFeishuTenantV2BitableRole应用、数据表、记录、字段、视图、表单、仪表盘、角色、自动化流程
日历日程V4IFeishuTenantV4Calendar、IFeishuTenantV4CalendarEvent日历、ACL、日程事件
视频会议V1IFeishuTenantV1VideoConferencingMeeting、IFeishuTenantV1VideoConferencingRoom会议、配置、会议室、层级、预定、录制、纪要、导出、数据、报表
AI 能力V1IFeishuTenantV1AIDocument、IFeishuTenantV1AIOpticalCharRecognition文档解析、OCR、语音转文字、文本翻译
邮箱管理V1IFeishuTenantV1MailMessage、IFeishuTenantV1MailTemplate邮件消息、别名、联系人、草稿、文件夹、邮件组、标签、公共邮箱、规则、模板、会话
搜索V2IFeishuTenantV2SearchDataSource、IFeishuTenantV2SearchDocWiki数据源、文档/知识库搜索、套件搜索
服务台V1IFeishuTenantV1HelpDeskAgent、IFeishuTenantV1HelpDeskTicket客服管理、工单管理

令牌类型的接口划分 ​

同一业务对象通常按令牌类型提供三套接口,继承关系为「父类公共接口 ← 租户令牌接口 / 用户令牌接口」:

接口类型命名示例说明
父类接口(公共)IFeishuV3User租户与用户令牌均可调用的公共方法
租户令牌接口IFeishuTenantV3User使用 tenant_access_token 调用(创建、更新、删除等)
用户令牌接口IFeishuUserV3User使用 user_access_token 调用(以当前用户身份查询等)

组织管理示例 ​

csharp
// 用户管理:父类接口 IFeishuV3User 提供查询类方法,租户接口补充写操作
public interface IFeishuV3User
{
    Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoByIdAsync(string userId);
    Task<FeishuApiResult<BatchGetUserResult>?> GetUserByIdsAsync(IEnumerable<string> userIds);
    Task<FeishuApiResult<GetUserPageListResult>?> GetUserByDepartmentIdAsync(string departmentId);
}

public interface IFeishuTenantV3User : IFeishuV3User
{
    Task<FeishuApiResult<CreateOrUpdateUserResult>?> CreateUserAsync(CreateUserRequest request);
    Task<FeishuApiResult<DeleteUserResult>?> DeleteUserByIdAsync(string userId);
    Task<FeishuApiResult<string>?> GetJsTicketAsync(...);
}

public interface IFeishuUserV3User : IFeishuV3User
{
    Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoAsync();
}
csharp
// 部门树
var result = await _deptApi.GetDepartmentsByParentIdAsync("0", fetch_child: true);
if (result?.Code == 0)
{
    var departments = result.Data.Items;
    var nextPageToken = result.Data.PageToken;
}

消息服务示例 ​

csharp
var textContent = new MessageTextContent { Text = "Hello World!" };
var result = await _messageApi.SendMessageAsync(new SendMessageRequest
{
    ReceiveId = "user_123",
    MsgType = "text",
    Content = JsonSerializer.Serialize(textContent)
}, receive_id_type: "user_id");

if (result?.Code != 0)
{
    throw new Exception($"发送失败: {result?.Msg}");
}

分页处理 ​

分页接口统一以 ...PageListAsync 命名,返回 FeishuApiPageListResult<T>,通过 PageToken 迭代:

csharp
public async Task<List<T>> GetAllItemsAsync<T>(
    Func<string?, Task<FeishuApiPageListResult<T>>> pageFetcher)
{
    var allItems = new List<T>();
    string? pageToken = null;

    do
    {
        var result = await pageFetcher(pageToken);

        if (result.Code == 0 && result.Data?.Items != null)
        {
            allItems.AddRange(result.Data.Items);
            pageToken = result.Data.PageToken;
        }
        else
        {
            break;
        }

    } while (!string.IsNullOrEmpty(pageToken));

    return allItems;
}

// 使用示例
var allUsers = await GetAllItemsAsync(pageToken =>
    userApi.GetUserByDepartmentIdAsync("dept_123", page_size: 50, page_token: pageToken));

🏢 多应用支持 ​

csharp
// 配置多个应用
builder.Services.AddFeishuApp(configure =>
{
    configure.AddDefaultApp("default", "cli_xxx", "dsk_xxx");
    configure.AddApp("hr-app", "cli_yyy", "dsk_yyy", opt =>
    {
        opt.TimeOut = 45;
        opt.RetryCount = 5;
    });
});
csharp
public class MultiAppService
{
    private readonly IFeishuAppManager _appManager;

    public MultiAppService(IFeishuAppManager appManager)
    {
        _appManager = appManager;
    }

    // 方式一:获取指定应用的 API(内部已切换应用上下文,推荐)
    public async Task UseSpecificAppAsync()
    {
        var userApi = _appManager.GetWebApi<IFeishuTenantV3User>("hr-app");
        var result = await userApi.GetUserInfoByIdAsync("user_123");
    }

    // 方式二:使用 BeginScope 在作用域内切换应用上下文(作用域结束自动恢复)
    public async Task UseScopedAppAsync(IFeishuTenantV3User userApi)
    {
        using (userApi.BeginScope("hr-app"))
        {
            // 在此作用域内,userApi 的所有调用都使用 hr-app 的凭证
            var result = await userApi.GetUserInfoByIdAsync("user_123");
        }
    }
}
API说明
AddFeishuApp(IConfiguration)从配置注册(单/多应用)
AddFeishuApp(Action<...> configure)代码方式注册多应用
configure.AddDefaultApp(appKey, appId, appSecret)添加默认应用
configure.AddApp(appKey, appId, appSecret, Action<options>)添加命名应用 + 选项覆盖
IFeishuAppManager.GetWebApi<T>(appKey)获取指定应用的 API 实例并切换上下文
IFeishuAppManager.GetDefaultWebApi<T>()获取默认应用的 API 实例
IFeishuAppManager.ConfiguredAppKeys获取全部已配置的 AppKey(不触发懒加载)
api.BeginScope(appKey)在作用域内切换应用上下文

重要提示:

  • ⚠️ 线程安全:UseApp() / UseDefaultApp() 为无作用域切换,会改变服务实例状态,长生命周期宿主存在上下文泄漏风险;推荐使用 GetWebApi<T>(appKey) 或 BeginScope(appKey)。
  • 📝 后台任务:必须明确指定应用,不能依赖默认应用。
  • 🔄 凭据轮换:配置热更新检测到 AppId/AppSecret 变更时,会立即清除该应用的全部持久化令牌;仅 BaseUrl/TimeOut 等变更时保留令牌热迁移。
  • 🏢 多租户:多租户 = 多应用,但 UseApp/BeginScope 只切换令牌与端点,不做租户隔离授权,需业务层自行实现。

💡 令牌管理、多应用/多租户与配置热更新的完整说明见飞书多应用管理及认证授权指南。


🎯 常见操作快速参考 ​

令牌管理 ​

csharp
// 直接从应用上下文获取指定类型的令牌管理器(令牌管理实现位于 Mud.HttpUtils)
var token = await appContext
    .GetTokenManager(FeishuTokenTypes.TenantAccessToken)
    .GetTokenAsync();

// 注意:自 3.0.0 起,GetAllApps() 只返回已实例化的应用,不会触发懒初始化
// 需要获取全部已配置的 AppKey 请使用 ConfiguredAppKeys
foreach (var appKey in _appManager.ConfiguredAppKeys)
{
    Console.WriteLine(appKey);
}

ℹ️ 令牌缓存条目按应用(AppKey)通过键前缀隔离,TokenKeyBuilder 是 Memory / Redis 令牌键布局的单一真相源。

自定义模块注册 ​

通过 IFeishuModuleRegistrar 扩展自定义 API 模块:

csharp
public class CustomModuleRegistrar : IFeishuModuleRegistrar
{
    public FeishuModule Module => FeishuModule.All + 1;

    public void Register(IServiceCollection services)
    {
        services.AddTransient<ICustomApi, CustomApi>();
    }
}

// 注册自定义模块
builder.Services.CreateFeishuServicesBuilder()
    .RegisterModule(new CustomModuleRegistrar())
    .Build();

错误处理 ​

csharp
public class FeishuServiceBase
{
    protected async Task<T> ExecuteWithErrorHandling<T>(
        Func<Task<FeishuApiResult<T>>> operation,
        string operationName)
    {
        var result = await operation();

        if (result.Code != 0)
        {
            throw new FeishuServiceException(
                $"飞书 API 调用失败: {operationName}",
                result.Code,
                result.Msg);
        }

        return result.Data!;
    }
}

// 使用示例
public async Task<UserInfo> GetUserSafelyAsync(string userId)
{
    return await ExecuteWithErrorHandling(
        () => userApi.GetUserInfoByIdAsync(userId),
        "获取用户信息");
}

💡 所有 API 统一返回 FeishuApiResult<T>(含 Code / Msg / Data),业务判断以 Code == 0 为准; 文件下载类接口(返回 Task<byte[]?>)存在「HTTP 200 + JSON 错误体」的残余风险,需按接口文档声明处理。


⚡ Native AOT 支持 ​

自 3.0.0 起,Mud.Feishu 在 net8.0+ 目标框架下一等公民支持 .NET Native AOT 发布:

  • 全链路源生成 JSON 序列化(内置 FeishuJsonContext)
  • 源生成配置绑定(EnableConfigurationBindingGenerator)
  • AOT 安全辅助类 FeishuJsonAot
  • 通过 AOT 严格模式质量门禁保证 AOT00x / IL2026 / IL3050 诊断为 0
bash
dotnet publish -r win-x64 -c Release /p:PublishAot=true

⚠️ 注意事项:

  • 自定义类型的序列化请通过 FeishuJsonDefaults.ConfigureUserResolver 注册自定义 JsonSerializerContext
  • 扩展配置 DTO 请勿使用 required 修饰,改在 Validate() 方法中校验

📊 与原生飞书 SDK 的对比 ​

对比维度原生 SDK 调用Mud.Feishu 组件优势说明
开发效率需要手动构造 HTTP 请求、处理响应、解析 JSON 等大量样板代码只需调用简洁的接口方法,一行代码完成操作大幅减少代码量,提高开发效率
类型安全手动处理 JSON 序列化/反序列化,容易出现类型转换错误提供完整的强类型支持,编译时就能发现类型错误提高代码健壮性,减少运行时错误
令牌管理需要手动获取、刷新和管理访问令牌自动处理令牌获取和刷新机制减少开发者负担,避免令牌管理错误
异常处理需要手动处理各种网络异常和业务异常统一的响应模型与异常处理机制简化异常处理逻辑,提高代码可读性
重试/熔断需要手动实现重试逻辑内置智能重试与熔断机制(可配置)提高系统稳定性
可测试性直接调用 HTTP 接口,难以进行单元测试基于接口设计,易于进行 Mock 测试提高代码质量和可维护性
文档完善度需要在飞书官方文档中查找各个接口的详细说明提供完整的中文 API 文档和示例代码降低学习成本,快速上手
AOT 部署反射式序列化难以 AOT全链路源生成,可直接发布原生二进制启动更快、内存更省

🛠️ 技术栈 ​

设计模式 ​

  • 策略模式 - 事件处理器接口和实现
  • 工厂模式 - 处理器工厂和模块注册工厂
  • 建造者模式 - 服务注册构造者
  • 中间件模式 - Webhook 中间件和限流中间件

企业级特性 ​

  • 自动令牌管理 - 智能缓存(提前刷新),解决缓存击穿和竞态条件
  • 智能重试 - 基于 Polly 策略,指数退避算法
  • 统一异常处理 - 统一响应模型与详细日志记录
  • 高性能缓存 - ConcurrentDictionary + Lazy<Task>,并发安全
  • 分布式支持 - 配合 Mud.Feishu.Redis 实现多实例部署

依赖项 ​

包版本说明
Mud.HttpUtilsv2.0.7HTTP 客户端工具类(含源代码生成器)
Mud.HttpUtils.Generatorv2.0.7HTTP 客户端代码生成器(编译时)
Mud.Feishu.Abstractions同版本飞书 SDK 抽象层
Mud.Feishu.DataModels同版本飞书 API 强类型数据模型

框架支持 ​

.NET 版本支持状态说明
.NET Standard 2.0✅兼容 .NET Framework 4.6.1+
.NET 6.0✅ LTS长期支持版本
.NET 8.0✅ LTS长期支持版本(推荐,支持 Native AOT 发布)
.NET 10.0✅ LTS长期支持版本(推荐,支持 Native AOT 发布)

🔗 相关项目 ​


📄 许可证 ​

MudFeishu 遵循 MIT 许可证。


如果觉得 MudFeishu 对你有帮助,请给个 ⭐Star 支持一下!

Made with ❤️ by MudTools