Mud.Feishu.Webhook 1.2.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Mud.Feishu.Webhook --version 1.2.1
                    
NuGet\Install-Package Mud.Feishu.Webhook -Version 1.2.1
                    
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="Mud.Feishu.Webhook" Version="1.2.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mud.Feishu.Webhook" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="Mud.Feishu.Webhook" />
                    
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 Mud.Feishu.Webhook --version 1.2.1
                    
#r "nuget: Mud.Feishu.Webhook, 1.2.1"
                    
#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 Mud.Feishu.Webhook@1.2.1
                    
#: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=Mud.Feishu.Webhook&version=1.2.1
                    
Install as a Cake Addin
#tool nuget:?package=Mud.Feishu.Webhook&version=1.2.1
                    
Install as a Cake Tool

Mud.Feishu.Webhook

飞书事件订阅与处理的 Webhook 组件,提供完整的飞书事件接收、验证、解密和分发功能。

🚀 新特性:极简API - 一行代码完成服务注册,开箱即用!

NuGet License

功能特性

  • 极简API:一行代码完成服务注册,开箱即用
  • 灵活配置:支持配置文件、代码配置和建造者模式
  • 自动事件路由:根据事件类型自动分发到对应的处理器
  • 安全验证:支持事件订阅验证、请求签名验证和时间戳验证
  • 加密解密:内置 AES-256-CBC 解密功能,自动处理飞书加密事件
  • 使用模式:支持中间件模式
  • 依赖注入:完全集成 .NET 依赖注入容器
  • 异常处理:完善的异常处理和日志记录
  • 性能监控:可选的性能指标收集和监控
  • 健康检查:内置健康检查端点
  • 异步处理:完全异步的事件处理机制
  • 并发控制:可配置的并发事件处理数量限制,支持热更新
  • 分布式支持:提供分布式去重接口,支持 Redis 等外部存储
  • 配置热更新:支持运行时配置变更,无需重启服务
  • 请求频率限制:内置滑动窗口限流中间件,防止恶意请求
  • 多机器人支持:支持多个飞书机器人共享同一个 Webhook 端点
  • 后台处理模式:支持异步后台处理,避免飞书超时重试
  • 安全加固:强化 IP 验证、签名验证和密钥安全检查
  • 跨平台兼容:支持 .NET Standard 2.0、.NET 6.0、.NET 8.0、.NET 10.0
  • 内容类型验证:仅接受 application/json 请求
  • JSON 深度限制:防止深度嵌套 JSON 导致 DoS 攻击
  • 流式请求体读取:防止伪造 Content-Length 的 DoS 攻击
  • Nonce 过期清理:防止内存泄漏
  • 断路器模式:使用 Polly 实现熔断机制
  • 失败事件重试:后台自动重试失败事件
  • 事件处理拦截器:前置/后置事件处理拦截器机制
  • 日志脱敏:自动脱敏敏感字段防止信息泄露
  • 配置锁定机制:生产环境强制安全检查
  • 指数退避重试:失败事件指数退避重试机制

快速开始

1. 安装 NuGet 包

dotnet add package Mud.Feishu.Webhook

2. 最简配置(一行代码)

Program.cs 中:

using Mud.Feishu.Webhook;
using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 一行代码注册Webhook服务(需要至少一个事件处理器)
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageEventHandler>()
    .Build();

var app = builder.Build();

// 添加飞书Webhook中间件
app.UseFeishuWebhook();

app.Run();

💡 说明:Webhook 服务使用中间件模式,通过 app.UseFeishuWebhook() 自动注册端点。默认路由为 /feishu/Webhook

3. 完整配置(添加多个事件处理器)

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 注册多个事件处理器
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageReceiveEventHandler>()      // 消息接收事件
    .AddHandler<DepartmentCreatedEventHandler>()   // 部门创建事件
    .AddHandler<DepartmentUpdateEventHandler>()    // 部门更新事件
    .AddHandler<DepartmentDeleteEventHandler>()    // 部门删除事件
    .Build();

var app = builder.Build();

// 添加飞书Webhook中间件
app.UseFeishuWebhook();

app.Run();

4. 配置文件(appsettings.json)

