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 如下:
namespace WechatMessageSample
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
第二步:使用 Nuget 添加 Senparc.Weixin SDK:

上图标注出来的 3 个包分别是:公众号、小程序和企业微信,本实例主要演示公众号,其他两个平台使用方法是一致的,可以举一反三,不再赘述。
第三步:创建自定义消息处理器(MessageHandler):
/// <summary>
/// 自定义公众号消息处理
/// </summary>
public class CustomMpMessageHandler : Senparc.Weixin.MP.MessageHandlers.MessageHandler<DefaultMpMessageContext>
{
public CustomMpMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = , bool onlyAllowEcryptMessage = false, DeveloperInfo developerInfo = null)
: base(inputStream, postModel, maxRecordCount, onlyAllowEcryptMessage, developerInfo)
{
} public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
throw new NotImplementedException();
}
}
一般情况下,此文件是独立的 .cs 文件,当前实例为了方便展示,一起写在了 startup.cs 文件中。
以上是一个默认的空的 MessageHandler,还不能正常运行,我们为 DefaultResponseMessage 添加默认的返回消息:
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageNews>();
responseMessage.Articles.Add(new Article()
{
Title = "欢迎使用 Senparc.Weixin SDK",
Description = "这是一条默认消息",
PicUrl = "https://sdk.weixin.senparc.com/images/v2/logo.png",
Url = "https://weixin.senparc.com"
});
return responseMessage;
}
也可以再创建一系列响应规则,例如处理文本信息,并返回一条文本:
public override async Task<IResponseMessageBase> OnTextRequestAsync(RequestMessageText requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = $"您发送了文字:{requestMessage.Content}";
return responseMessage;
}
以此类推,可以为每一种类型的消息创建处理过程。
为了方便接下去的中间件对接,再创建一个初始化当前自定义 MessageHandler 示例的委托:
public static Func<Stream, PostModel, int, CustomMpMessageHandler> GenerateMessageHandler = (stream, postModel, maxRecordCount)
=> new CustomMpMessageHandler(stream, postModel, maxRecordCount, false);
上述 CustomMpMessageHandler 构造函数中的最后一个 bool 参数(onlyAllowEcryptMessage),提供了一种加强的安全策略,可以指定是否只允许处理加密消息,开启之后,试图使用明文进行消息推送(嗅探)的请求将被拒绝(前提是对方已经拿到了正确的 Token),并终止后续处理流程,确保程序安全。
第四步:修改 startup.cs 进行全局注册
修改 ConfigureServices() 方法:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();//使用本地缓存必须添加(按需) services.AddSenparcWeixinServices(Configuration);//Senparc.Weixin 注册
}
修改 Configure() 方法参数:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
IOptions<SenparcSetting> senparcSetting, IOptions<SenparcWeixinSetting> senparcWeixinSetting)
Configure() 方法内追加:
app.UseSenparcGlobal(env, senparcSetting.Value, globalRegister => { })
.UseSenparcWeixin(senparcWeixinSetting.Value, weixinRegister =>
{
weixinRegister.RegisterMpAccount(senparcWeixinSetting.Value, "【盛派网络小助手】公众号");
});
至此注册工作已经全部完成!
指定使用 MessageHandler 中间件,只需一行:
app.UseMessageHandlerForMp("/WeixinAsync", CustomMpMessageHandler.GenerateMessageHandler,
o => o.AccountSettingFunc = c => senparcWeixinSetting.Value);
第五步:配置 appsetting.json
找到公众号的相关设置,修改 Token、AppId 等参数。
第六步:完成。
使用
使用 Ctrl + F5 打开当前项目,可以看到默认输出的 Hello World 消息,打开上述设置的 /Weixin 地址:

测试地址:https://sdk.weixin.senparc.com/WeixinAsync
此时我们已经可以开始将站点部署到外网,提供给公众进行服务,所有的去重、加解密、上下文等过程系统已经全部配备。
测试
Senparc.Weixin SDK 为了方便开发者测试公众号消息,已经提供了一套模拟器,可以用于发送和接收公众号消息的测试。
注意:如果测试本地 localhost 的项目,需要在本地运行模拟器,上述模拟器也已经包含在开源 Sample 中,可以下载后在本地运行并使用:

同样也支持并发测试以及加密模式:

如果同时发送两条 MsgId 相同的消息,会被自动去重过滤:

Senparc.Weixin.MP SDK 微信公众平台开发教程(二十二):在 .NET Core 2.0/3.0 中使用 MessageHandler 中间件的更多相关文章
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明
紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十八):Web代理功能
在Senparc.Weixin.dll v4.5.7版本开始,我们提供了Web代理功能,以方便在受限制的局域网内的应用可以顺利调用接口. 有关的修改都在Senparc.Weixin/Utilities ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十):多客服接口说明
微信官方的多客服接口原理是通过用户发送的信息,开发者服务器返回一条指定类型的响应信息,使用户的对话状态切换到官方的多客服状态(持续一段时间),这段时间内用户发送的所有信息都不会到达开发者的服务器,而是 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十四):请求消息去重
为了确保信息请求消息的到达率,微信服务器在没有及时收到响应消息(ResponseMessage)的情况下,会多次发送同一条请求消息(RequestMessage),包括MsgId等在内的所有文本内容都 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十五):消息加密
前不久,微信的企业号使用了强制的消息加密方式,随后公众号也加入了可选的消息加密选项.目前企业号和公众号的加密方式是一致的(格式会有少许差别). 加密设置 进入公众号后台的“开发者中心”,我们可以看到U ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制
在<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>中,我介绍了获取AccessToken(通用接口)的方法. 在实际的开发过程中,所有的高级接口都需 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十九):MessageHandler 的未知类型消息处理
这是<微信开发深度解析:微信公众号.小程序高效开发秘籍>出版之后写的第一篇微信相关的文章.从这一篇开始,将介绍第一版出版之后添加或修改的功能,或者对书上内容需要做的补充. MP v14.8 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十七):个性化菜单接口说明
前不久微信上线了个性化菜单接口,Senparc.Weixin SDK也已经同步更新. 本次更新升级Senparc.Weixin.MP版本到v13.5.2,依赖Senparc.Weixin版本4.5.4 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(三):微信公众平台开发验证
要对接微信公众平台的"开发模式",即对接到自己的网站程序,必须在注册成功之后(见Senparc.Weixin.MP SDK 微信公众平台开发教程(一):微信公众平台注册),等待官方 ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(四):Hello World
============= 以下写于2013-07-20 ============= 这一篇文章其实可以写在很前面,不过我还是希望开发者们尽多地了解清楚原理之后再下手. 通过上一篇Senparc.W ...
随机推荐
- 让docker中的mysql启动时自动执行sql
在用docker创建mysql容器的时,有时候我们期望容器启动后数据库和表已经自动建好,初始化数据也已自动录入,也就是说容器启动后我们就能直接连上容器中的数据库,使用其中的数据了. 其实mysql的官 ...
- C#开发BIMFACE系列22 服务端API之获取模型数据7:获取多个模型的楼层信息
系列目录 [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列21 服务端API之获取模型数据6:获取单模型的楼层信息>中介绍获取单个模型的所有楼层信息.某些场景下 ...
- hive正则表达式的用法
regexp_replace用法 1. 截取字符串中的汉字部分: 举个栗子:select regexp_replace('七夕节comming!来啦','([^\\u4E00-\\u9FA5]+)' ...
- Spring Cloud Alibaba | 微服务分布式事务之Seata
Spring Cloud Alibaba | 微服务分布式事务之Seata 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud:Green ...
- GIT常见问题及其解决方案
问题: remote: Permission to beijing01/learn_github.git denied to liuhongyang02. fatal: unable to acces ...
- SSM整合activiti框架
一:WorkFlow简介 1:什么是工作流工作流(Workflow),指“业务过程的部分或整体在计算机应用环境下的自动化”.是对工作流程及其各操作步骤之间业务规则的抽象.概括描述.在计算机中,工作流属 ...
- Phpstudy被暴存在隐藏后门-检查方法
Phpstudy被暴存在隐藏后门-检查方法 一.事件背景 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOp ...
- MOOC C++笔记(四):运算符重载
第四周:运算符重载 基本概念 运算符重载,就是对已有的运算符(C++中预定义的运算符)赋予多重的含义,使同一运算符作用于不同类型的数据时导致不同类型的行为. 运算符重载的目的是:扩展C++中提供的运算 ...
- [VB.NET Tips]字符串分隔
在实际应用中,很多场景下都需要分隔字符串,如解析CSV文件等. 一般我们使用split方法来按照指定的分隔符来进行分隔字符串获得一个数组. Split方法的签名是: Split(ParamArray ...
- [Leetcode] 第313题 超级丑数
一.题目描述 编写一段程序来查找第 n 个超级丑数. 超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数. 示例: 输入: n = 12, primes = [2,7,13, ...