微信公眾號開發之基礎梳理


 目錄

(一)微信公眾號開發之VS遠程調試
(二)微信公眾號開發之基礎梳理
(三)微信公眾號開發之自動消息回復和自定義菜單
(四)微信公眾號開發之網頁授權獲取用戶基本信息
(五)微信公眾號開發之網頁中及時獲取當前用戶Openid及注意事項
(六)微信公眾號開發之掃碼支付
(七)微信公眾號開發之公眾號支付
(八)微信公眾號開發之現金紅包
(九)微信公眾號開發之回復圖文消息(被動)

前言

微信公眾號開發已經不在是新鮮事了,不過相信也有很多小伙伴和我一樣,沒有接觸過或者剛剛接觸不久。再此,記錄下學習經歷和一些比較坑的注意點。

理論介紹

首先,微信公眾號分兩種類型和兩種情況,兩種類型分別是訂閱號和服務號,兩種情況是,已認證或未認證的公眾號。他們分別具體的接口權限大家可以在微信后台的“開發者中心-接口權限”看到。

顯示“未獲得”的接口狀態,就是需要訂閱號或服務號微信認證之后才有擁有的權限。

簡單說,未認證的訂閱號只有基礎支持、自動回復和發送回復消息的接口,只有實現一些較簡單的數據交互功能,

 

那么,什么是接口?微信接口又是什么意思?

打個比方,如果一家公司是一個系統,創業之初,你可能一個人身兼多職,同時負責營銷、財務、研發等,發展到了一定規模后為了提高公司整體的運行效率和服務水平,你就需要聘用不同的人才來幫你承擔相應的一部分工作,那么同時,你也需要向這部分人提供對應的工作權限以滿足他們的工作需要,這就類似於接口的概念。

 

微信接口簡單說,是微信公眾平台向第三方開發者提供的一個用戶資源數據及功能的訪問/使用權限。通過對開發者提供開放統一的API接口環境,來幫助微信第三方開發者訪問微信公眾平台的功能和資源,以達到充分自由的運用微信公眾平台用戶資源及功能的目的。

在微信上,要實現這一目的,需要開啟“服務器配置”如下圖所示:

如圖所示:大家需要注意的是,一旦開啟了服務器配置,微信平台自帶的自動回復、自定義菜單等功能全部失效,所有的事件推送都會被轉發到你所配置的服務器地址URL上。

 

簡單解釋下開發者ID和服務器配置各參數的作用:

AppID是應用ID,也就是微信開發者編號的意思,在微信中主要用於創建微信菜單等。

AppSecret是應用密匙,與AppID是相配合的,意思可理解為這是私密的應用編號。

URL服務器地址是微信服務器像開發者服務器推送消息和事件的地址,可理解為你家的住址。這里沒什么特別要求,無論你使用什么語言開發,只要能通過HTTP服務的80端口返回符合微信要求的XML信息即可。

Token令牌可理解為用來驗證安全接頭暗號,讓微信服務器知道對方就是我要找的人。

EncodingAESKey可理解為暗語加密交流,以免你與用戶之間的交互信息被第三方獲取到后泄露敏感數據

基本原理

微信服務器就相當於一個轉發服務器,終端(手機、Pad等)發起請求至微信服務器,然后微信服務器將請求轉發給自定義服務(也就是開發者服務器,url對應的服務器)。

服務處理完畢,然后回發給微信服務器,微信服務器再將具體響應回復到終端。

通信協議為:HTTP

數據格式為:XML

具體的流程如下圖所示:

                                          

其實,我們需要做的事情,就是對HTTP請求,做出響應。

具體的請求內容,我們按照特定的XML格式去解析,處理完畢后,也要按照特定的XML格式返回。

我們只需要一個簡單的實現HttpHandler即可。

當然,微信平台還能實現更加復雜的業務,比如微信可以作為內嵌的瀏覽器,我們可以通過微信的鏈接,打開htm界面,然后實現自己的邏輯。

當普通微信用戶向公眾賬號發消息時,微信服務器將POST該消息到填寫的URL上。結構如下

 業務流程

 前面的注冊及消息接入就不過多贅述了,上面我們已經初步講解了微信公眾賬號開發的基本原理,這里我們來探索設計實現

主要功能介紹如下:

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

2)分發層。由接口層傳入請求,然后具體分析請求類型,分發至不同的處理器

3)業務邏輯層。這里是我們的具體業務邏輯了,根據請求,實現具體的業務邏輯。

4)數據層。我們在實現某個應用時可能需要訪問數據,可以是數據庫或者是文件。如果是簡單應用,可能沒有這一層。

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

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

