微信公衆號開發系列-二、微信公衆平臺接入指南

file

概述

微信公衆平臺消息接口的工做原理大概能夠這樣理解:從用戶端到公衆號端一個流程是這樣的,用戶發送消息到微信服務器,微信服務器將接收到的消息post到用戶接入時填寫的url中,在url處理程序中,首先判斷消息的合法性,判斷成功後根據消息體的內容作相應的處理。原理很容易理解,接觸過socket的可能理解起來更容易。對於微信開發者模式的接入官網文檔很是的簡潔,對於初學者不少都摸不着頭腦,微信官方技術文檔的接入指南能夠參考接入指南 大體步驟就是:git

  1. 填寫服務器配置
  2. 驗證服務器地址的有效性
  3. 依據接口文檔實現業務邏輯

準備工做

要接入微信,首先咱們須要一個微信公衆號,相信作微信公衆號開發的朋友都會遇到這樣的問題,就是微信公衆號提供的接口權限問題。若是是我的訂閱號,官方提供的接口不多,不少接口都不能用。若是想測試接口功能怎麼辦?其實,微信公衆號官方給咱們提供一個微信公衆測試號,測試號除了不能用微信支付接口,其餘接口基本均可以用獲取而且可使用。下面我就教你們如何申請微信公衆號測試號。全微信掃一掃公衆平臺測試帳號系統登陸便可,很是的方便。微信公衆平臺測試帳號系統地址:公衆平臺測試帳號系統登陸後咱們就能夠輕鬆愉快的進行下面的玩耍了。對於常規的微信公衆號接入方式與測試公衆號大同小異,這兒成功了其餘的相似。github

填寫服務器配置與驗證消息的確來自微信服務器

  • 填寫服務器配置

在填寫服務器配置以前咱們須要瞭解一下微信與咱們的服務器交互的過程:算法

當咱們在微信app上,給公衆號發送一條消息時,這條消息其實是發送到了微信的服務器上,此時微信的服務器就會對消息進行封裝成某種格式的數據好比xml格式,再轉發到咱們配置好的URL上,因此該URL實際就是咱們處理數據的一個請求路徑。所以該URL必須是能暴露給外界訪問的一個公網地址,不能使用內網地址,生產環境能夠申請騰訊雲,阿里雲服務器等,但在開發環境中可暫時利用一些軟件來完成內網穿透以便於修改和測試,如NATAPP,花生殼等軟件,使用起來也很方便,在本地安裝對應的軟件,配置運行後,直接使用軟件分配的臨時域名來訪問本地應用便可,只是偶爾會存在網絡不穩定的狀況,具體的外網映射工具與調試的方法後面的文章咱們會接受。編程

微信與咱們的服務器交互的過程

有了這樣一個基本的概念後,咱們看下接口配置信息相關的說明。瀏覽器

接口配置以下圖所示:安全

接口配置

對於測試號信息中的appid與appsecret兩個屬性是惟一的標識,每一個測試號都會有本身的appid與appsecret ,是比較重要的信息,不要隨意發給別人。服務器

  1. appid:是公衆號開發識別碼,配合開發者密碼可調用公衆號的接口能力。
  2. appsecret:是校驗公衆號開發者身份的密碼,具備極高的安全性。

服務器地址URL是開發者用來接收微信消息和事件的接口URL,是咱們服務器的響應微信請求的地址。 假設咱們本身的服務器域名是www.rdiframework.net,準備用/WeiXin/WeChat/來接收消息,就填寫: www.rdiframework.net/WeiXin/WeCh…微信

Token能夠任意填寫,爲了安全性和防止黑客攻擊建議設置得複雜一些,並要防止泄露。 測試號通常只須要填寫URL與Token兩項內容,真實項目的填寫還要填寫EncodingAESKey,能夠由開發者手動填寫或隨機生成,將用做消息體加解密密鑰。 開發者還可選擇消息加解密方式:明文模式、兼容模式和安全模式,具體可參看開發者文檔。網絡

另請注意,微信公衆號接口地址必須以http://或https://開頭,分別支持80端口和443端口。微信開發

  • 驗證消息的確來自微信服務器

當咱們填入url與token的值,並提交後,微信會發送一個get請求到咱們填寫的url上,而且攜帶4個參數,而signature參數結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數來作的加密簽名,咱們在後臺須要對該簽名進行校驗,看是否合法。實際上,咱們發現微信帶過來的4個參數中並無帶token參數,僅有signature是和token有關的,因此咱們應該在本地應用中也準備一個和填入的token相同的參數,再經過微信傳入的timestamp與nonce作相同算法的加密操做,若結果與微信傳入的signature相同,即爲合法,則原樣返回echostr參數,表明接入成功,不然不作處理,則接入失敗。

詳細流程可參考微信官方提供的邏輯流程圖,咱們的應用須要以該流程圖的步驟來實現。

邏輯流程圖

下面爲咱們以.NET MVC代碼實現get請求樣例代碼,可供參考:

[HttpGet]
[ActionName("Index")]
public Task<ActionResult> Get(string signature, string timestamp, string nonce, string echostr)
{       
    return Task.Factory.StartNew(() =>
    {

        if (CheckSignature.Check(signature, timestamp, nonce, "WeiXinToken"))
        {
            return echostr; //返回隨機字符串則表示驗證經過
        }
        else
        {
            return "failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, weixinOfficialAccountEntity.Token) + "。" + "若是你在瀏覽器中看到這句話,說明此地址能夠被做爲微信公衆帳號後臺的Url,請注意保持Token一致。";
        }
    }).ContinueWith<ActionResult>(task => Content(task.Result));
}
複製代碼

