FeishuNetSdk 2.2.2

dotnet add package FeishuNetSdk --version 2.2.2
NuGet\Install-Package FeishuNetSdk -Version 2.2.2
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="FeishuNetSdk" Version="2.2.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FeishuNetSdk --version 2.2.2
#r "nuget: FeishuNetSdk, 2.2.2"
#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.
// Install FeishuNetSdk as a Cake Addin
#addin nuget:?package=FeishuNetSdk&version=2.2.2

// Install FeishuNetSdk as a Cake Tool
#tool nuget:?package=FeishuNetSdk&version=2.2.2

FeishuNetSdk

内置自动缓存和过期重取Token机制。

.NET FeishuNetSdk

飞书开放平台网址:https://open.feishu.cn/

接口清单详见:

TenantAccessToken 适用接口清单

UserAccessToken 适用接口清单

<img src="https://github.com/vicenteyu/FeishuNetSdk/blob/main/business.png" alt="商业合作、定制开发" height="350px">

用法:

1、安装Nuget包

PM> Install-Package FeishuNetSdk

2、服务注册

输入应用凭证的方式

builder.Services.AddFeishuNetSdk(options =>
{
    options.AppId = "cli_test";
    options.AppSecret = "secret_test";
    //options.EnableLogging = true; //启用日志 (true = 启用, false = 关闭, 默认 = 启用)
    //options.IgnoreStatusException = true; //忽略状态异常错误(true = 忽略, false = 启用, 默认 = 忽略)
});

使用配置文件的方式

builder.Services.AddFeishuNetSdk(builder.Configuration.GetSection("FeishuNetSdk"));

appsettings.json根节点上增加配置:

"FeishuNetSdk": {
    "AppId": "cli_test",
    "AppSecret": "secret_test",
    "EnableLogging": true, //启用日志 (true = 启用, false = 关闭, 默认 = 启用)
    "IgnoreStatusException": true //忽略状态异常错误(true = 忽略, false = 启用, 默认 = 忽略)
}

3、注入和调用

public class TestController : ControllerBase
{
    private readonly IFeishuTenantApi _tenantApi;  // <== TenantAccessToken 适用API
    private readonly IFeishuUserApi _userApi;      // <== UserAccessToken 适用API
    
    public TestController(IFeishuTenantApi tenantApi, IFeishuUserApi userApi)
    {
        _tenantApi = tenantApi;
        _userApi = userApi;
    }
    
    [HttpGet("t2")]
    public async Task<IResult> GetT2Async()
    {
        var result = await _tenantApi.GetImV1ChatsAsync();
        return Results.Json(result);
    }
}

4、UserAccessToken 接口使用方法

  1. 跳转登录页面,获取登录预授权码:code
  2. 使用IFeishuAppApi,根据code获取user_access_token
  3. 使用IFeishuUserApi,调用接口。user_access_token默认为第一参数。

示例:

消息卡片(模板消息)

[HttpGet("t2")]
public async Task<IResult> GetT2Async()
{
    var dto = new TemplateCardDto
    {
        Data = new()
        {
            TemplateId = "ctp_xx0123456789",  // <== 模板Id
            TemplateVariable = new()          // <== 模板变量
            {
                { "aa", Aa },
                { "bb", Bb },
                { "cc", Cc }
            }
        }
    };
    var result = await _feishuApi.PostImV1MessagesAsync("open_id",
        new FeishuNetSdk.Im.PostImV1MessagesBodyDto
        {
            MsgType = "interactive",
            ReceiveId = "ou_3c5beeexxxxxx6ce936414bb0d13d386",
            Content = dto.ToString(),
        });
}

文件上传示例

参数类型 FormDataFile 支持 filePathFileInfobyte[]Stream

需要注意部分接口注释上有关于文件格式限制的说明。

[HttpGet("t3")]
public async Task<IResult> GetT3Async()
{
    //定义文件存储路径
    var filePath = @"D:\Users\Downloads\e9bd937f1d7a4c4f992724f5de44bb14.jpg";
    //调用接口
    var result = await _feishuApi.PostImV1ImagesAsync(
        new FeishuNetSdk.Im.PostImV1ImagesBodyDto
        {
            ImageType = "message"
        },
        new FormDataFile(filePath));
    //当返回码异常时,返回错误消息
    if (!result.IsSuccess)
        return Results.Problem(result.Msg);
    return Results.Json(result);
}

文件下载示例

下载操作默认返回HttpResponseMessage,由于没有返回码(code)可以判断操作是否成功,所以建议配合 EnsureSuccessStatusCode() 方法使用,当响应状态码异常时,会抛出异常,需要自行捕获处理。

[HttpGet("t4")]
public async Task<IResult> GetT4Async()
{
    //定义文件存储路径
    var filePath = @"D:\Users\Downloads\e9bd937f----1.jpg";
    //调用接口
    var result = (await _feishuApi.GetImV1ImagesByImageKeyAsync(
        image_key: "img_xxxx-fbdc-4c36-b17c-ac8aa1aee7dg"))
        //当响应状态码异常时,会抛出异常,需要自行捕获处理
        .EnsureSuccessStatusCode();

    //保存文件到指定路径
    await result.SaveAsAsync(filePath);
    return Results.Json(result);
}

