微信公衆平臺開發教程(三) 基礎框架搭建

微信公衆平臺開發教程(三) 基礎框架搭建

上一章,咱們已經初步講解了微信公衆帳號開發的基本原理,今天咱們來探索設計實現。算法

首先咱們設計了模塊層次圖,固然圖中只是給出一種實現方式,不侷限於此。具體見下圖。數據庫

主要功能介紹以下:服務器

1)請求接口層。處理HTTP請求,及響應微信

2)分發層。由接口層傳入請求,而後具體分析請求類型,分發至不一樣的處理器微信公衆平臺

3)業務邏輯層。這裏是咱們的具體業務邏輯了,根據請求,實現具體的業務邏輯。框架

4)數據層。咱們在實現某個應用時可能須要訪問數據,能夠是數據庫或者是文件。若是是簡單應用,可能沒有這一層。ide

其實,具體的應用能夠在這個結構上去擴展,能夠擴展消息對象層、業務對象層、數據訪問層、功能管理層等。這裏只是提供一種思路,不侷限於此。函數

 

 

根據層次圖,設計流程圖,具體講述實現的各個過程。以便了解整個處理過程。以下圖所示:性能

  

根據流程圖,咱們可以清晰的瞭解整個流程,消息處理的具體實現步驟。ui

下面咱們針對每一個流程進行代碼實現。

1、接收HTTP請求

咱們須要一個HttpHandler或者一個網頁,來處理微信服務端HTTP請求。

這裏咱們使用了HttpHandler。由於其靈活性高,性能好。

具體實現以下。

    public class WeiXinHttpHandler:IHttpHandler
    {
        /// <summary>
        /// 
        /// </summary>
        public bool IsReusable
        {
            get { return true; }
        }
        /// <summary>
        /// 處理請求
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            //由微信服務接收請求,具體處理請求
            WeiXinService wxService = new WeiXinService(context.Request);
            string responseMsg = wxService.Response();
            context.Response.Clear();
            context.Response.Charset = "UTF-8";
            context.Response.Write(responseMsg);
            context.Response.End();
        }
    }

 

若是是HTTPHandler,須要在配置文件中,配置具體的應用。具體的節點配置,咱們不做說明。直接給出例子,配置HttpHandler節點以下

 

<httpHandlers>
   <add verb="*" path="WXService.ashx" type="namespace.WeiXinHttpHandler,WXWeb" validate="true"/>
</httpHandlers>

 

2、分發請求

 爲了能功能封裝,咱們也將此封裝在了處理組件中。其實能夠放置在HttpHandler中的。 

 1)驗證簽名

 若是是首次請求,須要驗證簽名。就至關於一次HTTP握手。以前在上一章中,設置的服務器URL以及token值,這個功能就是檢驗是否連接成功。

這個請求是GET請求。如下具體說明(官方):

業務邏輯:

加密/校驗流程:

<1> 將token、timestamp、nonce三個參數進行字典序排序

<2> 將三個參數字符串拼接成一個字符串進行SHA1加密

 <3> 開發者得到加密後的字符串可與signature對比,標識該請求來源於微信 

而官方只提供了PHP的代碼示例,不少東西在C#中並不是直譯既得。因此這裏面也有一些具體處理。先看官方的代碼: 

    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];    
                
        $token = TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );
        
        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

