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

来源:https://www.cnblogs.com/i3yuan/archive/2019/05/12/10850169.html
-Advertisement-
Play Games

前言: 回顧上一節伺服器配置的內容,我們已經可以自己完成公眾號伺服器的配置。配置完成之後,我們就可以通過調用的方式,完成對消息管理的處理。當用戶關註公眾號或者發送消息的時候,我們應該啟用預設回覆,要不然用戶得不到回應, 從而導致丟失體驗。所以這一章節,我們將通過消息管理的方式,對用戶的信息進行處理, ...


前言

       回顧上一節伺服器配置的內容,我們已經可以自己完成公眾號伺服器的配置。配置完成之後,我們就可以通過調用的方式,完成對消息管理的處理。當用戶關註公眾號或者發送消息的時候,我們應該啟用預設回覆,要不然用戶得不到回應,

從而導致丟失體驗。所以這一章節,我們將通過消息管理的方式,對用戶的信息進行處理,完成公眾號消息回覆功能,實現公眾號與用戶之間的完整對話。

瞭解:

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

同時根據嚴格命名規則命名了所有類型的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用於接收來自微信伺服器的請求流

第二步

       基本用戶不同類型的請求,比如用戶向我們發送一條信息,那麼會最終會調用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簡化消息處理流程


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 資料庫連接 配置Session的生命周期 Mode:包括Off(禁用會話狀態)、Inproc(工作進程自身存儲會話裝填)、StateServer(把會話信息存放在一個單獨的ASP.NET狀態服務中)、SqlServer(會話信息存放在SQLServer資料庫中) stateConnectionStr ...
  • 在C#語言程式設計中,List集合是常用的集合數據類型,在涉及集合類型的運算中,有時候我們需要計算2個List集合中共有的數據,即對2個List集合求交集運算。此時可以使用C#語言提供的Intersect方法快速來實現兩個集合之間的交集運算。Except方法調用的格式為:List1.Intersec ...
  • 在騰訊雲伺服器的控制後臺,有個專門的功能變數名稱解析控制頁面,我們可以在功能變數名稱解析頁面對我們自己的功能變數名稱進行解析,如將功能變數名稱解析到我們的騰訊雲伺服器上,也可將功能變數名稱指向跳轉到另一個功能變數名稱,或者在功能變數名稱雲解析控制台設置禁止國外IP訪問你的功能變數名稱等等。相應的功能變數名稱解析操作比較簡單,支持頂級功能變數名稱的解析,也支持子功能變數名稱解析到伺服器網 ...
  • 在C#的List操作中,針對List對象集合的排序我們可以使用OrderBy、OrderByDescending、ThenBy、ThenByDescending等方法按照特定的對象屬性進行排序,其中Orderby表示按指定的第一個屬性升序排序,OrderByDescending表示按指定的第一個屬性 ...
  • 在騰訊雲伺服器採購過程中,一般在採購的時候會讓你開啟預設的安全組策略,此時預設開啟的只有幾個常規埠,如80的Web網站埠,3306的遠程桌面埠等,有時候我們伺服器應用還需要開啟其他自定義埠號,此時在伺服器部署相應的應用後,我們還需要在騰訊雲控制台的安全組功能中放行對應的埠號,否則這個應用將 ...
  • 在C#語言的編程開發中,針對List集合的運算有時候需要計算兩個List集合的差集數據,集合的差集是取在該集合中而不在另一集合中的所有的項。A集合針對B集合的差集數據指的是所有在A集合但不在B集合的元素。在C#語言中可以使用Except方法來計算兩個List集合的差集數據,簡單快捷只需要一條語句。 ...
  • 今天開發一個ASP.NET MVC網站時,有個頁面使用到了FCKEditor富文本編輯器,通過Post方式提交內容時候拋出異常,仔細分析後得出應該是伺服器阻止了帶有HTML標簽內容的提交操作,ASP.NET認為客戶端提交的數據中包含大量Html標簽是危險數據,請求直接就被終止了,然後拋出異常。可設置 ...
  • 簡化版: 效果如圖: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Drawing;using S ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...