C#微信公眾號(hào)開發(fā)之消息處理
前言:
回顧上一節(jié)服務(wù)器配置的內(nèi)容,我們已經(jīng)可以自己完成公眾號(hào)服務(wù)器的配置。配置完成之后,我們就可以通過調(diào)用的方式,完成對(duì)消息管理的處理。當(dāng)用戶關(guān)注公眾號(hào)或者發(fā)送消息的時(shí)候,我們應(yīng)該啟用默認(rèn)回復(fù),要不然用戶得不到回應(yīng),
從而導(dǎo)致丟失體驗(yàn)。所以這一章節(jié),我們將通過消息管理的方式,對(duì)用戶的信息進(jìn)行處理,完成公眾號(hào)消息回復(fù)功能,實(shí)現(xiàn)公眾號(hào)與用戶之間的完整對(duì)話。
了解:
微信公眾平臺(tái)對(duì)信息做了比較清晰的分類,最基本的包括請(qǐng)求(Request)和響應(yīng)(Response)兩大類信息,這兩類信息有分為文字、語音、圖片等格式。Senparc.Weixin.MP提供了MessageHandler消息處理類,這些類型在以枚舉的方式區(qū)分,
同時(shí)根據(jù)嚴(yán)格命名規(guī)則命名了所有類型的RequestMessage和ResponseMessage。在Senparc里也詳細(xì)說明了如何這個(gè)類的

開始:
第一步:
新建一個(gè)UserMessageHandler.cs,需要繼承Senparc.Weixin.MP.MessageHandlers<TC>這個(gè)抽象類,并重寫所有方法:
public class UserMessageHandler : MessageHandler<UserMessageContext>
{
/// <summary>
/// 構(gòu)造函數(shù)
/// </summary>
/// <param name="inputStream">構(gòu)造函數(shù)的inputStream用于接收來自微信服務(wù)器的請(qǐng)求流(如果需要在外部處理,這里也可以傳入XDocument)</param>
/// <param name="postModel">微信公眾服務(wù)器Post過來的加密參數(shù)集合(不包括PostData)</param>
public UserMessageHandler(Stream inputStream, PostModel postModel)
: base(inputStream, postModel)
{
}
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
/* 所有沒有被處理的消息會(huì)默認(rèn)返回這里的結(jié)果
*/
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();//ResponseMessageText也可以是News等其他類型
responseMessage.Content = "這條消息來自DefaultResponseMessage。";
return responseMessage;
}
}using Senparc.Weixin.Context;
using Senparc.Weixin.MP.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WeiXinHandler
{
public class UserMessageContext: MessageContext<IRequestMessageBase, IResponseMessageBase>
{
public UserMessageContext()
{
/*
* 注意:即使使用其他類實(shí)現(xiàn)IMessageContext,
* 也務(wù)必在這里進(jìn)行下面的初始化,尤其是設(shè)置當(dāng)前時(shí)間,
* 這個(gè)時(shí)間關(guān)系到及時(shí)從緩存中移除過期的消息,節(jié)約內(nèi)存使用
*/
base.MessageContextRemoved += UserMessageContext_MessageContextRemoved;
}
/// <summary>
/// 當(dāng)上下文過期,被移除時(shí)觸發(fā)的時(shí)間
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void UserMessageContext_MessageContextRemoved(object sender, Senparc.Weixin.Context.WeixinContextRemovedEventArgs<IRequestMessageBase, IResponseMessageBase> e)
{
/* 注意,這個(gè)事件不是實(shí)時(shí)觸發(fā)的(當(dāng)然你也可以專門寫一個(gè)線程監(jiān)控)
* 為了提高效率,根據(jù)WeixinContext中的算法,這里的過期消息會(huì)在過期后下一條請(qǐng)求執(zhí)行之前被清除
*/
var messageContext = e.MessageContext as CustomMessageContext;
if (messageContext == null)
{
return;//如果是正常的調(diào)用,messageContext不會(huì)為null
}
//TODO:這里根據(jù)需要執(zhí)行消息過期時(shí)候的邏輯,下面的代碼僅供參考
//Log.InfoFormat("{0}的消息上下文已過期",e.OpenId);
//api.SendMessage(e.OpenId, "由于長(zhǎng)時(shí)間未搭理客服,您的客服狀態(tài)已退出!");
}
}
}重寫的方法對(duì)應(yīng)了接收不同的Request類型,構(gòu)造函數(shù)的inputStream用于接收來自微信服務(wù)器的請(qǐng)求流
第二步:
基本用戶不同類型的請(qǐng)求,比如用戶向我們發(fā)送一條信息,那么會(huì)最終會(huì)調(diào)用OnTextRequest這個(gè)方法,所以在不同的重寫方法內(nèi),實(shí)現(xiàn)自己的方法。
比如:我們對(duì)于文字(Text)信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnTextRequest:
public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您剛剛發(fā)送了文字信息:" + requestMessage.Content; //requestMessage.Content即用戶發(fā)過來的文字內(nèi)容
return responseMessage;
}對(duì)于圖片信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnImageRequest
/// <summary>
/// 處理圖片請(qǐng)求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnImageRequest(RequestMessageImage requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
responseMessage.Articles.Add(new Article()
{
Title = "您剛才發(fā)送了圖片信息",
Description = "您發(fā)送的圖片將會(huì)顯示在邊上",
PicUrl = requestMessage.PicUrl,
Url = "https://www.cnblogs.com/i3yuan/"
});
return responseMessage;
}對(duì)于語音信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnVoiceRequest
/// <summary>
/// 處理語音請(qǐng)求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
{
//獲取公眾號(hào)
AccessTokenResult account = Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(AppId, AppSecret);
var responseMessage = CreateResponseMessage<ResponseMessageMusic>();
//上傳縮略圖
var uploadResult = Senparc.Weixin.MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(account.access_token, UploadMediaFileType.image,
Server.GetMapPath("~/Images/Logo.jpg"));
//設(shè)置音樂信息
responseMessage.Music.Title = "天籟之音";
responseMessage.Music.Description = "播放您上傳的語音";
responseMessage.Music.MusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.HQMusicUrl = "http://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.ThumbMediaId = uploadResult.media_id;
return responseMessage;
}對(duì)于視頻信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnVideoRequest
/// <summary>
/// 處理視頻請(qǐng)求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnVideoRequest(RequestMessageVideo requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您發(fā)送了一條視頻信息,ID:" + requestMessage.MediaId;
return responseMessage;
}對(duì)于地理信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnLocationRequest
/// <summary>
/// 處理位置請(qǐng)求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLocationRequest(RequestMessageLocation requestMessage)
{
var locationService = new LocationService();
var responseMessage = locationService.GetResponseMessage(requestMessage as RequestMessageLocation);
return responseMessage;
}對(duì)于鏈接信息進(jìn)行這樣的處理,在UserMessageHandler中我們可以重寫方法OnLinkRequest
/// <summary>
/// 處理鏈接消息請(qǐng)求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnLinkRequest(RequestMessageLink requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = string.Format(@"您發(fā)送了一條連接信息:
Title:{0}
Description:{1}
Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
return responseMessage;
}第三步:
在Action中使用MessageHandler,返回對(duì)用戶的處理,在上一節(jié)中我們已經(jīng)新建了WXController.cs,在其中通過Post的方式處理用戶的請(qǐng)求
[HttpPost]
[ActionName("Index")]
public Task<ActionResult> Post(PostModel postModel)
{
return Task.Factory.StartNew<ActionResult>(() =>
{
if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
{
return new WeixinResult("參數(shù)錯(cuò)誤!");
}
var messageHandler = new UserMessageHandler(Request.InputStream);
messageHandler.Execute(); //執(zhí)行微信處理過程
return new FixWeixinBugWeixinResult(messageHandler);
}).ContinueWith<ActionResult>(task => task.Result);
}messageHandler.Execute();用于執(zhí)行整個(gè)信息處理過程,其中會(huì)調(diào)用重寫的OnxxRequest方法
效果:
測(cè)試發(fā)送文本