{
  "FeishuWebhook": {
    "VerificationToken": "your_verification_token",
    "EncryptKey": "your_encrypt_key_32_bytes_long",
    "RoutePrefix": "feishu/Webhook",
    "AutoRegisterEndpoint": true,
    "EnableRequestLogging": true,
    "EnableExceptionHandling": true,
    "EventHandlingTimeoutMs": 30000,
    "MaxConcurrentEvents": 10,
    "EnablePerformanceMonitoring": false,
    "AllowedHttpMethods": [ "POST" ],
    "MaxRequestBodySize": 10485760,
    "ValidateSourceIP": false,
    "AllowedSourceIPs": [],
    "EnforceHeaderSignatureValidation": true,
    "EnableBodySignatureValidation": true,
    "TimestampToleranceSeconds": 60,
    "EnableBackgroundProcessing": false,
    "MultiAppEncryptKeys": {
      "cli_a1b2c3d4e5f6g7h8": "your_app1_encrypt_key_32_bytes_long",
      "cli_h8g7f6e5d4c3b2a1": "your_app2_encrypt_key_32_bytes_long"
    },
    "DefaultAppId": "cli_a1b2c3d4e5f6g7h8",
    "RateLimit": {
      "EnableRateLimit": false,
      "WindowSizeSeconds": 60,
      "MaxRequestsPerWindow": 100,
      "EnableIpRateLimit": true,
      "TooManyRequestsStatusCode": 429,
      "TooManyRequestsMessage": "请求过于频繁,请稍后再试",
      "WhitelistIPs": [ "127.0.0.1", "::1" ]
    },
    "MaxRetryCount": 3,
    "CircuitBreakerEnabled": true,
    "MaxDepth": 64,
    "MaxIpEntries": 100000
  }
}

🏗️ 服务注册方式

🚀 方式一:从配置文件注册(推荐)

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 从 appsettings.json 读取配置
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageReceiveEventHandler>()
    .Build();

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

⚙️ 方式二:代码配置

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 通过代码配置
builder.Services.CreateFeishuWebhookServiceBuilder(options =>
{
    options.VerificationToken = "your_verification_token";
    options.EncryptKey = "your_encrypt_key_32_bytes_long";
    options.RoutePrefix = "feishu/Webhook";
    options.EnableRequestLogging = true;
    options.EnableExceptionHandling = true;
    options.MaxConcurrentEvents = 10;
})
.AddHandler<MessageEventHandler>()
.Build();

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

🔌 方式三:添加事件拦截器

using Mud.Feishu.Webhook.Extensions;
using Mud.Feishu.Abstractions.Interceptors;

var builder = WebApplication.CreateBuilder(args);

// 添加内置和自定义拦截器
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddInterceptor<LoggingEventInterceptor>()  // 内置日志拦截器
    .AddInterceptor<TelemetryEventInterceptor>()  // 内置遥测拦截器
    .AddInterceptor<AuditLogInterceptor>()  // 自定义审计拦截器
    .AddHandler<MessageEventHandler>()
    .Build();

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

🔧 方式四:高级建造者模式

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 使用建造者模式进行复杂配置
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .EnableHealthChecks()    // 启用健康检查
    .AddHandler<MessageReceiveEventHandler>()
    .AddHandler<DepartmentCreatedEventHandler>()
    .Build();

var app = builder.Build();

// 添加健康检查端点
app.MapHealthChecks("/health");

app.UseFeishuWebhook();
app.Run();

🔥 方式五:指定配置节名称

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 从自定义配置节读取
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration, "MyFeishuConfig")
    .AddHandler<MessageEventHandler>()
    .Build();

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

使用模式

中间件模式

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageEventHandler>()
    .Build();

var app = builder.Build();
app.UseFeishuWebhook(); // 自动处理路由前缀下的请求
app.Run();

💡 说明:Webhook 服务目前仅支持中间件模式,通过配置 RoutePrefix 来自定义路由路径。

创建事件处理器

方式一:实现 IFeishuEventHandler 接口

using Microsoft.Extensions.Logging;
using Mud.Feishu.Abstractions;
using System.Text.Json;

public class MessageReceiveEventHandler : IFeishuEventHandler
{
    private readonly ILogger<MessageReceiveEventHandler> _logger;

    public MessageReceiveEventHandler(ILogger<MessageReceiveEventHandler> logger)
    {
        _logger = logger;
    }

    // 指定支持的事件类型
    public string SupportedEventType => "im.message.receive_v1";

    public async Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("收到消息事件: EventId={EventId}, EventType={EventType}", 
            eventData.EventId, eventData.EventType);
        
        // 处理消息逻辑
        var messageData = JsonSerializer.Deserialize<MessageEventData>(
            eventData.Event?.ToString() ?? string.Empty);
        
        // 你的业务逻辑...
        _logger.LogInformation("处理消息: {MessageId}", messageData?.MessageId);
        
        await Task.CompletedTask;
    }
}

public class MessageEventData
{
    public string MessageId { get; set; }
    public string Content { get; set; }
    // ... 其他字段
}

方式二:继承基类处理器(推荐)

使用 Mud.Feishu.Abstractions.EventHandlers 命名空间下的基类处理器,提供类型安全和自动去重:

using Mud.Feishu.Abstractions;
using Mud.Feishu.Abstractions.DataModels.Organization;
using Mud.Feishu.Abstractions.EventHandlers;
using Mud.Feishu.Abstractions.Services;

/// <summary>
/// 部门创建事件处理器
/// </summary>
public class DemoDepartmentEventHandler : DepartmentCreatedEventHandler
{
    private readonly DemoEventService _eventService;

    public DemoDepartmentEventHandler(
        IFeishuEventDeduplicator businessDeduplicator, 
        ILogger<DemoDepartmentEventHandler> logger,
        DemoEventService eventService) 
        : base(businessDeduplicator, logger)
    {
        _eventService = eventService;
    }

    protected override async Task ProcessBusinessLogicAsync(
        EventData eventData, 
        DepartmentCreatedResult? eventEntity, 
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("处理部门创建事件: 部门ID={DepartmentId}, 部门名={DepartmentName}",
            eventEntity.DepartmentId, eventEntity.Name);

        // 你的业务逻辑
        await _eventService.RecordDepartmentEventAsync(eventEntity, cancellationToken);
        
        // 模拟权限初始化
        _logger.LogInformation("初始化部门权限: {DepartmentName}", eventEntity.Name);
        
        // 模拟通知部门主管
        if (!string.IsNullOrWhiteSpace(eventEntity.LeaderUserId))
        {
            _logger.LogInformation("通知部门主管: {LeaderUserId}", eventEntity.LeaderUserId);
        }
    }
}

可用的基类事件处理器

  • DepartmentCreatedEventHandler - 部门创建事件
  • DepartmentUpdateEventHandler - 部门更新事件
  • DepartmentDeleteEventHandler - 部门删除事件
  • 更多处理器请参考 Mud.Feishu.Abstractions.EventHandlers 命名空间

配置选项

基本配置

选项 类型 默认值 说明
VerificationToken string - 飞书事件订阅验证 Token
EncryptKey string - 飞书事件加密密钥(32字节)
RoutePrefix string "feishu/Webhook" Webhook 路由前缀
AutoRegisterEndpoint bool true 是否自动注册端点
MaxRetryCount int 3 失败事件最大重试次数
CircuitBreakerEnabled bool true 是否启用断路器模式
MaxDepth int 64 JSON 反序列化最大深度
MaxIpEntries int 100000 限流中间件最大 IP 条目数(LRU 淘汰)

多机器人配置

选项 类型 默认值 说明
MultiAppEncryptKeys Dictionary<string, string> - 多机器人密钥配置(AppId → EncryptKey)
DefaultAppId string - 默认应用 ID(多机器人场景回退)

安全配置

选项 类型 默认值 说明
ValidateSourceIP bool false 是否验证来源 IP
AllowedSourceIPs HashSet<string> - 允许的源 IP 地址列表
AllowedHttpMethods HashSet<string> ["POST"] 允许的 HTTP 方法
MaxRequestBodySize long 10MB 最大请求体大小
EnforceHeaderSignatureValidation bool true 是否强制验证请求头签名
EnableBodySignatureValidation bool true 是否在服务层再次验证请求体签名
TimestampToleranceSeconds int 60 时间戳验证容错范围(秒)

性能配置

