微信公众号开发文章目录

1.微信公众号开发 - 环境搭建
2.微信公众号开发 - 配置表设计以及接入公众号接口开发
3.微信公众号开发 - token获取(保证同一时间段内只请求一次)
4.微信公众号开发 - 菜单按钮bean封装
5.微信公众号开发 - 创建菜单
6.微信公众号开发 - 事件处理和回复消息
7.微信公众号开发 - 发送Emoji表情

项目完整代码请访问github:https://github.com/liaozq0426/wx.git

在上篇文章中完成了菜单、按钮bean的封装,现在来实现微信公众号菜单的创建

向wx_cfg配置表中插入若干菜单记录

INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('4', 'app_url', 'appUrl', 'http://www.gavin.com', NULL, NULL, 'gavin', 'service', '1', '公众号域名');
INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('5', 'menu', 'view1', '/transfer/index.html', NULL, '1', 'gavin', 'service', '1', '学习资料');
INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('6', 'menu', 'view2', '/transfer/index.html', NULL, '2', 'gavin', 'service', '1', '在线题库');
INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('7', 'menu', 'click1', '/transfer/index.html', NULL, '3', 'gavin', 'service', '1', '关于');
INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('8', 'menu', 'view11', '/transfer/index.html', '5', '1', 'gavin', 'service', '1', 'JAVA');
INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `sort`, `platform`, `wx_type`, `enabled`, `desc`) VALUES ('9', 'menu', 'view12', '/transfer/index.html', '5', '2', 'gavin', 'service', '1', 'MySQL');

编写代码

创建WxMenuService接口

package com.gavin.service;import com.gavin.pojo.Menu;public interface WxMenuService {public Menu makeMenu(String platform) throws Exception;
}

创建实现类WxMenuServiceImpl,代码如下