咱們將其翻譯成C#版本: 

        /// <summary>
        /// 檢查簽名
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private bool CheckSignature()
        {
            string signature = Request.QueryString[SIGNATURE];
            string timestamp = Request.QueryString[TIMESTAMP];
            string nonce = Request.QueryString[NONCE];

            List<string> list = new List<string>();
            list.Add(TOKEN);
            list.Add(timestamp);
            list.Add(nonce);
            //排序
            list.Sort();
            //拼串
            string input = string.Empty;
            foreach (var item in list)
            {
                input += item;
            }
            //加密
            string new_signature = SecurityUtility.SHA1Encrypt(input);
            //驗證
            if (new_signature == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

這裏須要SHA1加密,具體的算法以下:

        /// <summary>
        /// SHA1加密
        /// </summary>
        /// <param name="intput">輸入字符串</param>
        /// <returns>加密後的字符串</returns>
        public static string SHA1Encrypt(string intput)
        {
            byte[] StrRes = Encoding.Default.GetBytes(intput);
            HashAlgorithm mySHA = new SHA1CryptoServiceProvider();
            StrRes = mySHA.ComputeHash(StrRes);
            StringBuilder EnText = new StringBuilder();
            foreach (byte Byte in StrRes)
            {
                EnText.AppendFormat("{0:x2}", Byte);
            }
            return EnText.ToString();
        }

2)分發請求

接下來就是具體的消息請求了,這裏都是POST請求。

由於有多種消息類型,咱們經過工廠類來進行封裝,而後每種消息都有專門的處理器來進行處理。具體實現邏輯:

        /// <summary>
        /// 處理請求
        /// </summary>
        /// <returns></returns>
        private string ResponseMsg()
        {
            string requestXml = Common.ReadRequest(this.Request);
            IHandler handler = HandlerFactory.CreateHandler(requestXml);
            if (handler != null)
            {
                return handler.HandleRequest();
            }

            return string.Empty;
        }

處理請求的對外方法(HttpHandler調用的方法就是這個了),即:

        /// <summary>
        /// 處理請求,產生響應
        /// </summary>
        /// <returns></returns>
        public string Response()
        {
            string method = Request.HttpMethod.ToUpper();
            //驗證簽名
            if (method == "GET")
            {
                if (CheckSignature())
                {
                    return Request.QueryString[ECHOSTR];
                }
                else
                {
                    return "error";
                }
            }

            //處理消息
            if (method == "POST")
            {
                return ResponseMsg();
            }
            else
            {
                return "沒法處理";
            }
        }

 

3、消息處理器具體處理消息

1)消息類型

首先咱們來看下,具體的消息類型,其實上一張中已經明確給了消息的接口。

這裏再看具體看一下,請求的消息類型有哪些,回覆的消息類型有哪些等。

千萬要注意,請求的消息是文本類型,回覆的消息,不必定也是文本哦,能夠是圖文、音樂等任意一種可回覆的消息。具體見下表所示。

 

2)根據具體的消息接口,設計消息類。

這裏給出類圖,供參考。

 

3)針對不一樣的消息,會有不一樣的處理器,來看下具體的類圖。

  

4)具體業務處理 

每一個handler裏面就是能夠處理具體請求。輸入的什麼消息,訪問那些數據,調用服務等,都在這裏處理。

仍是建議你們對具體的業務進行單獨封裝,在Handler中,只提供調用的接口。

由於隨着業務的增長,一個Handler可能要處理不少業務,若是全部的操做邏輯都寫在這裏,勢必影響閱讀,也不易於維護與擴展。 

5)產生回覆消息

在處理完請求後,須要生成回覆消息,響應到終端。消息格式,就是咱們介紹那些消息類型,但必須是可用於回覆的,當前支持的有:文本、圖文、音樂等。

必定要明確:回覆的消息類型不必定要與請求的消息類型同樣,好比,請求是文本,回覆的能夠是圖文、音樂。

產生回覆消息的過程,其實,就是特定的消息對象格式化爲對應的XML的過程,而後將XML響應至微信服務器。

6)實例

這裏以微信用戶關注公衆帳號,而後服務端處理處理事件請求,登記用戶,並提示歡迎信息。

    class EventHandler : IHandler
    {
        /// <summary>
        /// 請求的xml
        /// </summary>
        private string RequestXml { get; set; }
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="requestXml"></param>
        public EventHandler(string requestXml)
        {
            this.RequestXml = requestXml;
        }
        /// <summary>
        /// 處理請求
        /// </summary>
        /// <returns></returns>
        public string HandleRequest()
        {
            string response = string.Empty;
            EventMessage em = EventMessage.LoadFromXml(RequestXml);
            if (em.Event == EventType.Subscribe)
            {
                //註冊用戶
                User user = new User();
                user.OpenID = em.FromUserName;
                UserManager.Regester(user);

                //回覆歡迎消息
                TextMessage tm = new TextMessage();
                tm.ToUserName = em.FromUserName;
                tm.FromUserName = em.ToUserName;
                tm.CreateTime = Common.GetNowTime();
                tm.Content = "歡迎您關注xxx,我是小微。有什麼我能幫助您的嗎?";
                response = tm.GenerateContent();
            }

            return response;
        }
    }

 

4、HTTP響應

 最後將處理結果返回至最初HttpHandler,響應給微信服務器,直接Response處理。這也是在最開始設計的HttpHandler中實現的。

下面是代碼片斷,具體可見1、Http請求 

            context.Response.Clear();
            context.Response.Charset = "UTF-8";
            context.Response.Write(responseMsg);
            context.Response.End();
相關文章
相關標籤/搜索