选项 类型 默认值 说明
MaxConcurrentEvents int 10 最大并发事件数,支持热更新
EventHandlingTimeoutMs int 30000 事件处理超时时间(毫秒)
EnablePerformanceMonitoring bool false 是否启用性能监控
EnableBackgroundProcessing bool false 是否启用异步后台处理模式

日志配置

选项 类型 默认值 说明
EnableRequestLogging bool true 是否启用请求日志记录
EnableExceptionHandling bool true 是否启用异常处理

请求频率限制配置

选项 类型 默认值 说明
RateLimit.EnableRateLimit bool false 是否启用请求频率限制
RateLimit.WindowSizeSeconds int 60 时间窗口大小(秒)
RateLimit.MaxRequestsPerWindow int 100 每个时间窗口内允许的最大请求数
RateLimit.EnableIpRateLimit bool true 是否基于 IP 限流
RateLimit.TooManyRequestsStatusCode int 429 超出限制时的响应状态码
RateLimit.TooManyRequestsMessage string "请求过于频繁,请稍后再试" 超出限制时的响应消息
RateLimit.WhitelistIPs HashSet<string> [] 白名单 IP 列表(不参与限流)
RateLimit.MaxIpEntries int 100000 限流中间件最大 IP 条目数(LRU 淘汰)

高级功能

多机器人支持

支持多个飞书机器人共享同一个 Webhook 端点:

{
  "FeishuWebhook": {
    "MultiAppEncryptKeys": {
      "cli_a1b2c3d4e5f6g7h8": "your_app1_encrypt_key_32_bytes_long",
      "cli_h8g7f6e5d4c3b2a1": "your_app2_encrypt_key_32_bytes_long"
    },
    "DefaultAppId": "cli_a1b2c3d4e5f6g7h8"
  }
}

请求频率限制

内置滑动窗口限流中间件,防止恶意请求:

{
  "FeishuWebhook": {
    "RateLimit": {
      "EnableRateLimit": true,
      "WindowSizeSeconds": 60,
      "MaxRequestsPerWindow": 100,
      "EnableIpRateLimit": true,
      "WhitelistIPs": [ "127.0.0.1", "::1" ]
    }
  }
}

后台处理模式

启用后台处理模式,避免飞书超时重试:

{
  "FeishuWebhook": {
    "EnableBackgroundProcessing": true
  }
}
// 启用后台处理模式后,中间件会立即返回成功响应
// 然后在后台异步处理事件,适用于耗时较长的业务逻辑
builder.Services.CreateFeishuWebhookServiceBuilder(options =>
{
    options.EnableBackgroundProcessing = true;
}).AddHandler<LongRunningEventHandler>()
    .Build();

事件拦截器(Interceptors)

事件拦截器允许在事件处理前后执行自定义逻辑,如日志记录、指标收集、权限验证等。

内置拦截器

LoggingEventInterceptor - 记录事件处理日志

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddInterceptor<LoggingEventInterceptor>()  // 记录事件处理开始和结束
    .AddHandler<MessageEventHandler>()
    .Build();

TelemetryEventInterceptor - 遥测数据收集

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddInterceptor<TelemetryEventInterceptor>(sp =>
        new TelemetryEventInterceptor("My.Application"))  // 指定应用名称
    .AddHandler<MessageEventHandler>()
    .Build();

自定义拦截器

创建自定义拦截器需要实现 IFeishuEventInterceptor 接口:

using Mud.Feishu.Abstractions;

/// <summary>
/// 审计日志拦截器示例
/// </summary>
public class AuditLogInterceptor : IFeishuEventInterceptor
{
    private readonly ILogger<AuditLogInterceptor> _logger;

    public AuditLogInterceptor(ILogger<AuditLogInterceptor> logger)
        => _logger = logger;

    /// <summary>
    /// 事件处理前拦截
    /// </summary>
    /// <returns>返回 false 将中断事件处理流程</returns>
    public Task<bool> BeforeHandleAsync(string eventType, EventData eventData, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("[审计] 事件开始: {EventType}, EventId: {EventId}, TenantKey: {TenantKey}",
            eventType, eventData.EventId, eventData.TenantKey);
        return Task.FromResult(true); // 返回 true 继续处理,false 中断
    }

