??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
人工智能干貨推薦專注于人工智能領域的技術分享
游戲元宇宙專注于游戲領域的技術分享