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


前面幾篇繼續了我自己對於C#開發微信門戶及應用的技術探索和相關的經驗總結,繼續探索微信API並分享相關的技術,一方面是為了和大家對這方面進行互動溝通,另一方面也是專心做好微信應用的底層技術開發,把基礎模塊夯實,在未來的應用中派上用途。本隨筆繼續介紹微信門戶菜單的管理操作。

1、菜單的基礎信息

微信門戶的菜單,一般服務號和訂閱號都可以擁有這個模塊的開發,但是訂閱號好像需要認證后才能擁有,而服務號則不需要認證就可以擁有了。這個菜單可以有編輯模式和開發模式,編輯模式主要就是在微信門戶的平台上,對菜單進行編輯;而開發模式,就是用戶可以通過調用微信的API對菜單進行定制開發,通過POST數據到微信服務器,從而生成對應的菜單內容。本文主要介紹基於開發模式的菜單管理操作。

自定義菜單能夠幫助公眾號豐富界面,讓用戶更好更快地理解公眾號的功能。目前自定義菜單最多包括3個一級菜單,每個一級菜單最多包含5個二級菜單。一級菜單最多4個漢字,二級菜單最多7個漢字,多出來的部分將會以“...”代替。目前自定義菜單接口可實現兩種類型按鈕,如下:

click:
用戶點擊click類型按鈕后,微信服務器會通過消息接口推送消息類型為event    的結構給開發者(參考消息接口指南),並且帶上按鈕中開發者填寫的key值,開發者可以通過自定義的key值與用戶進行交互;
view:
用戶點擊view類型按鈕后,微信客戶端將會打開開發者在按鈕中填寫的url值    (即網頁鏈接),達到打開網頁的目的,建議與網頁授權獲取用戶基本信息接口結合,獲得用戶的登入個人信息。

菜單提交的數據,本身是一個Json的數據字符串,它的官方例子數據如下所示。

 {
     "button":[
     {    
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "type":"click",
           "name":"歌手簡介",
           "key":"V1001_TODAY_SINGER"
      },
      {
           "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"
            }]
       }]
 }

從上面我們可以看到,菜單不同的type類型,有不同的字段內容,如type為view的有url屬性,而type為click的,則有key屬性。而菜單可以有子菜單sub_button屬性,總得來說,為了構造好對應的菜單實體類信息,不是一下就能分析的出來。

2、菜單的實體類定義

我看過一些微信接口的開發代碼,把菜單的分為了好多個實體類,指定了繼承關系,然后分別對他們進行屬性的配置,大概的關系如下所示。

這種多層關系的繼承方式能解決問題,不過我覺得並不是優雅的解決方案。其實結合Json.NET自身的Attribute屬性配置,可以指定那些為空的內容在序列號為Json字符串的時候,不顯示出來的。

[JsonProperty( NullValueHandling = NullValueHandling.Ignore)]

有了這個屬性,我們就可以統一定義菜單的實體類信息更多的屬性了,可以把View類型和Click類型的菜單屬性的url和key合並在一起。

    /// <summary>
    /// 菜單基本信息
    /// </summary>
    public class MenuInfo
    {
        /// <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>
        /// 子按鈕數組,按鈕個數應為2~5個
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public List<MenuInfo> sub_button { get; set; }

.......

但是,這么多信息,不同的類型我需要指定不同的屬性類型,那不是挺麻煩,萬一我在View類型的菜單里面,把key屬性設置了,那怎么辦?

解決方法就是我們定義幾個構造函數,分別用來構造不同的菜單信息,如下所示是對菜單不同的類型,賦值給不同的屬性的構造函數。

        /// <summary>
        /// 參數化構造函數
        /// </summary>
        /// <param name="name">按鈕名稱</param>
        /// <param name="buttonType">菜單按鈕類型</param>
        /// <param name="value">按鈕的鍵值(Click),或者連接URL(View)</param>
        public MenuInfo(string name, ButtonType buttonType, string value)
        {
            this.name = name;
            this.type = buttonType.ToString();

            if (buttonType == ButtonType.click)
            {
                this.key = value;
            }
            else if(buttonType == ButtonType.view)
            {
                this.url = value;
            }
        }

好了,還有另外一個問題,子菜單也就是屬性sub_button是可有可無的東西,有的話,需要指定Name屬性,並添加它的sub_button集合對象就可以了,那么我們在增加一個構造子菜單的對象信息的構造函數。

        /// <summary>
        /// 參數化構造函數,用於構造子菜單
        /// </summary>
        /// <param name="name">按鈕名稱</param>
        /// <param name="sub_button">子菜單集合</param>
        public MenuInfo(string name, IEnumerable<MenuInfo> sub_button)
        {
            this.name = name;
            this.sub_button = new List<MenuInfo>();
            this.sub_button.AddRange(sub_button);
        }

由於只指定Name和sub_button的屬性內容,其他內容為null的話,自然構造出來的Json就沒有包含它們,非常完美!

為了獲取菜單的信息,我們還需要定義兩個實體對象,如下所示。

    /// <summary>
    /// 菜單的Json字符串對象
    /// </summary>
    public class MenuJson
    {
        public List<MenuInfo> button { get; set; }

        public MenuJson()
        {
            button = new List<MenuInfo>();
        }
    }

    /// <summary>
    /// 菜單列表的Json對象
    /// </summary>
    public class MenuListJson
    {
        public MenuJson menu { get; set; }
    }

3、菜單管理操作的接口實現

我們從微信的定義里面,可以看到,我們通過API可以獲取菜單信息、創建菜單、刪除菜單,那么我們來定義它們的接口如下。

    /// <summary>
    /// 菜單的相關操作
    /// </summary>
    public interface IMenuApi
    {              
        /// <summary>
        /// 獲取菜單數據
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <returns></returns>
        MenuJson GetMenu(string accessToken);
                       
        /// <summary>
        /// 創建菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuJson">菜單對象</param>
        /// <returns></returns>
        CommonResult CreateMenu(string accessToken, MenuJson menuJson);
                       
        /// <summary>
        /// 刪除菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <returns></returns>
        CommonResult DeleteMenu(string accessToken);
    }

具體的獲取菜單信息的實現如下。

        /// <summary>
        /// 獲取菜單數據
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <returns></returns>
        public MenuJson GetMenu(string accessToken)
        {
            MenuJson menu = null;

            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}", accessToken);
            MenuListJson list = JsonHelper<MenuListJson>.ConvertJson(url);
            if (list != null)
            {
                menu = list.menu;
            }
            return menu;
        }

