当前位置:网站首页>Senparc.Weixin.Sample.MP源码剖析
Senparc.Weixin.Sample.MP源码剖析
2022-07-29 09:28:00 【dotNET跨平台】
Senparc.Weixin.Sample.MP是微信公众号样例的.NET6源码,项目配置文件appsettings.json的修改和微信公众号测试环境的搭建参考:微信公众号调试与Natapp环境搭建。接下来从项目结构,项目应用和项目源码3个角度来进行讲解。
一.项目结构角度
项目代码整体结构如下所示:
重点部分是MessageHandlers消息处理器部分,包括消息上下文、消息处理器和事件处理器。项目启动起来后的界面为:
二.应用角度
1.数据流的直观过程
首先要明白微信客户端、微信服务器和第三方网站这3者之间的数据流关系,下面通过用户发送文字为例介绍数据流的过程:
用户通过微信客户端发送OpenId
微信服务器就把该文字发送给第三方网站。当然如果没有第三方网站,就是说没有对公众号做二次开发,那么用户得不到任何回应消息
第三方网站对消息进行处理,比如获取该用户的OpenId等相关信息
第三方网站把处理后的消息返回给微信服务器
微信服务器转发第三方网站的消息给微信客户端
这样用户就收到了微信客户端回应的消息
微信的消息类型主要包括请求消息和响应消息,请求消息就是微信服务器发送给网站的消息,而响应消息就是网站发送给微信服务器的消息。具体请求消息和响应消息包含的类型如下所示:
2.数据流的代码过程
(1)公众号消息模拟器
公众号消息模拟器输入和输出内容如下所示:
URL:通过Natapp映射的域名,即http://fengling.nat300.top -> 127.0.0.1:8080。
Token、AppId和AESKey:参考appsettings.json文件。
类型:文本、地理位置、图片、语音、视频、时间推送。
内容:OPENID。文本消息处理器对文本进行处理。
(2)Post(PostModel postModel)方法
用户发送消息后,微信平台自动Post一个请求到方法public async TaskPost(PostModel postModel),并等待响应XML:
在这个方法中通过自定义MessageHandler进行处理:
var messageHandler = new CustomMessageHandler(await Request.GetRequestMemoryStreamAsync(), postModel, maxRecordCount);真正的微信处理过程方法是:
public async Task ExecuteAsync(CancellationToken cancellationToken)(3)OnTextRequestAsync(RequestMessageText requestMessage)方法
该方法可以根据输入文本进行响应,可以是匹配关键字、正则表达式、不回复,或者默认响应。
三.源码角度
1.Program.cs代码
首先介绍下Senparc.Weixin SDK整体注册的相关代码:
// 使用本地缓存必须添加
builder.Services.AddMemoryCache();
// Senparc.Weixin 注册(必须)
builder.Services.AddSenparcWeixinServices(builder.Configuration);
...
var senparcWeixinSetting = app.Services.GetService<IOptions<SenparcWeixinSetting>>()!.Value;
//启用微信配置(必须)
var registerService = app.UseSenparcWeixin(app.Environment,
null /*不为null则覆盖appsettings中的SenpacSetting配置*/,
null /*不为null则覆盖appsettings中的SenpacWeixinSetting配置*/,
register => { /*CO2NET全局配置*/ },
(register, weixinSetting) =>
{
//注册公众号信息(可以执行多次,注册多个公众号)
register.RegisterMpAccount(weixinSetting, "XXX公众号");
});
......
// 使用公众号的MessageHandler中间件(不再需要创建Controller)
app.UseMessageHandlerForMp("/WeixinAsync", CustomMessageHandler.GenerateMessageHandler, options =>
{
options.AccountSettingFunc = context => Senparc.Weixin.Config.SenparcWeixinSetting;
});(1)builder.Services.AddMemoryCache()
框架支持内存缓存、Redis、Memcached等多种缓存策略。
(2)builder.Services.AddSenparcWeixinServices(builder.Configuration)
实现Senparc.Weixin的注册。
(3)app.UseSenparcWeixin()
该方法集成了CON2ET全局注册以及Senparc.Weixin SDK微信注册过程。
(4)app.UseMessageHandlerForMp
使用MessageHandler配置,会默认使用异步方法messageHandler.ExecuteAsync()。
2.WeixinController.cs代码
(1)public ActionResult Get(PostModel postModel, string echostr)
该方法主要用于微信后台地址验证,其它的时候用不到。
(2)public async Task<ActionResult> Post(PostModel postModel)
这个方法就是微信服务器转发消息[XML]给网站,等待网站处理后返回消息[XML]给微信服务器的过程。
(3)messageHandler.OmitRepeatedMessage = true;
当网站不能及时响应微信服务器的请求时,微信服务器会连续发送多条相同MsgId的消息到网站,以防止丢包。这种情况就需要利用MsgId对消息进行去重,否则网站就会多次执行同一个请求。
需要注意的是,对于多条带有相同MsgId的请求消息进行多次回复,客户端也只能收到微信服务器最后一次重发所对应的这条响应消息。
(4)messageHandler.DefaultMessageHandlerAsyncEvent = DefaultMessageHandlerAsyncEvent.SelfSynicMethod;
当同步方法被重写,且异步方法未被重写时,尝试调用同步方法。
3.CustomMessageContext.cs代码
(1)CustomMessageContext
CustomMessageContext是消息的上下文,写法基本固定,直接搬过来就可以使用了。消息上下文用于记录单个用户发送、接收消息的记录,就算不同微信公众号同时发送不同的消息,两者之间并不会有任何的干扰,因为两者的上下文是完全隔离的。
(2)CustomMessageContext_MessageContextRemoved
当上下文过期,被移除时触发的时间。根据WeixinContext中的算法,这里的过期消息会在过期后下一条请求执行之前被清除。
4.CustomMessageHandler.cs代码
CustomMessageHandler和CustomMessageHandler_Events是CustomMessageHandler类的2个部分类,前者处理非事件类型的消息,比如发送文本、图像等,而后者处理事件类型的消息,比如点击事件、订阅事件(订阅及取消订阅)等。
这里的请求消息都是普通消息:
5.CustomMessageHandler_Events.cs代码
这里的请求消息都是事件推送消息,而事件推送消息又分为3大类型:常规事件[公众号基础功能返回事件],菜单事件[各种类型的公众号菜单返回事件],应用事件[应用模块返回事件]:
参考文献:
[1]Senparc.Weixin.Sample.MP.sln:WeiXinMPSDK\Samples\MP\Senparc.Weixin.Sample.MP.sln
[2]Senparc.Weixin SDK源码:https://github.com/JeffreySu/WeiXinMPSDK
[3]Senparc.Weixin.MP SDK微信公众平台开发教程(二十三):在.NET Core 2.0/3.0中使用MessageHandler中间件:https://www.cnblogs.com/szw/p/Wechat-MessageHandler-Middleware.html
[4]微信开发深度解析:公众号、小程序高效开发秘籍:http://book.weixin.senparc.com/BookHelper
[5]微信公众平台接口调试工具:https://mp.weixin.qq.com/debug
人工智能干货推荐
专注于人工智能领域的技术分享
游戏元宇宙
专注于游戏领域的技术分享
边栏推荐
- 远程连接windows版本服务器redis的配置文件设置
- 如何为OpenHarmony做贡献
- 基于C语言模拟实现DFA识别字符串
- MySQL的数据类型
- Unity3d hodgepodge
- MySQL converts some table names to uppercase
- 1.2.24 fastjson deserialization templatesimpl uses chain analysis (very detailed)
- NFA determination and DFA minimization based on C language
- Asp graduation project - based on C # +asp Design and implementation of enterprise investment value analysis system based on. Net + sqlserver (graduation thesis + program source code) -- enterprise in
- Retinal Vessel Segmentation via a Semantics and Multi-Scale Aggregation Network
猜你喜欢

How to change MySQL into Chinese

Floweable advanced

How does xjson implement four operations?

Qmainwindow details

Could not receive a message from the daemon

基于C语言实现的NFA确定化和DFA最小化

Custom configuration

云原生管理实践:业务引领的DevOps持续交付体系

redis可视化工具读取数据乱码问题解决

Summary of pit trampling records and solutions of data warehouse project
随机推荐
The use and Simulation of string function, character function and memory function
How to export the old and new file names and locations to excel after file renaming
PyQt5快速开发与实战 6.1 好软件的三个维度 && 6.2 PyQt5中的布局管理 && 6.3 PyQt5的绝对位置布局
基于C语言模拟实现DFA识别字符串
Flowable UI制作流程图
ERROR 1045 (28000): Access denied for user ‘ODBC‘@‘localhost‘ (using password: NO)
smart-webcomponents 14.2.0 Crack
网络安全(6)
Leetcode:132. split palindrome string II
NFA determination and DFA minimization based on C language
[performance optimization methodology series] III. core idea of performance optimization (2)
机器学习之分类模型评估指标及sklearn代码实现
I don't know how lucky the boy who randomly typed logs is. There must be a lot of overtime
MySQL事务与MVCC如何实现的隔离级别
201803-3 CCF URL映射 满分题解
Trie树(字典树)讲解
Random number setting and reference between parameters
Basic operations of OpenCV image processing
Emmet syntax
Notes on network principles (five layer network)