/// <summary> /// 根据xml获取消息类型实体 /// </summary> /// <param name="xml">接收到消息解密后的xml</param> /// <param name="receiveMessageEnum">消息类型枚举</param> /// <returns>消息类型</returns> public static ReceiveMessage.Base Parse(XmlDocument xml, ref ReceiveMessageEnum receiveMessageEnum) { XmlNode root = xml.FirstChild; string msgType = root["MsgType"].InnerText.ToLower(); string Event = string.Empty; if (root["Event"] != null) { Event = root["Event"].InnerText.ToLower(); } receiveMessageEnum = Enums.QY.getEnum(msgType, Event);//ReceiveMessage_backup.getEnum(msgType, Event); ReceiveMessage.Base rec = null; switch (receiveMessageEnum) { case ReceiveMessageEnum.Unknow: break; case ReceiveMessageEnum.Text: rec = new ReceiveMessage.Text(); break; case ReceiveMessageEnum.Image: rec = new ReceiveMessage.Image(); break; case ReceiveMessageEnum.Voice: rec = new ReceiveMessage.Voice(); break; case ReceiveMessageEnum.Video: rec = new ReceiveMessage.Video(); break; case ReceiveMessageEnum.ShortVideo: rec = new ReceiveMessage.ShortVideo(); break; case ReceiveMessageEnum.Location: rec = new ReceiveMessage.Location(); break; case ReceiveMessageEnum.Event_Location: rec = new ReceiveMessage.EventLocation(); break; case ReceiveMessageEnum.Event_Click: rec = new ReceiveMessage.EventClick(); break; case ReceiveMessageEnum.Event_View: break; case ReceiveMessageEnum.Event_Scancode_Push: break; case ReceiveMessageEnum.Event_Scancode_Waitmsg: break; case ReceiveMessageEnum.Event_Pic_Sysphoto: break; case ReceiveMessageEnum.Event_Pic_Photo_Or_Album: break; case ReceiveMessageEnum.Event_Pic_Weixin: break; case ReceiveMessageEnum.Event_Location_Select: break; case ReceiveMessageEnum.Event_Enter_Agent: rec = new ReceiveMessage.EventEnterAgent(); break; case ReceiveMessageEnum.Event_Subscribe: rec = new ReceiveMessage.EventSubscribe(); break; case ReceiveMessageEnum.Event_Batch_Job_Result: rec = new ReceiveMessage.EventBatchJobResult(); break; default: break; } rec.FillReceiveMessageFromXml(xml); return(rec); }
/// <summary> /// 开始处理 /// </summary> public void Processing() { HttpContext context = HttpContext.Current; if (context == null || context.Request == null) { throw new Exception("HttpContext信息错误"); } //this.MsgSig = HttpUtility.UrlDecode(context.Request.QueryString["msg_signature"], Encoding.UTF8); //this.TimeStamp = HttpUtility.UrlDecode(context.Request.QueryString["timestamp"], Encoding.UTF8); //this.Nonce = HttpUtility.UrlDecode(context.Request.QueryString["nonce"], Encoding.UTF8); //this.Echostr = HttpUtility.UrlDecode(context.Request.QueryString["echostr"], Encoding.UTF8); this.MsgSig = context.Request.QueryString["msg_signature"]; this.TimeStamp = context.Request.QueryString["timestamp"]; this.Nonce = context.Request.QueryString["nonce"]; this.Echostr = context.Request.QueryString["echostr"]; if (AppSettings.IsDebug) { //DebugLog Logger.Info("MsgSig = " + MsgSig); Logger.Info("TimeStamp = " + TimeStamp); Logger.Info("Nonce = " + Nonce); Logger.Info("Echostr = " + Echostr); } if (string.IsNullOrEmpty(this.MsgSig) || string.IsNullOrEmpty(this.TimeStamp) || string.IsNullOrEmpty(this.Nonce)) { throw new Exception("HttpContext信息错误"); } int ret = 0; #region 微信平台开启回调模式,首次配置服务器信息时,校验服务器URL if (!string.IsNullOrEmpty(this.Echostr)) { /* * ------------使用示例一:验证回调URL--------------- *企业开启回调模式时,企业号会向验证url发送一个get请求 * 假设点击验证时,企业收到类似请求: * GET /cgi-bin/wxpush?msg_signature=5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3×tamp=1409659589&nonce=263014780&echostr=P9nAzCzyDtyTWESHep1vC5X9xho%2FqYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp%2B4RPcs8TgAE7OaBO%2BFZXvnaqQ%3D%3D * HTTP/1.1 Host: qy.weixin.qq.com * * 接收到该请求时,企业应 * 1.解析出Get请求的参数,包括消息体签名(msg_signature),时间戳(timestamp),随机数字串(nonce)以及公众平台推送过来的随机加密字符串(echostr), * 这一步注意作URL解码。 * 2.验证消息体签名的正确性 * 3.解密出echostr原文,将原文当作Get请求的response,返回给公众平台 * 第2,3步可以用公众平台提供的库函数VerifyURL来实现。 */ string sEchoStr = ""; ret = Wxcpt.VerifyURL(this.MsgSig, this.TimeStamp, this.Nonce, this.Echostr, ref sEchoStr); if (ret != 0) { throw new Exception("ERR: VerifyURL Fail, errorCode: " + ret + "。"); } //ret==0表示验证成功,sEchoStr参数表示明文,用户需要将sEchoStr作为get请求的返回参数,返回给企业号。 context.Response.ContentType = "text/plain"; context.Response.Write(sEchoStr); return; } #endregion //获取post请求内容 StreamReader postData = new StreamReader(context.Request.InputStream); string postDataString = postData.ReadToEnd(); if (AppSettings.IsDebug) { Logger.Info("postDataString = " + postDataString); } string sMsg = ""; // 解析之后的明文 //解密 ret = Wxcpt.DecryptMsg(MsgSig, TimeStamp, Nonce, postDataString, ref sMsg); if (ret != 0) { throw new Exception("ERR: Decrypt Fail, errorCode: " + ret); } if (AppSettings.IsDebug) { Logger.Info("sMsg = " + sMsg); } //解析XML XmlDocument doc = new XmlDocument(); doc.LoadXml(sMsg); ReceiveMessageEnum messageType = ReceiveMessageEnum.Unknow; ReceiveMessage.Base messageEntity = ReceiveMessageParser.Parse(doc, ref messageType); ReplyMessage.Base retMessage = null; #region 根据接收消息类型 执行相应事件 switch (messageType) { case ReceiveMessageEnum.Unknow: throw new Exception("未知的接收消息类型。"); case ReceiveMessageEnum.Text: if (ProcessingText != null) { ProcessingTextEventArgs e = new ProcessingTextEventArgs(messageEntity as ReceiveMessage.Text); ProcessingText(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Image: if (ProcessingImage != null) { ProcessingImageEventArgs e = new ProcessingImageEventArgs(messageEntity as ReceiveMessage.Image); ProcessingImage(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Voice: if (ProcessingVoice != null) { ProcessingVoiceEventArgs e = new ProcessingVoiceEventArgs(messageEntity as ReceiveMessage.Voice); ProcessingVoice(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Video: if (ProcessingVideo != null) { ProcessingVideoEventArgs e = new ProcessingVideoEventArgs(messageEntity as ReceiveMessage.Video); ProcessingVideo(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Location: if (ProcessingLocation != null) { ProcessingLocationEventArgs e = new ProcessingLocationEventArgs(messageEntity as ReceiveMessage.Location); ProcessingLocation(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Event_Location: //如果开启位置记录,则缓存 if (this.EnablePositionRecord) { if (AppSettings.IsDebug) { Logger.Info("enablePositionRecord! key = " + CacheKey.UserLocation + messageEntity.FromUserName); } HttpContext.Current.Cache.Insert(CacheKey.UserLocation + messageEntity.FromUserName, messageEntity, null, DateTime.UtcNow.AddHours(this.PositionRecordExpiresHours), System.Web.Caching.Cache.NoSlidingExpiration); } if (ProcessingEventLocation != null) { ProcessingEventLocationEventArgs e = new ProcessingEventLocationEventArgs(messageEntity as ReceiveMessage.EventLocation); ProcessingEventLocation(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Event_Click: if (ProcessingEventClick != null) { ProcessingEventClickEventArgs e = new ProcessingEventClickEventArgs(messageEntity as ReceiveMessage.EventClick); ProcessingEventClick(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Event_View: break; case ReceiveMessageEnum.Event_Scancode_Push: break; case ReceiveMessageEnum.Event_Scancode_Waitmsg: break; case ReceiveMessageEnum.Event_Pic_Sysphoto: break; case ReceiveMessageEnum.Event_Pic_Photo_Or_Album: break; case ReceiveMessageEnum.Event_Pic_Weixin: break; case ReceiveMessageEnum.Event_Location_Select: break; case ReceiveMessageEnum.Event_Enter_Agent: if (ProcessingEventEnterAgent != null) { ProcessingEventEnterAgentEventArgs e = new ProcessingEventEnterAgentEventArgs(messageEntity as ReceiveMessage.EventEnterAgent); ProcessingEventEnterAgent(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Event_Subscribe: if (ProcessingEventSubscribe != null) { ProcessingEventSubscribeEventArgs e = new ProcessingEventSubscribeEventArgs(messageEntity as ReceiveMessage.EventSubscribe); ProcessingEventSubscribe(this, e); retMessage = e.ReplyMessage; } break; case ReceiveMessageEnum.Event_Batch_Job_Result: if (ProcessingEventBatchJobResult != null) { ProcessingEventBatchJobResultEventArgs e = new ProcessingEventBatchJobResultEventArgs(messageEntity as ReceiveMessage.EventBatchJobResult); ProcessingEventBatchJobResult(this, e); retMessage = e.ReplyMessage; } break; default: throw new Exception("未知的接收消息类型。"); } #endregion if (AppSettings.IsDebug) { if (retMessage == null) { Logger.Info("retMessage = null"); } else { Logger.Log("retMessage = " + retMessage.ToString()); } } string sEncryptMsg = ""; //xml格式的密文 if (retMessage != null) { //未加密明文字符串 string replyMsg = ReplyMessageBuilder.BuildXml(retMessage); if (AppSettings.IsDebug) { Logger.Info("replyMsg = " + replyMsg); } //加密 //string sEncryptMsg = ""; //xml格式的密文 ret = Wxcpt.EncryptMsg(replyMsg, TimeStamp, Nonce, ref sEncryptMsg); if (ret != 0) { throw new Exception("ERR: Encrypt Fail, errorCode: " + ret); } if (AppSettings.IsDebug) { Logger.Info("sEncryptMsg = " + sEncryptMsg); } } context.Response.ContentType = "text/plain"; context.Response.Write(sEncryptMsg); }