這里就是把返回的Json數據,統一轉換為我們需要的實體信息了,一步到位。

調用代碼如下所示。

        private void btnGetMenuJson_Click(object sender, EventArgs e)
        {
            IMenuApi menuBLL = new MenuApi();
            MenuJson menu = menuBLL.GetMenu(token);
            if (menu != null)
            {
                Console.WriteLine(menu.ToJson());
            }
        }

創建和刪除菜單對象的操作實現如下所示。

        /// <summary>
        /// 創建菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <param name="menuJson">菜單對象</param>
        /// <returns></returns>
        public CommonResult CreateMenu(string accessToken, MenuJson menuJson)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}", accessToken);
            string postData = menuJson.ToJson();

            return Helper.GetExecuteResult(url, postData);
        }
                
        /// <summary>
        /// 刪除菜單
        /// </summary>
        /// <param name="accessToken">調用接口憑證</param>
        /// <returns></returns>
        public CommonResult DeleteMenu(string accessToken)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={0}", accessToken);

            return Helper.GetExecuteResult(url);
        }

看到這里,有些人可能會問,實體類你簡化了,那么創建菜單是不是挺麻煩的,特別是構造對應的信息應該如何操作呢?前面不是介紹了不同的構造函數了嗎,通過他們簡單就搞定了,不用記下太多的實體類及它們的繼承關系來處理菜單信息。

        private void btnCreateMenu_Click(object sender, EventArgs e)
        {                       
            MenuInfo productInfo = new MenuInfo("軟件產品", new MenuInfo[] { 
                new MenuInfo("病人資料管理系統", ButtonType.click, "patient"), 
                new MenuInfo("客戶關系管理系統", ButtonType.click, "crm"), 
                new MenuInfo("酒店管理系統", ButtonType.click, "hotel"), 
                new MenuInfo("送水管理系統", ButtonType.click, "water")
            });                                    

            MenuInfo frameworkInfo = new MenuInfo("框架產品", new MenuInfo[] { 
                new MenuInfo("Win開發框架", ButtonType.click, "win"),
                new MenuInfo("WCF開發框架", ButtonType.click, "wcf"),
                new MenuInfo("混合式框架", ButtonType.click, "mix"), 
                new MenuInfo("Web開發框架", ButtonType.click, "web"),
                new MenuInfo("代碼生成工具", ButtonType.click, "database2sharp")
            });

            MenuInfo relatedInfo = new MenuInfo("相關鏈接", new MenuInfo[] { 
                new MenuInfo("公司介紹", ButtonType.click, "Event_Company"),
                new MenuInfo("官方網站", ButtonType.view, "http://www.iqidi.com"),
                new MenuInfo("提點建議", ButtonType.click, "Event_Suggestion"),
                new MenuInfo("聯系客服", ButtonType.click, "Event_Contact"),
                new MenuInfo("發郵件", ButtonType.view, "http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email=S31yfX15fn8LOjplKCQm")
            });

            MenuJson menuJson = new MenuJson();
            menuJson.button.AddRange(new MenuInfo[] { productInfo, frameworkInfo, relatedInfo });

            //Console.WriteLine(menuJson.ToJson());

            if (MessageUtil.ShowYesNoAndWarning("您確認要創建菜單嗎") == System.Windows.Forms.DialogResult.Yes)
            {
                IMenuApi menuBLL = new MenuApi();
                CommonResult result = menuBLL.CreateMenu(token, menuJson);
                Console.WriteLine("創建菜單:" + (result.Success ? "成功" : "失敗:" + result.ErrorMessage));
            }
        }

這個就是我微信門戶里面的菜單操作了,具體效果可以關注我的微信門戶:廣州愛奇迪,也可以掃描下面二維碼進行關注了解。

菜單的效果如下:

 

如果對這個系列感興趣,可以關注我的其他文章,系列隨筆如下所示:

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)--開始使用微信接口


免責聲明!

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



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