个别接口支持部分下载,可以按需设置参数range,字符串格式为bytes=0-100表示下载第0字节到第100字节的数据,默认不填或者null表示下载整个文件。示例如下:

[HttpGet("t5")]
public async Task<IResult> GetT5Async()
{
    //定义文件存储路径
    var filePath = @"D:\Users\Downloads\e9bd937f----2.jpg";
    //调用接口
    var result = (await _feishuApi.GetDriveV1MediasByFileTokenDownloadAsync(
        file_token: "OQBpbF8AEoZ0gqxpCMwcRPWFn8c",
        range: "bytes=0-100"))
        //当响应状态码异常时,会抛出异常,需要自行捕获处理
        .EnsureSuccessStatusCode();

    //保存到指定路径,可能只是文件的一部分,并非完整。
    await result.SaveAsAsync(filePath);
    return Results.Json(result);
}

HTTP状态码为 200 时,表示成功,返回文件二进制流。

HTTP状态码为 206 时,表示下载部分内容成功,返回指定 Range 的部分文件的二进制流。

注意事项:

获取凭证异常时,内部异常类型为TokenException

try
{
    var result = await _feishuApi.GetEventV1OutboundIpAsync();
    return Results.Json(result);
}
catch (HttpRequestException ex) when (ex.InnerException is TokenException tokenException)
{
    return Results.Problem(tokenException.Message);
}

云文档操作

文档操作前提需要有编辑权限,步骤如下:

  1. 自建应用添加机器人能力。
  2. 应用机器人加入或创建一个新群组
  3. 进入目标文档,将该群组设置为文档协作者
  4. 调用接口方法。

以下是仅在特殊情况下使用。

关闭接口日志

true = 启用, false = 关闭, 默认 = 启用

使用配置文件方式可以实时切换。

启用状态异常错误

true = 忽略, false = 启用, 默认 = 忽略

飞书接口在返回结果异常时,同时会返回状态异常,状态异常通常无法实质判断异常原因,具体原因会在返回结果中提示。所以接口默认忽略状态异常。开启状态异常之后需要进行捕获,内部异常为ApiResponseStatusException

使用配置文件方式可以实时切换。

try
{
    var result = await _feishuApi.GetEventV1OutboundIpAsync();
    return Results.Json(result);
}
catch (HttpRequestException ex) when (ex.InnerException is ApiResponseStatusException statusException)
{
    // 响应状态码异常
    return Results.Problem(statusException.Message);
}

接口重载/覆盖

如果要覆盖方法,比如是在保持参数完全一致的情况下,修改http地址,需要在方法前加 new (参数不一致是重载,重载不用加new ),然后将新地址更换到属性上。更换http方法、返回参数及其他属性也是同理。

1、新建API,继承于 IFeishuTenantApi
public interface INewApi : IFeishuTenantApi
{
    [HttpGet("/open-apis/event/v1/outbound_ip1")]
    new System.Threading.Tasks.Task<HttpResponseMessage> GetEventV1OutboundIpAsync();
}
2、注册API
builder.Services.AddHttpApi<INewApi>();
3、修改注入
public class TestController : ControllerBase
{
    //此处更改为新的API:INewApi
    private readonly INewApi _feishuApi;
    public TestController(INewApi feishuApi)
    {
        _feishuApi = feishuApi;
    }
}

启用缓存

默认:不缓存

缓存属性Cache,在接口上使用表示对接口内所有方法启用,建议仅针对具体方法使用,在单个方法上增加属性即可。数值单位是毫秒

public interface INewApi : IFeishuTenantApi
{
    [Cache(10 * 1000)]
    [HttpGet("/open-apis/event/v1/outbound_ip1")]
    new System.Threading.Tasks.Task<HttpResponseMessage> GetEventV1OutboundIpAsync();
}
Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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. 
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
2.2.2 67 4/30/2024
2.2.1 84 4/27/2024
2.2.0 85 4/23/2024
2.1.9.1 77 4/19/2024
2.1.8 99 4/11/2024
2.1.7 101 4/9/2024
2.1.6 82 4/2/2024
2.1.5 87 3/29/2024
2.1.4 75 3/26/2024
2.1.3 130 3/19/2024
2.1.2 102 3/7/2024
2.1.1 102 3/1/2024
2.1.0 93 2/20/2024
2.0.9 99 2/5/2024
2.0.8 146 1/26/2024
2.0.7 87 1/23/2024
2.0.6 108 1/12/2024
2.0.5 98 1/9/2024
2.0.4 102 1/4/2024
2.0.3 107 12/28/2023
2.0.2 108 12/21/2023
2.0.1 416 12/12/2023
2.0.0 136 12/6/2023
1.0.13 119 11/13/2023
1.0.12 107 11/12/2023
1.0.11 106 11/9/2023
1.0.10 109 11/7/2023
1.0.9 196 11/2/2023
1.0.8 88 10/31/2023
1.0.7 104 10/27/2023
1.0.6 103 10/26/2023
1.0.5 112 10/26/2023