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


    一.前言

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

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

      我们可以看到这是消息处理的一个最基本的模式,有发送者,接受者,创建时间,类型,内容等等。

    首先我们来创建一个消息处理的类,这个类用来捕获,所有的消息请求,根据不同的消息请求类型来处理不同的消息回复。

    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类中的消息相应至关重要。

            /// <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();
        }

    EventHandler

    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;
            }
        }

    HandlerFactory

        /// <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模板消息

  • 相关阅读:
    Exception和Error有什么区别?
    网络流量劫持的含义
    安全术语:
    加载相关
    10、接到任务后的整个测试前准备流程总结
    fiddler工具栏数据解释
    HTTP的请求头标签 If-Modified-Since
    VueStudyDemo
    Vue从入门到放弃
    TypeScript初体验
  • 原文地址:https://www.cnblogs.com/fenglingyi/p/4650213.html
Copyright © 2020-2023  润新知