1. 程式人生 > >Senparc.Weixin.MP SDK 微信公眾平臺開發教程(二十二):在 .NET Core 2.0/3.0 中使用 MessageHandler 中介軟體

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 的方式。

  新的設計將達到如下目標或新特性:

  1. 不再依賴 Controller/Action,因此也不再依賴 FixWeixinBugWeixinResult 等一系列因為歷史原因而存在的類和方法。你不必再為處理微信訊息建立任何 Controller 或 WebApi;
  2. 不影響現有的執行效率,甚至更快;
  3. 預設僅支援非同步方法;
  4. 更輕量、更少的配置程式碼
  5. 高度可用,不閹割任何功能。

準備開發

  • 開發環境: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 }
View Code

 

第二步:使用 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 相同的訊息,會被自動去重過濾: