Senparc.Weixin.MP SDK 微信公眾平臺開發教程(二十二):在 .NET Core 2.0/3.0 中使用 MessageHandler 中介軟體
概述
在 《Senparc.Weixin.MP SDK 微信公眾平臺開發教程(六):瞭解MessageHandler》 中我們已經瞭解了 MessageHandler 的執行原理和使用方法,從我設計了這種處理方式到現在已經 6 年多的時間,這是一種非常穩定而且(在如此複雜環境下)相對易於維護的的設計。
現在 .NET Core 已經進入了一個新的階段,隨著 .NET Core 3.0 的釋出,我決在相容原有方式不改變的情況下,讓 MessageHandler 可以支援 .NET Core(或者說 .NET Standard 2.0+)的中介軟體,為開發者提供另外一種使用 SDK 的方式。
新的設計將達到如下目標或新特性:
- 不再依賴 Controller/Action,因此也不再依賴 FixWeixinBugWeixinResult 等一系列因為歷史原因而存在的類和方法。你不必再為處理微信訊息建立任何 Controller 或 WebApi;
- 不影響現有的執行效率,甚至更快;
- 預設僅支援非同步方法;
- 更輕量、更少的配置程式碼
- 高度可用,不閹割任何功能。
準備開發
- 開發環境:Visual Studio 2019 / Visual Studio Code
- .NET 版本:.NET Core 3.0
- 關於 .NET Core 的中介軟體介紹:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.0
開發步驟
第一步:建立一個 .NET Core 3.0 Web 專案(空):
原始的 startup.cs 如下:
1 1 namespace WechatMessageSample 2 2 { 3 3 public class Startup 4 4 { 5 5 // This method gets called by the runtime. Use this method to add services to the container. 6 6 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 7 7 public void ConfigureServices(IServiceCollection services) 8 8 { 9 9 } 10 10 11 11 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 12 12 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 13 13 { 14 14 if (env.IsDevelopment()) 15 15 { 16 16 app.UseDeveloperExceptionPage(); 17 17 } 18 18 19 19 app.UseRouting(); 20 20 21 21 app.UseEndpoints(endpoints => 22 22 { 23 23 endpoints.MapGet("/", async context => 24 24 { 25 25 await context.Response.WriteAsync("Hello World!"); 26 26 }); 27 27 }); 28 28 } 29 29 } 30 30 }
第二步:使用 Nuget 新增 Senparc.Weixin SDK:
上圖標註出來的 3 個包分別是:公眾號、小程式和企業微信,本例項主要演示公眾號,其他兩個平臺使用方法是一致的,可以舉一反三,不再贅述。
第三步:建立自定義訊息處理器(MessageHandler):
1 /// <summary> 2 /// 自定義公眾號訊息處理 3 /// </summary> 4 public class CustomMpMessageHandler : Senparc.Weixin.MP.MessageHandlers.MessageHandler<DefaultMpMessageContext> 5 { 6 public CustomMpMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEcryptMessage = false, DeveloperInfo developerInfo = null) 7 : base(inputStream, postModel, maxRecordCount, onlyAllowEcryptMessage, developerInfo) 8 { 9 } 10 11 public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) 12 { 13 throw new NotImplementedException(); 14 } 15 }
一般情況下,此檔案是獨立的 .cs 檔案,當前例項為了方便展示,一起寫在了 startup.cs 檔案中。
以上是一個預設的空的 MessageHandler,還不能正常執行,我們為 DefaultResponseMessage 新增預設的返回訊息:
1 public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage) 2 { 3 var responseMessage = base.CreateResponseMessage<ResponseMessageNews>(); 4 responseMessage.Articles.Add(new Article() 5 { 6 Title = "歡迎使用 Senparc.Weixin SDK", 7 Description = "這是一條預設訊息", 8 PicUrl = "https://sdk.weixin.senparc.com/images/v2/logo.png", 9 Url = "https://weixin.senparc.com" 10 }); 11 return responseMessage; 12 }
也可以再建立一系列響應規則,例如處理文字資訊,並返回一條文字:
1 public override async Task<IResponseMessageBase> OnTextRequestAsync(RequestMessageText requestMessage) 2 { 3 var responseMessage = base.CreateResponseMessage<ResponseMessageText>(); 4 responseMessage.Content = $"您傳送了文字:{requestMessage.Content}"; 5 return responseMessage; 6 }
以此類推,可以為每一種型別的訊息建立處理過程。
為了方便接下去的中介軟體對接,再建立一個初始化當前自定義 MessageHandler 示例的委託:
1 public static Func<Stream, PostModel, int, CustomMpMessageHandler> GenerateMessageHandler = (stream, postModel, maxRecordCount) 2 => new CustomMpMessageHandler(stream, postModel, maxRecordCount, false);
上述 CustomMpMessageHandler 建構函式中的最後一個 bool 引數(onlyAllowEcryptMessage),提供了一種加強的安全策略,可以指定是否只允許處理加密訊息,開啟之後,試圖使用明文進行訊息推送(嗅探)的請求將被拒絕(前提是對方已經拿到了正確的 Token),並終止後續處理流程,確保程式安全。
第四步:修改 startup.cs 進行全域性註冊
修改 ConfigureServices() 方法:
1 public Startup(IConfiguration configuration) 2 { 3 Configuration = configuration; 4 } 5 6 public IConfiguration Configuration { get; } 7 8 public void ConfigureServices(IServiceCollection services) 9 { 10 services.AddMemoryCache();//使用本地快取必須新增(按需) 11 12 services.AddSenparcWeixinServices(Configuration);//Senparc.Weixin 註冊 13 }
修改 Configure() 方法引數:
1 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 2 IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting)
Configure() 方法內追加:
1 app.UseSenparcGlobal(env, senparcSetting.Value, globalRegister => { }) 2 .UseSenparcWeixin(senparcWeixinSetting.Value, weixinRegister => 3 { 4 weixinRegister.RegisterMpAccount(senparcWeixinSetting.Value, "【盛派網路小助手】公眾號"); 5 });
至此註冊工作已經全部完成!
指定使用 MessageHandler 中介軟體,只需一行:
app.UseMessageHandlerForMp("/WeixinAsync", CustomMpMessageHandler.GenerateMessageHandler, o => o.AccountSettingFunc = c => senparcWeixinSetting.Value);
第五步:配置 appsetting.json
參考:appsetting.json
找到公眾號的相關設定,修改 Token、AppId 等引數。
第六步:完成。
使用
使用 Ctrl + F5 開啟當前專案,可以看到預設輸出的 Hello World 訊息,開啟上述設定的 /Weixin
地址:
測試地址:https://sdk.weixin.senparc.com/WeixinAsync
此時我們已經可以開始將站點部署到外網,提供給公眾進行服務,所有的去重、加解密、上下文等過程系統已經全部配備。
測試
Senparc.Weixin SDK 為了方便開發者測試公眾號訊息,已經提供了一套模擬器,可以用於傳送和接收公眾號訊息的測試。
注意:如果測試本地 localhost 的專案,需要在本地執行模擬器,上述模擬器也已經包含在開源 Sample 中,可以下載後在本地執行並使用:
同樣也支援併發測試以及加密模式:
如果同時傳送兩條 MsgId 相同的訊息,會被自動去重過濾: