Chinaunix首页 | 论坛 | 博客
  • 博客访问: 511731
  • 博文数量: 158
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 904
  • 用 户 组: 普通用户
  • 注册时间: 2016-10-10 11:17
文章分类

全部博文(158)

文章存档

2018年(74)

2017年(84)

我的朋友

分类: 其他平台

2017-12-19 17:21:48

【摘要】


进行微信公众号开发时,微信消息处理是比较重要的一块内容,但是微信接**互的数据结构比较多变。传统做法是使用xpath对节点进行判断和解析,代码不易维护。本文介绍使用xml序列化/反序列化的方式将微信的数据结构映射为.Net中的类并进行处理。


【正文】

    微信接收到的消息包括普通消息和事件推送消息两类。消息的数据结构类似:

 

 

 1348831860

 

 

 1234567890123456

 

查看相应文档,消息体中都包含ToUserName、FromUserName、MsgType三个类型,可以通过MsgType来区分具体的消息类型。因此可以通过识别MsgType的消息值,使用工厂方法来解析出具体的微信消息。


1、对内置的Xml序列化/反序列化类进行初步封装


反序列化类:

        public static T XmlDeserialize(string s, Encoding encoding)

        {

            if (string.IsNullOrEmpty(s))

                throw new ArgumentNullException("s");

            if (encoding == null)

                throw new ArgumentNullException("encoding");

 

            XmlSerializer mySerializer = new XmlSerializer(typeof(T));

            using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s)))

            {

                using (StreamReader sr = new StreamReader(ms, encoding))

                {

                    return (T)mySerializer.Deserialize(sr);

                }

            }

        }

序列化类:

        public static string XmlSerialize(object o, Encoding encoding)

        {

            using (MemoryStream stream = new MemoryStream())

            {

                XmlSerializeInternal(stream, o, encoding);

                stream.Position = 0;

                using (StreamReader reader = new StreamReader(stream, encoding))

                {

                    return reader.ReadToEnd();

                }

            }

        }

        private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding)

        {

            if (o == null)

                throw new ArgumentNullException("o");

            if (encoding == null)

                throw new ArgumentNullException("encoding");

            XmlSerializer serializer = new XmlSerializer(o.GetType());

            XmlWriterSettings settings = new XmlWriterSettings();

            settings.Indent = true;

            settings.NewLineChars = "\r\n";

            settings.Encoding = encoding;

            settings.IndentChars = " ";

            settings.OmitXmlDeclaration = true;

            using (XmlWriter writer = XmlWriter.Create(stream, settings))

            {

                // 强制指定命名空间,覆盖默认的命名空间 

                XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();

                namespaces.Add(string.Empty, string.Empty);

                serializer.Serialize(writer, o, namespaces);

                writer.Close();

            }

        }

    在序列化的封装中,虽然不影响xml数据结构的正确性,但为保持和微信数据结构的完全一致,去掉xml默认的命名空间。


2、定义各类微信消息的基类和默认处理方法

    [XmlRoot("xml")]

    public class MsgRoot

    {

        public string ToUserName { get; set; }

        public string FromUserName { get; set; }

        public string CreateTime { get; set; }

        public virtual string MsgType { get; set; }       

        public virtual string Handle()

        {

            return "";

        }

}

3、为不同的消息定义各个实体类(以文本、图片、语音为例):


文本消息:

    [XmlRoot("xml")]

    public class Text : MsgRoot

    {

        public string Content { get; set; }

        public string MsgId { get; set; }

    }

图片消息:

    [XmlRoot("xml")]

    public class Image : MsgRoot

    {

        public string PicUrl { get; set; }

        public string MediaId { get; set;}

        public string MsgId { get; set; }

    }

语音消息:

    [XmlRoot("xml")]

    public class Voice : MsgRoot

    {

        public string Format { get; set; }

        public string MediaId { get; set; }

        public string MsgId { get; set; }

        public string Recognition { get; set; }

    }

3、定义工厂方法反序列化接收到的微信消息

    public class WechatReveiveMsgBuildFactory

    {

        public static MsgRoot CreateReiceiveMsg(string xml)

        {

            XmlDocument xmlParse = new XmlDocument();

            xmlParse.LoadXml(xml);

            var eventType = xmlParse.SelectSingleNode("xml/MsgType");

 

            if(eventType == null)

            {

                return null;

            }

            switch(eventType.InnerText.ToLower()){

                case "event":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "text":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "image":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "voice":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "video":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "shortvideo":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "location":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                case "link":

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

                default:

                    return XmlHelper.XmlDeserialize(xml, Encoding.UTF8);

            }

        }

}


4、在具体的消息结构中重写Handle方法实现具体的业务逻辑




微信消息相关文档请查看:


阅读(1523) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~