一个还算简单的微信消息SDK(基于.Net Standard 2.0)
雖然微信公眾號(hào)出現(xiàn)了好久,不過(guò)在SDK這件事情上感覺(jué)并沒(méi)有多少人把它當(dāng)成一個(gè)有技術(shù)含量的事情來(lái)做,很多SDK做的事情就是一個(gè)代碼的堆疊,當(dāng)然也可能寫(xiě)的好的并沒(méi)有開(kāi)源出來(lái)。所以在某個(gè)翻遍github而無(wú)所獲的下午我寫(xiě)了一個(gè)基礎(chǔ)的基于事件的微信消息類,今年初我把它放到了github和開(kāi)源中國(guó)上并逐步完善,這篇文章就是簡(jiǎn)單介紹OSS開(kāi)源系列下的微信消息模塊SDK的使用方式,主要圍繞以下幾個(gè)方面分解:
????一. 全局介紹
????二. 配置管理
????三. 框架使用
????1. 框架組成元素
????2. 框架支持的模式
????四. 生命周期擴(kuò)展
????五. 常見(jiàn)問(wèn)題
????六. 終極定制
一. 全局介紹
整個(gè)SDK的核心框架代碼部分不超過(guò)300行,支持多租戶平臺(tái)模式,以及對(duì)各類特殊微信消息的擴(kuò)展性。代碼在?OSS.SnsSdk下的OSS.SnsSdk.Msg.Wx,【開(kāi)源中國(guó)】和【Github】都可以搜到。
Nuget安裝命令:Install-Package OSS.SnsSdk.Msg.Wx
二. 配置管理
(示例詳見(jiàn):WxMsgController.cs)
1. 通過(guò)構(gòu)造函數(shù)傳入,適合單一的應(yīng)用,這種情況下的配置信息生存周期和當(dāng)前config實(shí)例同步
2. 通過(guò) SetContext方式 注入,適合多租戶,平臺(tái)的方式使用,這個(gè)時(shí)候配置的生存周期只在當(dāng)前請(qǐng)求的整個(gè)上下文中有效。
三. 框架使用
首先,框架組成元素(可以直接跳到使用模式,再回過(guò)頭來(lái)看):
1. 實(shí)體對(duì)象,也就是消息體對(duì)象,主要分為:
? a. 接收消息(繼承自 WxBaseRecMsg 的普通消息 和 繼承自 WxBaseRecEventMsg 的事件消息系統(tǒng)默認(rèn)實(shí)現(xiàn)了 六種普通消息和五種事件消息對(duì)象,在后邊的使用模式中介紹如何擴(kuò)展其他對(duì)象類型
b. 回復(fù)消息(繼承自 WxBaseReplyMsg ,主要是響應(yīng)給微信接口的實(shí)體(當(dāng)前支持六種 + WxNoneReplyMsg)
除非特殊情況,否則返回消息就是這幾種類型。當(dāng)前可用回復(fù)消息:
WxTextReplyMsg-回復(fù)文本消息,WxImageReplyMsg-回復(fù)圖片消息,
WxVoiceReplyMsg-回復(fù)語(yǔ)音消息,WxVideoReplyMsg-回復(fù)視頻消息,
WxMusicReplyMsg-回復(fù)音頻消息,WxNewsReplyMsg-回復(fù)圖文消息
WxNoneReplyMsg 需要特殊解釋一下,這個(gè)表示不需要給對(duì)方響應(yīng),系統(tǒng)會(huì)返回給微信端success 。使用中可以使用 WxNoneReplyMsg.None 默認(rèn)值。
c. 消息上下文(WxMsgContext 對(duì)象?
其含有 RecMsg 和 ReplyMsg 兩個(gè)屬性,也就是上邊的接收消息和回復(fù)消息,方便在生命周期中控制
2. Handler,消息處理控制類,實(shí)現(xiàn)整個(gè)消息處理的生命周期和執(zhí)行調(diào)度
當(dāng)前系統(tǒng)有 WxMsgBaseHandler 和 WxMsgHandler 兩個(gè),前者作為基類,實(shí)現(xiàn)了生命周期的控制和調(diào)度。 后者則實(shí)現(xiàn)了系統(tǒng)基礎(chǔ)消息的事件定義(六個(gè)普通消息事件 和 五個(gè)Event消息事件)
3. Procesor(WxMsgProcessor<TRecMsg>),消息的具體執(zhí)行者.
這個(gè)只有在高級(jí)定制模式下才會(huì)需要用戶自定義
其次,框架支持的模式
1. 基礎(chǔ)模式?
系統(tǒng) WxMsgHandler.cs 默認(rèn)實(shí)現(xiàn)常見(jiàn)的六種普通消息和五種事件消息,只需要重寫(xiě)(overwrite)對(duì)應(yīng)的以 Process 開(kāi)頭的方法即可。每個(gè)方法的參數(shù)對(duì)應(yīng)的都是詳細(xì)的消息類型。以文本類型消息舉例:?
protected override WxBaseReplyMsg ProcessTextMsg(WxTextRecMsg msg) {return WxNoneReplyMsg.None; }那么可以重寫(xiě)的包含以下方法:// 處理文本消息 ProcessTextMsg(WxTextRecMsg msg)// 處理圖像消息 ProcessImageMsg(WxImageRecMsg msg)// 處理語(yǔ)音消息 ProcessVoiceMsg(WxVoiceRecMsg msg)// 處理視頻/小視頻消息 ProcessVideoMsg(WxVideoRecMsg msg)// 處理地理位置消息 ProcessLocationMsg(WxLocationRecMsg msg)// 處理鏈接消息 ProcessLinkMsg(WxLinkRecMsg msg)// 處理關(guān)注/取消關(guān)注事件 ProcessSubscribeEventMsg(WxSubscribeRecEventMsg msg)// 處理掃描帶參數(shù)二維碼事件 ProcessScanEventMsg(WxSubscribeRecEventMsg msg)// 處理上報(bào)地理位置事件 ProcessLocationEventMsg(WxLocationRecEventMsg msg)// 處理點(diǎn)擊菜單拉取消息時(shí)的事件推送 ProcessClickEventMsg(WxClickRecEventMsg msg)// 處理點(diǎn)擊菜單跳轉(zhuǎn)鏈接時(shí)的事件推送 ProcessViewEventMsg(WxViewRecEventMsg msg)
??2. 進(jìn)階模式
對(duì)于不在基礎(chǔ)實(shí)現(xiàn)類型的消息,系統(tǒng)提供注入消息處理委托的模式來(lái)處理消息,以一個(gè) test_msg 消息類型注入示例
a. 定義消息實(shí)體:?
public class WxTestRecMsg : WxBaseRecMsg {public string Test { get; set; }// 重寫(xiě)實(shí)體實(shí)體內(nèi)部屬性賦值protected override voidFormatPropertiesFromMsg(){Test = this["Test"];} }
b. 定義處理委托:
private static WxTextReplyMsg ProcessTestMsg(WxTestRecMsg msg) {return new WxTextReplyMsg(){ Content = " test_msg 類型消息返回 " }; }
c. 注入(內(nèi)含:RegisteEventProcessor方法):
WxMsgProcessorProvider.RegisteProcessor<WxTextRecMsg>("test_msg", ProcessTestMsg);
? 恭喜,你已經(jīng)完成了新的消息類型處理注入。
3. 高級(jí)模式
自定義Processor,基礎(chǔ)模式和進(jìn)階模式中都在內(nèi)部實(shí)現(xiàn)了Processor的調(diào)度,這里依然使用上邊示例:
a. 定義實(shí)體(這里繼續(xù)使用 WxTestRecMsg)
b. 定義CustomeHandler, 重寫(xiě)獲取Processor方法
public class CustomeHandler
{protected override WxMsgProcessor GetCustomProcessor(string msgType,string eventName,
? ? IDictionary<string, string> msgInfo){if (msgType=="test_msg"){return new WxMsgProcessor<WxTestRecMsg>(){// 此委托屬性滿足對(duì)性能有要求的同學(xué)// 如果不填則通過(guò)泛型的 new t() 創(chuàng)建RecInsCreater=() => new WxTestRecMsg(),// 具體事件處理委托// 也可以使用上例的 ProcessTestMsgProcessFunc = msg => WxNoneReplyMsg.None};}return null;}
}
? 恭喜,你又完成了高級(jí)模式下的定制。
四. 生命周期擴(kuò)展
????上邊講解了幾種模式主要實(shí)現(xiàn)方式,那么在實(shí)際的使用過(guò)程中你會(huì)遇到消息的重復(fù)判斷,對(duì)特定消息的轉(zhuǎn)發(fā)等。在系統(tǒng)處理的不同階段,我定義了幾個(gè)主要的處理事件,來(lái)滿足對(duì)消息處理時(shí)的全局和局部控制,分別對(duì)應(yīng)在WxMsgBaseHandler的以Execute開(kāi)頭的虛方法:
1.?Executing(WxMsgContext context),開(kāi)始執(zhí)行事件,作為范圍為全部消息類型。所有的消息類型都會(huì)經(jīng)過(guò)這個(gè)事件,然后執(zhí)行具體消息類型對(duì)應(yīng)的委托,此時(shí) msgContext 中的 ReplyMsg,如果給context中的 ReplyMsg 屬性賦值,則 后邊定義的對(duì)應(yīng)的具體消息委托放棄執(zhí)行。
? ? ?在這個(gè)事件中我們可以過(guò)濾重復(fù)消息,用戶授權(quán)驗(yàn)證等
2.?ExecuteUnknowProcessor(WxBaseRecMsg msg)?,未知消息類型事件,作用范圍為所有未發(fā)現(xiàn)對(duì)應(yīng)處理委托的消息類型。在執(zhí)行具體的事件時(shí),如果當(dāng)前消息類型未能找到對(duì)應(yīng)的處理委托,則會(huì)喚起這個(gè)方法,需要注意的是,即使你使用的是 WxMsgHandler ,如果沒(méi)有重寫(xiě)其 實(shí)現(xiàn),或者返回了為空, 也會(huì)觸發(fā)此方法
可以通過(guò)這個(gè)方法中添加未知類型消息日志等
3.?ExecuteEnd(WxMsgContext msgContext), 執(zhí)行結(jié)束時(shí)調(diào)用的方法,作為范圍為全部消息類型。具體消息處理委托執(zhí)行結(jié)束,回復(fù)微信響應(yīng)之前。此時(shí) msgContext 中的 ReplyMsg 不為空,如果前面執(zhí)行方法中返回null,在執(zhí)行此方法之前,會(huì)默認(rèn)賦值 WxNoneReplyMsg.None
可以在這里添加全局日志,None類型的消息轉(zhuǎn)發(fā)客服等。
五. 常見(jiàn)問(wèn)題
1. 各模式的適用場(chǎng)景及區(qū)別
基礎(chǔ)模式,此模式已經(jīng)由系統(tǒng)內(nèi)部實(shí)現(xiàn),只需要重寫(xiě)委托方法即可,簡(jiǎn)單方便,
? ? ? ?基本適用大部分的場(chǎng)景
進(jìn)階模式,只需要消息類型,和消息處理委托 在程序入口處注冊(cè)即可,簡(jiǎn)單靈活。
其適用場(chǎng)景:基本滿足一般的所有定制需求,但消息體的MsgType不能為空,微信某些特殊事件無(wú)法滿足
高級(jí)模式,使用的是子類繼承模式,每個(gè)子類都可以實(shí)現(xiàn)同一消息類型下不同定制委托
其適用的場(chǎng)景: 多租戶平臺(tái)下針對(duì)每種消息類型,不同的平臺(tái)等級(jí)都有不同的特殊定制實(shí)現(xiàn),以及所有特殊的消息事件
2.幾種模式的優(yōu)先級(jí):
? ??基礎(chǔ)模式(使用WxMsgHandler時(shí)) => 高級(jí)模式 => 進(jìn)階模式
舉例:如果你同時(shí)在高級(jí)模式和進(jìn)階模式下定義了一個(gè)消息類型為"test"的處理實(shí)現(xiàn),系統(tǒng)默認(rèn)使用高級(jí)模式下的實(shí)現(xiàn)。如果你的控制類直接繼承了 WxMsgBaseHandler 則 不會(huì)進(jìn)入基礎(chǔ)模式
3. 對(duì)象屬性的賦值問(wèn)題
如果你自定義了接收消息實(shí)體的對(duì)象,需要重寫(xiě)FormatPropertiesFromMsg方法,詳見(jiàn) 進(jìn)階模式下 2.a 的實(shí)現(xiàn)。
對(duì)應(yīng)響應(yīng)的消息,不需要在執(zhí)行委托里給 ToUserName,FromUserName,CreateTime 賦值,系統(tǒng)自動(dòng)處理。
4.?使用反射的地方
為了盡可能減少系統(tǒng)底層給帶來(lái)的性能影響,所以在系統(tǒng)中基本沒(méi)有使用反射和序列化,有兩個(gè)地方需要注意一下:
1. 需要在 FormatPropertiesFromMsg 中給自己的屬性賦值,系統(tǒng)盡可能的提供了this索引來(lái)簡(jiǎn)化賦值的方式。
2. 自定義Processor(繼承WxMsgProcessor<TRecMsg>或者子類)時(shí),RecInsCreater屬性如果不賦值,
則系統(tǒng)底層在 創(chuàng)建對(duì)應(yīng)的實(shí)例時(shí),通過(guò)泛型的 new() 機(jī)制實(shí)現(xiàn),屬于反射。
六. 終極大招
前面基本都能滿足所有的定制需求了,但是如果可能...你還想要更大的定制自由度,那么我這里也盡力的滿足你。在生命周期擴(kuò)展中其實(shí)還有一個(gè)方法,這個(gè)方法是總的執(zhí)行方法,其他的生命周期事件也都是在這里觸發(fā):
ResultMo<WxMsgContext> Execute(string recMsgXml)
如果你希望自己定義一套完整的生命周期,OK,重寫(xiě)這里即可。系統(tǒng)將幫你完成驗(yàn)簽,消息對(duì)象賦值,加密等邊緣操作只需要記住一件事情,如果你重寫(xiě)了這里,上述的幾種模式和其他生命周期事件將無(wú)效。
相關(guān)文章:?
限時(shí)團(tuán)購(gòu),6.9折:《微信開(kāi)發(fā)深度解析:公眾號(hào)、小程序高效開(kāi)發(fā)秘籍》推薦序
OSS.Social微信項(xiàng)目標(biāo)準(zhǔn)庫(kù)介紹
微信和支付寶支付模式詳解及實(shí)現(xiàn)(.Net標(biāo)準(zhǔn)庫(kù))
原文地址:http://www.cnblogs.com/osscoder/p/7467537.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的一个还算简单的微信消息SDK(基于.Net Standard 2.0)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C#使用Xamarin开发可移植移动应用
- 下一篇: ASP.NET Core MVC – T