Example #1
0
        /// <summary>
        /// 开始处理
        /// </summary>
        public void Processing()
        {
            HttpContext context = HttpContext.Current;

            if (context == null || context.Request == null)
            {
                throw new Exception("HttpContext信息错误");
            }

            this.Signature = context.Request.QueryString["signature"];
            this.TimeStamp = context.Request.QueryString["timestamp"];
            this.Nonce     = context.Request.QueryString["nonce"];
            this.Echostr   = context.Request.QueryString["echostr"];

            this.EncryptType  = context.Request.QueryString["encrypt_type"];
            this.MsgSignature = context.Request.QueryString["msg_signature"];

            if (AppSettings.IsDebug)
            {
                //DebugLog
                Logger.Info("MsgSig = " + MsgSignature);
                Logger.Info("Signature = " + Signature);
                Logger.Info("TimeStamp = " + TimeStamp);
                Logger.Info("Nonce = " + Nonce);
                Logger.Info("Echostr = " + Echostr);
                Logger.Info("EncryptType = " + EncryptType);
                Logger.Info("MsgSignature = " + MsgSignature);
            }

            if (string.IsNullOrEmpty(this.Signature) ||
                string.IsNullOrEmpty(this.TimeStamp) ||
                string.IsNullOrEmpty(this.Nonce))
            {
                throw new Exception("HttpContext信息错误");
            }
            //校验Token签名(请求来源是否为微信服务器)
            if (!CheckSignature.Check(this.Signature, this.TimeStamp, this.Nonce, WechatConfig.Token))
            {
                throw new Exception("ERR: VerifyURL Fail, 签名校验失败。");
            }

            int ret = 0;

            #region 首次配置服务器信息时,直接返回Echostr
            if (!string.IsNullOrEmpty(this.Echostr))
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write(Echostr);
                return;
            }
            #endregion

            //获取post请求内容
            StreamReader postData       = new StreamReader(context.Request.InputStream);
            string       postDataString = postData.ReadToEnd();

            if (AppSettings.IsDebug)
            {
                Logger.Info("postDataString = " + postDataString);
            }


            if (EncryptType == "aes")
            {
                //解密
                ret = Wxcpt.DecryptMsg(MsgSignature, TimeStamp, Nonce, postDataString, ref postDataString);
                if (ret != 0)
                {
                    throw new Exception("ERR: Decrypt Fail, errorCode: " + ret);
                }
            }
            if (AppSettings.IsDebug)
            {
                Logger.Info("sMsg = " + postDataString);
            }


            //解析XML
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(postDataString);

            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.ShortVideo:
                break;

            case ReceiveMessageEnum.Location:
                if (ProcessingLocation != null)
                {
                    ProcessingLocationEventArgs e = new ProcessingLocationEventArgs(messageEntity as ReceiveMessage.Location);
                    ProcessingLocation(this, e);
                    retMessage = e.ReplyMessage;
                }
                break;

            case ReceiveMessageEnum.Link:
                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_Scan:
                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_MasssEndJobFinish:
                if (ProcessingEventMasssEndJobFinish != null)
                {
                    ProcessingEventMasssEndJobFinishEventArgs e = new ProcessingEventMasssEndJobFinishEventArgs(messageEntity as ReceiveMessage.EventMasssEndJobFinish);
                    ProcessingEventMasssEndJobFinish(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 replyMsg = ""; //xml格式字符串(明文或加密)

            if (retMessage != null)
            {
                //未加密明文字符串
                replyMsg = ReplyMessageBuilder.BuildXml(retMessage);

                if (AppSettings.IsDebug)
                {
                    Logger.Info("replyMsg = " + replyMsg);
                }

                if (EncryptType == "aes")
                {
                    //加密
                    //replyMsg变为xml格式的密文
                    ret = Wxcpt.EncryptMsg(replyMsg, TimeStamp, Nonce, ref replyMsg);
                    if (ret != 0)
                    {
                        throw new Exception("ERR: Encrypt Fail, errorCode: " + ret);
                    }

                    if (AppSettings.IsDebug)
                    {
                        Logger.Info("sEncryptMsg = " + replyMsg);
                    }
                }
            }

            context.Response.ContentType = "text/plain";
            context.Response.Write(replyMsg);
        }
        /// <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&timestamp=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);
        }