C#開發微信門戶及應用(29)--微信個性化菜單的實現

有一段時間沒有接着微信的主題繼續介紹裏面的功能模塊了,這段時間來,微信也作了很多的變化改動,針對這些特性我全面覈對了一下相關的微信公衆號和企業號的接口,對原有的微信API和系統管理作了全面的更新,本隨筆以及後面的隨筆就是基於這個工做上的總結,以期把微信涉及的功能模塊,都使用C#實現的方式來介紹。本隨筆主要介紹微信公衆號的個性化菜單的實現,雖然目前微信公衆號和企業號已經在功能上接近一致,不過在企業號上尚未個性化菜單的相關接口。html

一、個性化菜單介紹

咱們先了解一下個性化菜單的介紹,根據官方的資料,以下介紹。api

爲了幫助公衆號實現靈活的業務運營,微信公衆平臺新增了個性化菜單接口,開發者能夠經過該接口,讓公衆號的不一樣用戶羣體看到不同的自定義菜單。該接口開放給已認證訂閱號和已認證服務號。數組

開發者能夠經過如下條件來設置用戶看到的菜單:安全

一、用戶分組(開發者的業務需求能夠藉助用戶分組來完成)
二、性別
三、手機操做系統
四、地區(用戶在微信客戶端設置的地區)
五、語言(用戶在微信客戶端設置的語言)

個性化菜單接口說明:服務器

一、個性化菜單要求用戶的微信客戶端版本在iPhone6.2.2,Android 6.2.4以上。
二、菜單的刷新策略是,在用戶進入公衆號會話頁或公衆號profile頁時,若是發現上一次拉取菜單的請求在5分鐘之前,就會拉取一下菜單,若是菜單有更新,就會刷新客戶端的菜單。測試時能夠嘗試取消關注公衆帳號後再次關注,則能夠看到建立後的效果。
三、普通公衆號的個性化菜單的新增接口每日限制次數爲2000次,刪除接口也是2000次,測試個性化菜單匹配結果接口爲20000次
四、出於安全考慮,一個公衆號的全部個性化菜單,最多隻能設置爲跳轉到3個域名下的連接
五、建立個性化菜單以前必須先建立默認菜單(默認菜單是指使用普通自定義菜單建立接口建立的菜單)。若是刪除默認菜單,個性化菜單也會所有刪除

個性化菜單匹配規則說明:微信

當公衆號建立多個個性化菜單時,將按照發布順序,由新到舊逐一匹配,直到用戶信息與matchrule相符合。若是所有個性化菜單都沒有匹配成功,則返回默認菜單。
例如公衆號前後發佈了默認菜單,個性化菜單1,個性化菜單2,個性化菜單3。那麼當用戶進入公衆號頁面時,將從個性化菜單3開始匹配,若是個性化菜單3匹配成功,則直接返回個性化菜單3,不然繼續嘗試匹配個性化菜單2,直到成功匹配到一個菜單。
根據上述匹配規則,爲了不菜單生效時間的混淆,決定不予提供個性化菜單編輯API,開發者須要更新菜單時,需將完整配置從新發布一輪。

除正常的默認菜單外,個性化菜單提供了下面幾個處理操做。數據結構

1 建立個性化菜單微信公衆平臺

2 刪除個性化菜單post

3 測試個性化菜單匹配結果測試

4 查詢個性化菜單

5 刪除全部菜單

個性化自定義菜單功能,是指商家能夠根據粉絲的分組、性別、手機操做系統,甚至地區,來分別展現公衆號的菜單。

好比,一家健身會所的公衆號,將自定義菜單根據粉絲性別進行了分開設置。男性粉絲進入公衆號會展現男生們比較感興趣菜單內容,跆拳道、搏擊等;如果女性粉絲,則會展現瑜伽、舞蹈、防身術等女性粉絲感興趣的菜單課程等。

 

二、個性化菜單的C#設計處理

微信的菜單是微信處理中很重要的一環,由於它是微信給用戶入口體驗重要的一環,也是很直觀的界面呈現之一,菜單的展現就是須要咱們絞盡腦汁來精簡的界面元素了,因爲菜單的重要性以及功能的豐富性,我在以前好幾篇隨筆專門介紹了菜單的各類處理。

在《C#開發微信門戶及應用(6)--微信門戶菜單的管理操做》、《C#開發微信門戶及應用(9)-微信門戶菜單管理及提交到微信服務器》、《C#開發微信門戶及應用(11)--微信菜單的多種表現方式介紹》、《C#開發微信門戶及應用(20)-微信企業號的菜單管理》分別對相關的菜單有過介紹,有須要能夠參考瞭解一下。

菜單模塊,在微信公衆號和企業號,它們均可以共用一個模型,所以咱們把這些內容都放在微信共用模塊裏面,包括它的實體類信息(如菜單模塊),雖然有些地方,部分字段內容沒有,可是咱們能夠經過實體類的JSON標識來進行處理,從而實現比較彈性化的實體類信息承載。