通過測(cè)試公眾號(hào),我們可以發(fā)現(xiàn),當(dāng)我們發(fā)送文本的時(shí)候,系統(tǒng)會(huì)對(duì)用戶的信息進(jìn)行處理,完成公眾號(hào)消息回復(fù)功能,實(shí)現(xiàn)公眾號(hào)與用戶之間的完整對(duì)話。
測(cè)試發(fā)送圖文消息

public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
responseMessage.Articles.Add(new Article()
{
Title = "灌籃高手",
Description = "灌籃高手",
PicUrl = "http://images.cnblogs.com/cnblogs_com/i3yuan/1462639/o_timg%20(1).jpg",
Url = "https://www.cnblogs.com/i3yuan/"
});
return responseMessage;
}總結(jié):
1.通過MessageHandler的簡(jiǎn)單處理,我們就可以進(jìn)行對(duì)用戶文本消息的處理,完成公眾號(hào)與用戶的會(huì)話
2.發(fā)送不同的消息,處理不同的回復(fù),實(shí)現(xiàn)更多類型的消息回復(fù)
3.參考了如何使用MessageHandler簡(jiǎn)化消息處理流程
到此這篇關(guān)于C#微信公眾號(hào)開發(fā)之消息處理的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號(hào)的方法(適用于撥號(hào)用戶)
下面小編就為大家?guī)硪黄狢# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號(hào)的方法(適用于撥號(hào)用戶)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12
C#利用ScriptControl動(dòng)態(tài)執(zhí)行JS和VBS腳本
C#中利用ScriptControl動(dòng)態(tài)執(zhí)行JS和VBS腳本的實(shí)現(xiàn)方法,需要的朋友可以參考下2013-04-04
C#基于Socket實(shí)現(xiàn)簡(jiǎn)單聊天室功能
這篇文章主要為大家詳細(xì)介紹了C#基于Socket實(shí)現(xiàn)簡(jiǎn)單聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Unity Shader實(shí)現(xiàn)紋理遮罩效果
這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)紋理遮罩效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
C#枚舉類型與結(jié)構(gòu)類型實(shí)例解析
這篇文章主要介紹了C#枚舉類型與結(jié)構(gòu)類型實(shí)例,需要的朋友可以參考下2014-07-07

