微信公眾號開發C#系列-2、微信公眾平台接入指南


概述

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

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

准備工作

要接入微信,首先我們需要一個微信公眾號,相信做微信公眾號開發的朋友都會遇到這樣的問題,就是微信公眾號提供的接口權限問題。如果是個人訂閱號,官方提供的接口很少,很多接口都不能用。如果想測試接口功能怎么辦?其實,微信公眾號官方給我們提供一個微信公眾測試號,測試號除了不能用微信支付接口,其他接口基本都可以用獲取並且可以使用。下面我就教大家如何申請微信公眾號測試號。全微信掃一掃公眾平台測試賬號系統登錄即可,非常的方便。微信公眾平台測試賬號系統地址:公眾平台測試賬號系統登錄后我們就可以輕松愉快的進行下面的玩耍了。對於常規的微信公眾號接入方式與測試公眾號大同小異,這兒成功了其他的類似。

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

  • 填寫服務器配置

在填寫服務器配置之前我們需要了解一下微信與我們的服務器交互的過程:

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

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

有了這樣一個基本的概念后,我們看下接口配置信息相關的說明。

接口配置如下圖所示:

接口配置

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

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

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

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官方網站:http://www.rdiframework.net/

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

同時需要說明的,以后的所有技術文章以官方網站為准,歡迎大家收藏!

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

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

掃描二維碼立即關注

微信號:guosisoft


免責聲明!

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



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