搜尋
首頁微信小程式微信開發微信開發之接收文字訊息

微信開發之接收文字訊息

May 09, 2017 am 09:43 AM

微信中的消息類型有:文本,圖片,語音,視頻,地理位置,連結和事件訊息。除了事件訊息外,其他的統稱為普通訊息。微信中訊息的推送與回應都是以xml資料包傳輸的。當使用者傳送訊息給公眾號碼時,微信伺服器在五秒鐘內收不到回應會斷掉連接,並且重新發起請求,總共重試三次。普通訊息可以使用msgid排重,以避免重複的訊息對業務邏輯的影響。

假如伺服器無法保證在五秒內處理並回复,可以直接回复空串,微信伺服器不會對此座任何處理,並且不會發起重試。要注意的是:這裡說的回覆空串並不是回覆空的文字訊息,而是直接Response.Write(“”)即可。

下面簡單對各普通訊息說明一下。

文字訊息:
<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName> 
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>
圖片訊息:
<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[this is a url]]></PicUrl>
 <MediaId><![CDATA[media_id]]></MediaId>
 <MsgId>1234567890123456</MsgId>
 </xml>
語音訊息:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1357290913</CreateTime><MsgType><![CDATA[voice]]></MsgType><MediaId><![CDATA[media_id]]></MediaId><Format><![CDATA[Format]]></Format><MsgId>1234567890123456</MsgId></xml>
影片訊息:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1357290913</CreateTime><MsgType><![CDATA[video]]></MsgType><MediaId><![CDATA[media_id]]></MediaId><ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId><MsgId>1234567890123456</MsgId></xml>
地理位置訊息:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1351776360</CreateTime><MsgType><![CDATA[location]]></MsgType><Location_X>23.134521</Location_X><Location_Y>113.358803</Location_Y><Scale>20</Scale><Label><![CDATA[位置信息]]></Label><MsgId>1234567890123456</MsgId></xml>
連結訊息:
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>1351776360</CreateTime><MsgType><![CDATA[link]]></MsgType><Title><![CDATA[公众平台官网链接]]></Title><Description><![CDATA[公众平台官网链接]]></Description><Url><![CDATA[url]]></Url><MsgId>1234567890123456</MsgId></xml>

細心的程式猿應該發現了,所有的訊息中(包括事件訊息),都包含下面幾個欄位

參數 #描述
ToUserName 接收方微訊號
#FromUserName 發送方微訊號,若為普通用戶,則是一個OpenID
CreateTime 訊息建立時間
MsgType 訊息類型

而訊息的類型在文章開頭已經講了,分別是:文字(text),圖片(image),語音(voice),視訊(video),地理位置(location),連結(link),事件(event)

為了方便管理和程式碼編寫,我們可以把這些訊息類型寫一個枚舉。如下:

/// <summary>
    /// 消息类型枚举    /// </summary>
    public enum MsgType
    {        /// <summary>
        ///文本类型        /// </summary>        TEXT,        /// <summary>
        /// 图片类型        /// </summary>        IMAGE,        /// <summary>
        /// 语音类型        /// </summary>        VOICE,        /// <summary>
        /// 视频类型        /// </summary>        VIDEO,        /// <summary>
        /// 地理位置类型        /// </summary>        LOCATION,        /// <summary>
        /// 链接类型        /// </summary>        LINK,        /// <summary>
        /// 事件类型        /// </summary>        EVENT
    }

這裡說明下,C#中event是關鍵字,所以event在列舉中就不能使用了,所以為了統一,我這裡的枚舉全部使用大寫的。

