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

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

请注意:

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. SQL Server查询性能优化——覆盖索引(一)

    覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...

  2. centos解决ping unknown host的问题

    当ping www.baidu.com 的时候如果出现 unknown host的提示 再ping一下IP, ping 8.8.8.8 如果此时能ping通,那么就是DNS服务器没有设置,不能解析域名 ...

  3. oracle rac IP详解

    rac环境下vip/public/private IP的区别 每个节点要2块网卡, 3个IP,虚拟IP或者叫做业务IP,单个网卡当掉可以“漂”到其他网卡是继续提供服务 在Oracle RAC环境下,每 ...

  4. Codeforces Round #311 (Div. 2) D - Vitaly and Cycle(二分图染色应用)

    http://www.cnblogs.com/wenruo/p/4959509.html 给一个图(不一定是连通图,无重边和自环),求练成一个长度为奇数的环最小需要加几条边,和加最少边的方案数. 很容 ...

  5. 问题-[Delphi]用LoadLibrary加载DLL时返回0的错误

    问题现象:用LoadLibrary加载DLL一直返回0句柄,无法进行下一步操作,但同样的代码可以访问到别的DLL.问题处理:1.你加载的路径是不对的,一定要看好路径.2.你是在虚拟机中操作的DLL,因 ...

  6. 教程-Delphi MSComm 实时串口通讯

    Delphi  MSComm 实时串口通讯 MSComm控件具有丰富的与串口通信密切相关的属性,提供了对串口进行的多种操作,进而使串行通信变得十分简便.MSComm的控件属性较多,常用的属性如下:1) ...

  7. Learning JavaScript Design Patterns The Singleton Pattern

    The Singleton Pattern The Singleton pattern is thus known because it restricts instantiation of a cl ...

  8. AtomicLong

    Spring package com.uniubi.management.controller; import java.util.concurrent.atomic.AtomicLong; impo ...

  9. Android自定义进度条

    Android原生控件只有横向进度条一种,而且没法变换样式,比如原生rom的样子很丑是吧,当伟大的产品设计要求更换前背景,甚至纵向,甚至圆弧状的,咋办,比如ok,我们开始吧: 一)变换前背景 先来看看 ...

  10. AIDL-Android接口描述语言实现跨进程通讯

    在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享. 因此传递对象, ...