.NET微信公众号开发-4.0公众号消息处理

一.前言

  微信公众平台的消息处理仍是比较完善的,有最基本的文本消息,到图文消息,到图片消息,语音消息,视频消息,音乐消息其基本原理都是同样的,只不过所post的xml数据有所差异,在处理消息以前,咱们要认真阅读,官方给咱们的文档:http://mp.weixin.qq.com/wiki/14/89b871b5466b19b3efa4ada8e577d45e.html。首先咱们从最基本的文本消息处理开始。html

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>

  咱们能够看到这是消息处理的一个最基本的模式,有发送者,接受者,建立时间,类型,内容等等。node

首先咱们来建立一个消息处理的类,这个类用来捕获,全部的消息请求,根据不一样的消息请求类型来处理不一样的消息回复。微信

public class WeiXinService
    {
        /// <summary>
        /// TOKEN
        /// </summary>
        private const string TOKEN = "finder";
        /// <summary>
        /// 签名
        /// </summary>
        private const string SIGNATURE = "signature";
        /// <summary>
        /// 时间戳
        /// </summary>
        private const string TIMESTAMP = "timestamp";
        /// <summary>
        /// 随机数
        /// </summary>
        private const string NONCE = "nonce";
        /// <summary>
        /// 随机字符串
        /// </summary>
        private const string ECHOSTR = "echostr";
        /// <summary>
        /// 
        /// </summary>
        private HttpRequest Request { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="request"></param>
        public WeiXinService(HttpRequest request)
        {
            this.Request = request;
        }
        /// <summary>
        /// 处理请求,产生响应
        /// </summary>
        /// <returns></returns>
        public string Response()
        {
            string method = Request.HttpMethod.ToUpper();
            //验证签名
            if (method == "GET")
            {
                if (CheckSignature())
                {
                    return Request.QueryString[ECHOSTR];
                }
                else
                {
                    return "error";
                }
            }

            //处理消息
            if (method == "POST")
            {
                return ResponseMsg();
            }
            else
            {
                return "没法处理";
            }
        }

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        private string ResponseMsg()
        {
            string requestXml = CommonWeiXin.ReadRequest(this.Request);
            IHandler handler = HandlerFactory.CreateHandler(requestXml);
     
            if (handler != null)
            {
                return handler.HandleRequest();
            }

            return string.Empty;
        }
        /// <summary>
        /// 检查签名
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private bool CheckSignature()
        {
            string signature = Request.QueryString[SIGNATURE];
            string timestamp = Request.QueryString[TIMESTAMP];
            string nonce = Request.QueryString[NONCE];

            List<string> list = new List<string>();
            list.Add(TOKEN);
            list.Add(timestamp);
            list.Add(nonce);
            //排序
            list.Sort();
            //拼串
            string input = string.Empty;
            foreach (var item in list)
            {
                input += item;
            }
            //加密
            string new_signature = SecurityUtility.SHA1Encrypt(input);
            //验证
            if (new_signature == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

在来看看咱们的首先是如何捕获消息的。首页Default.ashx的代码以下微信公众平台

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            

            string postString = string.Empty;
            if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
            {
                //由微信服务接收请求,具体处理请求
               WeiXinService wxService = new WeiXinService(context.Request);                 string responseMsg = wxService.Response();
                context.Response.Clear();
                context.Response.Charset = "UTF-8";
                context.Response.Write(responseMsg);
                context.Response.End();
            }
            else
            {
                string token = "wei2414201";
                if (string.IsNullOrEmpty(token))
                {
                    return;
                }

                string echoString = HttpContext.Current.Request.QueryString["echoStr"];
                string signature = HttpContext.Current.Request.QueryString["signature"];
                string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
                string nonce = HttpContext.Current.Request.QueryString["nonce"];

                if (!string.IsNullOrEmpty(echoString))
                {
                    HttpContext.Current.Response.Write(echoString);
                    HttpContext.Current.Response.End();
                }
            }


        }

从上面的代码中咱们能够看到WeiXinService.cs类中的消息相应相当重要。ide

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        private string ResponseMsg()
        {
            string requestXml = CommonWeiXin.ReadRequest(this.Request);
            IHandler handler = HandlerFactory.CreateHandler(requestXml);
     
            if (handler != null)
            {
                return handler.HandleRequest();
            }

            return string.Empty;
        }

IHandler是一个消息处理接口,其下面有EventHandler,TextHandler处理类实现这个接口。代码以下函数

    /// <summary>
    /// 处理接口
    /// </summary>
    public interface IHandler
    {
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        string HandleRequest();
    }

EventHandlerpost

class EventHandler : IHandler
    {
        /// <summary>
        /// 请求的xml
        /// </summary>
        private string RequestXml { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="requestXml"></param>
        public EventHandler(string requestXml)
        {
            this.RequestXml = requestXml;
        }
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        public string HandleRequest()
        {
            string response = string.Empty;
            EventMessage em = EventMessage.LoadFromXml(RequestXml);
            if (em.Event.Equals("subscribe", StringComparison.OrdinalIgnoreCase))//用来判断是否是首次关注
            {


                PicTextMessage tm = new PicTextMessage();//我本身建立的一个图文消息处理类
                tm.ToUserName = em.FromUserName;
                tm.FromUserName = em.ToUserName;
                tm.CreateTime = CommonWeiXin.GetNowTime();
                response = tm.GenerateContent();

            }

            return response;
        }
    }

TextHandler微信支付

    /// <summary>
    /// 文本信息处理类
    /// </summary>
    public class TextHandler : IHandler
    {
        string openid { get; set; }
        string access_token { get; set; }

        /// <summary>
        /// 请求的XML
        /// </summary>
        private string RequestXml { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="requestXml">请求的xml</param>
        public TextHandler(string requestXml)
        {
            this.RequestXml = requestXml;
        }
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <returns></returns>
        public string HandleRequest()
        {
            string response = string.Empty;
            TextMessage tm = TextMessage.LoadFromXml(RequestXml);
            string content = tm.Content.Trim();
            if (string.IsNullOrEmpty(content))
            {
                response = "您什么都没输入,无法帮您啊。";
            }
            else
            {
                    string username = System.Configuration.ConfigurationManager.AppSettings["weixinid"].ToString();
                    AccessToken token = AccessToken.Get(username);
                    access_token = token.access_token;
                    openid = tm.FromUserName;
                    response = HandleOther(content);
                
            }
            tm.Content = response;
            //进行发送者、接收者转换
            string temp = tm.ToUserName;
            tm.ToUserName = tm.FromUserName;
            tm.FromUserName = temp;
            response = tm.GenerateContent();
            return response;
        }
        /// <summary>
        /// 处理其余消息
        /// </summary>
        /// <param name="tm"></param>
        /// <returns></returns>
        private string HandleOther(string requestContent)
        {
            string response = string.Empty;
            if (requestContent.Contains("你好") || requestContent.Contains("您好"))
            {
                response = "您也好~";
     }else if (requestContent.Contains("openid") || requestContent.Contains("id") || requestContent.Contains("ID"))//用来匹配用户输入的关键字 { response = "你的Openid: "+openid; } else if (requestContent.Contains("token") || requestContent.Contains("access_token"))
            {
                response = "你的access_token: " + access_token;
            }else 
            {
                response = "试试其余关键字吧。";
            }
            return response;
        }
    }

HandlerFactorythis

    /// <summary>
    /// 处理器工厂类
    /// </summary>
    public class HandlerFactory
    {
        /// <summary>
        /// 建立处理器
        /// </summary>
        /// <param name="requestXml">请求的xml</param>
        /// <returns>IHandler对象</returns>
        public static IHandler CreateHandler(string requestXml)
        {
            IHandler handler = null;
            if (!string.IsNullOrEmpty(requestXml))
            {
                //解析数据
                XmlDocument doc = new System.Xml.XmlDocument();
                doc.LoadXml(requestXml);
                XmlNode node = doc.SelectSingleNode("/xml/MsgType");
                if (node != null)
                {
                    XmlCDataSection section = node.FirstChild as XmlCDataSection;
                    if (section != null)
                    {
                        string msgType = section.Value;

                        switch (msgType)
                        {
                            case "text":
                                handler = new TextHandler(requestXml);
                                break;
                            case "event":
                                handler = new EventHandler(requestXml);
                                break;
                        }
                    }
                }
            }

            return handler;
        }
    }

 在这里基本的一些类已经完成了,如今咱们来完成,关注咱们的微信公众号,咱们就发送一条图文消息,同时输入咱们的一些关键字,返回一些消息,好比输入id返回用户的openid等等。加密

二.PicTextMessage

public class PicTextMessage : Message
    {
        /// <summary>
        /// 模板静态字段
        /// </summary>
        private static string m_Template;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public PicTextMessage()
        {
            this.MsgType = "news";
        }
        /// <summary>
        /// 从xml数据加载文本消息
        /// </summary>
        /// <param name="xml"></param>
        public static PicTextMessage LoadFromXml(string xml)
        {
            PicTextMessage tm = null;
            if (!string.IsNullOrEmpty(xml))
            {
                XElement element = XElement.Parse(xml);
                if (element != null)
                {
                    tm = new PicTextMessage();
                    tm.FromUserName = element.Element(CommonWeiXin.FROM_USERNAME).Value;
                    tm.ToUserName = element.Element(CommonWeiXin.TO_USERNAME).Value;
                    tm.CreateTime = element.Element(CommonWeiXin.CREATE_TIME).Value;
                }
            }

            return tm;
        }
        /// <summary>
        /// 模板
        /// </summary>
        public override string Template
        {
            get
            {
                if (string.IsNullOrEmpty(m_Template))
                {
                    LoadTemplate();
                }

                return m_Template;
            }
        }
        /// <summary>
        /// 生成内容
        /// </summary>
        /// <returns></returns>
        public override string GenerateContent()
        {
            this.CreateTime = CommonWeiXin.GetNowTime();
            string str= string.Format(this.Template, this.ToUserName, this.FromUserName, this.CreateTime);
            return str;
        }


        /// <summary>
        /// 加载模板
        /// </summary>
        private static void LoadTemplate()
        {
            m_Template= @"<xml>
                            <ToUserName><![CDATA[{0}]]></ToUserName>
                            <FromUserName><![CDATA[{1}]]></FromUserName>
                            <CreateTime>{2}</CreateTime>
                            <MsgType><![CDATA[news]]></MsgType>
                            <ArticleCount>1</ArticleCount>
                            <Articles>
                                <item>
                                <Title><![CDATA[有位停车欢迎你!]]></Title> 
                                <Description><![CDATA[若有问题请致电400-6238-136或直接在微信留言,咱们将第一时间为您服务!]]></Description>
                                <PicUrl><![CDATA[http://www.baidu.com/youwei.jpg]]></PicUrl>
                                <Url><![CDATA[http://www.baidu.com]]></Url>
                                </item>
                            </Articles>
                        </xml> ";
        }
    }

最后咱们的效果以下所示;

本人能力有限,但愿你们多多包涵.

三.微信公众号开发系列导航

1.0初始微信公众号

2.0建立自定义菜单

3.0查询自定义菜单

4.0公众号消息处理

5.0微信支付

6.0模板消息