微信开发创建view菜单_微信公众号开发创建菜单 - CSDN
  • 微信开发(自定义菜单整套流程)

    万次阅读 2016-10-04 15:44:39
    一、自定义菜单概述 自定义菜单能够帮助公众号丰富界面,让用户更好更快地理解公众号的功能。开启自定义菜单后,公众号界面如图所示: 二、申请自定义菜单 个人订阅号使用微博认证、企业订阅号通过...

    一、自定义菜单概述

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


    二、申请自定义菜单

    个人订阅号使用微博认证、企业订阅号通过微信认证;可以申请到自定义菜单资格

    服务号默认有菜单权限。

    三、获得AppId 和AppSecert

    AppId和AppSecret在开发者中心-开发者ID中,可以找到。



    四、获得Access Token

    appid和appsecert获得access token,接口为

    https://api.weixin.qq.com/cgi-bi ... mp;secret=APPSECRET

    程序实现如下

    $appid = "";
    $appsecret = "";
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appsecret";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    $jsoninfo = json_decode($output, true);
    $access_token = $jsoninfo["access_token"];

    复制代码

    你也可以直接在浏览器地址栏中,拼接出地址,执行后,获得如下数据

    {"access_token":"N2L7KXa084WvelONYjkJ_traBMCCvy_UKmpUUzlrQ0EA2yNp3Iz6eSUrRG0bhaR_viswd50vDuPkY5nG43d1gbm-olT2KRMxOsVE08RfeD9lvK9lMguNG9kpIkKGZEjIf8Jv2m9fFhf8bnNa-yQH3g",
    "expires_in":7200}


    复制代码

    参数说明如下


    其中的

    N2L7KXa084WvelONYjkJ_traBMCCvy_UKmpUUzlrQ0EA2yNp3Iz6eSUrRG0bhaR_viswd50vDuPkY5nG43d1gbm-olT2KRMxOsVE08RfeD9lvK9lMguNG9kpIkKGZEjIf8Jv2m9fFhf8bnNa-yQH3g
    就是access token。

    或者使用官方的接口调试工具,地址为:

    https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95&form=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E5%88%9B%E5%BB%BA%E6%8E%A5%E5%8F%A3%20/menu/create

    使用网页调试工具调试自定义菜单接口


    点击检查问题得,得到


    这样也获得了access token

    五、组织菜单内容

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

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

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


    接口调用请求说明

    http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bi ... _token=ACCESS_TOKEN

    请求示例

    1.{
    2.     "button":[
    3.     {    
    4.          "type":"click",
    5.          "name":"今日歌曲",
    6.          "key":"V1001_TODAY_MUSIC"
    7.      },
    8.      {
    9.           "type":"click",
    10.           "name":"歌手简介",
    11.           "key":"V1001_TODAY_SINGER"
    12.      },
    13.      {
    14.           "name":"菜单",
    15.           "sub_button":[
    16.           {    
    17.               "type":"view",
    18.               "name":"搜索",
    19.               "url":"http://www.soso.com/"
    20.            },
    21.            {
    22.               "type":"view",
    23.               "name":"视频",
    24.               "url":"http://v.qq.com/"
    25.            },
    26.            {
    27.               "type":"click",
    28.               "name":"赞一下我们",
    29.               "key":"V1001_GOOD"
    30.            }]
    31.       }]
    32.}

    复制代码

    参数说明


    返回结果

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

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

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

    {"errcode":40018,"errmsg":"invalid button name size"}

    六、提交菜单内容给服务器

    菜单的JSON结构为

    {"button": [{"name":"天气预报","sub_button":[{"type":"click","name":"北京天气","key":"天气北 京"},
    {"type":"click","name":"上海天气","key":"天气上海"},
    {"type":"click","name":" 广州天气","key":"天气广州"},{"type":"click","name":"深圳天气","key":"天气深圳"}, 
    {"type":"view","name":"本地天气","url":"http://m.hao123.com/a/tianqi"}]},
     {"name":"方倍工作室","sub_button":[{"type":"click","name":"公司简 介","key":"company"},
    {"type":"click","name":"趣味游戏","key":"游戏"}, {"type":"click","name":"讲个笑话","key":"笑话"}]}]}

    复制代码

    将以下代码保存为menu.php,并且在浏览器中运行该文件(比如 http://127.0.0.1/menu.php),将直接向微信服务器提交菜单,

    1.?php
    2.
    3.$access_token = "";
    4.
    5.$jsonmenu = '{
    6.      "button":[
    7.      {
    8.            "name":"天气预报",
    9.           "sub_button":[
    10.            {
    11.               "type":"click",
    12.               "name":"北京天气",
    13.               "key":"天气北京"
    14.            },
    15.            {
    16.               "type":"click",
    17.               "name":"上海天气",
    18.               "key":"天气上海"
    19.            },
    20.            {
    21.               "type":"click",
    22.               "name":"广州天气",
    23.               "key":"天气广州"
    24.            },
    25.            {
    26.               "type":"click",
    27.               "name":"深圳天气",
    28.               "key":"天气深圳"
    29.            },
    30.            {
    31.                "type":"view",
    32.                "name":"本地天气",
    33.                "url":"http://m.hao123.com/a/tianqi"
    34.            }]
    35.      
    36.
    37.       },
    38.       {
    39.           "name":"瑞雪",
    40.           "sub_button":[
    41.            {
    42.               "type":"click",
    43.               "name":"公司简介",
    44.               "key":"company"
    45.            },
    46.            {
    47.               "type":"click",
    48.               "name":"趣味游戏",
    49.               "key":"游戏"
    50.            },
    51.            {
    52.                "type":"click",
    53.                "name":"讲个笑话",
    54.                "key":"笑话"
    55.            }]
    56.       
    57.
    58.       }]
    59.}';
    60.
    61.
    62.$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
    63.$result = https_request($url, $jsonmenu);
    64.var_dump($result);
    65.
    66.function https_request($url,$data = null){
    67.    $curl = curl_init();
    68.    curl_setopt($curl, CURLOPT_URL, $url);
    69.    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    70.    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    71.    if (!empty($data)){
    72.        curl_setopt($curl, CURLOPT_POST, 1);
    73.        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    74.    }
    75.    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    76.    $output = curl_exec($curl);
    77.    curl_close($curl);
    78.    return $output;
    79.}
    80.
    81.?>


    复制代码

    或者使用官方的调试接口 使用网页调试工具调试该接口



    提交成功后,重新关注后即可看到菜单。菜单效果类似如下:


    七、响应菜单点击事件

    在消息接口中处理event事件,其中的click代表菜单点击,通过响应菜单结构中的key值回应消息,view事件无须响应,将直接跳转过去

    define("TOKEN", "weixin");
    
    $wechatObj = new wechatCallbackapiTest();
    if (!isset($_GET['echostr'])) {
        $wechatObj->responseMsg();
    }else{
       $wechatObj->valid();
    }
    
    class wechatCallbackapiTest
    {
       public function valid()
       {
            $echoStr = $_GET["echostr"];
           if($this->checkSignature()){
                echo $echoStr;
               exit;
           }
      }
    
       private function checkSignature()
       {
            $signature = $_GET["signature"];
          $timestamp = $_GET["timestamp"];
           $nonce = $_GET["nonce"];
    
          $token = TOKEN;
            $tmpArr = array($token, $timestamp, $nonce);
           sort($tmpArr);
           $tmpStr = implode( $tmpArr );
            $tmpStr = sha1( $tmpStr );
    
            if( $tmpStr == $signature ){
                return true;
            }else{
                return false;
            }
       }
    
        public function responseMsg()
        {
            $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
            if (!empty($postStr)){
               $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $RX_TYPE = trim($postObj->MsgType);
    
              switch ($RX_TYPE)
               {
                    case "text":
                        $resultStr = $this->receiveText($postObj);
                        break;
                    case "event":
                      $resultStr = $this->receiveEvent($postObj);
                        break;
                   default:
                        $resultStr = "";
                      break;
               }
                echo $resultStr;
            }else {
               echo "";
              exit;
            }
       }
    
        private function receiveText($object)
       {
           $funcFlag = 0;
           $contentStr = "你发送的内容为:".$object->Content;
           $resultStr = $this->transmitText($object, $contentStr, $funcFlag);
            return $resultStr;
       }
        
       private function receiveEvent($object)
       {
           $contentStr = "";
            switch ($object->Event)
           {
                case "subscribe":
                    $contentStr = "欢迎洋洋博客";
               case "unsubscribe":
                    break;
                case "CLICK":
                   switch ($object->EventKey)
                   {
                        case "company":
                           $contentStr[] = array("Title" =>"公司简介", 
                            "Description" =>"洋洋的博客", 
                           "PicUrl" =>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", 
                           "Url" =>"weixin://addfriend/pondbaystudio");
                           break;
                        default:
                           $contentStr[] = array("Title" =>"默认菜单回复", 
                            "Description" =>"您正在使用的是<span style="font-family: Arial, Helvetica, sans-serif;">洋洋的博客</span><span style="font-family: Arial, Helvetica, sans-serif;">", </span>
                           "PicUrl" =>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", 
                            "Url" =>"weixin://addfriend/pondbaystudio");
                            break;
                    }
                    break;
                default:
                   break;      
    
           }
            if (is_array($contentStr)){
               $resultStr = $this->transmitNews($object, $contentStr);
           }else{
               $resultStr = $this->transmitText($object, $contentStr);
          }
           return $resultStr;
       }
    
        private function transmitText($object, $content, $funcFlag = 0)
        {
           $textTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime>%s</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[%s]]></Content>
    <FuncFlag>%d</FuncFlag>
    </xml>";
            $resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content, $funcFlag);
            return $resultStr;
        }
    
       private function transmitNews($object, $arr_item, $funcFlag = 0)
        {
           //首条标题28字,其他标题39字
            if(!is_array($arr_item))
               return;
    
            $itemTpl = "    <item>
            <Title><![CDATA[%s]]></Title>
           <Description><![CDATA[%s]]></Description>
           <PicUrl><![CDATA[%s]]></PicUrl>
           <Url><![CDATA[%s]]></Url>
       </item>
    ";
            $item_str = "";
           foreach ($arr_item as $item)
               $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
    
            $newsTpl = "<xml>
    <ToUserName><![CDATA[%s]]></ToUserName>
    <FromUserName><![CDATA[%s]]></FromUserName>
    <CreateTime>%s</CreateTime>
    <MsgType><![CDATA[news]]></MsgType>
    <Content><![CDATA[]]></Content>
    <ArticleCount>%s</ArticleCount>
    <Articles>
    $item_str</Articles>
    <FuncFlag>%s</FuncFlag>
    </xml>";
    
          $resultStr = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item), $funcFlag);
            return $resultStr;
        }
    }
    ?> 

    复制代码

    八、菜单中获取OpenID

    由于菜单中只能填写固定的url地址,对于想要菜单中获取用户的OpenID的情况,可以使用OAuth2.0授权的方式来实现。

    URL中填写的地址为一个固定的回调地址。原理方法可以参考  微信公众平台开发(99) 自定义菜单获取OpenID

    <?php
    /*
        洋洋的博客
    */
    
    define("TOKEN", "weixin");
    $wechatObj = new wechatCallbackapiTest();
    if (isset($_GET['echostr'])) {
        $wechatObj->valid();
    }else{
        $wechatObj->responseMsg();
    }
    
    class wechatCallbackapiTest
    {
        public function valid()
        {
            $echoStr = $_GET["echostr"];
            if($this->checkSignature()){
                header('content-type:text');
                echo $echoStr;
                exit;
            }
        }
    
        private function checkSignature()
        {
            $signature = $_GET["signature"];
            $timestamp = $_GET["timestamp"];
            $nonce = $_GET["nonce"];
    
            $token = TOKEN;
            $tmpArr = array($token, $timestamp, $nonce);
            sort($tmpArr, SORT_STRING);
            $tmpStr = implode( $tmpArr );
            $tmpStr = sha1( $tmpStr );
    
            if( $tmpStr == $signature ){
                return true;
            }else{
                return false;
            }
        }
    
        public function responseMsg()
        {
            $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    
            if (!empty($postStr)){
                $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
                $fromUsername = $postObj->FromUserName;
                $toUsername = $postObj->ToUserName;
                $keyword = trim($postObj->Content);
                $time = time();
                $textTpl = "<xml>
                            <ToUserName><![CDATA[%s]]></ToUserName>
                            <FromUserName><![CDATA[%s]]></FromUserName>
                            <CreateTime>%s</CreateTime>
                            <MsgType><![CDATA[%s]]></MsgType>
                            <Content><![CDATA[%s]]></Content>
                            <FuncFlag>0</FuncFlag>
                            </xml>";
                if($keyword == "?" || $keyword == "?")
                {
                    $msgType = "text";
                    $contentStr = '当前时间是:'.date("Y-m-d H:i:s",time());
                    $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
                    echo $resultStr;
                }
            }else{
                echo "";
                exit;
            }
        }
    }
    ?>

    展开全文
  • 在上篇文章实现微信扫码获取带指定参数时,微信公众号后台启用了服务器配置,导致之前设置好的微信自定义菜单失效。 开启了服务器配置,就无法用之前的方式在微信公众平台配置自定义菜单 此时,我们要通过接口来...

    在上篇文章实现微信扫码获取带指定参数时,微信公众号后台启用了服务器配置,导致之前设置好的微信自定义菜单失效。
    这里写图片描述
    开启了服务器配置,就无法用之前的方式在微信公众平台配置自定义菜单
    此时,我们要通过接口来配置微信自定义菜单,微信自定义菜单接口链接

    这里写图片描述

    首先,我们打开微信公众平台接口调试工具 接口调试工具
    1.通过appid以及secret来获取access_token,
    这里写图片描述

    2.组织创建菜单内容。微信提供了许多不同功能的按钮类型,可根据实际需求组织创建。
    这里简单的创建两个1级view类型按钮:即用户点击按钮实现跳转URL。

    {
        "button": [
            {
                "type": "view", 
                "name": "百度", 
                "url": "http://www.baidu.com"
            }, 
            {
                "type": "view", 
                "name": "淘宝", 
                "url": "http://www.taobao.com"
            }
        ]
    }

    3.在接口调试工具- - -选择 ‘自定义菜单’的接口类型,填入access_token,以及刚刚构建好的菜单内容。

    这里写图片描述

    点击检查问题,如果填写参数正确,则请求成功。
    这里写图片描述

    此时,重新打开或重新关注公众号,即能看到刚刚构建的自定义菜单已经生效。

    展开全文
  • 距离写上一篇文章《自定义菜单创建菜单事件响应》整整过了两个月的时间,那时公众平台还没有开放view类型的菜单。在不久前,微信公众平台悄悄开放了view类型的菜单,却没有在首页发布任何通知,貌似微信团队很...

    引言及内容概要

    距离写上一篇文章《自定义菜单的创建及菜单事件响应》整整过了两个月的时间,那时公众平台还没有开放view类型的菜单。在不久前,微信公众平台悄悄开放了view类型的菜单,却没有在首页发布任何通知,貌似微信团队很喜欢这么干。一个偶然的机会,我留意到API文档的自定义菜单接口发生了变化,增加了对菜单view类型的说明:

    view(访问网页):

     用户点击view类型按钮后,会直接跳转到开发者指定的url中。

    于是我在第一时间更新了小q机器人(微信号:xiaoqrobot)的菜单,在一级菜单“更多”下增加了二级菜单“使用帮助”,点击该菜单项会直接跳转到网页,如下图所示。


    最近也有不少网友问起这种类型的菜单是如何创建的,本篇文章就为大家介绍下view类型的自定义菜单该如何创建。


    自定义菜单的两种类型(click和view)

    公众平台API文档中给出了自定义菜单的json结构示例,我从中截取两个菜单项的json代码,一个是click类型,另一个是view类型,如下所示。

    {	
    	"type":"click",
    	"name":"今日歌曲",
    	"key":"V1001_TODAY_MUSIC"
    },
    {
    	"type":"view",
    	"name":"歌手简介",
    	"url":"http://www.qq.com/"
    }
    从上面可以看出,两种类型的菜单除了type值不同之外,属性也有差别。click类型的菜单有key属性,而view类型的菜单没有key属性,与之对应的是url属性。通过上一篇的学习我们知道,key值是用于判断用户点击了哪个click类型的菜单项。而view类型的菜单没有key属性,目前无法在公众账号后台判断是否有用户点击了view类型的菜单项,也就没办法知道哪个用户点击了view类型的菜单项。


    建立view类型的菜单对象

    View类型的菜单有3个属性:type、name和url。在上一篇文章中,我们创建了菜单项的基类Button,Button类只有一个属性name。View类型的菜单对象也需要继承Button类,代码如下:

    package org.liufeng.weixin.pojo;
    
    /**
     * view类型的菜单
     * 
     * @author liuyq
     * @date 2013-04-10
     */
    public class ViewButton extends Button {
    	private String type;
    	private String url;
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	public String getUrl() {
    		return url;
    	}
    
    	public void setUrl(String url) {
    		this.url = url;
    	}
    }


    创建带view类型的菜单示例

    我们对前一篇文章中给出的菜单创建代码进行调整,增加view类型的菜单项,完整的菜单创建代码如下:

    package org.liufeng.weixin.main;
    
    import org.liufeng.weixin.pojo.AccessToken;
    import org.liufeng.weixin.pojo.Button;
    import org.liufeng.weixin.pojo.CommonButton;
    import org.liufeng.weixin.pojo.ComplexButton;
    import org.liufeng.weixin.pojo.Menu;
    import org.liufeng.weixin.pojo.ViewButton;
    import org.liufeng.weixin.util.WeixinUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 菜单管理器类
     * 
     * @author liufeng
     * @date 2013-08-08
     */
    public class MenuManager {
    	private static Logger log = LoggerFactory.getLogger(MenuManager.class);
    
    	public static void main(String[] args) {
    		// 第三方用户唯一凭证
    		String appId = "000000000000000000";
    		// 第三方用户唯一凭证密钥
    		String appSecret = "00000000000000000000000000000000";
    
    		// 调用接口获取access_token
    		AccessToken at = WeixinUtil.getAccessToken(appId, appSecret);
    
    		if (null != at) {
    			// 调用接口创建菜单
    			int result = WeixinUtil.createMenu(getMenu(), at.getToken());
    
    			// 判断菜单创建结果
    			if (0 == result)
    				log.info("菜单创建成功!");
    			else
    				log.info("菜单创建失败,错误码:" + result);
    		}
    	}
    
    	/**
    	 * 组装菜单数据
    	 * 
    	 * @return
    	 */
    	private static Menu getMenu() {
    		CommonButton btn11 = new CommonButton();
    		btn11.setName("天气预报");
    		btn11.setType("click");
    		btn11.setKey("11");
    
    		CommonButton btn12 = new CommonButton();
    		btn12.setName("公交查询");
    		btn12.setType("click");
    		btn12.setKey("12");
    
    		CommonButton btn13 = new CommonButton();
    		btn13.setName("周边搜索");
    		btn13.setType("click");
    		btn13.setKey("13");
    
    		CommonButton btn14 = new CommonButton();
    		btn14.setName("历史上的今天");
    		btn14.setType("click");
    		btn14.setKey("14");
    		
    		CommonButton btn15 = new CommonButton();
    		btn15.setName("电影排行榜");
    		btn15.setType("click");
    		btn15.setKey("32");
    
    		CommonButton btn21 = new CommonButton();
    		btn21.setName("歌曲点播");
    		btn21.setType("click");
    		btn21.setKey("21");
    
    		CommonButton btn22 = new CommonButton();
    		btn22.setName("经典游戏");
    		btn22.setType("click");
    		btn22.setKey("22");
    
    		CommonButton btn23 = new CommonButton();
    		btn23.setName("美女电台");
    		btn23.setType("click");
    		btn23.setKey("23");
    
    		CommonButton btn24 = new CommonButton();
    		btn24.setName("人脸识别");
    		btn24.setType("click");
    		btn24.setKey("24");
    
    		CommonButton btn25 = new CommonButton();
    		btn25.setName("聊天唠嗑");
    		btn25.setType("click");
    		btn25.setKey("25");
    
    		CommonButton btn31 = new CommonButton();
    		btn31.setName("Q友圈");
    		btn31.setType("click");
    		btn31.setKey("31");
    
    		CommonButton btn33 = new CommonButton();
    		btn33.setName("幽默笑话");
    		btn33.setType("click");
    		btn33.setKey("33");
    		
    		CommonButton btn34 = new CommonButton();
    		btn34.setName("用户反馈");
    		btn34.setType("click");
    		btn34.setKey("34");
    		
    		CommonButton btn35 = new CommonButton();
    		btn35.setName("关于我们");
    		btn35.setType("click");
    		btn35.setKey("35");
    		
    		ViewButton btn32 = new ViewButton();
    		btn32.setName("使用帮助");
    		btn32.setType("view");
    		btn32.setUrl("http://liufeng.gotoip2.com/xiaoqrobot/help.jsp");
    
    		ComplexButton mainBtn1 = new ComplexButton();
    		mainBtn1.setName("生活助手");
    		mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13, btn14, btn15 });
    
    		ComplexButton mainBtn2 = new ComplexButton();
    		mainBtn2.setName("休闲驿站");
    		mainBtn2.setSub_button(new Button[] { btn21, btn22, btn23, btn24, btn25 });
    
    		ComplexButton mainBtn3 = new ComplexButton();
    		mainBtn3.setName("更多");
    		mainBtn3.setSub_button(new Button[] { btn31, btn33, btn34, btn35, btn32 });
    
    		/**
    		 * 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项<br>
    		 * 
    		 * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br>
    		 * 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:<br>
    		 * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 });
    		 */
    		Menu menu = new Menu();
    		menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 });
    
    		return menu;
    	}
    }

    119~122行代码就是用于创建view类型菜单项的。上面的菜单结构也是小q机器人(微信号:xiaoqrobot)目前在使用的,读者可以对照着理解。

    补充:居然还有些网友问我上面的自定义菜单创建代码在哪里调用,问我为什么不把调用的代码也公开?搞的我都有点不好意思了。上面的菜单创建代码是写在main方法中,直接在开发工具中运行一下就可以了,这应该是最最基础的Java知识了。另外,菜单只要创建一次,会一直存在的,不需要每次启动应用程序都去创建菜单。当然,你也可以把菜单的创建代码集成到项目中,并非一定要放在main方法中。程序是死的,人是活的,解决方法往往有很多种,怎么方便实用就怎么来!


    如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号xiaoqrobot来支持柳峰!

    转帖请注明本文出自柳峰的博客(http://blog.csdn.net/lyq8479),请尊重他人的辛勤劳动成果,谢谢!


    展开全文
  • 首先要了解,在做微信开发项目的时候,都是需要进行一个token验证的,微信服务端去验证你传来的token,校验通过之后,才能给你开放一些借口以便于你进行一些详细的读写操作,所以我们在做开发之前都是需要先通过微信...

    首先要了解,在做微信开发项目的时候,都是需要进行一个token验证的,微信服务端去验证你传来的token,校验通过之后,才能给你开放一些借口以便于你进行一些详细的读写操作,所以我们在做开发之前都是需要先通过微信端的接口来获取到access_token来进行接下来的一些操作,具体看代码
    这是微信提供的获取access_token的地址
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    这其中有三个参数:

    • grant_type——获取access_token填写client_credential
    • appid——第三方用户唯一凭证
    • secret——第三方用户唯一凭证密钥,即appsecret
      通过你传来的appid和secret来识别唯一的用户,就是判断你是否是开发者并且你的账号没有异常,校验通过以后
      正常情况下,微信会返回下述JSON数据包:{“access_token”:“ACCESS_TOKEN”,“expires_in”:7200}
      这里的access_token就是你获取到的token,expires_in就是这个token的过期时间2个小时,当我们获取到这个token以后就可以进行接下来的具体的操作了
      如果我们想要新建一个自定义菜单例如:

    {
    “button”:[
    {
    “type”:“click”,
    “name”:“今日歌曲”,
    “key”:“V1001_TODAY_MUSIC”
    },
    {
    “name”:“菜单”,
    “sub_button”:[
    {
    “type”:“view”,
    “name”:“搜索”,
    “url”:“http://www.soso.com/
    },
    {
    “type”:“miniprogram”,
    “name”:“wxa”,
    “url”:“http://mp.weixin.qq.com”,
    “appid”:“wx286b93c14bbf93aa”,
    “pagepath”:“pages/lunar/index”
    },
    {
    “type”:“click”,
    “name”:“赞一下我们”,
    “key”:“V1001_GOOD”
    }]
    }]
    }

    这样模块的一个菜单,通过一些json拼接数组的操作就可以得到这样的数据

    //根据pid去数据库查询一级菜单
    List<WeChatMenu> menuList = wechatMapper.findById(0);
    JSONObject parentjson = new JSONObject();
    
    JSONArray parentarray = new JSONArray();
    
    //循环集合,拼接第一级菜单
    for (int i = 0; i < menuList.size() ; i++) {
        WeChatMenu weChatMenu = menuList.get(i);//获取第一级菜单
    
        JSONObject jsonObject = new JSONObject();
    
        JSONArray jsonArray = new JSONArray();
        //判断同级菜单中是否存在type为null的情况
        if(!StringUtils.isBlank(weChatMenu.getM_type())){//type不为空,添加type类型,否则不添加
            jsonObject.put("type",weChatMenu.getM_type());
            jsonObject.put("name",weChatMenu.getM_name());
            //根据获取到的type类型判断增加的是key还是url
            if(weChatMenu.getM_type().equals("click")){
                jsonObject.put("key",weChatMenu.getM_key());
            }
            if(weChatMenu.getM_type().equals("view")){
                jsonObject.put("url",weChatMenu.getM_url());
            }
        }else{
            jsonObject.put("name",weChatMenu.getM_name());
            List<WeChatMenu> list = wechatMapper.findById(weChatMenu.getId());//根据一级菜单的id查询对应的子菜单
            for (int j = 0; j < list.size(); j++) {
                WeChatMenu menu = list.get(j);
                JSONObject childrenjson = new JSONObject();
                childrenjson.put("type",menu.getM_type());
                childrenjson.put("name",menu.getM_name());
    
                if(menu.getM_type().equals("click")){
                    childrenjson.put("key",menu.getM_key());
                }
    
                if(menu.getM_type().equals("view")){
                    childrenjson.put("url",menu.getM_url());
                }
                jsonArray.add(childrenjson);
            }
            jsonObject.put("sub_button",jsonArray);
        }
    
        parentarray.add(jsonObject);
    }
    //拼接一级菜单
    parentjson.put("button", parentarray);//{"button":[]}
    

    这是我的数据库的表结构,展示一下
    在这里插入图片描述
    这是嵌套循环的方式获取到的数据的代码,也可以通过递归的方法来获取,具体看个人喜好,在这里关于菜单的type类型我只判断了click和view,因为开发中基本上用的最多的就是这两种,如果还需要其他的那么久自行添加。拼接完这些数据之后,就需要通过调用微信提供的接口把我们的数据和获取到的access_token传过去,等微信端校验完成之后就可以看到新建好的菜单了。
    那么怎么在项目中通过java代码来实现操作呢,就需要用到httpclient post请求方式

    public static String postMethod(String url,String param){
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);
        String result = null;
        try {
            StringEntity entity = new StringEntity(param,Charset.forName("UTF-8"));
            post.setEntity(entity);
            HttpResponse execute = httpClient.execute(post);
            result = EntityUtils.toString(execute.getEntity());//将返回来的实体对象转换成字符串
    
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    

    这里我自定义了一个工具类,只需要把拼接好的数据放入进来就可以了

    //将拼接好的字符串和地址通过httputils发送请求
    String result = HttpClientUtils.postMethod(change_menulist_url, parentjson.toString());
    

    如果校验成功并且拼接的数据没有错的话就会返回来{“errcode”:0,“errmsg”:“ok”}这样的result

    这是关于返回来的状态码的详细解释

    展开全文
  • java版微信公众号开发之自定义菜单创建

    万次阅读 多人点赞 2016-05-11 19:33:49
    java版微信公众号开发之自定义菜单创建
  • 以下是微信公众平台对 添加自定义菜单 的文档说明:1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。 2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。 3、创建...
  • 前文说到接入了开发者模式后用户通过微信后台创建菜单就会丢失。这时候就要程序员通过微信的接口手动去创建菜单微信创建菜单比较简单。 可以参照微信的官方文档点击打开链接 需要注意的是微信创建菜单有一定的...
  • 3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消...
  • 微信企业号创建菜单 <?php define('CorpID', "wx82e2c31215d9a5a7"); define('CorpSecret', ""); //当前管理组 设置->功能设置->权限管理->系统管理组->深圳管理(新建的管理组)->Secret ...
  • 10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例 欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/ 首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有...
  • 在上篇文章中完成了菜单、按钮bean的封装,现在来实现微信公众号菜单创建 向wx_cfg配置表中插入若干菜单记录 INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx...
  • 使用JAVA后端去自定义创建菜单微信公众号开发文档中提供了API: https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013,请大家认真的观看文档的中的信息, 创建菜单中有一些要注意的地方: 1、...
  • 大家可能经常看到一些微信公众号具有功能强大的自定义菜单,点击之后可以访问很多有用的功能。 这篇教程就教大家如何动手做一做。 这个教程最后实现的效果是:创建一个...文档里给了创建自定义菜单需要维护参数的H...
  • 微信5.0发布 2013年8月5日,伴随着微信5.0 iPhone版的发布,公众平台也进行了重要的更新,主要包括: 1)运营主体为组织,可选择成为服务号或者订阅号; 2)服务号可以申请自定义菜单; 3)使用QQ登录的公众号,...
  • 1 方式一:不写代码,使用微信公众平台接口调试工具来创建菜单{ "button": [ { "name": "百度", "type": "view", "url": "...
  • 微信开发模式下自定义菜单配置

    千次阅读 2018-03-24 12:27:54
    微信打开开发者模式后,以前通过微信后台配置的菜单就失效了,需要通过我们自己服务器后台配置(需要开发),还有一种比较简单的方法,就是通过微信提供的“微信公众平台接口测试工具”进行配置。下面重点说一下通过...
  • 自定义菜单这个功能在我们普通的编辑模式下是可以直接在后台编辑的,但是一旦我们进入开发模式之后我们的自定义菜单就需要自己用代码实现,所以对于刚开始接触的人来说可能存在一定的疑惑,这里我说下平时我们在开发...
  • 微信公众号开发教程(四)自定义菜单

    千次阅读 2018-06-22 14:19:09
    作者:陈惠,叩丁狼教育...菜单效果:打开开发文档,选择”自定义菜单”的”菜单创建接口”。注意: 1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。 2、一级菜单最多4个汉字,二级菜单最多...
  • Java微信公众平台开发之自定义菜单

    千次阅读 2017-09-01 11:21:03
    一、自定义菜单的说明和...3)创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单
1 2 3 4 5 ... 20
收藏数 6,728
精华内容 2,691
关键字:

微信开发创建view菜单