前言:

1,目前公众号类型分为两种:服务号和订阅号(服务号主要面向企业、政府和其他组织,而订阅号主要面向媒体和个人)

区别:只有服务号可以申请自定义菜单;服务号每月只能群发四条消息,而订阅号每天能群发一条消息(规则可能会变化,请以官方文档为准)

2,如果开发者想通过HTTP请求访问公众平台的接口,就必须要有访问凭证,也就是access_token(方法在第二章)

3,菜单数量为3(一级)*5(二级);一级菜单最多4个汉字,二级菜单最多7个汉字;可以有表情符号(自定义菜单实测字数可以更多)

4,菜单创建或变更后可能并不会立即在公众号上显示出来,最长可能要24小时。但取消关注后再关注可以立即看到新菜单

5,发布菜单:我是发送消息到公众号,判定如果是“menu”(随便什么都可以)则触发更新菜单(消息的发送和接收第四章会讲到)

6,我目前修改菜单,需要改动代码,重新发布后再触发更新菜单。其实比较麻烦,最好是在数据库存储,在后台管理。

正文:

1,对菜单结构的封装  最终提交的json格式菜单数据应该是由对象直接转换得到,而不是在程序代码中拼一大堆json数据

以下都是基类:

菜单项的基类(所有一级菜单、二级菜单都共有一个相同的属性,那就是name)

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

子菜单项的封装(有可能是二级菜单项,也有可能是不含二级菜单的一级菜单)

//click类型public class CommonButton 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;  }
}   

//view类型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 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;  }
}  

整个菜单对象的封装

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

2,生成菜单   主要介绍click和view,其他类型还没接触到

public static String menuManager() {           String respContent = "";//返回到微信的消息String access_token = WeixinUtil.getAccessToken(Config.fileName, Config.appId(), Config.appSecret());// 调用接口获取access_tokenif (!StringUtils.isEmpty(access_token)) {  // 调用接口创建菜单  int result = WeixinUtil.createMenu(getMenu(), access_token);  // 判断菜单创建结果  if (0 == result){               respContent = "菜单创建成功!";}else{respContent = "菜单创建失败,错误码:" + result; }  }  return respContent;
} 

    //组装菜单数据   private static Menu getMenu() {  ViewButton btn11 = new ViewButton();btn11.setName("测试view类型");  btn11.setType("view");  btn11.setUrl("https://www.ceshi.com/");  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 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 btn32 = new CommonButton();  btn32.setName("电影排行榜");  btn32.setType("click");  btn32.setKey("32");  CommonButton btn33 = new CommonButton();  btn33.setName("幽默笑话");  btn33.setType("click");  btn33.setKey("33");  ComplexButton mainBtn1 = new ComplexButton();  mainBtn1.setName("生活助手");  mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13, btn14 });  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, btn32, btn33 });  /** * 这个公众号目前的菜单结构,每个一级菜单都有二级菜单项 *  * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?* 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义 * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 }); */  Menu menu = new Menu();  menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 });  return menu;  }
}  

public static int createMenu(Menu menu, String accessToken) {
  int result = 0;String url = menu_create_url.replace("ACCESS_TOKEN", accessToken); // 拼装创建菜单的urlString jsonMenu = JSONObject.fromObject(menu).toString(); // 将菜单对象转换成json字符串JSONObject jsonObject = HttpRequest.httpRequest(url, "POST", jsonMenu); // 调用接口创建菜单
  if (null != jsonObject) {
    if (0 != jsonObject.getInt("errcode")) {result = jsonObject.getInt("errcode");logger.info("创建菜单失败 errcode:{}" + jsonObject.getInt("errcode") + "errmsg:{}" + jsonObject.getString("errmsg"));}}
  return result;
}

其中的httpRequest方法

    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  JSONObject jsonObject = null;  StringBuffer buffer = new StringBuffer();  try {  // 创建SSLContext对象,并使用我们指定的信任管理器初始化  TrustManager[] tm = { new MyX509TrustManager() };  SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  sslContext.init(null, tm, new java.security.SecureRandom());  // 从上述SSLContext对象中得到SSLSocketFactory对象  SSLSocketFactory ssf = sslContext.getSocketFactory();  URL url = new URL(requestUrl);  HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  httpUrlConn.setSSLSocketFactory(ssf);  httpUrlConn.setDoOutput(true);  httpUrlConn.setDoInput(true);  httpUrlConn.setUseCaches(false);  // 设置请求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);  if ("GET".equalsIgnoreCase(requestMethod))  httpUrlConn.connect();  // 当有数据需要提交时  if (null != outputStr) {  OutputStream outputStream = httpUrlConn.getOutputStream();  // 注意编码格式,防止中文乱码  outputStream.write(outputStr.getBytes("UTF-8"));  outputStream.close();  }  // 将返回的输入流转换成字符串  InputStream inputStream = httpUrlConn.getInputStream();  InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  String str = null;  while ((str = bufferedReader.readLine()) != null) {  buffer.append(str);  }  bufferedReader.close();  inputStreamReader.close();  // 释放资源
            inputStream.close();  inputStream = null;  httpUrlConn.disconnect();  logger.info("返回信息:"+ buffer.toString());jsonObject = JSONObject.fromObject(buffer.toString());  } catch (ConnectException ce) {  logger.info("Weixin server connection timed out.");  } catch (Exception e) {  logger.info("https request error:{}"+e);  }  return jsonObject;  }   