上面的代碼注意token不是微信服務器發過來的,而是咱們本身寫死的一個常量,就是在微信後臺填寫的Token,這兒我填寫的是:WeiXinToken

依據接口文檔實現業務邏輯

驗證URL有效性成功後咱們就能夠接收來自微信的數據,並對接收到的數據按需作相應的業務處理。用戶每次向公衆號發送消息、或者產生自定義菜單、或產生微信支付訂單等狀況時,開發者填寫的服務器配置URL將獲得微信服務器推送過來的消息和事件,開發者能夠依據自身業務邏輯進行響應,如回覆消息。

公衆號調用各接口時,通常會得到正確的結果,具體結果可見對應接口的說明。返回錯誤時,可根據返回碼來查詢錯誤緣由。全局返回碼說明

微信後臺發送消息是一個POST請求,但和普通的POST請求不一樣的是,首先,URL會帶上signature、timestamp、nonce這3個參數:

POST http://www.rdiframework.net/WeiXin/WeChat/?signature=xxx&timestamp=123456&nonce=123
複製代碼

而後,HTTP請求的BODY是一個不規範的XML:

<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>
複製代碼

咱們本身的服務器只須要處理該XML,而後,向微信返回一個相似以下的XML:

<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName>
    <CreateTime>12345678</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[你好]]></Content>
</xml>
複製代碼

就能夠完成消息的回覆。微信後臺要求必須在5秒內回覆,最多重試3次,不然咱們本身的回覆消息就到達不了用戶的手機了。若是咱們本身的服務器沒法在5秒內回覆,就回復一個空字符串,告訴微信服務器,不用重試了,這個消息處理不了,不給用戶回覆了。

上面的交互邏輯看起來很簡單,但實際上坑有不少。

首先,微信服務器發送的POST請求根本就不符合HTTP規範。原則上POST請求不該該在URL上附帶參數,但微信後臺恰恰要這麼幹,這就讓不少編程語言的標準框架沒法獲取到POST參數,由於標準的POST參數是從HTTP BODY中解析的。因此從POST獲取URL參數就須要用到更底層的代碼。如今不管作什麼都講究的是效率,什麼東西有現成的咱們就不須要去重複的造輪子,直接拿來使用便可。在.net下微信開發咱們推薦使用開源的SENPARC.WEIXIN SDK,這個sdk基本完成了微信全系列的操做功能,使用的客戶多,一直在升級中,可放心使用。簡單的幾行代碼就能夠實現一個功能,何樂而不爲呢。 接收微信的請求代碼參考:

[HttpPost]
[ActionName("Index")]
public Task<ActionResult> Post(PostModel postModel)
{
    return Task.Factory.StartNew<ActionResult>(() =>
    {           
        if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, "WeiXinToken"))
        {
            return new WeixinResult("參數錯誤!");
        }
        postModel.Token = "****Token***";
        postModel.EncodingAESKey = "***EncodingAESKey***"; //根據本身後臺的設置保持一致
        postModel.AppId = "****AppId***"; //根據本身後臺的設置保持一致
		
		//自定義MessageHandler,對微信請求的詳細判斷操做都在這裏面。
        var messageHandler = new CustomMessageHandler(Request.InputStream, postModel,10);

        messageHandler.Execute(); //執行微信處理過程

        return new FixWeixinBugWeixinResult(messageHandler);

    }).ContinueWith<ActionResult>(task => task.Result);
}
複製代碼

吐槽:微信和微信公衆平臺雖然產品很先進,但後臺API設計得確實不咋地。因爲API是給開發人員使用的,因此,設計一個好的API要從開發人員的角度出發。與其使用笨重的XML,不如使用更符合Web潮流的JSON。 例如驗證服務器:

{
    "signature": "xxx",
    "timestamp": 123456,
    "nonce": "xxx",
    "action": "verify",
    "data": {
        "echostr": "echo"
    }
}
複製代碼

這樣設計的API,各類編程語言都能處理,並且處理邏輯更簡單,速度更快。

參考文章

微信公衆平臺技術文檔-官方

Senparc.Weixin SDK + 官網示例源代碼

RDIFramework.NET — 基於.NET的快速信息化系統開發框架 — 系列目錄

RDIFramework.NET ━ .NET快速信息化系統開發框架 ━ 工做流程組件介紹

RDIFramework.NET框架SOA解決方案(集Windows服務、WinForm形式與IIS形式發佈)-分佈式應用

RDIFramework.NET代碼生成器全新V3.5版本發佈-重大升級


一路走來數個年頭,感謝RDIFramework.NET框架的支持者與使用者,你們能夠經過下面的地址瞭解詳情。

RDIFramework.NET官方網站:www.rdiframework.net/

RDIFramework.NET官方博客:blog.rdiframework.net/

同時須要說明的,之後的全部技術文章以官方網站爲準,歡迎你們收藏!

RDIFramework.NET框架由專業團隊長期打造、一直在更新、一直在升級,請放心使用!

歡迎關注RDIFramework.net框架官方公衆微信(微信號:guosisoft),及時瞭解最新動態。

掃描二維碼當即關注

file
相關文章
相關標籤/搜索