微信公衆號開發:消息處理

前言html

       回顧上一節服務器配置的內容,咱們已經能夠本身完成公衆號服務器的配置。配置完成以後,咱們就能夠經過調用的方式,完成對消息管理的處理。當用戶關注公衆號或者發送消息的時候,咱們應該啓用默認回覆,要否則用戶得不到迴應,git

從而致使丟失體驗。因此這一章節,咱們將經過消息管理的方式,對用戶的信息進行處理,完成公衆號消息回覆功能,實現公衆號與用戶之間的完整對話。github

瞭解:算法

       微信公衆平臺對信息作了比較清晰的分類,最基本的包括請求(Request)和響應(Response)兩大類信息,這兩類信息有分爲文字、語音、圖片等格式。Senparc.Weixin.MP提供了MessageHandler消息處理類,這些類型在以枚舉的方式區分,api

同時根據嚴格命名規則命名了全部類型的RequestMessage和ResponseMessage。在Senparc裏也詳細說明了如何這個類的緩存

開始服務器

第一步微信

       新建一個UserMessageHandler.cs,須要繼承Senparc.Weixin.MP.MessageHandlers<TC>這個抽象類,並重寫全部方法:微信公衆平臺

    public class UserMessageHandler : MessageHandler<UserMessageContext>
    {
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="inputStream">構造函數的inputStream用於接收來自微信服務器的請求流(若是須要在外部處理,這裏也能夠傳入XDocument)</param>
        /// <param name="postModel">微信公衆服務器Post過來的加密參數集合(不包括PostData)</param>
        public UserMessageHandler(Stream inputStream, PostModel postModel)
            : base(inputStream, postModel)
        {
           
        }
        public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
        {
            /* 全部沒有被處理的消息會默認返回這裏的結果
            */
            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()
        {
            /*
            * 注意:即便使用其餘類實現IMessageContext,
            * 也務必在這裏進行下面的初始化,尤爲是設置當前時間,
            * 這個時間關係到及時從緩存中移除過時的消息,節約內存使用
            */
            base.MessageContextRemoved += UserMessageContext_MessageContextRemoved;
        }

        /// <summary>
        /// 當上下文過時,被移除時觸發的時間
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void UserMessageContext_MessageContextRemoved(object sender, Senparc.Weixin.Context.WeixinContextRemovedEventArgs<IRequestMessageBase, IResponseMessageBase> e)
        {
            /* 注意,這個事件不是實時觸發的(固然你也能夠專門寫一個線程監控)
             * 爲了提升效率,根據WeixinContext中的算法,這裏的過時消息會在過時後下一條請求執行以前被清除
             */
            var messageContext = e.MessageContext as CustomMessageContext;
            if (messageContext == null)
            {
                return;//若是是正常的調用,messageContext不會爲null
            }
            //TODO:這裏根據須要執行消息過時時候的邏輯,下面的代碼僅供參考
            //Log.InfoFormat("{0}的消息上下文已過時",e.OpenId);
            //api.SendMessage(e.OpenId, "因爲長時間未搭理客服,您的客服狀態已退出!");
        }
    }
}

       重寫的方法對應了接收不一樣的Request類型,構造函數的inputStream用於接收來自微信服務器的請求流ide

第二步

       基本用戶不一樣類型的請求,好比用戶向咱們發送一條信息,那麼會最終會調用OnTextRequest這個方法,因此在不一樣的重寫方法內,實現本身的方法。

好比:咱們對於文字(Text)信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnTextRequest:

        public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
        {
            var responseMessage = base.CreateResponseMessage<ResponseMessageText>();
            responseMessage.Content = "您剛剛發送了文字信息:" + requestMessage.Content;  //requestMessage.Content即用戶發過來的文字內容
            return responseMessage;
        }

 對於圖片信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnImageRequest

        /// <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 = "https://www.cnblogs.com/i3yuan/"
            });
            return responseMessage;
        }

 對於語音信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnVoiceRequest

        /// <summary>
        /// 處理語音請求
        /// </summary>
        /// <param name="requestMessage"></param>
        /// <returns></returns>
        public override IResponseMessageBase OnVoiceRequest(RequestMessageVoice requestMessage)
        {

            //獲取公衆號
            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"));

            //設置音樂信息
            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;
        }   

對於視頻信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnVideoRequest

        /// <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;
        }

對於地理信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnLocationRequest

        /// <summary>
        /// 處理位置請求
        /// </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;
        }

對於連接信息進行這樣的處理,在UserMessageHandler中咱們能夠重寫方法OnLinkRequest

        /// <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;
        }

第三步

        在Action中使用MessageHandler,返回對用戶的處理,在上一節中咱們已經新建了WXController.cs,在其中經過Post的方式處理用戶的請求

        [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("參數錯誤!");
                }
                var messageHandler = new UserMessageHandler(Request.InputStream);
                messageHandler.Execute(); //執行微信處理過程
                return new FixWeixinBugWeixinResult(messageHandler);
            }).ContinueWith<ActionResult>(task => task.Result);
        }
    }

       messageHandler.Execute();用於執行整個信息處理過程,其中會調用重寫的OnxxRequest方法

效果

 測試發送文本

       經過測試公衆號,咱們能夠發現,當咱們發送文本的時候,系統會對用戶的信息進行處理,完成公衆號消息回覆功能,實現公衆號與用戶之間的完整對話。

測試發送圖文消息

        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;

        }

總結

       1.經過MessageHandler的簡單處理,咱們就能夠進行對用戶文本消息的處理,完成公衆號與用戶的會話

       2.發送不一樣的消息,處理不一樣的回覆,實現更多類型的消息回覆

       3.參考了如何使用MessageHandler簡化消息處理流程

相關文章
相關標籤/搜索