多个自定义菜单 微信开发创建_微信小程序自定义菜单最多包括几个一级菜单 - CSDN
  • 大家可能经常看到一些微信公众号具有功能强大的自定义菜单,点击之后可以访问很有用的功能。 这篇教程就教大家如何动手做一做。 ...每二级菜单都能完成一些任务。...文档里给了创建自定义菜单需要维护参数的H...

    大家可能经常看到一些微信公众号具有功能强大的自定义菜单,点击之后可以访问很多有用的功能。

    这篇教程就教大家如何动手做一做。

    这个教程最后实现的效果是:创建一个一级菜单“UI5”, 点击之后弹出两个二级菜单,如下图蓝色区域所示。每个二级菜单都能完成一些任务。

    那么用什么API创建这些自定义菜单呢?微信公众号平台技术文档中,点击”自定义菜单”:

    文档里给了创建自定义菜单需要维护参数的HTTPpost报文的格式:

    回到我的例子,我用postman发送这个HTTP post请求:

    这是我HTTP post的报文内容:

    {
    
    "button":[
    
    {
    
    "name":"UI5",
    
    "sub_button":[{
    
    "type": "view",
    
    "name": "Jerry List",
    
    "url": "http://wechatjerry.herokuapp.com/ui5"
    
    },{
    
    "type": "click",
    
    "name": "Other UI5 application",
    
    "key": "dataQuery"
    
    }]
    
    }
    
    ]
    
    }

    上述json格式的报文定义了一个一级菜单,标签文本为UI5。两个二级菜单(sub_button),类型分别为view和click。

    view类型即绑定一个HTML页面到该二级菜单,点击之后跳转到这个页面去。我的例子绑定的html页面是http://wechatjerry.herokuapp.com/ui5。 类型为click的菜单很好理解,点击后,微信平台会发送一个事件给您公众号的微信服务器上。您需要在您的微信服务器里对这个时间做处理。事件类型通过参数key指定,我上述例子的类型是dataQuery,这个参数可以随意指定。

    响应类型为click的微信自定义二级菜单的伪代码如下:

    app.route('/').post(function(req,res){
        req.on("end",function(){
            var msgType = formattedValue(getXMLNodeValue('MsgType', content));
            if( msgType === "event"){
                var eventKey = formattedValue(getXMLNodeValue('EventKey', content));
                if( eventKey === "dataQuery"){
                    // 响应微信自定义二级菜单的点击
                }
            }
        }
        );

    要获取更多Jerry的原创技术文章,请关注公众号”汪子熙”或者扫描下面二维码:

    展开全文
  • 作者:陈惠,叩丁狼教育...菜单效果:打开开发文档,选择”自定义菜单”的”菜单创建接口”。注意: 1、自定义菜单最多包括3一级菜单,每一级菜单最多包含5二级菜单。 2、一级菜单最多4汉字,二级菜单最多...

    作者:陈惠,叩丁狼教育高级讲师。原创文章,转载请注明出处。

    本篇文章,我们来做一个最常见的,也是用户最喜欢使用的功能——自定义菜单。
    因为菜单只需要点一下就可以获取需要的信息,无需用户手动输入关键字,用户体验相对来说比较好。

    菜单效果:

    图片.png

    打开开发文档,选择”自定义菜单”的”菜单创建接口”。

    图片.png

    注意:
    1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
    2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
    3、创建自定义菜单后,微信是有一定的菜单刷新策略,不会立马看到效果,尽量尝试先取消关注后再次关注,即可以看到创建后的效果。
    

    菜单的类型非常多,文档中列了10种类型,这里不一一说明。

    举两个比较常见的类型:
    1、click:点击推事件类型,即点击之后微信服务器会推送一个事件类型的消息到我们的URL上,与之前的关注/取消关注类似。
    2、view:跳转URL类型,即点击之后可以跳转到指定的网页地址。
    
    现在我们利用click类型的按钮来实现需求:

    用户点击”开班信息”按钮后,公众号马上推送最近开班信息,点击”校区地址”按钮后,马上推送地址信息,不需要用户再手动输入关键字。

    实现细节:

    1.用户点击click类型按钮后,微信服务器会推送一个事件类型的消息到URL上,也就是意味着需要使用之前的MsgType判断是否为event类型。
    2.需要判断是什么事件,我们之前判断的是关注事件subscribe,但现在是click类型,所以Event属性我们需要判断是否为click。
    3.我们可能会有很多个click类型的按钮,所以需要根据不同的按钮来回复不同的内容,微信为每个click类型的按钮提供了key属性,不同的按钮设置不同的key值,根据key值即可知道当前需要处理的是哪个按钮。

    创建菜单:

    那么接下来,我们就需要创建自定义菜单了。

    开发文档中,已经提供创建菜单的接口地址了,我们需要把菜单转换为json数据传递过去。

    下图是官方提供的菜单具体参数:
    图片.png

    先把我们的要创建的自定义菜单对应的json数据准备好:

    {
         "button":[
         {    
              "type":"click",
              "name":"开班信息",
              "key":"classinfo"
          },
         {    
              "type":"click",
              "name":"校区地址",
              "key":"address"
          },
          {
               "name":"学科介绍",
               "sub_button":[
               {    
                   "type":"view",
                   "name":"Java课程",
                   "url":"http://www.wolfcode.cn/zt/java/index.html"
                },
               {    
                   "type":"view",
                   "name":"Python课程",
                   "url":"http://www.wolfcode.cn/zt/python/index.html"
                }]
           }]
     }
    

    这里我是创建了2个click类型的一级菜单,并且有对应的key值,还创建了1个有子菜单的一级菜单, 里面的2个子菜单都是view类型的,点击后直接链接到课程介绍页面。

    access_token介绍

    接下来,我们注意看这个接口的地址:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

    地址最后有一个access_token的参数,对于该参数的介绍,在开发文档的”首页”有这么一句话。

    公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,也就意味着它就是一个门票,请求接口时需要带上这个门票,如果没有就无法获取需要的信息,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限,开发者需自行存储,详见获取接口调用凭据(access_token)文档。

    这句话说明了我们在调用接口之前,必须先获取到access_token这么一个凭据。

    获取access_token

    打开文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

    文档告诉我们,access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效,而且也有获取的次数限制,所以我们应该把它缓存起来,2个小时内重复使用,另外, 如果access_token要保存在数据库中,至少要保留512个字符空间。

    通过文档介绍可知,我们请求指定的接口地址,并且把我们之前分配到的appid与secret作为参数传递过去,即可以获取到有效的access_token。

    图片.png

    代码:

    public class WeChatUtil {
        //URL验证时使用的token
        public static final String TOKEN = "wolfcode";
        //appid
        public static final String APPID = "wx59687be81dd3d388";
        //secret
        public static final String SECRET = "d4624c36b6795d1d99dcf0547af5443d";
            //创建菜单接口地址
        public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
        //获取access_token的接口地址
        public static final String GET_ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        //缓存的access_token
        private static String accessToken;
        //access_token的失效时间
        private static long expiresTime;
    
        /**
         * 获取accessToken
         * @return
         */
        public static String getAccessToken(){
            //判断accessToken是否已经过期,如果过期需要重新获取
            if(accessToken==null||expiresTime < new Date().getTime()){
                //发起请求获取accessToken
                String result = HttpUtil.get(GET_ACCESSTOKEN_URL.replace("APPID", APPID).replace("APPSECRET", SECRET));
                //把json字符串转换为json对象
                JSONObject json = JSON.parseObject(result);
                //缓存accessToken
                accessToken = json.getString("access_token");
                //设置accessToken的失效时间
                long expires_in = json.getLong("expires_in");
                //失效时间 = 当前时间 + 有效期(提前一分钟)
                expiresTime = new Date().getTime()+ (expires_in-60) * 1000;
            }
            return accessToken;
        }
    }
    

    代码中的HttpUtil是发起http请求的工具类,网上可以找到很多,这里就不贴出来了。

    通过getAccessToken方法我们就可以获取到需要的accessToken凭据了。

    接下来我们就可以调用创建自定义菜单的接口了,使用main方法直接调用createMenu方法,把菜单的json数据传入即可。当然,想要更灵活的设置菜单,需要写菜单管理的相关页面使用可视化的方式来编辑菜单。

        /**
         * 创建自定义菜单
         * @param menu
         */
        public static void createMenu(String menu){
            String result = HttpUtil.post(CREATE_MENU_URL.replace("ACCESS_TOKEN", getAccessToken()),menu);
            System.out.println(result);
        }
    

    接口响应的结果为:{“errcode”:0,”errmsg”:”ok”},代表菜单创建成功,这时候就可以打开公众号测试了,如果不能及时看到新的菜单,应先取消关注再重新关注公众号。

    如果响应的结果是其他,代表创建过程出错了,这时候应该对照错误码,查找错误原因。

    图片.png

    上面列出的是比较常见的错误,如果上面找不到,需要在全局返回码中搜索。
    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234

    菜单效果:
    图片.png

    菜单已经创建成功,我们最后一步就是做业务处理了。

    1.InMsgEntity类添加EventKey属性

    @Setter
    @Getter
    @XmlRootElement(name="xml")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class InMsgEntity {
    
        ....省略不相关的属性...
    
        /**
         * 消息类型
         * text 文本消息
         * image 图片消息
         * voice 语音消息
         * video 视频消息
         * music 音乐消息
         * event 事件推送
         */
        protected String MsgType;
        /**
         * 事件类型
         * subscribe(订阅)
         * unsubscribe(取消订阅)
         * LOCATION(上报地理位置)
         * CLICK(点击普通的菜单)
         * VIEW(点击跳转链接的菜单)
         */
        private String Event;
        //菜单按钮的key值
        private String EventKey;
    }
    

    2.判断菜单key值

        /**
         * 微信消息处理
         */
        @RequestMapping(value = "/weChat", method = RequestMethod.POST)
        @ResponseBody
        public Object handleMessage(@RequestBody InMsgEntity msg) {
            //创建消息响应对象
            OutMsgEntity out = new OutMsgEntity();
            //把原来的发送方设置为接收方
            out.setToUserName(msg.getFromUserName());
            //把原来的接收方设置为发送方
            out.setFromUserName(msg.getToUserName());
            //获取接收的消息类型
            String msgType = msg.getMsgType();
            //设置消息创建时间
            out.setCreateTime(new Date().getTime());
            //公众号回复的内容
            String outContent = null;
            //根据类型设置不同的消息数据
            if("text".equals(msgType)){
               //.....
            }else if("image".equals(msgType)){
               //.....
            }else if("event".equals(msgType)){
                //判断关注事件
                if("subscribe".equals(msg.getEvent())){
                    out.setContent("欢迎关注![愉快]");
                    //设置消息的响应类型
                    out.setMsgType("text");
                }else if("click".equals(msg.getEvent())){
                    //获取菜单的key值
                    String key = msg.getEventKey();
                    if("classinfo".equals(key)){
                        outContent = "上海Java基础班第05期于2018/05/10开班\n" +
                                "广州Java基础班第24期于2018/04/02开班";
                    }else if("address".equals(key)){
                        outContent = "北京校区:北京昌平区沙河镇万家灯火装饰城2楼8077号\n" +
                                "广州校区:广州市天河区棠下涌东路大地工业区D栋六楼\n" +
                                "上海校区:上海市青浦区华新镇华隆路1777号E通世界商务园华新园A座4楼402";
                    }
                    //设置消息的响应类型
                    out.setMsgType("text");
                    out.setContent(outContent);
                }
            }
            return out;
        }
    

    菜单效果演示:

    7a825b948d2d2954d0875a5e06cf60b6.gif


    展开全文
  • 1.根据微信公众平台文档,得知创建自定义菜单有如下规则: a.目前自定义菜单最多包括3一级菜单,每一级菜单最多包含5二级菜单。一级菜单最多4汉字,二级菜单最多7汉字,出来的部分将会以“...”代替。...

    1.根据微信公众平台文档,得知创建自定义菜单有如下规则:

    a.目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。请注意,创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。


    注:所以最多只能创建15个功能菜单,多了就出错了!


    b.

    目前自定义菜单接口可实现两种类型按钮,如下:

    click:
    用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event	的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
    view:
    用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值	(即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息。
    

    c.

    接口调用请求说明

    http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN


    2.根据文档提供的规则和接口调用说明,封装成一个类编写代码如下

    1. class WeChatCreateMenu  
    2. {  
    3. <span style="white-space:pre">    </span>//判断token是否过期,如果过期重新获取,不然直接从数据库取  
    4.     public function Get_access_token($appid,$secret){  
    5.       
    6.         $db = DBManage::getInstance();  
    7.         $db->ConnDB();  
    8.         $sql = "select * from t_token";  
    9.           
    10.         if($db-> GetEffectRows($sql) > 0)  
    11.         {  
    12.             $sql = "select * from t_token where TokenFlag='sd'";  
    13.             $res = $db->GetData($sql);  
    14.               
    15.             while$obj = mysqli_fetch_object($res))  
    16.             {  
    17.                 if($obj->TokenTime-60 > time()) //Token还没过期  
    18.                 {  
    19.                     return $obj->Token;  
    20.                 }  
    21.                 else  //过期  
    22.                 {  
    23.                     break;  
    24.                 }  
    25.                   
    26.             }  
    27.         }  
    28.           
    29.         $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;  
    30.         $json=self::DoCurlGetRequest($url);  
    31.         $retData=json_decode($json,true);  
    32.           
    33.         if(!$retData)  
    34.         {  
    35.             return false;  
    36.         }  
    37.           
    38.         $token = $retData['access_token'];  
    39.         $expire = $retData['expires_in'];  
    40.         $oldTime = time() + $expire;  
    41.           
    42.         $sql = "select * from t_token";  
    43.       
    44.         if($db-> GetEffectRows($sql) == 0) //无数据  
    45.         {  
    46.             $sql = "insert into t_token values('sd','$token','$oldTime')";  
    47.             $db->ExecSql($sql);  
    48.         }  
    49.         else //更新 数据  
    50.         {  
    51.             $sql = "update t_token set Token='$token',TokenTime='$oldTime' where TokenFlag='sd'";  
    52.             $db->ExecSql($sql);  
    53.         }  
    54.         //file_put_contents("debug.txt", "token====".$token.PHP_EOL,FILE_APPEND);  
    55.           
    56.         return $token;  
    57.     }  
    58.       
    59.     //因为url是https 所有请求不能用file_get_contents,用curl请求json 数据  
    60.     private function DoCurlGetRequest($url){  
    61.         $ch = curl_init();  
    62.         curl_setopt($ch, CURLOPT_URL,$url);  
    63.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  
    64.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  
    65.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
    66.         $result = curl_exec($ch);  
    67.         curl_close($ch);  
    68.         return $result;  
    69.     }  
    70.       
    71.     function DoCurlPostRequest($url$jsonData){  
    72.         $con = curl_init((string)$url);  
    73.         curl_setopt($con,CURLOPT_HEADER, false);  
    74.         curl_setopt($con, CURLOPT_POSTFIELDS,$jsonData);  
    75.         curl_setopt($con, CURLOPT_POST, true);  
    76.         curl_setopt($con, CURLOPT_RETURNTRANSFER, true);  
    77.         curl_setopt($con,CURLOPT_SSL_VERIFYPEER,false);  //略过证书验证  
    78.         $result = curl_exec($con) ;  
    79.         if(curl_errno($con))  
    80.         {  
    81.             file_put_contents("tmp.txt", curl_errno($con).PHP_EOL,FILE_APPEND);  
    82.         }  
    83.           
    84.         return $result;  
    85.     }  
    86.       
    87.     public  function  CreateMenu()  
    88.     {  
    89.         $token = $this->Get_access_token("wxa5fd3441ffa34","a49921c7d71b57850c57d1f589");  
    90.         $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$token;  //自定义菜单接口  
    91.           
    92.         $menuData = array(  
    93.             'button' => array(  
    94.                 array(  
    95.                         'name' => '走进窗骑',  
    96.                         'sub_button' => array(  
    97.                                 array(  
    98.                                         'type' =>'click',  
    99.                                         'name' => '微官网',  
    100.                                         'key' => 'sdwgw'  
    101.                                 ),  
    102.                                 array(  
    103.                                         'type' =>'view',  
    104.                                         'name' => '全品牌推广',  
    105.                                         'url' => 'http://128.88.44.11/WXProject/DataHtml/html/qpptg.html'  
    106.                                 ),  
    107.                                 array(  
    108.                                         'type' =>'view',  
    109.                                         'name' => '3D影视包装',  
    110.                                         'url' => 'http://128.88,44,11/WXProject/DataHtml/html/3d.html'  
    111.                                 ),  
    112.                                 array(  
    113.                                         'type' =>'view',  
    114.                                         'name' => '互动体验',  
    115.                                         'url' => 'http://128.88.44.11/WXProject/DataHtml/html/hudong.html'  
    116.                                 ),  
    117.                                 array(  
    118.                                         'type' =>'view',  
    119.                                         'name' => '合作客户',  
    120.                                         'url' => 'http://128.88.44.11/WXProject/DataHtml/html/partner.html'  
    121.                                 )  
    122.                                   
    123.                                   
    124.                     )  
    125.                 ),  
    126.                 array(  
    127.                         'name' => '微楼书',  
    128.                         'sub_button' =>array(  
    129.                                 array(  
    130.                                         'type' =>'click',  
    131.                                         'name' => '项目概况',  
    132.                                         'key' => 'xmgk'  
    133.                                 ),  
    134.                                 array(  
    135.                                         'type' =>'view',  
    136.                                         'name' => '区位配套',  
    137.                                         'url' => 'http://128.88.44.11/WXProject/DataHtml/qwpt.html'  
    138.                                 ),  
    139.                                 array(  
    140.                                         'type' =>'view',  
    141.                                         'name' => '景观鉴赏',  
    142.                                         'url' => 'http://128.88.44.11/WXProject/WXPicBrowser/jgjd.php'  
    143.                                 ),  
    144.                                 array(  
    145.                                         'type' =>'view',  
    146.                                         'name' => '户型展示',  
    147.                                         'url' => 'http://128.88.44.11/WXProject/WXPicBrowser/jdhx.php'  
    148.                                 ),  
    149.                                 array(  
    150.                                         'type' =>'view',  
    151.                                         'name' => '3D视频',  
    152.                                         'url' => 'http://128.88.44.11/WXProject/DataHtml/video.html'  
    153.                                 )  
    154.                         )   
    155.                 ),  
    156.                 array(  
    157.                     'name' => "互动体验",  
    158.                     'sub_button' => array(  
    159.                                 array(  
    160.                                         'type' =>'click',  
    161.                                         'name' => '会员中心',  
    162.                                         'key' => 'hyzx'  
    163.                                 ),  
    164.                                 array(  
    165.                                         'type' =>'view',  
    166.                                         'name' => '看房预约',  
    167.                                         'url' => 'http://128.88.44.11/WXProject/DataPHP/seehouse.php'  
    168.                                 ),  
    169.                                 array(  
    170.                                         'type' =>'view',  
    171.                                         'name' => '智能问答',  
    172.                                         'url' => 'http://128.88.44.11/WXProject/DataPHP/test.php'  
    173.                                 ),  
    174.                                 array(  
    175.                                         'type' =>'view',  
    176.                                         'name' => '一键功能',  
    177.                                         'url' => 'http://128.88.44.11/WXProject/onetouchdial.html#mp.weixin.qq.com'  
    178.                                 ),  
    179.                                 array(  
    180.                                         'type' =>'click',  
    181.                                         'name' => '刮刮乐',  
    182.                                         'key' => 'ggl'  
    183.                                 )  
    184.                     )  
    185.                 )  
    186.             )  
    187.         );  
    188.           
    189.         $data = JSON($menuData);  
    190.           
    191.         $this->DoCurlPostRequest($url,$data);  //以https发送post请求  
    192.     }  
    193. }  
    写完上面的类,直接在index.php,调用就行了;然后按前面几篇介绍的方法传到sae上面,运行测试


    3.大概思路:根据微信的文档说明,首先按规则创建好菜单,然后按规定写好创建自定义菜单接口,接着用https发送post请求,微信服务器收到请求,判断发送过来的接口没错;微信服务器发送创建好的菜单到每一位微信用户的客户端显示。


    ----------------------------------------------------------------------------------------------------------------------------------------------------------

    有同学说没有数据库操作类,我也直接贴出来吧!

    1. <?php  
    2. class DBManage  
    3. {  
    4.     private $conn;  
    5.     private static $_instance;  
    6.       
    7.     public function __clone()  
    8.     {  
    9.         trigger_error("Clone is not allow!",E_USER_ERROR);  
    10.     }  
    11.       
    12.     public static function getInstance()  
    13.     {  
    14.         if(!self::$_instance instanceof self)  
    15.         {  
    16.             self::$_instance = new self;  
    17.         }  
    18.         return self::$_instance;  
    19.     }  
    20.       
    21.     function ConnDB()  
    22.     {  
    23.         $this->conn = mysqli_init();  
    24.         $ret = mysqli_real_connect($this->conn, "122.128.111.111""root""mima222""wxdb", 6033, "t_userinfo", MYSQLI_CLIENT_FOUND_ROWS);  
    25.           
    26.     }  
    27.   
    28.     function ExecSql($sql)  
    29.     {  
    30.         $ret = mysqli_query($this->conn, $sql);  
    31.         return $ret;  
    32.     }  
    33.       
    34.     function GetEffectRows($sql)  
    35.     {  
    36.         $ret = mysqli_query($this->conn, $sql);  
    37.         return mysqli_num_rows($ret);  
    38.     }  
    39.       
    40.     function GetData($sql)  
    41.     {  
    42.         $ret = mysqli_query($this->conn, $sql);  
    43.           
    44.         return $ret;  
    45.     }  
    46.       
    47.       
    48. }  
    49. ?>  

    展开全文
  • 以下是微信公众平台对 添加自定义菜单 的文档说明:1、自定义菜单最多包括3一级菜单,每一级菜单最多包含5二级菜单。 2、一级菜单最多4汉字,二级菜单最多7汉字,出来的部分将会以“...”代替。 3、创建...

    以下是微信公众平台对 添加自定义菜单 的文档说明:

    自定义菜单创建接口

    自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示:

    请注意:

    1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
    2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
    3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。

    自定义菜单接口可实现多种类型按钮,如下:

    1、click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
    2、view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
    3、scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
    4、scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
    5、pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
    6、pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
    7、pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
    8、location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
    9、media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    10、view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。

    请注意,3到8的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。9和10,是专门给第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,它们是没有事件推送的,能力相对受限,其他类型的公众号不必使用。

    接口调用请求说明

    http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

    click和view的请求示例

     {
         "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"
                }]
           }]
     }

    其他新增按钮类型的请求示例

    {
        "button": [
            {
                "name": "扫码", 
                "sub_button": [
                    {
                        "type": "scancode_waitmsg", 
                        "name": "扫码带提示", 
                        "key": "rselfmenu_0_0", 
                        "sub_button": [ ]
                    }, 
                    {
                        "type": "scancode_push", 
                        "name": "扫码推事件", 
                        "key": "rselfmenu_0_1", 
                        "sub_button": [ ]
                    }
                ]
            }, 
            {
                "name": "发图", 
                "sub_button": [
                    {
                        "type": "pic_sysphoto", 
                        "name": "系统拍照发图", 
                        "key": "rselfmenu_1_0", 
                       "sub_button": [ ]
                     }, 
                    {
                        "type": "pic_photo_or_album", 
                        "name": "拍照或者相册发图", 
                        "key": "rselfmenu_1_1", 
                        "sub_button": [ ]
                    }, 
                    {
                        "type": "pic_weixin", 
                        "name": "微信相册发图", 
                        "key": "rselfmenu_1_2", 
                        "sub_button": [ ]
                    }
                ]
            }, 
            {
                "name": "发送位置", 
                "type": "location_select", 
                "key": "rselfmenu_2_0"
            },
            {
               "type": "media_id", 
               "name": "图片", 
               "media_id": "MEDIA_ID1"
            }, 
            {
               "type": "view_limited", 
               "name": "图文消息", 
               "media_id": "MEDIA_ID2"
            }
        ]
    }

    参数说明

    参数 是否必须 说明
    button 一级菜单数组,个数应为1~3个
    sub_button 二级菜单数组,个数应为1~5个
    type 菜单的响应动作类型
    name 菜单标题,不超过16个字节,子菜单不超过60个字节
    key click等点击类型必须 菜单KEY值,用于消息接口推送,不超过128字节
    url view类型必须 网页链接,用户点击菜单可打开链接,不超过1024字节
    media_id media_id类型和view_limited类型必须 调用新增永久素材接口返回的合法media_id


    返回结果

    正确时的返回JSON数据包如下:

    {"errcode":0,"errmsg":"ok"}

    错误时的返回JSON数据包如下(示例为无效菜单名长度):

    {"errcode":40018,"errmsg":"invalid button name size"}
    根据微信的开发文档,我们可以知道能创建的菜单按钮类型一共有以下几种:

    1、click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
    2、view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
    3、scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
    4、scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
    5、pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
    6、pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
    7、pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
    8、location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
    9、media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    10、view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
    今天我就只给大家演示 click 和 view 类型按钮的创建,其他类型的按钮的创建方式是一模一样的。

    看着微信的开发文档,好像非常麻烦的样子。

    其实,当你真正了解了之后,会发现其实是无比的简单。。。 我们要撇弃我们的 “先入之见”。

    静下心来。。你会发现一切没有什么大不了。


    ----------------------------------------------------------------华丽丽的分割线-----------------------------------------------------------------------------------


    根据上面的文档我们知道 我们要想 创建自定义菜单要通过 POST 数据  到这个地址来完成:

     https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN


    然后我们要POST的数据是类似这样的:

     {
         "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解析工具解析下上面的数据  你会发现上面的数据就是类似 一个树形菜单。

    它包含了两个主菜单 “今日歌曲” 和 “菜单”  其中 “菜单” 这个主菜单又包含了三个子菜单:VIEW类型的 “搜索” 菜单,VIEW类型的“视频”菜单,click类型的“赞一下我们”  菜单。(可能有点绕口,文笔不行尴尬

    这就是我们要创建的东西。知道了我们要POST的数据,然后就可以写代码了。。。。。吗?还有一个重要的东西没有取到呢。

    就是我们POST数据地址后面那个 access_token,这个东西是我们开发微信公众号第一步就要获取的东西,在这里我就不多做说明了,大家可以参考我的另一篇文章:

    使用C# .net开发微信公众号之获取AccessToken


    现在万事具备,只欠写代码了。。。。。 我把自己写的代码贴过来供大家参考:

            /// <summary>
            /// 添加菜单
            /// </summary>
            /// <param name="accessToken"></param>
            /// <param name="data"></param>
            /// <returns></returns>
            public static string AddMenu(string accessToken, string data)
            {
                string url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}", accessToken);
                HttpWebRequest hwr = WebRequest.Create(url) as HttpWebRequest;
                hwr.Method = "POST";
                hwr.ContentType = "application/x-www-form-urlencoded";
                byte[] payload;
                payload = System.Text.Encoding.UTF8.GetBytes(data);
                hwr.ContentLength = payload.Length;
                Stream writer = hwr.GetRequestStream();
                writer.Write(payload, 0, payload.Length);
                writer.Close();
                var result = hwr.GetResponse() as HttpWebResponse;
                return strMsg;
            }

    通过上面的方法我们就可以设置自定义菜单了。

    返回结果

    正确时的返回JSON数据包如下:

    {"errcode":0,"errmsg":"ok"}

    错误时的返回JSON数据包如下(示例为无效菜单名长度):

    {"errcode":40018,"errmsg":"invalid button name size"}
    错误时会返回相应的errcode代码,大家可以去开发手册里查询 errcode 代表的意思:

    大家可以去手册里查 微信的 全局返回码说明
    
    
    创建自定义菜单方法到此结束。

    此方式或许有不妥之处,热烈欢迎大家吐槽。。。 错误之处也请大家指正,谢谢  -----    WeepingWeeper

    谢谢大家观看参考,让我们一同进步。

    微信的其他接口调用在持续更新中。。。欢迎关注持续关注。。


    展开全文
  • 1、自定义菜单最多包括3一级菜单,每一级菜单最多包含5二级菜单。 2、一级菜单最多4汉字,二级菜单最多7汉字,出来的部分将会以“...”代替。 3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号...
  • 微信开发交流群:148540125系列文章参考地址 极速开发微信公众号欢迎留言、转发 项目源码参考地址 点我点我–欢迎Start 前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开发者,重源码分析消息是如何...
  • 2)服务号可以申请自定义菜单; 3)使用QQ登录的公众号,可以升级为邮箱登录; 4)使用邮箱登录的公众号,可以修改登录邮箱; 5)编辑图文消息可选填作者; 6)群发消息可以同步到腾讯微博。 其中,大家议论...
  • 微信自定义菜单的创建与使用微信自定义菜单的创建与使用 需求 菜单类介绍 场景 代码 总结需求当微信公众号设置为开发者模式,想要自己创建和开发菜单的话,就需要自己调用微信创建菜单的接口来创建菜单了。创建菜单...
  • 微信企业号自定义菜单创建
  • 一、自定义菜单创建接口说明 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示: 请注意: ①自定义菜单最多包括3一级菜单,每一级菜单最多...
  • java版微信公众号开发自定义菜单创建
  • 很久以前写的微信自定义菜单由于当时没有保存源码,现在再写服务器后台发布页面又要写一遍(在网上搜了一遍没有找到这方面UI和交互的,也没有尝试去扒微信公众平台的),花了些时间又写了一,除了没有更换菜单位置...
  • 最近在做一基于微信公众号的资源回收系统,由于与队长的想法发生冲突的原因,就打算自己自学一下微信公众号的自定义菜单。 ▍概述 由于目前只是在大学阶段,没有企业身份,不能进行企业注册,也就无法使用...
  • 自定义菜单最多包括3一级菜单,每一级菜单最多包含5二级菜单。 2、一级菜单最多4汉字,二级菜单最多7汉字,出来的部分将会以“...”代替。 3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号...
  • 使用JAVA后端去自定义创建菜单微信公众号开发文档中提供了API: https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421141013,请大家认真的观看文档的中的信息, 创建菜单中有一些要注意的地方: ...
  • 在这里介绍微信公众号的自定义菜单开发 先恭迎我们的TX文档 微信公众号——自定义菜单栏 官方文档里说明了一些需要注意的事项 在这里 我只使用了几我业务中用到的类型 哈哈哈 本来在考虑要不要加在后台上...
  • 一、自定义菜单的说明和...3)创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。
  • 创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注...
1 2 3 4 5 ... 20
收藏数 15,861
精华内容 6,344
关键字:

多个自定义菜单 微信开发创建