使用 Senparc 完成自定义菜单功能
官方参考资料
- Senparc 官网:http://weixin.senparc.com
- 自定义菜单相关文档可参考 Senparc 官方 Wiki 及《微信开发深度解析》相关章节
一、自定义菜单规则
- 自定义菜单分为一级菜单和二级菜单。
- 一级菜单数量为 1~3 个,即打开公众号直接显示在最下方的按钮。一级菜单文字最多 16 字节(约 8 个汉字)。
- 二级菜单从属于一级菜单,数量为 1~5 个。二级菜单文字最多 40 字节(约 20 个汉字)。
- 无论一级还是二级菜单,均支持两种触发事件:
- click(点击):键值不超过 128 字节
- view(跳转网页):URL 不超过 256 字节
- 当一级菜单下存在二级菜单时,点击该一级菜单不会触发任何事件,仅展开子菜单。
二、使用 Senparc 创建菜单
使用 Senparc.Weixin.MP SDK 创建自定义菜单只需三步:
第一步:获取 AccessToken
var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret);Code language: JavaScript (javascript)
提示:如果在第三步中直接使用
appId替代accessToken,则这一步可以省略。SDK 内部会自动处理 Token 的缓存与刷新。
第二步:组织菜单内容
使用 ButtonGroup 构建菜单结构:
ButtonGroup bg = new ButtonGroup();
// 一级菜单 - 单击测试(click 类型)
bg.button.Add(new SingleClickButton()
{
name = "单击测试",
key = "OneClick",
type = ButtonType.click.ToString() // 默认已设为 click,此处仅作演示
});
// 一级菜单 - 包含二级菜单
var subButton = new SubButton()
{
name = "二级菜单"
};
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_Text",
name = "返回文本"
});
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_News",
name = "返回图文"
});
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_Music",
name = "返回音乐"
});
subButton.sub_button.Add(new SingleViewButton()
{
url = "http://weixin.senparc.com",
name = "Url跳转"
});
bg.button.Add(subButton);Code language: JavaScript (javascript)
第三步:提交到微信服务器
var result = CommonApi.CreateMenu(accessToken, bg);Code language: JavaScript (javascript)
SingleClickButton 对应 click 类型,SingleViewButton 对应 view 类型。
成功返回结果示例:
{
"errcode": 0,
"errcode_name": "请求成功",
"errmsg": "ok"
}Code language: JSON / JSON with Comments (json)
三、关键点说明
ButtonGroup是菜单容器,最多添加 3 个一级菜单按钮。SubButton用于创建包含子菜单的一级菜单,其下最多添加 5 个sub_button。SingleClickButton:用户点击后,微信服务器会推送一个CLICK事件到开发者服务器,需在MessageHandler中重写OnEvent_ClickRequest来处理。SingleViewButton:用户点击后直接跳转至指定 URL,不会向开发者服务器发送事件推送。- 菜单创建后,微信客户端需要重新关注或清除缓存才会立即显示最新菜单(通常 24 小时内自动刷新)。
- 测试账号与正式公众号的菜单创建接口一致,但测试账号的菜单功能可能受权限限制。
注意:创建菜单的 Action 通常放在后台管理页面或一个独立的初始化接口中调用,不需要每次接收用户消息时都执行。

三、菜单查询
查询菜单同样需要先获取 AccessToken,然后只需一行代码即可完成:
var result = CommonApi.GetMenu(accessToken);Code language: JavaScript (javascript)
返回的 result.menu 结构类似于创建菜单时使用的 ButtonGroup bg 变量,可以直接查看当前公众号已配置的菜单结构。
四、菜单删除
获取 AccessToken 后,删除菜单同样只需一行代码:
var result = CommonApi.DeleteMenu(accessToken);Code language: JavaScript (javascript)
删除成功后,公众号原有的自定义菜单将被清除,用户端将在短时间内(通常 24 小时内)同步更新。
五、菜单响应事件
无论是 click 还是 view 类型的菜单,微信服务器都会向开发者服务器推送不同的事件响应(详见《Senparc.Weixin.MP SDK 微信公众平台开发教程(六):了解 MessageHandler》),分别触发以下方法:
OnEvent_ClickRequest()—— 处理 click 菜单点击事件OnEvent_ViewRequest()—— 处理 view 菜单跳转事件
两者的区别在于:
| 类型 | 服务器是否收到事件 | 客户端是否可收到回复 |
|---|---|---|
| click | 是,推送 CLICK 事件 | 是,可返回文本、图文等任意消息 |
| view | 是,推送 VIEW 事件 | 否,用户直接跳转至 URL,回复内容无效 |
注意:view 类型菜单点击后,用户直接打开配置的网页链接,开发者服务器虽然能收到请求,但无论返回什么内容,微信客户端都不会展示。
六、菜单管理页面示例
Controller 代码
[HttpGet]
[ActionName("Menu")]
public ActionResult MenuGet()
{
return View("menu");
}
[HttpPost]
[ActionName("Menu")]
public WxJsonResult MenuPost()
{
//第一步:获取AccessToken
var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret);
//第二步:准备好菜单
ButtonGroup bg = new ButtonGroup();
//单击
bg.button.Add(new SingleClickButton()
{
name = "单击测试",
key = "OneClick",
type = ButtonType.click.ToString(), //默认已设为此类型,这里只作为演示
});
//二级菜单
var subButton = new SubButton()
{
name = "二级菜单"
};
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_Text",
name = "返回文本"
});
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_News",
name = "返回图文"
});
subButton.sub_button.Add(new SingleClickButton()
{
key = "SubClickRoot_Music",
name = "返回音乐"
});
subButton.sub_button.Add(new SingleViewButton()
{
url = "http://www.bamn.cn",
name = "北盟网校"
});
bg.button.Add(subButton);
//第三步:提交到微信服务器
var result = CommonApi.CreateMenu(accessToken, bg);
return result;
}Code language: PHP (php)
视图代码(Menu.cshtml)
@{
ViewBag.Title = "更新菜单";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form action="/home/menu" method="post">
<input type="submit" value="提交" />
</form>Code language: HTML, XML (xml)
页面仅提供一个提交按钮,点击后向 /home/menu 发送 POST 请求,触发 MenuPost() 方法,完成菜单创建。创建结果(WxJsonResult)将直接显示在页面上。
提示:实际项目中可扩展此页面,增加菜单预览、查询、删除等功能按钮,方便后台管理。