開發微信企業號可以通過程序自定義菜單,只需要調用相關的接口就可以實現。
其實這個菜單也就是微信底部的菜單,目前自定義菜單最多包括3個一級菜單,每個一級菜單最多包含5個二級菜單。一級菜單最多4個漢字,二級菜單最多7個漢字,多出來的部分將會以“...”代替。其實創建菜單也很簡單。
但有一點需要說明,如果有子菜單,那么這個菜單就不會向后端發送事件。例如:我定義了三個一級菜單一個click,兩個view。
**如果沒有子菜單,則點擊click類型的菜單時,后主動向后端發送上報菜單事件,如果有則不會發送上報菜單事件。**
如果沒有子菜單,則點擊view類型的菜單時,回主動向后端發送點擊菜單跳轉鏈接的事件。并且會打開對應的網頁,如果有則不會發送點擊菜單跳轉鏈接的事件,也不會打開對應的網頁。
**也就是,如果有子菜單,則這個菜單,就是點擊單純的顯示子菜單,不會有其他的動作了。**
例如:

核心代碼菜單相關:
~~~
public enum MenuTypeEnum
{
click = 1,
view = 2,
scancode_push = 3,
scancode_waitmsg = 4,
pic_sysphoto = 5,
pic_photo_or_album = 6,
pic_weixin = 7,
location_select = 8
};
public abstract class SubButton
{
/// <summary>
/// 菜單的響應動作類型,目前有click、view兩種類型 scancode_push 掃碼推事件scancode_waitmsg 掃碼推事件且彈出“消息接收中”提示框
/// </summary>
public string type { get; protected set; }
/// <summary>
/// 菜單標題,不超過16個字節,子菜單不超過40個字節
/// </summary>
public string name { get; set; }
public List<SubButton> sub_button { get; set; }
public virtual bool HasError()
{
if (string.IsNullOrEmpty(this.name))
{
LogInfo.Error("菜單名稱為空");
return true;
}
if (string.IsNullOrEmpty(this.type))
{
LogInfo.Error("菜單類型為空");
return true;
}
if (sub_button!=null&&sub_button.Count > 0)
{
foreach (SubButton bt in sub_button)
{
if (bt.HasError())
{
return true;
}
}
}
return false;
}
public static SubButton CreateSubButton(MenuTypeEnum type,string name,string key,string url)
{
SubButton subButton = null;
string menuTypeText = GetMenuTypeText(type);
switch (type)
{
case MenuTypeEnum.view:
subButton = new SubViewButton(menuTypeText,name, url);
break;
case MenuTypeEnum.click:
case MenuTypeEnum.scancode_push:
case MenuTypeEnum.scancode_waitmsg:
case MenuTypeEnum.pic_sysphoto:
case MenuTypeEnum.pic_photo_or_album:
case MenuTypeEnum.pic_weixin:
case MenuTypeEnum.location_select:
subButton = new SubClickButton(menuTypeText, name, key);
break;
default:
throw new Exception("type=" + type + ",此類型的SubButton沒有實現");
}
return subButton;
}
public static MenuTypeEnum GetMenuType(string type)
{
MenuTypeEnum text = MenuTypeEnum.click;
switch (type)
{
case "click":
text = MenuTypeEnum.click;
break;
case "view":
text = MenuTypeEnum.view ;
break;
case "scancode_push":
text =MenuTypeEnum.scancode_push ;
break;
case "scancode_waitmsg":
text = MenuTypeEnum.scancode_waitmsg ;
break;
case "pic_sysphoto" :
text = MenuTypeEnum.pic_sysphoto;
break;
case "pic_photo_or_album":
text = MenuTypeEnum.pic_photo_or_album ;
break;
case "pic_weixin":
text = MenuTypeEnum.pic_weixin ;
break;
case "location_select":
text =MenuTypeEnum.location_select ;
break;
default:
throw new Exception("type=" + type + ",此類型的MenuTypeEnum沒有找到");
}
return text;
}
public static string GetMenuTypeText(MenuTypeEnum type)
{
string text = "";
switch (type)
{
case MenuTypeEnum.click:
text = "click";
break;
case MenuTypeEnum.view:
text = "view";
break;
case MenuTypeEnum.scancode_push:
text = "scancode_push";
break;
case MenuTypeEnum.scancode_waitmsg:
text = "scancode_waitmsg";
break;
case MenuTypeEnum.pic_sysphoto:
text = "pic_sysphoto";
break;
case MenuTypeEnum.pic_photo_or_album:
text = "pic_photo_or_album";
break;
case MenuTypeEnum.pic_weixin:
text = "pic_weixin";
break;
case MenuTypeEnum.location_select:
text = "location_select";
break;
default:
throw new Exception("type=" + type + ",此類型的MenuTypeEnum沒有實現");
}
return text;
}
}
public class SubClickButton : SubButton
{
public SubClickButton(string type,string name,string key)
{
this.type = type;
this.name = name;
this.key = key;
}
/// <summary>
/// 菜單KEY值,用于消息接口推送,不超過128字節
/// </summary>
public string key { get; set; }
public override bool HasError()
{
if (string.IsNullOrEmpty(this.key))
{
LogInfo.Error("菜單key為空");
return true;
}
return base.HasError();
}
}
public class SubViewButton : SubButton
{
public SubViewButton(string type, string name, string url)
{
this.type = type;
this.name = name;
this.url = url;
}
/// <summary>
/// 成員點擊view類型按鈕后,微信客戶端將會打開開發者在按鈕中填寫的網頁URL,可與網頁授權獲取成員基本信息接口結合,獲得成員基本信息。
/// </summary>
public string url { get; set; }
public override bool HasError()
{
if (string.IsNullOrEmpty(this.url))
{
LogInfo.Error("菜單url為空");
return true;
}
return base.HasError();
}
}
~~~
~~~
/// <summary>
/// 自定義菜單
/// </summary>
public class Menu
{
public List<SubButton> button { get; set; }
public virtual bool HasError()
{
if (button.Count >= 4)
{
LogInfo.Error("最多包括3個一級菜單");
return true;
}
foreach(SubButton bt in button)
{
if (bt.HasError())
{
return true;
}
}
return false;
}
}
~~~
添加修改,刪除菜單
~~~
public class BLLMenu
{
/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <param name="agentid">企業應用的id,整型。可在應用的設置頁面查看</param>
/// <returns></returns>
public static bool Create(Menu info, int agentid)
{
if (info.HasError())
{
return false;
}
string urlFormat = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?access_token={0}&agentid={1}";
var url = string.Format(urlFormat, BLLAccessToken.GetAccessToken(), agentid);
WebUtils wut = new WebUtils();
var postData = Tools.ToJsonString<Menu>(info);
//數據不用加密發送
LogInfo.Info("創建應用菜單消息: " + postData);
string sendResult = wut.DoPost(url, postData);
ReturnResult tempAccessTokenjson = Tools.JsonStringToObj<ReturnResult>(sendResult);
if (tempAccessTokenjson.HasError())
{
LogInfo.Error("發送創建應用菜單返回錯誤: " + Tools.ToJsonString<ReturnResult>(tempAccessTokenjson));
return false;
}
return true;
}
/// <summary>
///
/// </summary>
/// <param name="agentid">企業應用的id,整型。可在應用的設置頁面查看</param>
/// <returns></returns>
public static bool DelAll(int agentid)
{
string urlFormat = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?access_token={0}&agentid={1}";
var url = string.Format(urlFormat, BLLAccessToken.GetAccessToken(), agentid);
WebUtils wut = new WebUtils();
//數據不用加密發送
LogInfo.Info("發送刪除菜單消息: " + url);
string sendResult = wut.DoGet(url);
ReturnResult tempAccessTokenjson = Tools.JsonStringToObj<ReturnResult>(sendResult);
if (tempAccessTokenjson.HasError())
{
LogInfo.Error("發送刪除菜單返回錯誤: " + Tools.ToJsonString<ReturnResult>(tempAccessTokenjson));
return false;
}
return true;
}
public static bool GetAll(int agentid)
{
string urlFormat = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?access_token={0}&agentid={1}";
var url = string.Format(urlFormat, BLLAccessToken.GetAccessToken(), agentid);
WebUtils wut = new WebUtils();
//數據不用加密發送
LogInfo.Info("發送獲取菜單列表消息: " + url);
string sendResult = wut.DoGet(url);
MenuListResult tempAccessTokenjson = Tools.JsonStringToObj<MenuListResult>(sendResult);
if (tempAccessTokenjson.HasError())
{
LogInfo.Error("發送獲取菜單列表返回錯誤: " + Tools.ToJsonString<MenuListResult>(tempAccessTokenjson));
return false;
}
return true;
}
}
~~~
測試代碼
~~~
private void button7_Click(object sender, EventArgs e)
{
///測試添加
ConmonWeixin.MenuInfo.Menu info = new ConmonWeixin.MenuInfo.Menu();
SubButton subbt1 = SubButton.CreateSubButton(MenuTypeEnum.click, "Click1", "Click1", "");
subbt1.sub_button = new List<SubButton>();
SubButton bt11 = SubButton.CreateSubButton(MenuTypeEnum.scancode_push, "codePush2", "CancodePushButton11", "");
SubButton bt12 = SubButton.CreateSubButton(MenuTypeEnum.scancode_waitmsg, "codeWaitmsg2", "CancodeWaitmsgButton12", "");
SubButton bt13 = SubButton.CreateSubButton(MenuTypeEnum.click, "Click12", "Click12", "");
SubButton bt14 = SubButton.CreateSubButton(MenuTypeEnum.view, "V2級", "V22", "https://www.baidu.com");
subbt1.sub_button.Add(bt11);
subbt1.sub_button.Add(bt12);
subbt1.sub_button.Add(bt13);
subbt1.sub_button.Add(bt14);
SubButton subbt2 = SubButton.CreateSubButton(MenuTypeEnum.view, "V1級", "", "www.baidu.com");
subbt2.sub_button = new List<SubButton>();
SubButton bt21 = SubButton.CreateSubButton(MenuTypeEnum.pic_sysphoto, "PicSysphoto", "PicSysphotoButton21", "");
SubButton bt22 = SubButton.CreateSubButton(MenuTypeEnum.pic_photo_or_album, "photoalbum2", "PicSysphotoButton22", "");
subbt2.sub_button.Add(bt21);
subbt2.sub_button.Add(bt22);
SubButton subbt3 = SubButton.CreateSubButton(MenuTypeEnum.view, "V1級", "", "http://hlogin.html");
subbt3.sub_button = new List<SubButton>();
SubButton bt31 = SubButton.CreateSubButton(MenuTypeEnum.pic_weixin, "pic_weixin2", "Subpic_weixinButton31", "");
SubButton bt32 = SubButton.CreateSubButton(MenuTypeEnum.location_select, "location_selec", "location_selec32", "");
subbt3.sub_button.Add(bt31);
subbt3.sub_button.Add(bt32);
info.button = new List<SubButton>();
info.button.Add(subbt1);
info.button.Add(subbt2);
info.button.Add(subbt3);
BLLMenu.Create(info,7);
// Menu info, int agentid
}
private void button8_Click(object sender, EventArgs e)
{
//測試刪除
BLLMenu.DelAll(7);
}
~~~
[創建應用菜單官方文檔](http://qydev.weixin.qq.com/wiki/index.php?title=%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%E8%8F%9C%E5%8D%95)
[菜單接收事件官方文檔](http://qydev.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E6%94%B6%E4%BA%8B%E4%BB%B6)