.NET6用起来-飞书dotnet sdk

dotNET知音

共 6824字,需浏览 14分钟

 ·

2022-04-27 19:28

最近有用到飞书开放平台的功能,然后在github上找了下,没找到对应的sdk,于是自己封装了一个飞书dotnet sdk,方便调用,只需要结合官网文档,传递对应的参数,接收到返回的数据。


一、飞书开放平台服务端api约定和实现


api请求约定:

基本信息:{api的url、http method(GET or POST)}

请求头:{访问凭证(token)、http content-type}

路径参数:{放置在url中,以开头}

查询参数:{这部分参数需要在 URL 后使用?进行连接,多个查询参数间以&分隔}

请求体:这部分参数需要放在 HTTP 请求的 Body 中,一般为 JSON 格式


api请求实现:

1.创建一个类库项目(dotnet-feishu)

2.定义个飞书请求的接口(IFeishuRequest),所有的请求都会继承它

 public interface IFeishuRequest where T : BaseResponse    {        public  string GetUrl();        public  string GetHttpMethod();
/// /// 获取所有的Key-Value形式的文本请求参数字典。 /// IDictionary<string, object> GetParameters();
/// /// 获取自定义HTTP请求头参数。 /// IDictionary<string, string> GetHeaderParameters(); /// /// 获取路径参数 已:路径参数名称 在url中 /// /// IDictionary<string, string> GetPathParameters(); }

再定义一个抽象的请求基类(BaseRequest),实现接口IFeishuRequest部分的方法,如:header、path参数的get和add和httpMethod的set和get。

 public abstract class BaseRequest : IFeishuRequest where T : BaseResponse    {
private String httpMethod = "POST"; private IDictionary<string, string> headerParams; private IDictionary<string, string> pathParams; public string GetHttpMethod() { return httpMethod; }
public abstract string GetUrl();
public IDictionary<string, string> GetHeaderParameters() { if (this.headerParams == null) { this.headerParams = new Dictionary<string, string>(); } return this.headerParams; } public void AddHeaderParameter(string key, string value){ GetHeaderParameters().Add(key, value); } /// /// 设置请求 /// /// 默认POST public void SetHttpMethod(String httpMethod){ this.httpMethod = httpMethod; }
public IDictionary<string, string> GetPathParameters() { if (this.pathParams == null) { this.pathParams = new Dictionary<string, string>(); } return this.pathParams; } public void AddPathParameter(string key, string value){ GetPathParameters().Add($":{key}", value); }

public abstract IDictionary<string, object> GetParameters();

}

具体的请求需要实现BaseRequest,来实现获取api的url 和 api的请求参数。以获取访问凭证接口为例:

public class GetTenantAccessTokenRequest : BaseRequest<GetTenantAccessTokenResponse>    {
[JsonProperty("app_id")] public string AppId { get; set; }
[JsonProperty("app_secret")] public string AppSecret { get; set; }
public override IDictionaryobject> GetParameters() { IDictionaryobject> keyValues = new Dictionaryobject>(); keyValues.Add("app_id", this.AppId); keyValues.Add("app_secret", this.AppSecret); return keyValues; } public override string GetUrl() { return $"{FeiShuConstant.BASE_URL}/open-apis/auth/v3/tenant_access_token/internal"; } }

api响应(返回值)约定:


绝大多数 API 的响应体结构包括 code、msg、data 三个部分。

code为错误码,msg为错误信息,data为 API 的调用结果。默认请求成功时,code 为 0,msg 为 success。data 在一些操作类 API 的返回中可能不存在。


api响应实现:

定义一个返回的基类BaseResponse,定义两个属性,如:

 public class BaseResponse    {        ///         /// 返回码        ///         [JsonProperty("code")]        public int Code { get; set; }        ///         /// 返回消息        ///         [JsonProperty("msg")]        public string Msg { get; set; }    }

具体api的返回需要继承BaseResponse,还是以获取访问token为例,如:

public class GetTenantAccessTokenResponse : BaseResponse    {        [JsonProperty("tenant_access_token")]        public string TenantAccessToken { get; set; }
[JsonProperty("expire")] public int Expire { get; set; } }

api的请求和响应部分实现已经完成了,如何执行调用飞书api呢?主要利用IHttpClientFactory创建httpclient进行调用,代码如下:

 public async Task ExcueAsync(IFeishuRequest req) where T : BaseResponse        {
var httpClient = _httpClientFactory.CreateClient(); var response = new HttpResponseMessage(); var paras = req.GetParameters(); var dicHeader = req.GetHeaderParameters(); var dicPath = req.GetPathParameters(); httpClient.DefaultRequestHeaders.Clear(); foreach (var kv in dicHeader) { var value = kv.Key == "Authorization"? "Bearer " + kv.Value : kv.Value; httpClient.DefaultRequestHeaders.Add(kv.Key, value); } var httpUrl = req.GetUrl(); if (dicPath.Count()>0) { httpUrl = httpUrl.Replace($"{dicPath.First().Key}", dicPath.First().Value); } if (req.GetHttpMethod() == "POST") { //body json var jsonParas = JsonConvert.SerializeObject(paras); StringContent stringContent = new StringContent(jsonParas, Encoding.UTF8, "application/json");
response = await httpClient.PostAsync(req.GetUrl(), stringContent); } else { //querystring KEY=VALUE & KEY=VALUE var serverUrl = string.Empty; var queryString = HttpClientUtil.GetQueryString(paras); if (httpUrl.IndexOf("?") > 0) { serverUrl = httpUrl + "&" + queryString; } else { serverUrl = httpUrl + "?" + queryString; } response = await httpClient.GetAsync(serverUrl); }
var content = await response.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(content); }

以上是请求、响应代码的封装,以及请求飞书api的代码,下面演示如何使用。


二、dotnet飞书sdk的使用


大致调用流程:new api请求实例并进行赋值,调用IFeishuClient的ExcueAsync方法,返回api结构体。


创建一个单元测试项目(Test-Feishu)如图:

添加TestGetTenantAccessToken方法,测试获取访问凭证api

   ///         /// 获取token        ///         [Fact]        public async Task<string> TestGetTenantAccessToken()        {
if (!_memoryCache.TryGetValue("token", out string cacheValue)) { //测试获取token var req = new GetTenantAccessTokenRequest(); req.AppId = AppSetting.FeiShuAppId; req.AppSecret = AppSetting.FeiShuAppSecret;
var getTenantAccessTokenResponse = await _feishuClient.ExcueAsync(req);
cacheValue = getTenantAccessTokenResponse.TenantAccessToken;
var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(getTenantAccessTokenResponse.Expire)); _memoryCache.Set("token", cacheValue, cacheEntryOptions);
Assert.True(getTenantAccessTokenResponse.Code == 0);
}
return cacheValue;
}

如代码所示,我们访问一个飞书api接口,只需要 new GetTenantAccessTokenRequest(),然后调用IFeishuClient的ExcueAsync方法,返回值就是对应飞书返回的结构体。

到此,封装的代码已经结束,后面代码会上传到github上。


参考:

飞书开放平台:https://open.feishu.cn/document/ukTMukTMukTM/uITNz4iM1MjLyUzM



浏览 45
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报