以下標識代碼所示。

    /// <summary>
    /// 菜單基本信息(公衆號、企業號公用,其餘部分同樣)
    /// </summary>
    public class MenuJson : BaseJsonResult
    {
        /// <summary>
        /// 按鈕描述,既按鈕名字,不超過16個字節,子菜單不超過40個字節
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 按鈕類型(click或view)
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string type { get; set; }

        /// <summary>
        /// 按鈕KEY值,用於消息接口(event類型)推送,不超過128字節
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string key { get; set; }

        /// <summary>
        /// 網頁連接,用戶點擊按鈕可打開連接,不超過256字節
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string url { get; set; }

        /// <summary>
        /// media_id類型和view_limited類型必須,調用新增永久素材接口返回的合法media_id
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string media_id { get; set; }

        /// <summary>
        /// 子按鈕數組,按鈕個數應爲2~5個
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public List<MenuJson> sub_button { get; set; }

上面這個實體類是菜單信息的基礎信息,咱們須要從這個基礎上擴展出來幾個實體類,方便在構建,獲取菜單信息的時候進行信息轉換,以下幾個類圖的設計所示。

經過這幾個類的關係,咱們就能夠適應全部的默認菜單和個性化菜單,以及企業號的菜單信息轉換處理了,經過JSON轉換爲對應的實體類,實現信息的強類型處理。

其中咱們菜單處理的API實現類代碼以下所示。

    /// <summary>
    /// 菜單的相關操做
    /// </summary>
    public class MenuApi : IMenuApi

這樣咱們在IMenuApi的基礎上增長几個個性化的接口。

        /// <summary>
        /// 建立個性化菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuJson">菜單對象</param>
        /// <returns></returns>
        string CreateConditionalMenu(string accessToken, MenuListJson menuJson);

        /// <summary>
        /// 根據菜單ID刪除個性化菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuid">菜單ID</param>
        /// <returns></returns>
        CommonResult DeleteConditionalMenu(string accessToken, string menuid);

        /// <summary>
        /// 測試個性化菜單匹配結果
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <returns></returns>
        MenuListJson TryMatchConditionalMenu(string accessToken, string user_id);

而後在MenuApi實現類裏面實現相關的邏輯處理便可。

下面是建立個性化菜單的接口說明。

建立個性化菜單

http請求方式:POST(請使用https協議)

https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN

請求示例

{
 	"button":[
 	{	
    	"type":"click",
    	"name":"今日歌曲",
     	"key":"V1001_TODAY_MUSIC" 
	},
	{ 
		"name":"菜單",
		"sub_button":[
		{	
			"type":"view",
			"name":"搜索",
			"url":"http://www.soso.com/"
		},
		{
			"type":"view",
			"name":"視頻",
			"url":"http://v.qq.com/"
		},
		{
			"type":"click",
			"name":"贊一下咱們",
			"key":"V1001_GOOD"
		}]
 }],
"matchrule":{
  "group_id":"2",
  "sex":"1",
  "country":"中國",
  "province":"廣東",
  "city":"廣州",
  "client_platform_type":"2"
  "language":"zh_CN"
  }
}

其中上面的信息,轉換爲咱們的實體類對象信息就是以下所示。

MenuListJson menuJson

它API返回結果以下所示。

{
	"menuid":"208379533"
}

爲了承載這個信息,咱們須要定義一個實體類來承載這個信息。

    /// <summary>
    /// 返回MenuId的結果
    /// </summary>
    public class MenuIdResult
    {       
        /// <summary>
        /// 菜單的ID
        /// </summary>
        public string menuid { get; set; }
    }

最後咱們的API接口只須要獲取裏面的菜單ID值,字符串類型的就能夠了,API具體實現代碼以下所示。

        /// <summary>
        /// 建立個性化菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuJson">菜單對象</param>
        /// <returns></returns>
        public string CreateConditionalMenu(string accessToken, MenuListJson menuJson)
        {
            string result = "";
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token={0}", accessToken);
            //matchrule不能爲空
            ArgumentValidation.CheckForNullReference(menuJson.matchrule, "matchrule");

            string postData = menuJson.ToJson();
            MenuIdResult list = JsonHelper<MenuIdResult>.ConvertJson(url, postData);
            if (list != null)
            {
                result = list.menuid;
            }
            return result;
        }

而刪除個性化菜單的接口也是相似的處理,以下所示。

        /// <summary>
        /// 根據菜單ID刪除個性化菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuid">菜單ID</param>
        /// <returns></returns>
        public CommonResult DeleteConditionalMenu(string accessToken, string menuid)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token={0}", accessToken);
            var data = new
            {
                menuid = menuid
            };

            string postData = data.ToJson();
            return Helper.GetExecuteResult(url, postData);
        }

