通過前面章節的學習,我們已經對微信的開發有了基本的掌握與熟悉,基本可以上手做複雜的應用了。本篇我們將詳細講解微信消息管理中普通消息的接收與處理。當普通微信用戶向公眾賬號發消息時,微信伺服器將POST消息的XML數據包到開發者填寫的URL上。接收普通消息微信官方文檔參考:[接收普通消息文檔API](... ...
1、概述
通過前面章節的學習,我們已經對微信的開發有了基本的掌握與熟悉,基本可以上手做複雜的應用了。本篇我們將詳細講解微信消息管理中普通消息的接收與處理。當普通微信用戶向公眾賬號發消息時,微信伺服器將POST消息的XML數據包到開發者填寫的URL上。接收普通消息微信官方文檔參考:接收普通消息文檔API
消息接收後,就有一個處理或回覆的過程,單單發送消息了沒有響應也是不人性化的,下麵我們就對接收到微信各類型消息分別講解處理的方法。
2、消息接收
當普通微信用戶向公眾賬號發消息時,微信伺服器會先接收到用戶發送的消息,然後將用戶消息按照指定的XML格式組裝好數據,最後POST消息的XML數據包到開發者填寫的URL上。
接收到的普通消息的消息類型目前有以下幾種:
- 文本消息
- 圖片消息
- 語音消息
- 視頻消息
- 小視頻消息
- 地理位置消息
- 鏈接消息
每一種消息類型都有其指定的XML數據格式,這7種消息的xml格式請到官方文檔查看,有具體的格式定義和屬性說明。格式很簡單,基本共有屬性包括ToUserName、FromUserName、CreateTime、MsgType、MsgId,並且每種類型有自己特殊的屬性。
接收消息的過程其實就是獲取post請求的這個xml,然後對這個xml進行分析的過程。post請求的入口還是之前提到的微信公眾號接入的那個地址,整個公眾號的所有請求都會走這個入口,只是接入時是get請求,其它情況下是post請求。
3、消息回覆
微信伺服器在將用戶的消息發給公眾號的開發者伺服器地址後,會等待開發者伺服器回覆響應消息。微信伺服器在五秒內收不到響應會斷掉連接,並且重新發起請求,總共重試三次。
假如伺服器無法保證在五秒內處理並回覆,必須做出下述回覆,這樣微信伺服器才不會對此作任何處理,並且不會發起重試(這種情況下,可以使用客服消息介面進行非同步回覆),否則,將出現嚴重的錯誤提示。詳見下麵說明:
1、(推薦方式)直接回覆success
2、直接回覆空串(指位元組長度為0的空字元串,而不是XML結構體中content欄位的內容為空)
一旦遇到以下情況,微信都會在公眾號會話中,向用戶下發系統提示“該公眾號暫時無法提供服務,請稍後再試”:
1、開發者在5秒內未回覆任何內容
2、開發者回覆了異常數據,比如JSON數據等
另外,請註意,回覆圖片等多媒體消息時需要預先通過素材管理介面上傳臨時素材到微信伺服器,可以使用素材管理中的臨時素材,也可以使用永久素材。
消息回覆目前支持回覆文本、圖片、圖文、語音、視頻、音樂,每一種類型的消息都有特定的XML數據格式。這幾種回覆消息的xml數據格式請參考官方文檔,有具體的格式定義和屬性說明。格式很簡單,基本共有屬性包括ToUserName、FromUserName、CreateTime、MsgType,並且每種類型有自己特殊的屬性。
4、各類型消息的接收與回覆
使用Senparc.Weixin框架來快速處理各種接收的普通消息,實現非常簡單,自定義一個繼承MessageHandler的類,重寫這7種類型的方法即可。註意:DefaultResponseMessage必須重寫,用於返回沒有處理過的消息類型(也可以用於預設消息,如幫助信息等);其中所有原OnXX的抽象方法已經都改為虛方法,可以不必每個都重寫。若不重寫,預設返回DefaultResponseMessage方法中的結果。
CustomMessageHandle.cs需要繼承Senparc.Weixin.MP.MessageHandlers
可能如下:
public class CustomMessageHandler : MessageHandler<CustomMessageContext>
{
public CustomMessageHandler(Stream inputStream, PostModel postModel)
: base(inputStream, postModel)
{
}
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>(); //ResponseMessageText也可以是News等其他類型
responseMessage.Content = "這條消息來自DefaultResponseMessage。";
return responseMessage;
}
}
我們可以看到必須要重寫實現的抽象方法名為DefaultResponseMessage(),這一條信息用於返回一條的消息,假如對應類型(如語音)的微信消息沒有被代碼處理,那麼預設會返回這裡的結果。在DefaultResponseMessage()方法中,我們看到這樣一句:
var responseMessage = base.CreateResponseMessage<ResponseMessageText>(); //ResponseMessageText也可以是News等其他類型
這裡的CreateResponseMessage
- ResponseMessageText - 對應文本消息
- ResponseMessageNews - 對應圖文消息
- ResponseMessageMusic - 對應音樂消息
- ResponseMessageXXX - 其他類型以此類推
各種類型的消息我們可以根據我們自己的業務要求進行重寫回覆,如果沒重寫就會返回預設的消息(重寫預設響應的基礎上)。
4.1、文本消息的接收與回覆
文本消息對應的數據包XML格式如下:
<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>
參數說明:
參數 描述
ToUserName 開發者微信號(直接把它當做你的公眾號的微信號即可)
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 消息類型,文本為text
Content 文本消息內容
MsgId 消息id,64位整型
處理文本消息參考代碼:
/// <summary>
/// 處理文字請求
/// </summary>
/// <returns></returns>
public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
//註意:下麵泛型ResponseMessageText即返回給客戶端的類型,可以根據自己的需要填寫ResponseMessageNews等不同類型。
var responseMessage = CreateResponseMessage<ResponseMessageText>();
var result = new StringBuilder();
result.AppendFormat("您剛發送了文本信息:{0}\r\n\r\n", requestMessage.Content);
if (CurrentMessageContext.RequestMessages.Count > 1)
{
result.AppendFormat("您剛還發送瞭如下消息({0}/{1}):\r\n", CurrentMessageContext.RequestMessages.Count, CurrentMessageContext.StorageData);
for (int i = CurrentMessageContext.RequestMessages.Count - 2; i >= 0; i--)
{
var historyMessage = CurrentMessageContext.RequestMessages[i];
result.AppendFormat("{0} 【{1}】{2}\r\n",
historyMessage.CreateTime.ToShortTimeString(),
historyMessage.MsgType.ToString(),
(historyMessage is RequestMessageText)
? (historyMessage as RequestMessageText).Content
: "[非文字類型]"
);
}
result.AppendLine("\r\n");
}
result.AppendFormat("如果您在{0}分鐘內連續發送消息,記錄將被自動保留(當前設置:最多記錄{1}條)。過期後記錄將會自動清除。\r\n", WeixinContext.ExpireMinutes, WeixinContext.MaxRecordCount);
result.AppendLine("\r\n");
result.AppendLine("您還可以發送【位置】【圖片】【語音】【視頻】等類型的信息(註意是這幾種類型,不是這幾個文字),查看不同格式的回覆。");
responseMessage.Content = result.ToString();
return responseMessage;
}
4.2、圖片消息的接收與回覆
圖片消息對應的數據包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>
參數說明:
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 消息類型,圖片為image
PicUrl 圖片鏈接(由系統生成)
MediaId 圖片消息媒體id,可以調用獲取臨時素材介面拉取數據。
MsgId 消息id,64位整型
處理圖片消息參考代碼:
/// <summary>
/// 處理圖片請求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
responseMessage.Articles.Add(new Article()
{
Title = "您剛纔發送了圖片信息",
Description = "您發送的圖片將會顯示在邊上",
PicUrl = requestMessage.PicUrl,
Url = "http://blog.rdiframework.net/"
});
responseMessage.Articles.Add(new Article()
{
Title = "第二條",
Description = "第二條帶連接的內容",
PicUrl = requestMessage.PicUrl,
Url = "http://blog.rdiframework.net/"
});
return responseMessage;
}
在上面代碼中我們返回了用戶發送的圖片消息,同時加上了鏈接地址,用戶單擊消息會自動跳轉到指定的URL地址。
4.3、語音消息的接收與回覆
語音消息對應的數據包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>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 語音為voice
MediaId 語音消息媒體id,可以調用獲取臨時素材介面拉取數據。
Format 語音格式,如amr,speex等
MsgID 消息id,64位整型
參數說明:
處理語音消息參考代碼:
/// <summary>
/// 處理語音請求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
{
//獲得當前公眾號
WeixinOfficialAccountEntity account = RDIFrameworkService.Instance.WeixinBasicService.GetOfficialAccountEntity(Id);
var responseMessage = CreateResponseMessage<ResponseMessageMusic>();
//上傳縮略圖
var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(account.AccessToken, UploadMediaFileType.image,Server.GetMapPath("~/Content/Images/weixing-ma.png"));
//設置音樂信息
responseMessage.Music.Title = "天籟之音";
responseMessage.Music.Description = "播放您上傳的語音";
responseMessage.Music.MusicUrl = "http://www.rdiframework.net/resource/25375532.mp3";
responseMessage.Music.HQMusicUrl = "http://www.rdiframework.net/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.ThumbMediaId = uploadResult.media_id;
return responseMessage;
}
4.4、視頻消息的接收與回覆
視頻消息對應的數據包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>
參數說明:
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 視頻為video
MediaId 視頻消息媒體id,可以調用獲取臨時素材介面拉取數據。
ThumbMediaId 視頻消息縮略圖的媒體id,可以調用多媒體文件下載介面拉取數據。
MsgId 消息id,64位整型
處理視頻消息參考代碼:
/// <summary>
/// 處理視頻請求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您發送了一條視頻信息,ID:" + requestMessage.MediaId;
return responseMessage;
}
4.5、小視頻消息的接收與回覆
視頻與小視頻主要區別是在MsgType上,其他的都一樣。
小視頻消息對應的數據包XML格式如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType><![CDATA[shortvideo]]></MsgType>
<MediaId><![CDATA[media_id]]></MediaId>
<ThumbMediaId><![CDATA[thumb_media_id]]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
參數說明:
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 小視頻為shortvideo
MediaId 視頻消息媒體id,可以調用獲取臨時素材介面拉取數據。
ThumbMediaId 視頻消息縮略圖的媒體id,可以調用獲取臨時素材介面拉取數據。
MsgId 消息id,64位整型
處理小視頻消息參考代碼:
public override IResponseMessageBase OnShortVideoRequest(RequestMessageShortVideo requestMessage)
{
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您剛纔發送的是小視頻";
return responseMessage;
}
4.6、地理位置消息的接收與回覆
地理位置消息對應的數據包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>
參數說明:
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 消息類型,地理位置為location
Location_X 地理位置維度
Location_Y 地理位置經度
Scale 地圖縮放大小
Label 地理位置信息
MsgId 消息id,64位整型
處理地理位置消息參考代碼:
/// <summary>
/// 處理位置請求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage)
{
//返回的是圖文消息,是關於地址的圖文消息。
var responseLocation = base.CreateResponseMessage<ResponseMessageNews>();
var markersList = new List<BaiduMarkers>();
markersList.Add(new BaiduMarkers()
{
Size = BaiduMarkerSize.m,
Color = "red",
Label = "A",
Latitude = requestMessage.Location_X,
Longitude = requestMessage.Location_Y,
});
var mapUrl = BaiduMapHelper.GetBaiduStaticMap(requestMessage.Location_Y, requestMessage.Location_X, 1, 13, markersList);
responseLocation.Articles.Add(new Article()
{
Description = string.Format("您剛纔發送了地理位置信息。Location_X:{0},Location_Y:{1},Scale:{2},標簽:{3}", requestMessage.Location_X, requestMessage.Location_Y, requestMessage.Scale, requestMessage.Label),
PicUrl = SystemInfo.WeChatSiteUrl +"/Content/Images/toplogo.png",
Title = "國思軟體快速開發框架-地圖返回",
Url = mapUrl
});
return responseLocation;
}
對於回覆的消息,我們還可以單擊彈出百度地圖返回的位置詳情,具體應用可據此擴展。
4.7、鏈接消息的接收與回覆
鏈接消息對應的數據包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 消息類型,鏈接為link
Title 消息標題
Description 消息描述
Url 消息鏈接
MsgId 消息id,64位整型
鏈接位置消息參考代碼:
/// <summary>
/// 處理鏈接消息請求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = string.Format(@"您發送了一條連接信息:
Title:{0}
Description:{1}
Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
return responseMessage;
}
參考文章
RDIFramework.NET ━ .NET快速信息化系統開發框架 ━ 工作流程組件介紹
RDIFramework.NET ━ .NET快速信息化系統開發框架 ━ 工作流程組件介紹
RDIFramework.NET框架SOA解決方案(集Windows服務、WinForm形式與IIS形式發佈)-分散式應用
RDIFramework.NET代碼生成器全新V3.5版本發佈-重大升級
一路走來數個年頭,感謝RDIFramework.NET框架的支持者與使用者,大家可以通過下麵的地址瞭解詳情。
RDIFramework.NET官方網站:http://www.rdiframework.net/
RDIFramework.NET官方博客:http://blog.rdiframework.net/
同時需要說明的,以後的所有技術文章以官方網站為準,歡迎大家收藏!
RDIFramework.NET框架由專業團隊長期打造、一直在更新、一直在升級,請放心使用!
歡迎關註RDIFramework.net框架官方公眾微信(微信號:guosisoft),及時瞭解最新動態。
掃描二維碼立即關註