package com.gavin.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.gavin.cfg.WxCfgEnum;
import com.gavin.pojo.AccessToken;
import com.gavin.pojo.Button;
import com.gavin.pojo.ClickButton;
import com.gavin.pojo.ComplexButton;
import com.gavin.pojo.Menu;
import com.gavin.pojo.ViewButton;
import com.gavin.pojo.WxApiCfg;
import com.gavin.pojo.WxCfg;
import com.gavin.service.WxCfgService;
import com.gavin.service.WxMenuService;
import com.gavin.service.WxTokenService;
import com.gavin.util.EncryptionUtil;
import com.gavin.util.WxUtil;
import com.google.gson.Gson;@Service
public class WxMenuServiceImpl implements WxMenuService{private Logger logger = Logger.getLogger(this.getClass());@Autowiredprivate WxTokenService wxTokenService;@Autowiredprivate WxCfgService wxCfgService;/*** @title 根据平台创建微信公众号菜单* @author gavin* @date 2019年5月23日* @param platform* @return* @throws Exception*/@Overridepublic Menu makeMenu(String platform) throws Exception {// 查询一级菜单System.out.println(platform);WxCfg parentParam = new WxCfg();parentParam.setType(WxCfgEnum.MENU.getType());parentParam.setEnabled(true);parentParam.setPlatform(platform);parentParam.setOrderBy("sort asc");List<WxCfg> cfgList = this.wxCfgService.select(parentParam);if (cfgList.size() > 0) {Menu menu = new Menu();List<Button> buttons = new ArrayList<Button>();for (WxCfg cfg : cfgList) {WxCfg subParam = new WxCfg();subParam.setType(WxCfgEnum.MENU.getType());subParam.setParentId(cfg.getId());subParam.setEnabled(true);subParam.setPlatform(platform);// 查询二级菜单List<WxCfg> subCfgList = this.wxCfgService.select(subParam);if (subCfgList.size() > 0) {// 构建多级按钮List<Button> subButtons = new ArrayList<Button>();for (WxCfg subCfg : subCfgList) {Button sub = createButton(subCfg);subButtons.add(sub);}ComplexButton complexButton = new ComplexButton();complexButton.setName(cfg.getDesc());complexButton.setSub_button(subButtons.toArray(new Button[subButtons.size()]));buttons.add(complexButton);} else {Button button = createButton(cfg);buttons.add(button);}}// 获取accessTokenAccessToken token = this.wxTokenService.readAccessToken(AccessToken.TYPE_ACCESS_TOKEN, platform);menu.setButton(buttons.toArray(new Button[buttons.size()]));Gson gson = new Gson();String menuJson = gson.toJson(menu);System.out.println(menuJson);Map<String , Object> message = WxUtil.createMenu(menu, token.getAccess_token());logger.info(message.toString());if (message.get("errcode") != null && (Integer)message.get("errcode") == 0&& "ok".equalsIgnoreCase((String)message.get("errmsg"))) {logger.info("微信菜单创建成功!");return menu;}else {             logger.error("微信菜单创建失败");}}return null;}/*** @title 根据配置信息创建button,这里只实现了最常用的click和view两种类型的按钮* @author gavin* @date 2019年5月23日* @param cfg* @return* @throws Exception*/private Button createButton(WxCfg cfg) throws Exception {String btnType = cfg.getName();if (btnType.startsWith(Button.TYPE_CLICK)) {// 普通点击按钮ClickButton click = new ClickButton();click.setName(cfg.getDesc());click.setType(Button.TYPE_CLICK);// key可以根据自己的需要设置,这里我设置为[name_desc]click.setKey(cfg.getName() + "_" + cfg.getDesc());return click;} else if (btnType.startsWith(Button.TYPE_VIEW)) {// view按钮ViewButton view = new ViewButton();view.setName(cfg.getDesc());view.setType(Button.TYPE_VIEW);// 动态生成urlWxCfg cfgParam = new WxCfg();cfgParam.setPlatform(cfg.getPlatform());cfgParam.setType(WxCfgEnum.WX_KEY_APPID.getType());cfgParam.setName(WxCfgEnum.WX_KEY_APPID.getName());WxCfg queryCfg = this.wxCfgService.selectOne(cfgParam);if(queryCfg != null) {String appId = EncryptionUtil.base64Decode(queryCfg.getValue());String wxType = cfg.getWxType();String url = null;if(WxCfgEnum.WX_TYPE_SERVICE.getType().equals(wxType)) {// 如果是服务号,生成网页授权的格式urlString redirectUrl = cfg.getValue();if(!StringUtils.isBlank(redirectUrl)) {redirectUrl = redirectUrl + "?state=" + cfg.getName() + "&platform=" + cfg.getPlatform();}url = WxUtil.makeViewUrl(appId, WxApiCfg.SCOPE_BASE, redirectUrl,cfg.getName());}else if(WxCfgEnum.WX_TYPE_SUBSCRIBE.getType().equals(wxType)) {// 如果是订阅号,生成普通url格式url = cfg.getValue();if(!StringUtils.isBlank(url))url = url + "?state=" + cfg.getName() + "&platform=" + cfg.getPlatform();}logger.info(url);view.setUrl(url);return view;                }}return null;}
}

上述代码中的几个要点
1)在查询数据库配置中,首先查询了parent_id为空的记录,也就是一级菜单
2)查询出一级菜单后,遍历一级菜单集合,用一级菜单记录的id作为parent_id参数去查询二级菜单
3)createButton为创建按钮对象方法,创建时会判断name字段的值,如果name值的前缀是click,则创建成ClickButton,如果name值得前缀是view,则创建成ViewButton。
4)如果创建的按钮是ViewButton,会进一步判断wx_type字段(公众号类型),如果是服务号,url会创建成网页授权的格式,因为网页授权格式才能在后续获取openid和用户基本信息;如果是订阅号,则创建成普通格式的url。

接下来在WxController中新增一个方法,调用service

@GetMapping("wx/menu")
public Menu getWxMenu(String platform) {try {return this.wxMenuService.makeMenu(platform);} catch (Exception e) {e.printStackTrace();}return null;
}

测试

最后,用postman测试一下wx/menu接口,调用结果如下图所示

再用手机看一下公众号

说明公众号菜单创建成功!