另外,對於個性化菜單來講,查詢、刪除全部的菜單操做接口和普通默認菜單是同樣的,所以能夠重用這兩個接口,不過因爲咱們擴展了查詢返回的信息類,因此若是是個性化菜單,那麼它返回的JSON字符串裏面,包含了conditionalmenu的屬性,這個是一個集合 ,也就是說個性化菜單是多個規則的個性化菜單的集合。

菜單的JSON數據結構以下所示。

 

三、個性化菜單封裝接口的使用

有了上面接口的封裝,咱們能夠在建立個性化菜單的時候很方便了,構建個性化菜單的時候,咱們須要把所有須要出現的菜單都須要放在一個conditionalmenu的單元裏面,雖然這樣的單元在集合裏面出現多個。

以下面是構建一個個性化的菜單項目,和普通的默認菜單不一樣,它須要指定一個matchrule的對象,以下代碼所示。

            MenuJson conditional = new MenuJson("相關連接", new MenuJson[] { 
                new MenuJson("個性化菜單", ButtonType.click, "event_company")
            });
            MatchRule rule = new MatchRule()
            {
                sex = "1"
            };

            MenuListJson menuJson = new MenuListJson();
            menuJson.button.AddRange(new MenuJson[] { conditional });
            menuJson.matchrule = rule;

經過上面的代碼瞭解,咱們若是須要增長多個個性化菜單,那麼就是經過這個方法,每次建立一個個性化菜單的方式進行構建,固然若是咱們使用查詢個性化菜單的結果能夠看到,若是建立多個,那麼conditionalmenu集合裏面是多個對象的。

調用代碼每次添加一個個性化菜單的操做以下所示。

                string menuid = menuBLL.CreateConditionalMenu(token, menuJson);
                Console.WriteLine("建立菜單:" + (!string.IsNullOrEmpty(menuid) ? "成功:" + menuid : "失敗"));

咱們建立多個規則後,能夠經過TryMatch的方式來檢查匹配的結果,也就是對應不一樣用戶(openid)會出現不一樣的個性化菜單列表了。

                    var myResult = menuBLL.TryMatchConditionalMenu(token, openId);
                    if (myResult != null)
                    {
                        Console.WriteLine(myResult.ToJson());
                    }

                    var userid_female = "oSiLnt2J4mYkhVG3aLTdMIF1hv-s";//女性的ID
                    myResult = menuBLL.TryMatchConditionalMenu(token, userid_female);
                    if (myResult != null)
                    {
                        Console.WriteLine(myResult.ToJson());
                    }

 

若是對這個《C#開發微信門戶及應用》系列感興趣,能夠關注個人其餘文章,系列隨筆以下所示:

C#開發微信門戶及應用(28)--微信「搖一搖·周邊」功能的使用和接口的實現

C#開發微信門戶及應用(27)-公衆號模板消息管理 

C#開發微信門戶及應用(26)-公衆號微信素材管理

C#開發微信門戶及應用(25)-微信企業號的客戶端管理功能

C#開發微信門戶及應用(24)-微信小店貨架信息管理

C#開發微信門戶及應用(23)-微信小店商品管理接口的封裝和測試

C#開發微信門戶及應用(22)-微信小店的開發和使用

C#開發微信門戶及應用(21)-微信企業號的消息和事件的接收處理及解密 

C#開發微信門戶及應用(20)-微信企業號的菜單管理

C#開發微信門戶及應用(19)-微信企業號的消息發送(文本、圖片、文件、語音、視頻、圖文消息等)

C#開發微信門戶及應用(18)-微信企業號的通信錄管理開發之成員管理

C#開發微信門戶及應用(17)-微信企業號的通信錄管理開發之部門管理

C#開發微信門戶及應用(16)-微信企業號的配置和使用

C#開發微信門戶及應用(15)-微信菜單增長掃一掃、發圖片、發地理位置功能

 C#開發微信門戶及應用(14)-在微信菜單中採用重定向獲取用戶數據

C#開發微信門戶及應用(13)-使用地理位置擴展相關應用

C#開發微信門戶及應用(12)-使用語音處理

C#開發微信門戶及應用(11)--微信菜單的多種表現方式介紹

C#開發微信門戶及應用(10)--在管理系統中同步微信用戶分組信息

C#開發微信門戶及應用(9)-微信門戶菜單管理及提交到微信服務器

C#開發微信門戶及應用(8)-微信門戶應用管理系統功能介紹

C#開發微信門戶及應用(7)-微信多客服功能及開發集成

C#開發微信門戶及應用(6)--微信門戶菜單的管理操做

C#開發微信門戶及應用(5)--用戶分組信息管理

C#開發微信門戶及應用(4)--關注用戶列表及詳細信息管理

C#開發微信門戶及應用(3)--文本消息和圖文消息的應答

C#開發微信門戶及應用(2)--微信消息的處理和應答

C#開發微信門戶及應用(1)--開始使用微信接口

相關文章
相關標籤/搜索