随笔- 155  评论- 1472  文章- 1 

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. 高度可用,不阉割任何功能。

准备开发

开发步骤

第一步:创建一个 .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 相同的消息,会被自动去重过滤:

posted on 2019-10-15 17:18  SZW  阅读(...)  评论(... 编辑 收藏