既然所有的消息體都有上面的幾個字段,那就可以寫一個基類,然後不同的消息實體繼承這個基類。 (一直在糾結一個問題,以前我都是將所有的消息體中的字段寫在一個類中,調用起來也很方便,只是類中的字段越來越多,看著都不爽。再加上本人才疏淺,物件導向也使用的不熟練,所以一直都是在一個類別中羅列所有的欄位

呼叫的時候直接   var ss = WeiXinRequest.RequestHelper(token, EncodingAESKey, appid );

返回一個WeiXinRequest,然後再對訊息類型和事件類型判斷,做出回應。讀性提高了,呼叫起來卻沒有之前方便了,各位朋友給點建議唄。

public abstract class BaseMessage
    {        /// <summary>
        /// 开发者微信号        /// </summary>
        public string ToUserName { get; set; }       /// <summary>
        /// 发送方帐号(一个OpenID)       /// </summary>
        public string FromUserName { get; set; }        /// <summary>
        /// 消息创建时间 (整型)        /// </summary>
        public string CreateTime { get; set; }        /// <summary>
        /// 消息类型        /// </summary>
        public MsgType MsgType { get; set; }        public virtual void ResponseNull()
        {
            Utils.ResponseWrite("");
        }        public virtual void ResText(EnterParam param, string content)
        {            
        }        /// <summary>
        /// 回复消息(音乐)        /// </summary>
        public  void ResMusic(EnterParam param, Music mu)
        {
        }        public  void ResVideo(EnterParam param, Video v)
        {        }        /// <summary>
        /// 回复消息(图片)        /// </summary>
        public  void ResPicture(EnterParam param, Picture pic, string domain)
        {
}        /// <summary>
        /// 回复消息(图文列表)        /// </summary>
        /// <param name="param"></param>
        /// <param name="art"></param>
        public  void ResArticles(EnterParam param, List<Articles> art)
        {        }        /// <summary>
        /// 多客服转发        /// </summary>
        /// <param name="param"></param>
        public  void ResDKF(EnterParam param)
        {
}        /// <summary>
        /// 多客服转发如果指定的客服没有接入能力(不在线、没有开启自动接入或者自动接入已满),该用户会一直等待指定客服有接入能力后才会被接入,而不会被其他客服接待。建议在指定客服时,先查询客服的接入能力指定到有能力接入的客服,保证客户能够及时得到服务。        /// </summary>
        /// <param name="param">用户发送的消息体</param>
        /// <param name="KfAccount">多客服账号</param>
        public  void ResDKF(EnterParam param, string KfAccount)
        {        }        private  void Response(EnterParam param, string data)
        {            
        }
    }

基類中定義了訊息體的公共字段,以及用於回應使用者請求的虛擬方法(回應訊息不是本文重點,所以方法體就沒有貼出來,請關注後續文章) 。

基底類別中方法的參數有個是EnterParam類型的,這個類別是用戶存取時和驗證訊息真實性需要使用的參數,包括token,加密金鑰,appid等。定義如下:

/// <summary>
    /// 微信接入参数    /// </summary>
    public class EnterParam
    {        /// <summary>
        /// 是否加密        /// </summary>
        public bool IsAes { get; set; }        /// <summary>
        /// 接入token        /// </summary>
        public string token { get; set; }        /// <summary>
        ///微信appid        /// </summary>
        public string appid { get; set; }        /// <summary>
        /// 加密密钥        /// </summary>
        public string EncodingAESKey { get; set; }
    }

文字實體:

public class TextMessage:BaseMessage
    {       /// <summary>
       /// 消息内容       /// </summary>
        public string Content { get; set; }       /// <summary>
        /// 消息id,64位整型       /// </summary>
        public string MsgId { get; set; }

    
    }
圖片實體:
public class ImgMessage : BaseMessage
    {       /// <summary>
       /// 图片路径       /// </summary>
        public string PicUrl { get; set; }       /// <summary>
        /// 消息id,64位整型       /// </summary>
        public string MsgId { get; set; }        /// <summary>
        /// 媒体ID        /// </summary>
        public string MediaId { get; set; }

     
    }

語音實體:

public class VoiceMessage : BaseMessage
    {       /// <summary>
       /// 缩略图ID       /// </summary>
        public string MsgId { get; set; }       /// <summary>
        /// 格式       /// </summary>
        public string Format { get; set; }        /// <summary>
        /// 媒体ID        /// </summary>
        public string MediaId { get; set; }        /// <summary>
        /// 语音识别结果        /// </summary>
        public string Recognition { get; set; }

    
    }

視訊實體:

public class VideoMessage : BaseMessage
    {       /// <summary>
       /// 缩略图ID       /// </summary>
        public string ThumbMediaId { get; set; }       /// <summary>
        /// 消息id,64位整型       /// </summary>
        public string MsgId { get; set; }        /// <summary>
        /// 媒体ID        /// </summary>
        public string MediaId { get; set; }

    
    }

連結實體:

public class LinkMessage : BaseMessage
    {       /// <summary>
       /// 缩略图ID       /// </summary>
        public string MsgId { get; set; }       /// <summary>
        /// 标题       /// </summary>
        public string Title { get; set; }        /// <summary>
        /// 描述        /// </summary>
        public string Description { get; set; }        /// <summary>
        /// 链接地址        /// </summary>
        public string Url { get; set; }

     
    }

訊息實體定義好了,下一步就是根據微信伺服器推送的訊息體解析成對應的實體。本打算用C#自帶的xml序列化發序列化的元件,結果試了一下總是報什麼xmls的錯,索性用反射寫了個處理方法:

public static T ConvertObj<T>(string xmlstr)
        {
            XElement xdoc = XElement.Parse(xmlstr);            var type = typeof(T);            var t = Activator.CreateInstance<T>();            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<TextMessage>(xml);                case MsgType.IMAGE: return Utils.ConvertObj<ImgMessage>(xml);                case MsgType.VIDEO: return Utils.ConvertObj<VideoMessage>(xml);                case MsgType.VOICE: return Utils.ConvertObj<VoiceMessage>(xml);                case MsgType.LINK:                    return Utils.ConvertObj<LinkMessage>(xml);                case MsgType.LOCATION:                    return Utils.ConvertObj<LocationMessage>(xml);                case MsgType.EVENT://事件类型                {
                    
                } break;                default:                    return Utils.ConvertObj<BaseMessage>(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);
       }
    }

【相關推薦】

1.

微信公眾號平台原始碼下載

2.

微信啦啦外送2.2.4解密開源版微信魔術方塊原始碼

#

以上是微信開發之接收文字訊息的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。