    /// <summary>
    /// 事件处理后拦截
    /// </summary>
    public Task AfterHandleAsync(string eventType, EventData eventData, Exception? exception, CancellationToken cancellationToken = default)
    {
        if (exception == null)
        {
            _logger.LogInformation("[审计] 事件成功: {EventType}, EventId: {EventId}", eventType, eventData.EventId);
        }
        else
        {
            _logger.LogError(exception, "[审计] 事件失败: {EventType}, EventId: {EventId}", eventType, eventData.EventId);
        }
        return Task.CompletedTask;
    }
}

注册自定义拦截器

// 类型注册
.AddInterceptor<AuditLogInterceptor>()

// 工厂注册
.AddInterceptor(sp => new AuditLogInterceptor(
    sp.GetRequiredService<ILogger<AuditLogInterceptor>>()))

// 实例注册
var interceptor = new AuditLogInterceptor(logger);
.AddInterceptor(interceptor)

拦截器执行顺序

拦截器按注册顺序依次执行,完整流程:

Webhook 事件到达
    ↓
拦截器1: BeforeHandleAsync
    ↓
拦截器2: BeforeHandleAsync
    ↓
...
    ↓
拦截器N: BeforeHandleAsync
    ↓
[事件处理器处理事件]
    ↓
拦截器N: AfterHandleAsync
    ↓
...
    ↓
拦截器2: AfterHandleAsync
    ↓
拦截器1: AfterHandleAsync
    ↓
处理完成

应用场景

  • 日志记录:记录事件处理的开始、成功、失败
  • 指标收集:统计事件处理时间、成功率等
  • 安全审计:记录敏感事件的处理情况
  • 权限控制:根据事件类型或内容决定是否处理
  • 性能监控:记录处理耗时,识别性能瓶颈
  • 业务追踪:将事件信息写入审计日志或追踪系统

注册事件处理器

链式调用注册多个处理器

using Mud.Feishu.Webhook.Extensions;

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageReceiveEventHandler>()      // 消息接收
    .AddHandler<DepartmentCreatedEventHandler>()   // 部门创建
    .AddHandler<DepartmentUpdateEventHandler>()    // 部门更新
    .AddHandler<DepartmentDeleteEventHandler>()    // 部门删除
    .Build();

使用工厂方法注册

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageEventHandler>(sp =>
    {
        var logger = sp.GetRequiredService<ILogger<MessageEventHandler>>();
        var myService = sp.GetRequiredService<MyCustomService>();
        return new MessageEventHandler(logger, myService);
    })
    .Build();

使用实例注册

var handler = new MessageEventHandler(loggerFactory.CreateLogger<MessageEventHandler>());

builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler(handler)
    .Build();

支持的事件类型

本库支持所有飞书开放平台的事件类型。常见事件类型包括:

消息事件

  • im.message.receive_v1 - 接收消息事件
  • im.message.recalled_v1 - 消息撤回事件

群聊事件

  • im.chat.member_user.added_v1 - 用户加入群聊
  • im.chat.member_user.withdrawn_v1 - 用户离开群聊
  • im.chat.disbanded_v1 - 群聊解散
  • im.chat.updated_v1 - 群信息变更

通讯录事件

  • contact.user.created_v3 - 员工入职
  • contact.user.updated_v3 - 员工信息变更
  • contact.user.deleted_v3 - 员工离职
  • contact.department.created_v3 - 部门创建
  • contact.department.updated_v3 - 部门信息变更
  • contact.department.deleted_v3 - 部门删除

审批事件

  • approval.approval.approved_v1 - 审批通过
  • approval.approval.rejected_v1 - 审批拒绝
  • approval.approval.updated_v1 - 审批更新

任务事件

  • task.task.created_v1 - 任务创建
  • task.task.updated_v1 - 任务更新

💡 提示:更多事件类型请参考飞书开放平台事件列表

飞书平台配置

1. 创建事件订阅

  1. 登录飞书开放平台
  2. 进入你的应用详情页
  3. 点击"事件订阅"
  4. 配置请求网址:https://your-domain.com/feishu/Webhook
  5. 设置验证 Token 和加密 Key

2. 配置事件类型

选择你需要订阅的事件类型:

  • 消息事件
  • 群聊事件
  • 用户事件
  • 部门事件
  • 等...

