前面幾篇繼續了我自己對於C#開發微信門戶及應用的技術探索和相關的經驗總結,繼續探索微信API並分享相關的技術,一方面是為了和大家對這方面進行互動溝通,另一方面也是專心做好微信應用的底層技術開發,把基礎模組夯實,在未來的應用上派上用途。本隨筆繼續介紹微信門戶選單的管理操作。
微信入口網站的選單,一般服務號碼和訂閱號碼都可以擁有這個模組的開發,但是訂閱號好像需要認證後才能擁有,而服務號碼則不需要認證就可以擁有了。這個選單可以有編輯模式和開發模式,編輯模式主要就是在微信入口網站的平台上,對選單進行編輯;而開發模式,就是使用者可以透過呼叫微信的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屬性,總得來說,為了建構好對應的選單實體類別訊息,不是一下就能分析的出來。
我看過一些微信介面的開發程式碼,把選單的分為了好多個實體類,指定了繼承關係,然後分別對他們進行屬性的配置,大概的關係如下所示。
這種多層關係的繼承方式能解決問題,不過我覺得並不是優雅的解決方案。其實結合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; } .......</menuinfo>
但是,這麼多信息,不同的類型我需要指定不同的屬性類型,那不是挺麻煩,萬一我在View類型的菜單裡面,把key屬性設置了,那怎麼辦?
解決方法就是我們定義幾個建構函數,分別用來構造不同的選單訊息,如下所示是對選單不同的類型,賦值給不同的屬性的建構函數。
/// <summary> /// 参数化构造函数 /// </summary> /// <param>按钮名称 /// <param>菜单按钮类型 /// <param>按钮的键值(Click),或者连接URL(View) 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>按钮名称 /// <param>子菜单集合 public MenuInfo(string name, IEnumerable<menuinfo> sub_button) { this.name = name; this.sub_button = new List<menuinfo>(); this.sub_button.AddRange(sub_button); }</menuinfo></menuinfo>
由於只指定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; } }</menuinfo></menuinfo>
我們從微信的定義裡面,可以看到,我們透過API可以取得選單資訊、建立選單、刪除選單,那麼我們來定義它們的介面如下。
/// <summary> /// 菜单的相关操作 /// </summary> public interface IMenuApi { /// <summary> /// 获取菜单数据 /// </summary> /// <param>调用接口凭证 /// <returns></returns> MenuJson GetMenu(string accessToken); /// <summary> /// 创建菜单 /// </summary> /// <param>调用接口凭证 /// <param>菜单对象 /// <returns></returns> CommonResult CreateMenu(string accessToken, MenuJson menuJson); /// <summary> /// 删除菜单 /// </summary> /// <param>调用接口凭证 /// <returns></returns> CommonResult DeleteMenu(string accessToken); }
具體的獲取選單資訊的實作如下。
/// <summary> /// 获取菜单数据 /// </summary> /// <param>调用接口凭证 /// <returns></returns> public MenuJson GetMenu(string accessToken) { MenuJson menu = null; var url = string.Format("http://www.php.cn/{0}", accessToken); MenuListJson list = JsonHelper<menulistjson>.ConvertJson(url); if (list != null) { menu = list.menu; } return menu; }</menulistjson>
這裡就是把返回的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>调用接口凭证 /// <param>菜单对象 /// <returns></returns> public CommonResult CreateMenu(string accessToken, MenuJson menuJson) { var url = string.Format("http://www.php.cn/{0}", accessToken); string postData = menuJson.ToJson(); return Helper.GetExecuteResult(url, postData); } /// <summary> /// 删除菜单 /// </summary> /// <param>调用接口凭证 /// <returns></returns> public CommonResult DeleteMenu(string accessToken) { var url = string.Format("http://www.php.cn/{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.php.cn/"), new MenuInfo("提点建议", ButtonType.click, "Event_Suggestion"), new MenuInfo("联系客服", ButtonType.click, "Event_Contact"), new MenuInfo("发邮件", ButtonType.view, "http://www.php.cn/") }); 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#開發微信入口網站及應用程式(6)--微信入口網站選單的管理操作相关文章请关注PHP中文网!