PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Senparc.Weixin.MP/Senparc.Weixin.MP/MessageHandlers/MessageHandler.cs

https://github.com/mjhuangzk/WeiXinMPSDK
C# | 340 lines | 192 code | 42 blank | 106 comment | 16 complexity | 32a6fa17fb7b47f0a40244fbc30f9c58 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Xml;
  7. using System.Xml.Linq;
  8. using Senparc.Weixin.MP.Context;
  9. using Senparc.Weixin.MP.Entities;
  10. using Senparc.Weixin.MP.Helpers;
  11. namespace Senparc.Weixin.MP.MessageHandlers
  12. {
  13. public interface IMessageHandler
  14. {
  15. /// <summary>
  16. /// 发送者用户名(OpenId)
  17. /// </summary>
  18. string WeixinOpenId { get; }
  19. /// <summary>
  20. /// 取消执行Execute()方法。一般在OnExecuting()中用于临时阻止执行Execute()。
  21. /// 默认为False。
  22. /// 如果在执行OnExecuting()执行前设为True,则所有OnExecuting()、Execute()、OnExecuted()代码都不会被执行。
  23. /// 如果在执行OnExecuting()执行过程中设为True,则后续Execute()及OnExecuted()代码不会被执行。
  24. /// </summary>
  25. bool CancelExcute { get; set; }
  26. /// <summary>
  27. /// 在构造函数中转换得到原始XML数据
  28. /// </summary>
  29. XDocument RequestDocument { get; set; }
  30. /// <summary>
  31. /// 根据ResponseMessageBase获得转换后的ResponseDocument
  32. /// 注意:这里每次请求都会根据当前的ResponseMessageBase生成一次,如需重用此数据,建议使用缓存或局部变量
  33. /// </summary>
  34. XDocument ResponseDocument { get; }
  35. /// <summary>
  36. /// 请求实体
  37. /// </summary>
  38. IRequestMessageBase RequestMessage { get; set; }
  39. /// <summary>
  40. /// 响应实体
  41. /// 只有当执行Execute()方法后才可能有值
  42. /// </summary>
  43. IResponseMessageBase ResponseMessage { get; set; }
  44. }
  45. /// <summary>
  46. /// 微信请求的集中处理方法
  47. /// 此方法中所有过程,都基于Senparc.Weixin.MP的基础功能,只为简化代码而设。
  48. /// </summary>
  49. public abstract class MessageHandler<TC> : IMessageHandler where TC : class, IMessageContext, new()
  50. {
  51. /// <summary>
  52. /// 上下文
  53. /// </summary>
  54. public static WeixinContext<TC> GlobalWeixinContext = new WeixinContext<TC>();
  55. /// <summary>
  56. /// 全局消息上下文
  57. /// </summary>
  58. public WeixinContext<TC> WeixinContext
  59. {
  60. get { return GlobalWeixinContext; }
  61. }
  62. /// <summary>
  63. /// 当前用户消息上下文
  64. /// </summary>
  65. public TC CurrentMessageContext
  66. {
  67. get { return WeixinContext.GetMessageContext(RequestMessage); }
  68. }
  69. /// <summary>
  70. /// 发送者用户名(OpenId)
  71. /// </summary>
  72. public string WeixinOpenId
  73. {
  74. get
  75. {
  76. if (RequestMessage != null)
  77. {
  78. return RequestMessage.FromUserName;
  79. }
  80. return null;
  81. }
  82. }
  83. /// <summary>
  84. ///
  85. /// </summary>
  86. [Obsolete("UserName属性从v0.6起已过期,建议使用WeixinOpenId")]
  87. public string UserName
  88. {
  89. get
  90. {
  91. return WeixinOpenId;
  92. }
  93. }
  94. /// <summary>
  95. /// 取消执行Execute()方法。一般在OnExecuting()中用于临时阻止执行Execute()。
  96. /// 默认为False。
  97. /// 如果在执行OnExecuting()执行前设为True,则所有OnExecuting()、Execute()、OnExecuted()代码都不会被执行。
  98. /// 如果在执行OnExecuting()执行过程中设为True,则后续Execute()及OnExecuted()代码不会被执行。
  99. /// </summary>
  100. public bool CancelExcute { get; set; }
  101. /// <summary>
  102. /// 在构造函数中转换得到原始XML数据
  103. /// </summary>
  104. public XDocument RequestDocument { get; set; }
  105. /// <summary>
  106. /// 根据ResponseMessageBase获得转换后的ResponseDocument
  107. /// 注意:这里每次请求都会根据当前的ResponseMessageBase生成一次,如需重用此数据,建议使用缓存或局部变量
  108. /// </summary>
  109. public XDocument ResponseDocument
  110. {
  111. get
  112. {
  113. if (ResponseMessage == null)
  114. {
  115. return null;
  116. }
  117. return EntityHelper.ConvertEntityToXml(ResponseMessage as ResponseMessageBase);
  118. }
  119. }
  120. //protected Stream InputStream { get; set; }
  121. /// <summary>
  122. /// 请求实体
  123. /// </summary>
  124. public IRequestMessageBase RequestMessage { get; set; }
  125. /// <summary>
  126. /// 响应实体
  127. /// 只有当执行Execute()方法后才可能有值
  128. /// </summary>
  129. public IResponseMessageBase ResponseMessage { get; set; }
  130. public MessageHandler(Stream inputStream)
  131. {
  132. using (XmlReader xr = XmlReader.Create(inputStream))
  133. {
  134. RequestDocument = XDocument.Load(xr);
  135. Init(RequestDocument);
  136. }
  137. }
  138. public MessageHandler(XDocument requestDocument)
  139. {
  140. Init(requestDocument);
  141. }
  142. private void Init(XDocument requestDocument)
  143. {
  144. RequestDocument = requestDocument;
  145. RequestMessage = RequestMessageFactory.GetRequestEntity(RequestDocument);
  146. //记录上下文
  147. if (WeixinContextGlobal.UseWeixinContext)
  148. {
  149. WeixinContext.InsertMessage(RequestMessage);
  150. }
  151. }
  152. /// <summary>
  153. /// 根据当前的RequestMessage创建指定类型的ResponseMessage
  154. /// </summary>
  155. /// <typeparam name="TR">基于ResponseMessageBase的响应消息类型</typeparam>
  156. /// <returns></returns>
  157. public TR CreateResponseMessage<TR>() where TR : ResponseMessageBase
  158. {
  159. if (RequestMessage == null)
  160. {
  161. return null;
  162. }
  163. return RequestMessage.CreateResponseMessage<TR>();
  164. }
  165. /// <summary>
  166. /// 执行微信请求
  167. /// </summary>
  168. public void Execute()
  169. {
  170. if (CancelExcute)
  171. {
  172. return;
  173. }
  174. OnExecuting();
  175. if (CancelExcute)
  176. {
  177. return;
  178. }
  179. try
  180. {
  181. if (RequestMessage == null)
  182. {
  183. return;
  184. }
  185. switch (RequestMessage.MsgType)
  186. {
  187. case RequestMsgType.Text:
  188. ResponseMessage = OnTextRequest(RequestMessage as RequestMessageText);
  189. break;
  190. case RequestMsgType.Location:
  191. ResponseMessage = OnLocationRequest(RequestMessage as RequestMessageLocation);
  192. break;
  193. case RequestMsgType.Image:
  194. ResponseMessage = OnImageRequest(RequestMessage as RequestMessageImage);
  195. break;
  196. case RequestMsgType.Voice:
  197. ResponseMessage = OnVoiceRequest(RequestMessage as RequestMessageVoice);
  198. break;
  199. case RequestMsgType.Event:
  200. ResponseMessage = OnEventRequest(RequestMessage as RequestMessageEventBase);
  201. break;
  202. default:
  203. throw new UnknownRequestMsgTypeException("未知的MsgType请求类型", null);
  204. }
  205. //记录上下文
  206. if (WeixinContextGlobal.UseWeixinContext && ResponseMessage != null)
  207. {
  208. WeixinContext.InsertMessage(ResponseMessage);
  209. }
  210. }
  211. catch (Exception ex)
  212. {
  213. throw ex;
  214. }
  215. finally
  216. {
  217. OnExecuted();
  218. }
  219. }
  220. public virtual void OnExecuting()
  221. {
  222. }
  223. public virtual void OnExecuted()
  224. {
  225. }
  226. /// <summary>
  227. /// 文字类型请求
  228. /// </summary>
  229. public abstract IResponseMessageBase OnTextRequest(RequestMessageText requestMessage);
  230. /// <summary>
  231. /// 位置类型请求
  232. /// </summary>
  233. public abstract IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage);
  234. /// <summary>
  235. /// 图片类型请求
  236. /// </summary>
  237. public abstract IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage);
  238. /// <summary>
  239. /// 语音类型请求
  240. /// </summary>
  241. public abstract IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage);
  242. /// <summary>
  243. /// 链接消息类型请求
  244. /// </summary>
  245. public abstract IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage);
  246. /// <summary>
  247. /// Event事件类型请求
  248. /// </summary>
  249. public virtual IResponseMessageBase OnEventRequest(RequestMessageEventBase requestMessage)
  250. {
  251. var strongRequestMessage = RequestMessage as IRequestMessageEventBase;
  252. IResponseMessageBase responseMessage = null;
  253. switch (strongRequestMessage.Event)
  254. {
  255. case Event.ENTER:
  256. responseMessage = OnEvent_EnterRequest(RequestMessage as RequestMessageEvent_Enter);
  257. break;
  258. case Event.LOCATION:
  259. responseMessage = OnEvent_LocationRequest(RequestMessage as RequestMessageEvent_Location);//目前实际无效
  260. break;
  261. case Event.subscribe://订阅
  262. responseMessage = OnEvent_SubscribeRequest(RequestMessage as RequestMessageEvent_Subscribe);
  263. break;
  264. case Event.unsubscribe://退订
  265. responseMessage = OnEvent_UnsubscribeRequest(RequestMessage as RequestMessageEvent_Unsubscribe);
  266. break;
  267. case Event.CLICK:
  268. responseMessage = OnEvent_ClickRequest(RequestMessage as RequestMessageEvent_Click);
  269. break;
  270. default:
  271. throw new UnknownRequestMsgTypeException("未知的Event下属请求信息", null);
  272. }
  273. return responseMessage;
  274. }
  275. #region Event 下属分类
  276. /// <summary>
  277. /// Event事件类型请求之ENTER
  278. /// </summary>
  279. public abstract IResponseMessageBase OnEvent_EnterRequest(RequestMessageEvent_Enter requestMessage);
  280. /// <summary>
  281. /// Event事件类型请求之LOCATION
  282. /// </summary>
  283. public abstract IResponseMessageBase OnEvent_LocationRequest(RequestMessageEvent_Location requestMessage);
  284. /// <summary>
  285. /// Event事件类型请求之subscribe
  286. /// </summary>
  287. public abstract IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage);
  288. /// <summary>
  289. /// Event事件类型请求之unsubscribe
  290. /// </summary>
  291. public abstract IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage);
  292. /// <summary>
  293. /// Event事件类型请求之CLICK
  294. /// </summary>
  295. public abstract IResponseMessageBase OnEvent_ClickRequest(RequestMessageEvent_Click requestMessage);
  296. #endregion
  297. }
  298. }