3. 发布应用

配置完成后发布应用,飞书服务器将开始向你的端点推送事件。

监控和诊断

性能监控

性能监控通过拦截器机制实现,支持 OpenTelemetry 和自定义指标收集:

// 添加遥测拦截器(OpenTelemetry 集成)
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddInterceptor<TelemetryEventInterceptor>()
    .AddHandler<MessageEventHandler>()
    .Build();

// 或使用自定义性能监控拦截器
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddInterceptor<PerformanceMonitoringInterceptor>()
    .AddHandler<MessageEventHandler>()
    .Build();

健康检查

内置健康检查支持,可监控 Webhook 服务的运行状态:

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 启用健康检查
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .EnableHealthChecks()    // 启用健康检查
    .AddHandler<MessageEventHandler>()
    .Build();

var app = builder.Build();

// 添加健康检查端点
app.MapHealthChecks("/health");

app.UseFeishuWebhook();
app.Run();

健康检查配置选项:

{
  "FeishuWebhook": {
    "HealthCheckUnhealthyFailureRateThreshold": 0.1,  // 不健康阈值(10%)
    "HealthCheckDegradedFailureRateThreshold": 0.05,  // 降级阈值(5%)
    "HealthCheckMinEventsThreshold": 10  // 最小事件数
  }
}

日志记录

本库使用标准的 .NET 日志记录框架,可以灵活配置日志级别:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Mud.Feishu.Webhook": "Debug",
      "Mud.Feishu.Webhook.Services": "Debug",
      "Mud.Feishu.Webhook.Middleware": "Information",
      "Mud.Feishu.Abstractions": "Information"
    }
  }
}

诊断端点(Demo 示例)

Demo 项目提供了诊断端点,可以查看已注册的事件处理器:

// 在 Demo 项目中使用
app.MapDiagnostics();  // 注册诊断端点

// 访问 /diagnostics/handlers 查看所有已注册的处理器

最佳实践

1. 错误处理

在事件处理器中妥善处理异常,避免影响其他事件的处理:

public class RobustEventHandler : IFeishuEventHandler
{
    private readonly ILogger<RobustEventHandler> _logger;

    public string SupportedEventType => "im.message.receive_v1";

    public async Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("开始处理事件: {EventId}", eventData.EventId);
            
            // 你的业务逻辑
            await ProcessBusinessLogicAsync(eventData, cancellationToken);
            
            _logger.LogInformation("事件处理完成: {EventId}", eventData.EventId);
        }
        catch (OperationCanceledException)
        {
            _logger.LogWarning("事件处理被取消: {EventId}", eventData.EventId);
            throw; // 超时取消应该抛出
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理事件时发生错误: {EventId}", eventData.EventId);
            // 不要重新抛出异常,避免影响其他处理器
            // 可以选择记录到失败队列或告警系统
        }
    }
    
    private async Task ProcessBusinessLogicAsync(EventData eventData, CancellationToken cancellationToken)
    {
        // 实际业务逻辑
        await Task.CompletedTask;
    }
}

2. 异步处理和取消支持

正确使用异步编程和取消令牌:

public async Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default)
{
    // ✅ 正确:使用异步 API 并传递取消令牌
    await ProcessMessageAsync(eventData, cancellationToken);
    await SaveToDatabaseAsync(eventData, cancellationToken);
    
    // ❌ 错误:不要使用阻塞调用
    // var result = ProcessMessageAsync(eventData).Result;
    // ProcessMessageAsync(eventData).Wait();
    
    // ✅ 正确:尊重取消令牌
    cancellationToken.ThrowIfCancellationRequested();
}

3. 依赖注入

合理使用依赖注入,确保服务生命周期正确:

public class MessageEventHandler : IFeishuEventHandler
{
    private readonly ILogger<MessageEventHandler> _logger;
    private readonly IMessageService _messageService;  // Scoped 服务
    private readonly IConfiguration _configuration;    // Singleton 服务

    public MessageEventHandler(
        ILogger<MessageEventHandler> logger,
        IMessageService messageService,
        IConfiguration configuration)
    {
        _logger = logger;
        _messageService = messageService;
        _configuration = configuration;
    }

    public string SupportedEventType => "im.message.receive_v1";