微信公众号开发 - 创建菜单相关推荐

  1. java自定义菜单跳转页面_微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解...

    微信公众号开发 自定义菜单 请先读完本文再进行配置开发 请先前往微信平台开发者文档阅读"网页授权获取用户基本信息"的接口说明 在微信公众账号开发中,往往有定义一个菜单,然后用户点击 ...

  2. 微信公众号开发--自定义菜单跳转页面并获取用户信息(续)

    之前写过一篇微信公众号开发–自定义菜单跳转页面并获取用户信息 由于当时是刚学习微信公众号开发当时的思路虽然可行,不过不是最好的,最近也用到了需要获取用户信息的地方,再次整理一下. 流程 注意点 ### ...

  3. 公众号如何跳转到页面php,图文详解微信公众号开发自定义菜单跳转页面并获取用户信息实例...

    这篇文章主要介绍了微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解的相关资料,需要的朋友可以参考下 微信公众号开发 自定义菜单 请先读完本文再进行配置开发 请先前往微信平台开发者文档阅读&qu ...

  4. 微信公众号开发 (3) 菜单处理

    一.前言 微信公众号开发 (1) 微信接入认证成为开发者 微信公众号开发 (2) 消息处理 本文将实现 根据AppID和AppSecret获取access_token 自定义菜单(创建菜单.查询菜单. ...

  5. 微信公众号开发---自定义菜单的创建及菜单事件响应(java)

    微信5.0发布 2013年8月5日,伴随着微信5.0 iPhone版的发布,公众平台也进行了重要的更新,主要包括: 1)运营主体为组织,可选择成为服务号或者订阅号: 2)服务号可以申请自定义菜单: 3 ...

  6. 微信公众号开发 - 配置表设计以及接入公众号接口开发

    微信公众号开发文章目录 1.微信公众号开发 - 环境搭建 2.微信公众号开发 - 配置表设计以及接入公众号接口开发 3.微信公众号开发 - token获取(保证同一时间段内只请求一次) 4.微信公众号 ...

  7. 微信公众号开发 - 事件处理和回复消息

    微信公众号开发文章目录 1.微信公众号开发 - 环境搭建 2.微信公众号开发 - 配置表设计以及接入公众号接口开发 3.微信公众号开发 - token获取(保证同一时间段内只请求一次) 4.微信公众号 ...

  8. 微信公众号开发 - token获取(保证同一时间段内只请求一次)

    微信公众号开发文章目录 1.微信公众号开发 - 环境搭建 2.微信公众号开发 - 配置表设计以及接入公众号接口开发 3.微信公众号开发 - token获取(保证同一时间段内只请求一次) 4.微信公众号 ...

  9. 微信公众号开发 - 发送Emoji表情

    微信公众号开发文章目录 1.微信公众号开发 - 环境搭建 2.微信公众号开发 - 配置表设计以及接入公众号接口开发 3.微信公众号开发 - token获取(保证同一时间段内只请求一次) 4.微信公众号 ...

最新文章

  1. 一个注解搞定 SpringBoot 接口防刷,还有谁不会?
  2. window下tomcat的内存溢出问题
  3. libSVM应用举例
  4. httpclient发起https请求以及获取https返回内容
  5. MySql修改数据库编码为UTF8
  6. 关于Python中的错误与异常,你是否了解的够仔细?
  7. 开创手机影像全新时代的微云台要来了!vivo X系列夏季新品发布会今晚高能来袭...
  8. 神秘TTY:The TTY demystified
  9. hadoop入门简介
  10. 林期苏曼属性标签编辑_标签打印软件如何打印指定日期
  11. java之j2se:再学java对象容器
  12. XMPP即时通讯机制
  13. 当前网络上迅雷各版本实际效果研究报告
  14. 计算机表格函数最大值操作,使用MAX最大值函数计算excel表格中学生成绩的最大值...
  15. Android简历附件2
  16. excel countifs 计算包含了空白单元格,结果错误,不对,特别大。
  17. 介绍一下Emily----大一
  18. 盛迈坤电子商务:自然搜索排名的优化
  19. 2020usnews计算机排名布朗,布朗大学排名在2020年USNEWS美国最佳综合大学排名第14...
  20. rust读条闪退_rust更新后无法连接服务器 | 手游网游页游攻略大全

热门文章

  1. jira oracle安装,JIRA使用教程:连接数据库—Oracle
  2. 商户后台返回数据签名错误_@梁平个体工商户,足不出户就能办营业执照,速看!...
  3. Nginx的前世今生
  4. 使用NPOI 导出EXCEL,设置样式,字体等详细代码方法教程
  5. linux网络及防火墙配置命令
  6. 智安网络丨2021有趣新解:什么叫网关?
  7. vue开发案例:基于Three.js搭建三维数字化场景
  8. html图片滚动原理,HTML 图片滚动
  9. ubuntu20.04 键盘经常卡住,无法使用,过一会又好了
  10. SQLServer Delayed durability 延迟持久化