公众号中,底部都是有自己定义的功能按钮,通过点击某个按钮来实现指定的业务逻辑操作。

下面就来说说这些按钮是怎样放到微信公众平台的,还是先来看看微信的官方解释:

请注意:

1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。

2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。

3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,

如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。

自定义菜单接口可实现多种类型按钮,如下:(由于click和view是最常见的事件,所以先讲这两个)

1、click:点击推事件 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),

并且带上按钮中开发者填写的key值, 开发者可以通过自定义的key值与用户进行交互;

2、view:跳转URL 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。

创建自定义菜单其实也是通过http请求方式,实现自定义菜单的写入,请求地址: https://api.weixin.qq.com/cgi-bin/menu/create?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"
}]
}]
}
观察上面的实例可以看出,其实就是一串JSON数据,你可以选择用字符串拼接的形式将其存储,也可以选择文件存储。
这里我使用的文件储存,将上面的实例存储到一个叫menu.txt文件中(这里建立的好处是可以把自定义菜单与微信公众号开发的程序文件分开,避免每次改自定义菜单也都要发布程序,除非有业务逻辑的更改)。建立一个专门创建自定义菜单的页面wxMenuManage.aspx,其实自定义菜单通过本地执行页面就可以将自定义菜单同步到微信服务器上面,具体请看下面的代码:
public partial class wxMenuManage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
} /// <summary>
/// 读取并创建自定义菜单
/// </summary>
private void CreateMenu()
{
FileStream fs = new FileStream(HttpContext.Current.Server.MapPath(".") + "\\menu.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("GBK"));
string menu = sr.ReadToEnd();
sr.Close();
fs.Close();
sr.Dispose();
fs.Dispose(); string access_token =wxAccess_token.IsExistAccess_Token(); //获取access_token
string i = GetPage("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + access_token, menu);
Response.Write("创建菜单结果:" + i);
Response.End();
} /// <summary>
/// 删除菜单
/// </summary>
private void DeleteMenu()
{
string access_token =wxAccess_token.IsExistAccess_Token(); //获取access_token
string i = GetPage("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=" + access_token, "");
Response.Write("删除菜单结果:" + i);
Response.End();
} /// <summary>
/// 获取自定义菜单
/// </summary>
/// <param name="posturl">自定义菜单请求的地址</param>
/// <param name="postData">自定义菜单内容</param>
/// <returns></returns>
private string GetPage(string posturl, string postData)
{
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
byte[] data = null;
if (postData.Length > ) //有值代表创建菜单
{
data = encoding.GetBytes(postData);
} // 准备请求...
try
{
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
if (postData.Length > )
{
request.Method = "POST"; //创建菜单
}
else
{
request.Method = "GET"; //删除菜单
} request.ContentType = "application/x-www-form-urlencoded"; if (postData.Length > ) //有值代表创建菜单
{
request.ContentLength = data.Length;
outstream = request.GetRequestStream();
outstream.Write(data, , data.Length);
outstream.Close();
} //发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty;
return content;
}
catch (Exception ex)
{
string err = ex.Message;
Response.Write(err);
Response.End();
return string.Empty;
}
} /// <summary>
/// 创建菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCreate_Click(object sender, EventArgs e)
{
CreateMenu();
} /// <summary>
/// 删除菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnDelete_Click(object sender, EventArgs e)
{
DeleteMenu();
}
}

再来看一下我的前台页面:

  <form id="form1" runat="server">
<div>
<table style="width: 100%;text-align: center;margin-top: 30px;">
<tr>
<td style="text-align: right;margin-right: 10px;">
<asp:Button runat="server" ID="btnCreate" Text="创建菜单" OnClick="btnCreate_Click"/>
</td>
<td style="text-align: left;margin-left: 10px;">
<asp:Button runat="server" ID="btnDelete" Text="删除菜单" OnClick="btnDelete_Click"/>
</td>
</tr>
<tr>
<td colspan="">
<h3 style="color: red;">*注:创建之前请先删除菜单<br/>(创建完成之后新菜单将在五分钟之内生效)</h3>
</td>
</tr>
</table>
</div>
</form>

这里需要注意的几点:

1、页面中我我用到了一个“创建菜单”的按钮和一个“删除菜单”的按钮,因为在创建菜单之前必须要删除之前的菜单,否则创建可能会失败(第一次的时候可以直接创建)

2、“wxAccess_token.IsExistAccess_Token(); //获取access_token”方法是我将前文提到的IsExistAccess_Token()方法和GetAccess_token()都封装到了一个wxAccess_token类中

3、创建菜单的时候请求的是https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + access_token使用POST请求,删除菜单的时候请求的是https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=" + access_token使用GET请求

4、这里我是将menu.txt和wxMenuManage.aspx放到了同一目录下,你在使用的时候注意他们的路径

这些工作完成之后,就可以在本地运行wxMenuManage.aspx页面了,

点击删除菜单按钮如果页面输出的结果是,“删除菜单结果:{"errcode":0,"errmsg":"ok"}”,说明删除成功

点击创建菜单按钮如果页面输出的结果是,“创建菜单结果:{"errcode":0,"errmsg":"ok"}",说明创建成功

然后把你的微信公众号取消关注,再关注就可以看到你自己的菜单了

C#微信公众号开发 -- (五)自定义菜单创建的更多相关文章

  1. node微信公众号开发--设置自定义菜单

    var request = require("request"); const querystring = require("querystring"); re ...

  2. Java微信公众平台开发_04_自定义菜单

    一.本节要点 1.菜单相关实体类的封装 参考官方文档中的请求包的内容,对菜单相关实体类进行封装. 2.数据传输格式—JSON 自定义菜单中请求包的数据是Json字符串格式的,请参见:  Java_数据 ...

  3. 微信公众平台开发(99) 自定义菜单获取OpenID

    关键字 微信公众平台 自定义菜单 OpenID作者:方倍工作室原文:http://www.cnblogs.com/txw1958/p/weixin-menu-get-openid.html 在这篇微信 ...

  4. tp6微信公众号开发者模式自定义菜单

    1,参考上篇博客,获取access_token https://www.cnblogs.com/xiaoyantongxue/p/15803334.html 2:控制器写以下代码 /* * 获取普通a ...

  5. 微信公众号开发者模式自定义菜单 node

    纯属分享 var config = require('./admin/wx/config/config'); var API = require('wechat-api'); var api = ne ...

  6. 微信公众号开发中遇到的几个bug

    一.测试自定义菜单接口时中文菜单名显示为null 设置的中文菜单名,中文未经过编码和解码过程,设置的中文菜单名在最后的微信服务器返回的json格式数据中显示为null. 解决办法:将中文先用uneco ...

  7. .NET微信公众号开发-2.0创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin ...

  8. C#微信公众号开发 -- (六)自定义菜单事件之CLICK

    微信公众号中当用户手动点击了按钮,微信公众号会被动的向用户发送文字消息或者图文消息. 通过C#微信公众号开发 -- (五)自定义菜单创建 我们知道了如何将CLICK类型的按钮添加到自己的微信公众平台上 ...

  9. .NET微信公众号开发-3.0查询自定义菜单

    一.前言 前面我们已经创建好了我们的自定义菜单.那么我们现在要如何查询我们自定义的菜单.原理都是一样的,而且都是相当简单,只是接口地址文档换掉了. 2.0开始编码 同样我们首先创建好我的查询页面,在这 ...

随机推荐

  1. POJ1680 Currency Exchange SPFA判正环

    转载来源:優YoU  http://user.qzone.qq.com/289065406/blog/1299337940 提示:关键在于反向利用Bellman-Ford算法 题目大意 有多种汇币,汇 ...

  2. SQL Server查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...

  3. debian下安装AMD驱动

    参考:http://blog.sciencenet.cn/blog-296919-464464.html 去AMD官网下载对应的驱动: amd-driver-installer-catalyst-13 ...

  4. linux驱动程序之电源管理 之linux休眠与唤醒(2)

    在Linux中,休眠主要分三个主要的步骤:(1)冻结用户态进程和内核态任务:(2)调用注册的设备的suspend的回调函数:(3)按照注册顺序休眠核心设备和使CPU进入休眠态.       冻结进程是 ...

  5. ARM--存储管理器

    初入领悟: 1. bank.L-bank的概念 2. s3c2440内部管理SDRAM寄存器配置 Frist part:原理分析 S3c2440为32位微处理器,其可访问空间为4G:但其中提供1G外设 ...

  6. Clean Code – Chapter 5 Formatting

    The Purpose of Formatting Code formatting is about communication, and communication is the professio ...

  7. iLearning D3.js 2.0 released

    There are some great changes in 2.0 version. Console in tutorial: In previous version, there will be ...

  8. POJ1155 - TELE(树形DP)

    题目大意 电视台要直播一场比赛,电视网络刚好形成了一棵树,其中有M个为客户端,其他的为中转站,其中中转站与中转站以及中转站与客户端之间连接都需要一定费用,每个客户i愿意支付pay[i]元钱,问电视台在 ...

  9. hdoj 1241 Oil Deposits

    Oil Deposits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  10. 为什么在Windows有两个临时文件夹的环境变量Temp和Tmp?

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:为什么在Windows有两个临时文件夹的环境变量Temp和Tmp?.