//证书信任管理器(用于https请求)
public class MyX509TrustManager implements X509TrustManager
{    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  }  public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  }  public X509Certificate[] getAcceptedIssuers() {  return null;  }
}

转载于:https://www.cnblogs.com/huashengweilong/p/7700244.html

【微信公众号开发】【3】自定义菜单相关推荐

  1. 微信公众号开发:自定义菜单

    前言: 回顾之前的微信公众号配置和消息处理的内容,我们已经掌握了如何配置服务器与微信公众号建立连接,也掌握了通过消息管理的方式,对用户的信息进行处理,完成公众号消息回复功能,实现公众号与用户之间的完整 ...

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

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

  3. 微信公众号编辑底部自定义菜单解决方案

    微信公众号编辑底部自定义菜单解决方案 1.需求背景 最近开发公众号项目,关于公众号里面底部的菜单栏设置一般常用有两种方法. 1,是进入公众号后台,找到自定义菜单,点击后进入编辑页面,进行编辑即可. 2 ...

  4. 微信公众平台开发,自定义菜单,群发消息,网页授权(3)

    前两节说的都是微信开发的初级篇,这一节说高级篇.微信公众号关注以后,下面都是有菜单的,底部有三个一级菜单,每个一级菜单可以添加5个二级菜单.一级菜单最多四个汉字,二级菜单最多7个汉字,多出来的汉字用& ...

  5. 微信公众平台开发(104) 自定义菜单扫一扫、发图片、发地理位置

    关键字:微信公众平台 自定义菜单 扫一扫 发图片 发地理位置 作者:方倍工作室 原文:http://www.cnblogs.com/txw1958/p/weixin-menu-new-type.htm ...

  6. c# 微信公众号开发之自定义菜单栏

    在微信公众号开启了第三方服务器之后,很多在微信平台上的配置都需要开发者通过微信提供的API,POST请求,将JSON字符串按格式,告知微信服务器 在这里介绍微信公众号的自定义菜单栏开发 先恭迎我们的T ...

  7. 微信公众平台开发教程--自定义菜单

    微信公众平台开发教程(五)自定义菜单 请尊重作者版权,如需转载,请标明出处. 应大家强烈要求,将自定义菜单功能课程提前. 一.概述: 如果只有输入框,可能太简单,感觉像命令行.自定义菜单,给我们提供了 ...

  8. 微信公众号之创建自定义菜单

    微信公众号菜单等功能如何开通 自定义菜单最大的优点是减少了用户的认知门槛,可以将公众账号里的重点信息入口直观的暴露给用户.当用户进入到公众账号时,可以一目了然的了解相关的服务,只需要点击,不需要再通过 ...

  9. php微信级联菜单,php微信公众号开发之二级菜单

    本文实例为大家分享了php微信公众号二级菜单的具体代码,供大家参考,具体内容如下 核心代码: $postObj = simplexml_load_string($postStr, 'SimpleXML ...

  10. 公众号 mysql数据库设计_微信公众号之灵活自定义菜单显示包含数据库结构设计...

    package com.ihaidou.entity.db.wechat; import io.swagger.annotations.ApiModelProperty; import lombok. ...

最新文章

  1. nginx请求频率限制模块ngx_http_limit_req_module
  2. Matlab策略模式
  3. 基于Windows8与Visual Studio2012开发内核隐藏注册表
  4. java访问方法修饰词四个_java中的四个修饰词(访问权限)
  5. RAID一个硬盘FAIL。
  6. 游戏筑基之游戏菜单制作(C语言)
  7. ueditor java_编辑器ueditor1.4.3 JAVA环境使用
  8. 如何彻底卸载VMware
  9. 小型功率三极管S9013
  10. RANGE MINIUM/MAXIUM QUERY问题
  11. 标准纸张尺寸 国际标准(ISO 216)
  12. 【LeetCode】跳步系列
  13. dismiss ios pop效果_动画切换效果之push、pop、present、dismiss
  14. 聊天气泡图片的动态拉伸、适配与镜像
  15. 雷锋工厂模式(笔记)
  16. 刀具、砂轮的过程监视和控制系统
  17. androidjni开发!应聘高级Android工程师历程感言,快来收藏!
  18. C++ Primer阅读笔记--书包程序
  19. 记录Spring cloud alibaba Nacos学习
  20. Python期末复习题:流程控制

热门文章

  1. C++11 atomic_exchange 实现无锁链表
  2. 那年我头脑发热,选择了自动化,后来我掉入计算机的世界无法自拔
  3. 全网最全的 Java 语法糖指南
  4. 1.定义一个结构体变量(包括年、月、日),编写程序,要求输入年、月、日,程序能判断该年是否为闰年。(闰年的条件是符合下面两者之一: ①能被4整除,但不能被100整除; ②能被100整除,又能被400整
  5. 【计算几何】凸包之graham算法(适合小白)
  6. 西门子PLC的符号表
  7. 让bug扼杀在摇篮里
  8. c#缩小至任务栏窗体弹出_C#实现任务栏通知窗口
  9. 转:用实际行动赢得别人追随
  10. 日期、时间、数字格式转换