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

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

    这里写图片描述

    首先,我们打开微信公众平台接口调试工具 接口调试工具
    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,以及刚刚构建好的菜单内容。

    这里写图片描述

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

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

    展开全文
  • 数据结构类型参照微信公众平台数据格式,这里不做分析: 创建相应的实体类: public class Button { //菜单类型 private String type; //菜单名称 private String name; //二级菜单 private Button[] sub_button...

    1.自定义菜单功能:

    数据结构类型参照微信公众平台数据格式,这里不做分析:

    创建相应的实体类:

    public class Button {
    //菜单类型
    private String type;
    //菜单名称
    private String name;
    //二级菜单
    private Button[] sub_button;
    public String getType() {
    return type;
    }
    public void setType(String type) {
    this.type = type;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public Button[] getSub_button() {
    return sub_button;
    }
    public void setSub_button(Button[] sub_button) {
    this.sub_button = sub_button;
    }

    }

    再创建ClickButton类

    public class ClickButton extends Button{
    //Click类型菜单key
    private String key;


    public String getKey() {
    return key;
    }


    public void setKey(String key) {
    this.key = key;
    }

    }

    再创建ViewButton类

    public class ViewButton extends Button{
    //view类型菜单url
    private String url;


    public String getUrl() {
    return url;
    }


    public void setUrl(String url) {
    this.url = url;
    }

    }

    再创建我们的菜单类:

    public class Menu {
    //一级菜单
    private Button[] button;


    public Button[] getButton() {
    return button;
    }


    public void setButton(Button[] button) {
    this.button = button;
    }

    }

    2.创建新增菜单的方法

    public static Menu initMenu(){
    Menu menu = new Menu();
    ClickButton button11 = new ClickButton();
    button11.setName("click菜单");
    button11.setType("click");
    button11.setKey("11");

    ViewButton button21 = new ViewButton();
    button21.setName("view菜单");
    button21.setType("view");
    button21.setUrl("http://www.baidu.com");//我这里测试使用百度网站

    ClickButton button31 = new ClickButton();
    button31.setName("扫码事件");
    button31.setType("scancode_push");
    button31.setKey("31");

    ClickButton button32 = new ClickButton();
    button32.setName("地理位置");
    button32.setType("location_select");
    button32.setKey("32");

    Button button = new Button();
    button.setName("菜单");
    button.setSub_button(new Button[]{button31,button32});

    menu.setButton(new Button[]{button11,button21,button});
    return menu;

    }

    新增创建菜单访问请求路径常量

    //创建菜单
    public static int createMenu(String token,String menu) throws ParseException, IOException{
    int result = 0;
    String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token);
    JSONObject jsonObject = doPostStr(url, menu);
    if(jsonObject != null){
    //正常返回0
    result = jsonObject.getInt("errcode");
    }
    return result;

    }

    测试:

    public class WeixinTest {
    public static void main(String[] args){
    try {
    AccessToken token = WenXinUntil.getAccessToken();
    /*String filePath = "‪D:/image/123.jpg";
    String mediaId = WenXinUntil.upload(filePath,token.getToken(), "thumb");
    System.out.println("票据"+token.getToken());
    System.out.println("有效时间"+token.getExpiresIn());
    System.out.println(mediaId);*/
    String menu = JSONObject.fromObject(WenXinUntil.initMenu()).toString();
    int result = WenXinUntil.createMenu(token.getToken(), menu);
    if(result == 0){
    System.out.println("创建菜单成功");
    }else{
    System.out.println("创建菜单失败");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }

    }

    }

    3.运行结果:

    至此 微信自定义菜单完成!
    源码链接:链接:https://pan.baidu.com/s/11X4TjtupKeR0EIh3Xpsn2Q 
    提取码:29mo

    展开全文
  • 10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例 欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/ 首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有...

    10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例

    欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/

    首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有不同类型的子菜单,点击子菜单可以实现用户和公众号实时交互

    http://blogs.chenyunkeji.com

    本案例技术栈:springboot,mysql,logback,mybatis

    菜单创建请求接口:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

    首先是菜单项(按钮)的基类,所有一级菜单、二级菜单都有一个相同的属性,那就是name。菜单项基类的封装代码如下:

    public class Button {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    接着是子菜单项的封装。这里对子菜单是这样定义的:底部根菜单的二级菜单。这类子菜单项一定会包含三个属性:type、name和key,封装的代码如下

    public class CommandButton extends Button{
    
        private String type;
        private String key;
        
        public String getType() {
    	  return type;
        }
        public void setType(String type) {
    	  this.type = type;
        }
        public String getKey() {
    	  return key;
        }
        public void setKey(String key) {
    	  this.key = key;
        }
    }

     接着封装父菜单项。对父菜单项的定义:包含有二级菜单项的一级菜单。这类菜单项包含有二个属性:name和sub_button,而sub_button是一个子菜单项数组。父菜单项的封装代码如下:

    public class ComplexButton extends Button{
    
        private Button[] sub_button;
    
        public Button[] getSub_button() {
            return sub_button;
        }
    
        public void setSub_button(Button[] sub_button) {
            this.sub_button = sub_button;
        }
    }

    最后是整个菜单对象的封装,菜单对象包含多个根菜单项(最多只能有3个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项),如果能明白上面所讲的,再来看封装后的代码就很容易理解了:

    public class Menu {
        private Button[] button;
        public Button[] getButton() {
            return button;
        }
    
        public void setButton(Button[] button) {
            this.button = button;
        }
    }

     最后再封装一个链接类型的菜单,根据此处的名字也很好理解,不再赘述

    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;
        }
    }

    关于菜单实体类以及菜单对象的封装就介绍完了,下面根据微信接口创建自定义菜单。

    一、封装菜单创建工具类

    public class WeiXinMenuUtil {
    
        private static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";        private static Logger log = LoggerFactory.getLogger(WeiXinMenuUtil.class);
        public static int createMenu(Menu menu, String accessToken) {
            int result = 0;
            // 拼接创建菜单的url
            String url = menu_create_url .replace("ACCESS_TOKEN", accessToken);
            // 将菜单对象转换成json字符串
            String jsonMenu = JSON.toJSONString(menu);
            // 调用接口创建菜单
            JSONObject jsonObject = WeiXinUtil.httpPost(url, "POST", jsonMenu);
            if (null != jsonObject) {
                if (0 != (Integer)jsonObject.get("errcode")) {
                    result = (Integer)jsonObject.get("errcode");
                    log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.get("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return result;
        }
        
        public static Menu initMenu(){
            //1.创建菜单
            Menu menu = new Menu();
            // 主菜单1
            ComplexButton cb1 = new ComplexButton();
            cb1.setName("技术干货");
            
            // 主菜单2
            ComplexButton cb2 = new ComplexButton();
            cb2.setName("交流合作");
            
            // 主菜单3
            ComplexButton cb3 = new ComplexButton();
            cb3.setName("演示功能");
            
            // 主菜单1下面的子菜单1
            ViewButton cb01 = new ViewButton();
            cb01.setName("微服务教程连载");
            cb01.setType("view");
            cb01.setUrl("https://blog.csdn.net/guobinhui/article/category/8739270");
            
            // 主菜单1下面的子菜单2
            ViewButton cb02 = new ViewButton();
            cb02.setName("公众号开发教程");
            cb02.setType("view");
            cb02.setUrl("https://blog.csdn.net/guobinhui/article/category/8534361");
            
            ViewButton cb03 = new ViewButton();
            cb03.setName("小程序开发教程");
            cb03.setType("view");
            cb03.setUrl("https://blog.csdn.net/guobinhui/article/category/7763266");
            
            ViewButton cb04 = new ViewButton();
            cb04.setName("JavaEE基础");
            cb04.setType("view");
            cb04.setUrl("https://blog.csdn.net/guobinhui");
            
            ViewButton cb05 = new ViewButton();
            cb05.setName("笔者博客");
            cb05.setType("view");
            cb05.setUrl("http://blogs.chenyunkeji.com/");
            cb1.setSub_button(new ViewButton[]{cb01,cb02,cb03,cb04,cb05});
            
            // 主菜单2下面的子菜单1
            CommandButton cb11 = new CommandButton();
            cb11.setType("click");
            cb11.setKey("联系我");
            cb11.setName("联系笔者");
            
            CommandButton cb12 = new CommandButton();
            cb12.setName("技术交流");
            cb12.setType("click");
            cb12.setKey("18629374628");
            cb2.setSub_button(new CommandButton[]{cb11,cb12});
            
            CommandButton cb21 = new CommandButton();
            cb21.setType("scancode_waitmsg");
            cb21.setKey("rselfmenu_0_0");
            cb21.setName("扫码带提示");
            
            CommandButton cb22 = new CommandButton();
            cb22.setType("pic_sysphoto");
            cb22.setKey("rselfmenu_1_0");
            cb22.setName("系统拍照发图");
            
            CommandButton cb23 = new CommandButton();
            cb23.setType("pic_photo_or_album");
            cb23.setKey("rselfmenu_1_1");
            cb23.setName("拍照或者相册发图");
            
            CommandButton cb24 = new CommandButton();
            cb24.setType("pic_weixin");
            cb24.setKey("rselfmenu_1_2");
            cb24.setName("微信相册发图");
            
            CommandButton cb25 = new CommandButton();
            cb25.setType("location_select");
            cb25.setKey("rselfmenu_2_0");
            cb25.setName("发送地理位置");
            cb3.setSub_button(new CommandButton[]{cb21, cb22,cb23, cb24,cb25});
            menu.setButton(new Button[] { cb1,cb2, cb3});
            return menu;        
        }
    }

    二、微信接口凭证access_token的获取以及缓存实现

    access_token可以用各种缓存插件或者线程,定时任务,写入数据库等多种方式对access_token进行缓存7200秒,开发者可以依据自己的喜好选择其一,本案例策略采用IO流定时写入文件的方法缓存。首先获取access_token:

    public static JSONObject getToken()throws IOException{
    
     private String GET_ACCESS_TOKEN= "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
     String url = GET_ACCESS_TOKEN.replace("APPID",WeixinConstant.APPID).replace("APPSECRET",WeixinConstant.APPSECRET);
       JSONObject tokenObj = HttpGet(url);
       return tokenObj;
    }

    接着缓存access_token,也就是每隔7200秒生成一次access_token,生成的缓存7200秒,这样其余用到access_token的从文件中读取的就是最新的,不会过期。

    public static  Map <String,Object> cacheToken() throws IOException {
          Gson gson = new Gson();
          Map <String,Object> map = new HashMap <String,Object> ();
          String token = null;
          JSONObject tokenObj = null; //需要获取的access_token对象;
          String filePath = System.getProperty("user.dir")+"/src/main/resources/static/token.txt";
          File file = new File(filePath);//Access_token保存的位置
          if (!file.exists())
            file.createNewFile();
          // 如果文件大小等于0,说明第一次使用,存入Access_token
          if (file.length() == 0) {
            tokenObj = WeiXinUtil.getToken();
            token = (String)tokenObj.get("access_token");
            FileOutputStream fos = new FileOutputStream(filePath, false);// 不允许追加
            tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
            String json = gson.toJson(tokenObj);
            fos.write(json.getBytes());
            fos.close();
          }else {
            //读取文件内容
            @SuppressWarnings("resource")
            FileInputStream fis = new FileInputStream(file);
            byte[] b = new byte[2048];
            int len = fis.read(b);
            String jsonAccess_token = new String(b, 0, len);// 读取到的文件内容
            JSONObject access_token = gson.fromJson(jsonAccess_token,JSONObject.class);
            if (access_token.get("expires_in") != null) {
              String lastSaveTime = (String)access_token.get("expires_in");
              long nowTime = System.currentTimeMillis()/1000;
              long remianTime = nowTime - Long.valueOf(lastSaveTime);
              if (remianTime < WeixinConstant.EXPIRESIN_TIME) {
                  JSONObject access = gson.fromJson(jsonAccess_token,JSONObject.class);
                  token = (String)access.get("access_token");
              } else {
                  tokenObj = WeiXinUtil.getToken();
                  FileOutputStream fos = new FileOutputStream(file, false);// 不允许追加
                  tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
                  String json = gson.toJson(tokenObj);
                  fos.write((json).getBytes());
                  fos.close();
              }
          }
          }
          map.put("access_token",token);
          return map;
        }

    最后在项目的启动入口文件的main方法调用菜单创建方法进行初始化,那么项目在启动的时候,公众号的菜单就进行了初始化,用户就能看到公众号的菜单。

    @SpringBootApplication
    @MapperScan(basePackages = "com.chenyun.cloud.dao")
    public class HelloServiceApplication {
        private final static Logger logger= LoggerFactory.getLogger(HelloServiceApplication.class);
        
        public static void main(String[] args) {
             SpringApplication.run(HelloServiceApplication.class, args);
             Map<String, Object> map;
            try {
                map = WeiXinUtil.cacheToken();
                 String accessToken = (String)map.get("access_token");
                 logger.info("accessToken:"+accessToken);
                 Menu menu = WeiXinMenuUtil.initMenu();
                 System.out.println(JSON.toJSONString(menu));
                 int result  = WeiXinMenuUtil.createMenu(menu,accessToken);
                 if (0 == result){
                      logger.info("菜单创建成功!");
                  }else{
                      logger.info("菜单创建失败,错误码:" + result);
                  }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }    
    }

    启动项目后,打印的JSON格式的日志打就显示了创建的菜单结构。

    下节内容为大家分享公众号菜单栏的各种点击事件开发案例,更多JavaEE资料请关注下面公众号,欢迎广大开发者朋友一起交流。更多微信公众号功能演示请扫码体验,笔者电话(微信):18629374628

    展开全文
  • 微信开发菜单设计

    2017-03-31 15:41:51
    package menu; public class Button { private String type; private String name; private Button[] sub_button; public String getType() { return type; } public void setType(String type) { thi
    package menu;
    
    public class Button {
    
    	private String type;
    	private String name;
    	private Button[] sub_button;
    
    	public String getType() {
    		return type;
    	}
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public Button[] getSub_button() {
    		return sub_button;
    	}
    
    	public void setSub_button(Button[] sub_button) {
    		this.sub_button = sub_button;
    	}
    
    }
    


    package menu;
    
    public class ClickButton extends Button {
    	private String key;
    
    	public String getKey() {
    		return key;
    	}
    
    	public void setKey(String key) {
    		this.key = key;
    	}
    
    }
    

    package menu;
    
    public class Menu {
    
    	private Button[] button;
    
    	public Button[] getButton() {
    		return button;
    	}
    
    	public void setButton(Button[] button) {
    		this.button = button;
    	}
    
    }
    

    package menu;
    
    public class ViewButton extends Button {
    	private String url;
    
    	public String getUrl() {
    		return url;
    	}
    
    	public void setUrl(String url) {
    		this.url = url;
    	}
    
    }
    


    展开全文
  • 微信公众号开发5-自定义菜单-微信开发php讲师介绍: 秦子恒,CEO/董事长/总经理,大秦电商创始人,专注网络技术的电商应用。已经出品《1小时快速建站》《微博营销实战》《PHP采集》《网络招商系统》课程介绍: ...

    微信公众号开发5-自定义菜单-微信开发php

    讲师介绍: 
    秦子恒,CEO/董事长/总经理,大秦电商创始人,专注网络技术的电商应用。已经出品《1小时快速建站》《微博营销实战》《PHP采集》《网络招商系统》

    课程介绍: 
    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    课程特色: 
    专属答疑+课件资料提供+视频无限时回放+VIP交流群

    开课时间: 
    随到随学,自由支配

    点我试看: http://edu.csdn.net/course/detail/2953?utm_source=blog11

    展开全文
  • 微信打开开发者模式后,以前通过微信后台配置的菜单就失效了,需要通过我们自己服务器后台配置(需要开发),还有一种比较简单的方法,就是通过微信提供的“微信公众平台接口测试工具”进行配置。下面重点说一下通过...
  • 很久以前写的微信自定义菜单由于当时没有保存源码,现在再写服务器后台发布页面又要写一遍(在网上搜了一遍没有找到这方面UI和交互的,也没有尝试去扒微信公众平台的),花了些时间又写了一个,除了没有更换菜单位置...
  • 自定义菜单创建接口: http请求方式:POST(请使用https协议)https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN 自定义菜单查询接口: http请求方式:GET...
  • 微信公众号菜单栏加图标,微信公众号菜单栏加图标,微信公众号菜单栏加图标。
  • 在这里介绍微信公众号的自定义菜单开发 先恭迎我们的TX文档 微信公众号——自定义菜单栏 官方文档里说明了一些需要注意的事项 在这里 我只使用了几个我业务中用到的类型 哈哈哈 本来在考虑要不要加在后台上...
  • 在完成了微信公众号的接入之后,菜单功能就不能直接在公众号的后台进行编辑了,我们需要自己开发菜单功能,丰富公众号的功能 自定义菜单分为一级菜单和二级菜单 菜单实际上就是按钮,自定义菜单接口可实现多种...
  • 1,调用微信开发测试工具,检查菜单是否正确。 2,正确的情况下,浏览器调用一下菜单查询接口,重新关注公众号,很快生效。 转载于:https://www.cnblogs.com/code-Officer/p/8366197.html...
  • 最近几个月一直从事微信开发,从刚开始的懵懂渐渐成长了一点。今天觉得微信底部自定义菜单,如果能在html的页面上也能显示就好了. 记得以前看过某个网页有类似效果.查找了该网页的css. ok现在html css 实现微信自定义...
  • 我理解的微信公共平台里面菜单分为button和sub_button,即菜单和子菜单,这些菜单都有一个name的属性,类别分为click和view,click类有key属性;而view类有url属性,含有子菜单菜单没有key属性也没有url属性。这些...
  • 微信开发交流群:148540125系列文章参考地址 极速开发微信公众号欢迎留言、转发 项目源码参考地址 点我点我–欢迎Start 前几篇文章已讲完如何导入项目,如何启动配置项目,如何成为开发者,重源码分析消息是如何...
  • 总结需求当微信公众号设置为开发者模式,想要自己创建和开发菜单的话,就需要自己调用微信创建菜单的接口来创建菜单了。创建菜单之后,如果需要迫切的看到效果,有时候需要取消关注-从新关注才能够看到的哦(缓存问题...
  • 微信开发学习总结(四)——自定义菜单(5)——个性化菜单接口 博客地址: https://blog.csdn.net/qq_29914837/article/details/82948779
  • Android开发微信底部菜单栏实现的几种方法汇总转载 2016-09-26 作者:sky-mxc 我要评论 转载自:http://www.jb51.net/article/93537.htm这篇文章主要介绍了Android开发微信底部菜单栏实现的几种方法,下面小编把...
  • 本文要实现仿微信微信底部菜单栏+顶部菜单栏,采用ViewPage来做,每一个page对应一个XML,当手指在ViewPage左右滑动时,就相应显示不同的page(其实就是xml)并且同时改变底部菜单按钮的图片变暗或变亮,同时如果点击...
  • 微信自定义菜单生成器 http://menu.fangbei.org/index.php
1 2 3 4 5 ... 20
收藏数 31,148
精华内容 12,459