以下文章來源于麥扣聊技術(shù) ,作者magiccodes
出容器、產(chǎn)品開發(fā)管理、微服務(wù)架構(gòu)系列文章和教程:docs.xin-lai.com。
Magicodes.Wx.Sdk致力于打造最簡潔最易于使用的微信Sdk,逐步包括公眾號Sdk、小程序Sdk、企業(yè)微信Sdk等,以及Abp VNext集成。
本篇將側(cè)重于講述如何向Magicodes.Wx.Sdk進行貢獻。
Magicodes.Wx.Sdk之簡潔很大層面依托于NCC的開源庫WebApiClientCore。Magicodes.Wx.Sdk依托WebApiClientCore完成了微信接口的包裝和校驗。
開源庫地址:
https://github.com/dotnetcore/WebApiClient
這里我們以【客服消息】【添加客服賬號】為例進行講解,官方接口文檔地址為:https://developers.weixin.qq.com/doc/offiaccount/Customer_Service/Customer_Service_Management.html#2。
比如添加客服賬號接口官方接口文檔說明如下所示:
主體步驟如下:
參考代碼如下所示:
/// <summary>
/// 客服管理
/// </summary>
[HttpHost("https://api.weixin.qq.com/customservice/kfaccount/")]
public interface IKfAccountApi : IWxApiWithAccessTokenFilter
{
/// <summary>
/// 添加客服賬號
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("add")]
Task<ApiResultBase> AddAsync(AddOrUpdateKfAccountInput input);
/// <summary>
/// 設(shè)置客服信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("update")]
Task<ApiResultBase> UpdateAsync(AddOrUpdateKfAccountInput input);
/// <summary>
/// 刪除客服賬號
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("del")]
Task<ApiResultBase> DelAsync(DelKfAccountInput input);
}
如上述代碼所示,有幾個注意事項:
需要定義接口
繼承自IWxApiWithAccessTokenFilter接口將自動在接口請求啟用AccessTokenApiFilter篩選器,即會自動會在接口請求時帶上access_token。
HttpHost用于定義接口跟地址
HttpPost用于設(shè)置接口請求方法,常用特性有:
特性名稱 | 功能描述 | 備注 |
---|
HttpHostAttribute | 請求服務(wù)http絕對完整主機域名 | 優(yōu)先級比Options配置低 |
HttpGetAttribute | 聲明Get請求方法與路徑 | 支持null、絕對或相對路徑 |
HttpPostAttribute | 聲明Post請求方法與路徑 | 支持null、絕對或相對路徑 |
HttpPutAttribute | 聲明Put請求方法與路徑 | 支持null、絕對或相對路徑 |
HttpDeleteAttribute | 聲明Delete請求方法與路徑 | 支持null、絕對或相對路徑 |
HeaderAttribute | 聲明請求頭 | 常量值 |
TimeoutAttribute | 聲明超時時間 | 常量值 |
FormFieldAttribute | 聲明Form表單字段與值 | 常量鍵和值 |
FormDataTextAttribute | 聲明FormData表單字段與值 | 常量鍵和值 |
這一步是非必要的,需要看參數(shù)的具體內(nèi)容和要求。添加客服接口的輸入?yún)?shù)代碼參考如下:
public class AddOrUpdateKfAccountInput
{
/// <summary>
/// 完整客服賬號,格式為:賬號前綴@公眾號微信號,賬號前綴最多10個字符,必須是英文、數(shù)字字符或者下劃線,后綴為公眾號微信號,長度不超過30個字符
/// </summary>
[JsonProperty("kf_account")]
[StringLength(30, MinimumLength = 3)]
[Required]
public string Account { get; set; }
/// <summary>
/// 客服昵稱,最長16個字
/// </summary>
[JsonProperty("nickname")]
[StringLength(16, MinimumLength = 1)]
public string Nickname { get; set; }
}
Dto實體的添加這里給大家分享一個小技巧。當實體字段以及層級比較多時,大家可以使用VS的【編輯】==》【選擇性粘貼】==》【將Json粘貼為類】:
框架中封裝了默認的返回結(jié)果基類,如果沒有其他額外的返回內(nèi)容,僅需返回ApiResultBase
即可。如果有額外的范圍內(nèi)容,則需要定義子類繼承自ApiResultBase
,在可能的情況下,有可能需要重寫部分方法(比如IsSuccess
)。如下述代碼:
public class TokenApiResult : ApiResultBase
{
/// <summary>
/// 獲取到的憑證
/// </summary>
[JsonProperty("access_token")]
public string AccessToken { get; set; }
/// <summary>
/// 憑證有效時間,單位:秒
/// </summary>
[JsonProperty("expires_in")]
internal int Expires { get; set; }
/// <summary>
/// 憑證過期時間
/// </summary>
public DateTime ExpiresTime { get; set; }
}
至此,一個接口就編寫完成了。只需要定義interface和Dto就可以了。是不是非常簡單?
/// <summary>
/// 模板消息單元測試
/// </summary>
public class TemplateApiTest : TestBase, IClassFixture<TestWebApplicationFactory>
{
private readonly ITemplateApi templateApi;
public TemplateApiTest(TestWebApplicationFactory webApplicationFactory, ITestOutputHelper output) : base(webApplicationFactory, output)
{
//通過父類的GetRequiredService獲取到Api
templateApi = GetRequiredService<ITemplateApi>();
}
/// <summary>
/// 模板消息發(fā)送測試
/// </summary>
/// <returns></returns>
[Fact]
public async Task SendAsync_Test()
{
var result = await templateApi.SendAsync(new SendTemplateMessageInput()
{
To = "oXELNwzZgamuLS0JrJhVgdelzKyw",
TemplateId = "riid7aad8OKRQD9Ey6dclWBBkrqZSFDhlpKh0_spGLA",
Data = new System.Collections.Generic.Dictionary<string, TemplateDataItem>()
{
{"first",new TemplateDataItem("測試") },
{"keyword1",new TemplateDataItem("雪雁") },
{"keyword2",new TemplateDataItem("2021.2.5") },
{"remark",new TemplateDataItem("備注") },
}
});
//判斷Api是否調(diào)用成功,未成功將拋出異常WxSdkException
result.EnsureSuccess();
}
}
整體參考:
https://github.com/xin-lai/Magicodes.Wx.Sdk/pull/1/commits/85263ed9a807581f7315a90fe6e00c51c994d386
IWxApiWithAccessTokenFilter接口IWxApiWithAccessTokenFilter
接口用于定義需要攜帶公眾號Acces sToken的接口。
如下述參考代碼所示,其啟用了AccessTokenApiFilter
篩選器,以及關(guān)閉了AcceptContentType的匹配約束(公眾號的接口官方寫的一塌糊涂,很不規(guī)范)。
參考代碼:
/// <summary>/// /// </summary>[JsonNetReturn(EnsureMatchAcceptContentType = false)][AccessTokenApiFilter]//[LoggingFilter]public interface IWxApiWithAccessTokenFilter{}
AccessTokenApiFilter
接口篩選器會在啟用的API、Action上自動添加access_token參數(shù)值。
參考代碼如下所示:
public class AccessTokenApiFilter : ApiFilterAttribute
{
public override async Task OnRequestAsync(ApiRequestContext context)
{
ITokenManager tokenManager = context.HttpContext.ServiceProvider.GetRequiredService<ITokenManager>();
string accessToken = await tokenManager.GetAccessTokenAsync();
context.HttpContext.RequestMessage.AddUrlQuery("access_token", accessToken);
}
public override Task OnResponseAsync(ApiResponseContext context)
{
return Task.CompletedTask;
}
}
ApiResultBase定義了公眾號API返回基類,用于接收錯誤碼、錯誤消息、是否執(zhí)行成功的判斷以及獲取友好消息提示。
參考代碼:
/// <summary>
/// API請求結(jié)果
/// {"errcode":40164,"errmsg":"invalid ip 218.76.8.29 ipv6 ::ffff:218.76.8.29, not in whitelist rid: 60122c35-705c3134-51b45a3d"}
/// </summary>
public class ApiResultBase
{
/// <summary>
/// 返回碼
/// </summary>
[JsonProperty("errcode")]
public virtual ReturnCodes ReturnCode { get; set; }
/// <summary>
/// 錯誤消息
/// </summary>
[JsonProperty("errmsg")]
public virtual string Message { get; set; }
/// <summary>
/// 是否為成功返回
/// </summary>
/// <returns></returns>
public virtual bool IsSuccess()
{
return ReturnCode == ReturnCodes.請求成功;
}
/// <summary>
/// 獲取友好提示
/// </summary>
/// <returns></returns>
public virtual string GetFriendlyMessage()
{
return ReturnCode.ToString();
}
}
《輕量易用的微信Sdk發(fā)布——Magicodes.Wx.Sdk》