前言:

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. php redis管理系统,php+redis实现小型的用户管理系统
  2. 你有哪些deep learning(rnn、cnn)调参的经验?
  3. 给CentOS添加第三方源
  4. android读取raw文件示例
  5. 动态规划 dp05 插入乘号问题 c代码
  6. MySQL中如何关闭事务的自动提交
  7. P1020 导弹拦截(LIS)
  8. 何时才有Email发布功能
  9. HDFS的块缓存和访问权限
  10. 费马大定理,集惊险与武侠于一体
  11. 评论数据获取、词频统计、词云图
  12. 计算机维修知识综述论文,机器学习领域各领域必读经典综述论文整理分享
  13. laravel 执行php命令报错PHP Parse error: syntax error, unexpected '=' in的解决方式
  14. inno setup 中文乱码问题_解决Inno Setup制作中文安装包在非中文系统上显示乱码的问题...
  15. python测试抽奖脚本_B站动态转发抽奖脚本+教程
  16. 最简理解空间射线与平面交点
  17. vue2 数据回显取消编辑不修改原数据
  18. 2019最值得关注的科技趋势【附罗振宇跨年演讲视频】
  19. html 锁屏模板,如何自定义锁屏样式
  20. Excel按照原图片名称批量导出工作簿中所有图片

热门文章

  1. 修改CS,IP的指令
  2. 【STM32扫描4x4矩阵键盘模块】 4x4 matrix keypad interface
  3. 储存quill与php,Quill自定义上传图片
  4. 《layui宇宙版教程》:徽章
  5. php mockery单元测试,使用testify和mockery库简化单元测试
  6. 肇兴:男人的天堂,来了就不想走--义工篇
  7. Django CORS指南
  8. 第一章--python入门之新手村的试炼
  9. Windows实现流媒体服务器搭建 ngnix+rtmp+ffmpg+hls实现播放rtmp和HLS/m3u8直播流
  10. python语言属于哪一种语言,python语言特点是什么