這篇文章將為大家詳細(xì)講解有關(guān)微信開發(fā)之如何實(shí)現(xiàn)接收文本消息,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
在丁青等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站制作、成都網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,營(yíng)銷型網(wǎng)站建設(shè),外貿(mào)營(yíng)銷網(wǎng)站建設(shè),丁青網(wǎng)站建設(shè)費(fèi)用合理。微信中的消息類型有:文本,圖片,語(yǔ)音,視頻,地理位置,鏈接和事件消息。除了事件消息外,其他的統(tǒng)稱為普通消息。微信中消息的推送與響應(yīng)都是以xml數(shù)據(jù)包傳輸?shù)?。在用戶發(fā)送消息給公眾號(hào)時(shí),微信服務(wù)器在五秒內(nèi)收不到響應(yīng)會(huì)斷掉連接,并且重新發(fā)起請(qǐng)求,總共重試三次。普通消息可以使用msgid排重,以避免重復(fù)的消息對(duì)業(yè)務(wù)邏輯的影響。
假如服務(wù)器無法保證在五秒內(nèi)處理并回復(fù),可以直接回復(fù)空串,微信服務(wù)器不會(huì)對(duì)此座任何處理,并且不會(huì)發(fā)起重試。需要注意的是:這里說的回復(fù)空串并不是回復(fù)空的文本消息,而是直接Response.Write(“”)即可。
下面簡(jiǎn)要對(duì)各普通消息說明一下。
1348831860 1234567890123456
1348831860 1234567890123456
1357290913 1234567890123456
1357290913 1234567890123456
1351776360 23.134521 113.358803 20 1234567890123456
1351776360 1234567890123456
細(xì)心的程序猿應(yīng)該發(fā)現(xiàn)了,所有的消息中(包括事件消息),都包含下面幾個(gè)字段
參數(shù) | 描述 |
---|---|
ToUserName | 接收方微信號(hào) |
FromUserName | 發(fā)送方微信號(hào),若為普通用戶,則是一個(gè)OpenID |
CreateTime | 消息創(chuàng)建時(shí)間 |
MsgType | 消息類型 |
而消息的類型在文章開頭已經(jīng)講了,分別是:文本(text),圖片(image),語(yǔ)音(voice),視頻(video),地理位置(location),鏈接(link),事件(event)
為了方便管理和代碼編寫,我們可以把這些消息類型寫一個(gè)枚舉。如下:
////// 消息類型枚舉 /// public enum MsgType { //////文本類型 /// TEXT, ////// 圖片類型 /// IMAGE, ////// 語(yǔ)音類型 /// VOICE, ////// 視頻類型 /// VIDEO, ////// 地理位置類型 /// LOCATION, ////// 鏈接類型 /// LINK, ////// 事件類型 /// EVENT }
這里說明下,C#中event是關(guān)鍵字,所以event在枚舉中就不能使用了,所以為了統(tǒng)一,我這里的枚舉全部使用大寫的。
既然所有的消息體都有上面的幾個(gè)字段,那就可以寫一個(gè)基類,然后不同的消息實(shí)體繼承這個(gè)基類。(一直在糾結(jié)一個(gè)問題,以前我都是將所有的消息體中的字段寫在一個(gè)類中,調(diào)用起來也很方便,只是類中的字段越來越多,看著都不爽。再加上本人才疏學(xué)淺,面向?qū)ο笠彩褂玫牟皇炀殻砸恢倍际窃谝粋€(gè)類中羅列所有的字段
調(diào)用的時(shí)候直接 var ss = WeiXinRequest.RequestHelper(token, EncodingAESKey, appid);
返回一個(gè)WeiXinRequest,然后再對(duì)消息類型和事件類型判斷,做出響應(yīng)。
今天重新做了下調(diào)整,也就是分了子類基類,代碼可讀性提高了,調(diào)用起來卻沒有之前方便了,各位朋友給點(diǎn)建議唄。
)
下面是各消息實(shí)體
基類:
public abstract class BaseMessage { ////// 開發(fā)者微信號(hào) /// public string ToUserName { get; set; } ////// 發(fā)送方帳號(hào)(一個(gè)OpenID) /// public string FromUserName { get; set; } ////// 消息創(chuàng)建時(shí)間 (整型) /// public string CreateTime { get; set; } ////// 消息類型 /// public MsgType MsgType { get; set; } public virtual void ResponseNull() { Utils.ResponseWrite(""); } public virtual void ResText(EnterParam param, string content) { } ////// 回復(fù)消息(音樂) /// public void ResMusic(EnterParam param, Music mu) { } public void ResVideo(EnterParam param, Video v) { } ////// 回復(fù)消息(圖片) /// public void ResPicture(EnterParam param, Picture pic, string domain) { } ////// 回復(fù)消息(圖文列表) /// /// /// public void ResArticles(EnterParam param, Listart) { } /// /// 多客服轉(zhuǎn)發(fā) /// /// public void ResDKF(EnterParam param) { } ////// 多客服轉(zhuǎn)發(fā)如果指定的客服沒有接入能力(不在線、沒有開啟自動(dòng)接入或者自動(dòng)接入已滿),該用戶會(huì)一直等待指定客服有接入能力后才會(huì)被接入,而不會(huì)被其他客服接待。建議在指定客服時(shí),先查詢客服的接入能力指定到有能力接入的客服,保證客戶能夠及時(shí)得到服務(wù)。 /// /// 用戶發(fā)送的消息體 /// 多客服賬號(hào) public void ResDKF(EnterParam param, string KfAccount) { } private void Response(EnterParam param, string data) { } }
基類中定義了消息體的公共字段,以及用于響應(yīng)用戶請(qǐng)求的虛方法(響應(yīng)消息不是本文重點(diǎn),所以方法體就沒有貼出來,請(qǐng)關(guān)注后續(xù)文章)。
基類中方法的參數(shù)有個(gè)是EnterParam類型的,這個(gè)類是用戶接入時(shí)和驗(yàn)證消息真實(shí)性需要使用的參數(shù),包括token,加密密鑰,appid等。定義如下:
////// 微信接入?yún)?shù) /// 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; } }
文本實(shí)體:
public class TextMessage:BaseMessage { ////// 消息內(nèi)容 /// public string Content { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } }
圖片實(shí)體:
public class ImgMessage : BaseMessage { ////// 圖片路徑 /// public string PicUrl { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } ////// 媒體ID /// public string MediaId { get; set; } }
語(yǔ)音實(shí)體:
public class VoiceMessage : BaseMessage { ////// 縮略圖ID /// public string MsgId { get; set; } ////// 格式 /// public string Format { get; set; } ////// 媒體ID /// public string MediaId { get; set; } ////// 語(yǔ)音識(shí)別結(jié)果 /// public string Recognition { get; set; } }
視頻實(shí)體:
public class VideoMessage : BaseMessage { ////// 縮略圖ID /// public string ThumbMediaId { get; set; } ////// 消息id,64位整型 /// public string MsgId { get; set; } ////// 媒體ID /// public string MediaId { get; set; } }
鏈接實(shí)體:
public class LinkMessage : BaseMessage { ////// 縮略圖ID /// public string MsgId { get; set; } ////// 標(biāo)題 /// public string Title { get; set; } ////// 描述 /// public string Description { get; set; } ////// 鏈接地址 /// public string Url { get; set; } }
消息實(shí)體定義好了,下一步就是根據(jù)微信服務(wù)器推送的消息體解析成對(duì)應(yīng)的實(shí)體。本打算用C#自帶的xml序列化發(fā)序列化的組件,結(jié)果試了下總是報(bào)什么xmls的錯(cuò),索性用反射寫了個(gè)處理方法:
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,竟然有子屬性,所以這里就做了個(gè)子屬性的處理 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的方法定義好后,下面就是講根據(jù)不同的消息類型來解析對(duì)應(yīng)的實(shí)體了:
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方法傳入數(shù)據(jù)包(如加密,需解密后傳入),以基類的形式返回對(duì)應(yīng)的實(shí)體。
講到這里普通消息的接收就差不多講完了,結(jié)合上一篇博文,現(xiàn)在把修改后的接入代碼貼出來如下:
public class WxRequest { public static BaseMessage Load(EnterParam param, bool bug = true) { string postStr = ""; Stream s = VqiRequest.GetInputStream();//此方法是對(duì)System.Web.HttpContext.Current.Request.InputStream的封裝,可直接代碼 byte[] b = new byte[s.Length]; s.Read(b, 0, (int)s.Length); postStr = Encoding.UTF8.GetString(b);//獲取微信服務(wù)器推送過來的字符串 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); } }
關(guān)于“微信開發(fā)之如何實(shí)現(xiàn)接收文本消息”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。