    public async Task HandleAsync(EventData eventData, CancellationToken cancellationToken = default)
    {
        // 使用注入的服务
        await _messageService.ProcessAsync(eventData, cancellationToken);
    }
}

4. 使用基类处理器(推荐)

继承基类处理器可以获得自动去重和类型安全:

using Mud.Feishu.Abstractions.EventHandlers;

// 继承基类处理器,自动处理去重和类型转换
public class MyDepartmentHandler : DepartmentCreatedEventHandler
{
    public MyDepartmentHandler(
        IFeishuEventDeduplicator deduplicator,
        ILogger<MyDepartmentHandler> logger)
        : base(deduplicator, logger)
    {
    }

    // 只需要实现业务逻辑
    protected override async Task ProcessBusinessLogicAsync(
        EventData eventData,
        DepartmentCreatedResult eventEntity,
        CancellationToken cancellationToken = default)
    {
        // eventEntity 已经是强类型的实体对象
        _logger.LogInformation("处理部门: {Name}", eventEntity.Name);
    }
}

5. 配置验证

启动时验证配置,尽早发现问题:

// 配置会在 Build() 时自动验证
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<MessageEventHandler>()
    .Build();  // 这里会验证配置

// 如果配置无效,会抛出 InvalidOperationException

6. 长时间运行的任务

对于耗时较长的任务,启用后台处理模式:

// appsettings.json
{
  "FeishuWebhook": {
    "EnableBackgroundProcessing": true,  // 立即返回成功,后台处理
    "EventHandlingTimeoutMs": 60000      // 增加超时时间
  }
}

7. 测试和调试

Demo 项目提供了测试端点,可用于调试:

// 在 Demo 项目中
app.MapTestEndpoints();        // 测试端点
app.MapDiagnostics();          // 诊断端点

// 可以使用以下端点:
// POST /test/capture - 捕获原始请求
// GET /test/captured - 查看捕获的请求
// GET /diagnostics/handlers - 查看已注册的处理器

故障排除

常见问题

  1. 验证失败

    • 检查 VerificationToken 是否正确
    • 确认请求 URL 配置正确
  2. 解密失败

    • 检查 EncryptKey 是否正确
    • 确认飞书平台已启用加密
  3. 签名验证失败

    • 检查时间同步
    • 确认请求没有被代理服务器修改
    • 生产环境确保 EnforceHeaderSignatureValidation 设置为 true
  4. 事件处理失败

    • 检查事件处理器是否正确注册
    • 查看日志中的详细错误信息
  5. 分布式部署事件重复

    • 默认使用内存去重,多实例部署需要实现分布式去重
    • 参考 IFeishuNonceDistributedDeduplicator 接口自定义 Redis 实现
  6. 超时处理

    • 检查 EventHandlingTimeoutMs 配置是否合理
    • 确保事件处理逻辑支持取消令牌
  7. 请求频率限制问题

    • 检查 RateLimit.EnableRateLimit 配置
    • 确认客户端 IP 是否在白名单中
    • 调整 MaxRequestsPerWindowWindowSizeSeconds 参数
  8. 多机器人配置问题

    • 检查 MultiAppEncryptKeys 配置是否正确
    • 确认 AppId 与密钥的映射关系
    • 验证 DefaultAppId 配置

调试技巧

// 启用详细日志
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Debug);

// 启用请求日志记录和性能监控
builder.Services.CreateFeishuWebhookServiceBuilder(options =>
{
    options.EnableRequestLogging = true;
    options.EnablePerformanceMonitoring = true;
    options.RateLimit.EnableRateLimit = true; // 启用限流调试
}).AddHandler<MessageEventHandler>()
    .Build();

完整示例

基础示例

完整的 Program.cs 示例:

using Mud.Feishu.Webhook.Extensions;
using Mud.Feishu.Webhook.Demo.Handlers;
using Mud.Feishu.Webhook.Demo.Services;

var builder = WebApplication.CreateBuilder(args);

// 注册自定义服务
builder.Services.AddSingleton<DemoEventService>();

// 注册飞书Webhook服务
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration, "FeishuWebhook")
    .AddHandler<DemoDepartmentEventHandler>()
    .AddHandler<DemoDepartmentDeleteEventHandler>()
    .AddHandler<DemoDepartmentUpdateEventHandler>()
    .Build();