根據流程圖,我們能夠清晰的了解整個流程,消息處理的具體實現步驟。

下面我們針對流程進行代碼實現。

具體實現

 

一、接收HTTP請求

 此處我是以MVC做演示,新建了一個MVC項目,右鍵新建一個一般應用程序,如下圖所示

一般應用程序里面代碼:

    public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            //context.Response.Write("Hello World");

            //由微信服務接收請求,具體處理請求
            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();

        }

二、分發請求

為了能功能封裝,我們也將此封裝在了處理組件中。其實可以放置在一般應用程序中處理的。 

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

處理請求的對外方法(一般應用程序中調用的方法就是這個了),即:

/// <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 "無法處理";
            }
        }

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

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 = "歡迎您關注我們,我是服務小二。有事兒您說話~";
                response = tm.GenerateContent();
            }
            return response;
        }
    }

消息推送

當普通微信用戶向公眾賬號發消息時,微信服務器將POST該消息到填寫的URL上。結構如下

文本消息

 <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位整型

圖片消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[image]]></MsgType>
 <PicUrl><![CDATA[this is a url]]></PicUrl>
 <MsgId>1234567890123456</MsgId>
 </xml>
參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType image
PicUrl 圖片鏈接
MsgId 消息id,64位整型

地理位置消息

<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位整型

鏈接消息

<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位整型

事件推送

事件推送只支持微信4.5版本,目前開啟自定義菜單接口事件推送、關注與取消關注事件推送。其余功能即將開放,敬請期待。

<xml><ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[EVENT]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>
參數 描述
ToUserName 接收方微信號
FromUserName 發送方微信號,若為普通用戶,則是一個OpenID
CreateTime 消息創建時間
MsgType 消息類型,event
Event 事件類型,subscribe(訂閱)、unsubscribe(取消訂閱)、CLICK(自定義菜單點擊事件)
EventKey 事件KEY值,與自定義菜單接口中KEY值對應

消息回復

對於每一個POST請求,開發者在響應包中返回特定xml結構,對該消息進行響應(現支持回復文本、圖文、語音、視頻、音樂)。

微信服務器在五秒內收不到響應會斷掉連接。

回復xml結構如下:

回復文本消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>12345678</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[content]]></Content>
 </xml>
參數 描述
ToUserName 接收方帳號(收到的OpenID)
FromUserName 開發者微信號
CreateTime 消息創建時間
MsgType text
Content 回復的消息內容,長度不超過2048字節

回復音樂消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>12345678</CreateTime>
 <MsgType><![CDATA[music]]></MsgType>
 <Music>
 <Title><![CDATA[TITLE]]></Title>
 <Description><![CDATA[DESCRIPTION]]></Description>
 <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
 <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
 </Music>
 </xml>
參數 描述
ToUserName 接收方帳號(收到的OpenID)
FromUserName 開發者微信號
CreateTime 消息創建時間
MsgType music
MusicUrl 音樂鏈接
HQMusicUrl 高質量音樂鏈接,WIFI環境優先使用該鏈接播放音樂

回復圖文消息

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>12345678</CreateTime>
 <MsgType><![CDATA[news]]></MsgType>
 <ArticleCount>2</ArticleCount>
 <Articles>
 <item>
 <Title><![CDATA[title1]]></Title> 
 <Description><![CDATA[description1]]></Description>
 <PicUrl><![CDATA[picurl]]></PicUrl>
 <Url><![CDATA[url]]></Url>
 </item>
 <item>
 <Title><![CDATA[title]]></Title>
 <Description><![CDATA[description]]></Description>
 <PicUrl><![CDATA[picurl]]></PicUrl>
 <Url><![CDATA[url]]></Url>
 </item>
 </Articles>
 </xml> 
參數 描述
ToUserName 接收方帳號(收到的OpenID)
FromUserName 開發者微信號
CreateTime 消息創建時間
MsgType news
ArticleCount 圖文消息個數,限制為10條以內
Articles 多條圖文消息信息,默認第一個item為大圖
Title 圖文消息標題
Description 圖文消息描述
PicUrl 圖片鏈接,支持JPG、PNG格式,較好的效果為大圖640*320,小圖80*80。
Url 點擊圖文消息跳轉鏈接

更多詳細內容請參考官網開發文檔:官方開發文檔

 最終效果

當新用戶關注的時候,首先會收到Http請求,之后根據上文中提到的相關步驟即可完成操作,對於調試操作可參考第一篇文章:微信公眾號開發之VS遠程調試

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 下一篇我們將介紹如何自定義文本消息回復和自定義菜單欄,敬請期待吧~

注:文章部分內容截取至:http://www.cnblogs.com/yank/p/3406308.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM