十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章将为大家详细讲解有关微信开发之如何实现接收文本消息,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
成都创新互联公司长期为上千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为万全企业提供专业的成都网站建设、做网站,万全网站改版等技术服务。拥有10年丰富建站经验和众多成功案例,为您定制开发。
微信中的消息类型有:文本,图片,语音,视频,地理位置,链接和事件消息。除了事件消息外,其他的统称为普通消息。微信中消息的推送与响应都是以xml数据包传输的。在用户发送消息给公众号时,微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。普通消息可以使用msgid排重,以避免重复的消息对业务逻辑的影响。
假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此座任何处理,并且不会发起重试。需要注意的是:这里说的回复空串并不是回复空的文本消息,而是直接Response.Write(“”)即可。
下面简要对各普通消息说明一下。
1348831860 1234567890123456
1348831860 1234567890123456
1357290913 1234567890123456
1357290913 1234567890123456
1351776360 23.134521 113.358803 20 1234567890123456
1351776360 1234567890123456
细心的程序猿应该发现了,所有的消息中(包括事件消息),都包含下面几个字段
参数 | 描述 |
---|---|
ToUserName | 接收方微信号 |
FromUserName | 发送方微信号,若为普通用户,则是一个OpenID |
CreateTime | 消息创建时间 |
MsgType | 消息类型 |
而消息的类型在文章开头已经讲了,分别是:文本(text),图片(image),语音(voice),视频(video),地理位置(location),链接(link),事件(event)
为了方便管理和代码编写,我们可以把这些消息类型写一个枚举。如下:
////// 消息类型枚举 /// public enum MsgType { //////文本类型 /// TEXT, ////// 图片类型 /// IMAGE, ////// 语音类型 /// VOICE, ////// 视频类型 /// VIDEO, ////// 地理位置类型 /// LOCATION, ////// 链接类型 /// LINK, ////// 事件类型 /// EVENT }
这里说明下,C#中event是关键字,所以event在枚举中就不能使用了,所以为了统一,我这里的枚举全部使用大写的。
既然所有的消息体都有上面的几个字段,那就可以写一个基类,然后不同的消息实体继承这个基类。(一直在纠结一个问题,以前我都是将所有的消息体中的字段写在一个类中,调用起来也很方便,只是类中的字段越来越多,看着都不爽。再加上本人才疏学浅,面向对象也使用的不熟练,所以一直都是在一个类中罗列所有的字段
调用的时候直接 var ss = WeiXinRequest.RequestHelper(token, EncodingAESKey, appid);
返回一个WeiXinRequest,然后再对消息类型和事件类型判断,做出响应。
今天重新做了下调整,也就是分了子类基类,代码可读性提高了,调用起来却没有之前方便了,各位朋友给点建议呗。
)
下面是各消息实体
基类:
public abstract class BaseMessage { ////// 开发者微信号 /// public string ToUserName { get; set; } ////// 发送方帐号(一个OpenID) /// public string FromUserName { get; set; } ////// 消息创建时间 (整型) /// public string CreateTime { get; set; } ////// 消息类型 /// public MsgType MsgType { get; set; } public virtual void ResponseNull() { Utils.ResponseWrite(""); } public virtual void ResText(EnterParam param, string content) { } ////// 回复消息(音乐) /// public void ResMusic(EnterParam param, Music mu) { } public void ResVideo(EnterParam param, Video v) { } ////// 回复消息(图片) /// public void ResPicture(EnterParam param, Picture pic, string domain) { } ////// 回复消息(图文列表) /// /// /// public void ResArticles(EnterParam param, Listart) { } /// /// 多客服转发 /// /// public void ResDKF(EnterParam param) { } ////// 多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。 /// /// 用户发送的消息体 /// 多客服账号 public void ResDKF(EnterParam param, string KfAccount) { } private void Response(EnterParam param, string data) { } }
基类中定义了消息体的公共字段,以及用于响应用户请求的虚方法(响应消息不是本文重点,所以方法体就没有贴出来,请关注后续文章)。
基类中方法的参数有个是EnterParam类型的,这个类是用户接入时和验证消息真实性需要使用的参数,包括token,加密密钥,appid等。定义如下:
////// 微信接入参数 /// public class EnterParam { ////// 是否加密 /// public bool IsAes { get; set; } ////// 接入token /// public string token { get; set; } //////微信appid /// public string appid { get; set; } ////// 加密密钥 /// public string EncodingAESKey { get; set; } }
文本实体:
public class TextMessage:BaseMessage { ////// 消息内容 /// public string Content { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } }
图片实体:
public class ImgMessage : BaseMessage { ////// 图片路径 /// public string PicUrl { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } ////// 媒体ID /// public string MediaId { get; set; } }
语音实体:
public class VoiceMessage : BaseMessage { ////// 缩略图ID /// public string MsgId { get; set; } ////// 格式 /// public string Format { get; set; } ////// 媒体ID /// public string MediaId { get; set; } ////// 语音识别结果 /// public string Recognition { get; set; } }
视频实体:
public class VideoMessage : BaseMessage { ////// 缩略图ID /// public string ThumbMediaId { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } ////// 媒体ID /// public string MediaId { get; set; } }
链接实体:
public class LinkMessage : BaseMessage { ////// 缩略图ID /// public string MsgId { get; set; } ////// 标题 /// public string Title { get; set; } ////// 描述 /// public string Description { get; set; } ////// 链接地址 /// public string Url { get; set; } }
消息实体定义好了,下一步就是根据微信服务器推送的消息体解析成对应的实体。本打算用C#自带的xml序列化发序列化的组件,结果试了下总是报什么xmls的错,索性用反射写了个处理方法:
public static T ConvertObj(string xmlstr) { XElement xdoc = XElement.Parse(xmlstr); var type = typeof(T); var t = Activator.CreateInstance (); foreach (XElement element in xdoc.Elements()) { var pr = type.GetProperty(element.Name.ToString()); if (element.HasElements) {//这里主要是兼容微信新添加的菜单类型。nnd,竟然有子属性,所以这里就做了个子属性的处理 foreach (var ele in element.Elements()) { pr = type.GetProperty(ele.Name.ToString()); pr.SetValue(t, Convert.ChangeType(ele.Value, pr.PropertyType), null); } continue; } if (pr.PropertyType.Name == "MsgType")//获取消息模型 { pr.SetValue(t, (MsgType)Enum.Parse(typeof(MsgType), element.Value.ToUpper()), null); continue; } if (pr.PropertyType.Name == "Event")//获取事件类型。 { pr.SetValue(t, (Event)Enum.Parse(typeof(Event), element.Value.ToUpper()), null); continue; } pr.SetValue(t, Convert.ChangeType(element.Value, pr.PropertyType), null); } return t; }
处理xml的方法定义好后,下面就是讲根据不同的消息类型来解析对应的实体了:
public class MessageFactory { public static BaseMessage CreateMessage(string xml) { XElement xdoc = XElement.Parse(xml); var msgtype = xdoc.Element("MsgType").Value.ToUpper(); MsgType type = (MsgType)Enum.Parse(typeof(MsgType), msgtype); switch (type) { case MsgType.TEXT: return Utils.ConvertObj(xml); case MsgType.IMAGE: return Utils.ConvertObj (xml); case MsgType.VIDEO: return Utils.ConvertObj (xml); case MsgType.VOICE: return Utils.ConvertObj (xml); case MsgType.LINK: return Utils.ConvertObj (xml); case MsgType.LOCATION: return Utils.ConvertObj (xml); case MsgType.EVENT://事件类型 { } break; default: return Utils.ConvertObj (xml); } } }
CreateMessage方法传入数据包(如加密,需解密后传入),以基类的形式返回对应的实体。
讲到这里普通消息的接收就差不多讲完了,结合上一篇博文,现在把修改后的接入代码贴出来如下:
public class WxRequest { public static BaseMessage Load(EnterParam param, bool bug = true) { string postStr = ""; Stream s = VqiRequest.GetInputStream();//此方法是对System.Web.HttpContext.Current.Request.InputStream的封装,可直接代码 byte[] b = new byte[s.Length]; s.Read(b, 0, (int)s.Length); postStr = Encoding.UTF8.GetString(b);//获取微信服务器推送过来的字符串 var timestamp = VqiRequest.GetQueryString("timestamp"); var nonce = VqiRequest.GetQueryString("nonce"); var msg_signature = VqiRequest.GetQueryString("msg_signature"); var encrypt_type = VqiRequest.GetQueryString("encrypt_type"); string data = ""; if (encrypt_type=="aes")//加密模式处理 { param.IsAes = true; var ret = new MsgCrypt(param.token, param.EncodingAESKey, param.appid); int r = ret.DecryptMsg(msg_signature, timestamp, nonce, postStr, ref data); if (r != 0) { WxApi.Base.WriteBug("消息解密失败"); return null; } } else { param.IsAes = false; data = postStr; } if (bug) { Utils.WriteTxt(data); } return MessageFactory.CreateMessage(data); } }
关于“微信开发之如何实现接收文本消息”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。