【C#版本】微信公眾號模板消息對接(一)(圖文詳解)


特此說明:本篇文章為個人原創文章,創作不易,未經作者本人同意、許可等條件,不得以任何形式搬運、轉載、抄襲(等包括但不限於此手段)本文章,否則保留追究有關侵權人責任的權利

一、認識微信公眾號模板消息

什么是微信公眾號模板消息呢?我們先看微信官方是怎么定義的:

模板消息僅用於公眾號向用戶發送重要的服務通知,只能用於符合其要求的服務場景中,如信用卡刷卡通知,商品購買成功通知等。不支持廣告等營銷類消息以及其它所有可能對用戶造成騷擾的消息。

以上定義對於普通人來說可能沒有什么概念,下面就列舉我們生活中觸手可及的微信公眾號模板消息的使用場景——豐巢快遞櫃。

大多數人都經歷過網購,購買的商品在最后環節由快遞員進行投遞時因為種種原因,快遞小哥有時會將商品放入豐巢快遞櫃。在商品進入豐巢快遞櫃且快遞小哥關閉櫃門后,豐巢公眾號(假設此時你已經關注了該公眾號)會向你推送一條快遞取件消息提醒,而這條消息本身就是我們要講的微信公眾號模板消息。如下圖所示:

二、接口測試號申請

由於用戶體驗和安全性方面的考慮,微信公眾號的注冊有一定門檻,某些高級接口的權限需要微信認證后才可以獲取。

所以,為了幫助開發者快速了解和上手微信公眾號開發,熟悉各個接口的調用,微信官方推出了微信公眾帳號測試號,通過手機微信掃描二維碼即可獲得測試號。

本篇(系列)文章的所有介紹內容,也將基於微信公眾賬號測試號進行講解,正式賬號與測試賬號的流程操作等相差無幾甚至有的一模一樣,不通之處可以進行類比參考。

進入微信公眾帳號測試號申請系統。如下圖所示:

點擊中間的登錄按鈕,打開微信APP,通過微信tab右上角的掃一掃登錄,登錄后的界面如下圖所示:

三、關注/取消關注公眾號事件

在微信用戶和公眾號產生交互的過程中,用戶的某些操作會使得微信服務器通過事件推送的形式通知到開發者在開發者中心處設置的服務器地址,從而開發者可以獲取到該信息。其中,某些事件推送在發生后,是允許開發者回復用戶的,某些則不允許。目錄如下:

  1. 關注/取消關注事件
  2. 掃描帶參數二維碼事件
  3. 上報地理位置事件
  4. 自定義菜單事件
  5. 點擊菜單拉取消息時的事件推送
  6. 點擊菜單跳轉鏈接時的事件推送

我們目前需要用到【關注/取消關注事件】,該事件有極大的使用用途。

用戶在關注與取消關注公眾號時,微信會把這個事件推送到開發者填寫的URL。方便開發者給用戶下發歡迎消息或者做帳號的解綁。為保護用戶數據隱私,開發者收到用戶取消關注事件時需要刪除該用戶的所有信息。

上面提到一個URL關鍵詞,這是非常重要的一個環節,在以后的開發中有着極為重要的用途。下面教大家如何填寫URL。接入指南概述。

第一步:了解需要填寫的信息

在【測試號管理】頁面找到【接口配置信息】一欄,如下圖:

因為我之前填寫過,所以這里有填寫好的信息展示。如果是第一次填寫,此處內容為空白。下面解釋需要填寫的信息名詞及作用:

1、URL:是開發者用來接收微信消息和事件的接口URL。

  • 目前該URL的請求方式為:GET。(后期需要改為POST,后面會有介紹)
  • 該URL作用:處理/響應微信發送的事件信息。
  • 該URL必須能在公網直接訪問並響應消息,且不需要任何權限驗證。
  • 該URL訪問端口需為80端口(公眾平台接口調用僅支持80端口)或者443端口
  • 該URL一種可能示例:http://{域名}:80/api/WX

2、Token:可由開發者可以任意填寫,用作生成簽名。(該Token會和接口URL中包含的Token進行比對,從而驗證安全性)

3、EncodingAESKey(測試賬號無需填寫):由開發者手動填寫或隨機生成,將用作消息體加解密密鑰。

4、消息加解密方式:此項內容在該處不多加闡述,有興趣的小伙伴可自行上網尋找相關資料了解。

第二步:了解微信服務器發起的請求並如何進行相應

當開發者提交URL等信息后,微信服務器將發送GET請求到填寫的服務器地址URL上,GET請求攜帶參數如下表所示:

參數 描述
signature 微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。
echostr 隨機字符串
timestamp 時間戳
nonce 隨機數

微信服務器某次發起的真實請求示例如下:

http://{域名}:80/api/WX?signature=169fadc3ce1cee923c5089c2a6be71843f0e2484&echostr=8343114011812817647&timestamp=1646381291&nonce=496537975

開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成為開發者成功,否則接入失敗。

加密/校驗流程如下:

  1. 將token、timestamp、nonce三個參數進行字典序排序
  2. 將三個參數字符串拼接成一個字符串進行sha1加密
  3. 開發者獲得加密后的字符串可與signature對比,標識該請求來源於微信

第三步:開發URL接口

直接貼上我寫的代碼如下:

public class WXController : Controller
{
    [HttpGet]
    [AllowAnonymous]
    public string Index([FromQuery] WXIndexInput input)
    {
        return input.echostr;
    }
}

Dto類WXIndexInput如下:

public class WXIndexInput
{
    public string signature { get; set; }
    
    public string echostr { get; set; }
    
    public long timestamp { get; set; }
    
    public long nonce { get; set; }
}

上述代碼開發完成后發布到公網服務器,並自測能成功訪問並響應數據。

第四步:填寫URL

  1. 在【測試號管理】頁面找到【接口配置信息】一欄,並點擊旁邊的【修改】按鈕,參見第一步中的圖片。
  2. 在URL輸入框中填寫第三步中開發的URL接口地址,如:http://{域名}:80/api/WX
  3. 在Token輸入框中填寫你自定義的Token值。
  4. 最后點擊提交按鈕,頁面彈出【配置成功】提示框,如下圖。
  5. URL配置項到此全部結束。如彈出其他錯誤信息,請小伙伴們查閱資料自行解決。

 

第五步:了解用戶關注/取消關注公眾號時微信服務器發起的事件請求

前面我們說到,用戶在關注與取消關注公眾號時,微信會把這個事件推送到開發者填寫的URL(也就是我們第三步中開發的URL接口,此時請求方式為POST,后面我們將對該接口進行改造)。方便開發者給用戶下發歡迎消息或者做帳號的解綁。為保護用戶數據隱私,開發者收到用戶取消關注事件時需要刪除該用戶的所有信息。微信服務器在五秒內收不到響應會斷掉連接,並且重新發起請求,總共重試三次。關於重試的消息排重,推薦使用FromUserName + CreateTime 排重。假如服務器無法保證在五秒內處理並回復,可以直接回復空串,微信服務器不會對此作任何處理,並且不會發起重試。

那么微信官方發起的事件請求是什么樣式的呢?下面將進行詳細的講解。

  • 微信官方服務器在用戶關注/取消關注公眾號時發起的事件請求的Content-Type為application/xml類型。參見如下形式:
<xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[FromUser]]></FromUserName>
    <CreateTime>123456789</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
</xml>

1、關注公眾號

  • 微信服務器發起的一次用戶關注公眾號的請求URL如下:
http://{域名}:80/api/WX?signature=33345f994ce4965279ac47e0f510ad395e6efaa1&timestamp=1646391249&nonce=1845667659&openid=oLrmn5rh9480z38etS-YMCDD-cwc
  • 微信服務器發起的一次用戶關注公眾號的xml請求體如下:
<xml>
    <ToUserName><![CDATA[gh_df27052ba1f3]]></ToUserName>
    <FromUserName><![CDATA[oLrmn5rh9480z38etS-YMCDD-cwc]]></FromUserName>
    <CreateTime>1646391249</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
</xml>

2、取消關注公眾號

  • 微信服務器發起的一次用戶取消關注公眾號的請求URL如下:
http://{域名}:80/api/WX?signature=c9223edc3e32dbed9115049d77f16e49ef5e3583&timestamp=1646391279&nonce=1449911721&openid=oLrmn5rh9480z38etS-YMCDD-cwc
  • 微信服務器發起的一次用戶取消關注公眾號的xml請求體如下:
<xml>
    <ToUserName><![CDATA[gh_df27052ba1f3]]></ToUserName>
    <FromUserName><![CDATA[oLrmn5rh9480z38etS-YMCDD-cwc]]></FromUserName>
    <CreateTime>1646391279</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[unsubscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
</xml>

參數說明如下表:

參數 描述
ToUserName 開發者微信號
FromUserName 發送方帳號(一個OpenID)
CreateTime 消息創建時間 (整型)
MsgType 消息類型,event
Event 事件類型,subscribe(訂閱)、unsubscribe(取消訂閱)

 第六步:改造URL接口

通過第五步真實的微信服務器發起的請求實例發現,原先第三步開發的URL接口已經無法滿足現有的需求了。

接下來,我們將保留原接口輸入輸出不變的情況下對原接口進行重寫,以滿足現在的需求功能。

重寫后的代碼如下所示:

public class WXController : Controller
{
    [HttpPost]
    [AllowAnonymous]
    [Produces("application/xml")]
    public string Index([FromQuery] WXIndexInput input)
    {
        var httpRequestBody = HttpContext.Request.Body;//獲取請求體
        XmlDocument xmlDoc = new XmlDocument();//初始化一個XmlDocument實例
        xmlDoc.Load(httpRequestBody);//從請求體流中載入xml
        var node = xmlDoc.SelectSingleNode("xml");//選擇與XPath表達式匹配的第一個XmlNode。
        var entityModel = new WXSubOrNotXmlEntityModel();//WXSubOrNotXmlEntityModel類的屬性與Http請求體的xml節點一一對應
        foreach (var item in node.ChildNodes)//遍歷xml節點的子節點
        {
            var xe = (XmlElement)item;//將子節點轉換成xml元素
            var p = entityModel.GetType().GetProperty(xe.Name);//獲取WXSubOrNotXmlEntityModel類實例與xml元素名稱相同的屬性
            if (p != null)
            {
                var text = xe.InnerText;//獲取xml元素節點的文本值【string類型】
                var pName = p.PropertyType.Name;//獲取p屬性的數據類型
                if (pName == typeof(long).Name)//如果p屬性的數據類型為long
                {
                    var textLongType = long.Parse(text);//將xml元素節點的文本值【string類型】轉換成long類型
                    p.SetValue(entityModel, textLongType);//給p屬性賦值為xml元素節點的文本值
                }
                else
                {
                    p.SetValue(entityModel, text);//給p屬性賦值為xml元素節點的文本值
                }
            }
        }
        //至此,entityModel實例已被全部賦值為相同xml節點名稱中的文本值,用此實例中的屬性值就可以進行接下開的業務邏輯開發……
        //比如,當判斷事件是用戶取消關注公眾號,則刪除用戶在關注后綁定或者其他業務邏輯產生的綁定數據關系……
        //……
        return input.echostr;
    }
}

Dto類WXIndexInput如下:

public class WXIndexInput
{
    public string signature { get; set; }
    
    public string echostr { get; set; }
    
    public long timestamp { get; set; }
    
    public long nonce { get; set; }
    
    public string openid { get; set; }
}

上述代碼修改完成后發布到公網服務器,並自測能成功訪問並響應數據。

第七步:測試用戶關注/取消關注公眾號時URL接口是否被成功調起

在【測試號管理】頁面中找到【測試號二維碼】一欄,如下圖所示:

掃描圖中二維碼關注/取消關注公眾號,查看該方法被調用的系統日志,即可知道該方法是否被成功調起。

如果方法未被成功調起,請小伙伴自行排查並解決問題,直到該方法被成功調起為止,否則影響后面業務邏輯的進行。

至此,關於用戶關注/取消關注公眾號事件的講解到此結束。

本篇文章未完待續……

文章后續正在創作中,敬請期待……

 

 

 

 


免責聲明!

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



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