var app = builder.Build();

// 添加飞书Webhook中间件
app.UseFeishuWebhook();

app.Run();

高级示例

包含健康检查、性能监控和自定义端点:

using Mud.Feishu.Webhook.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 配置日志
builder.Logging.AddConsole();
builder.Logging.SetMinimumLevel(LogLevel.Debug);

// 注册飞书Webhook服务(高级配置)
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .EnableHealthChecks()    // 启用健康检查
    .AddHandler<MessageReceiveEventHandler>()
    .AddHandler<DepartmentCreatedEventHandler>()
    .Build();

var app = builder.Build();

// 健康检查端点
app.MapHealthChecks("/health");

// 飞书Webhook中间件
app.UseFeishuWebhook();

app.Run();

Demo 项目完整示例

Demo 项目提供了完整的测试和诊断功能:

using Mud.Feishu.Webhook.Demo.Handlers;
using Mud.Feishu.Webhook.Demo.Services;
using Mud.Feishu.Webhook.Extensions;
using Mud.Feishu.Webhook.Demo;

var builder = WebApplication.CreateBuilder(args);

// 注册演示服务
builder.Services.AddSingleton<DemoEventService>();

// 注册飞书Webhook服务
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration, "FeishuWebhook")
    .AddHandler<DemoDepartmentEventHandler>()
    .AddHandler<DemoDepartmentDeleteEventHandler>()
    .AddHandler<DemoDepartmentUpdateEventHandler>()
    .Build();

var app = builder.Build();

// 添加诊断端点(仅开发环境)
if (app.Environment.IsDevelopment())
{
    app.MapDiagnostics();      // GET /diagnostics/handlers
    app.MapTestEndpoints();    // POST /test/capture 等
}

// 添加飞书Webhook中间件
app.UseFeishuWebhook();

app.Run();

快速参考

最常用的代码模式

// ✅ 推荐:从配置文件读取
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .AddHandler<YourEventHandler>()
    .Build();

// ✅ 代码配置
builder.Services.CreateFeishuWebhookServiceBuilder(options => {
    options.VerificationToken = "your_token";
    options.EncryptKey = "your_encrypt_key_32_bytes_long";
})
.AddHandler<YourEventHandler>()
.Build();


// ✅ 高级配置
builder.Services.CreateFeishuWebhookServiceBuilder(builder.Configuration)
    .EnableHealthChecks()
    .AddHandler<Handler1>()
    .AddHandler<Handler2>()
    .Build();

常用配置项速查

配置项 默认值 说明
RoutePrefix "feishu/Webhook" Webhook 路由前缀
VerificationToken - 验证令牌(必填)
EncryptKey - 加密密钥(32字节)
MaxConcurrentEvents 10 最大并发事件数
EventHandlingTimeoutMs 30000 事件处理超时(毫秒)
EnableBackgroundProcessing false 后台处理模式
EnablePerformanceMonitoring false 性能监控

🚀 立即开始使用飞书Webhook,构建稳定可靠的事件处理系统!

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  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 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. 
.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 was computed.  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.

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
3.0.0-preview3 36 5/22/2026
3.0.0-preview2 124 5/11/2026
3.0.0-preview1 143 5/1/2026
2.1.3 73 5/22/2026
2.1.2 126 5/12/2026
2.1.1 97 5/11/2026
2.1.0 119 5/1/2026
2.0.9 172 4/24/2026
2.0.8 155 4/12/2026
2.0.7 161 4/7/2026
2.0.6 113 4/5/2026
2.0.5 205 3/28/2026
2.0.4 114 3/19/2026
2.0.3 126 2/26/2026
2.0.2 141 1/30/2026
2.0.1 128 1/27/2026
1.2.2 151 1/19/2026 1.2.2 is deprecated because it is no longer maintained and has critical bugs.
1.2.1 146 1/16/2026 1.2.1 is deprecated because it is no longer maintained and has critical bugs.
1.2.0 132 1/14/2026 1.2.0 is deprecated because it is no longer maintained and has critical bugs.
1.1.2 159 1/11/2026 1.1.2 is deprecated because it is no longer maintained and has critical bugs.
Loading failed