• Java项目硅谷课堂学习笔记-P10-后台系统公众号部分


    1.公众号菜单管理

    1.1创建模块service_wechat

    在service下创建子模块service_wechat
    在这里插入图片描述

    1.2引入依赖

    <dependencies>
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.3生成菜单相关代码

    在这里插入图片描述

    1.4创建启动类和配置文件

    1.4.1启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages = "com.atguigu")
    @MapperScan("com.atguigu.ggkt.wechat.mapper")
    @ComponentScan(basePackages = "com.atguigu")
    public class ServiceWechatApplication {
        public static void main(String[] args) {
            SpringApplication.run(ServiceWechatApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    1.4.2配置文件

    # 服务端口
    server.port=8305
    # 服务名
    spring.application.name=service-wechat
    
    # 环境设置:dev、test、prod
    spring.profiles.active=dev
    
    # mysql数据库连接
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/glkt_wechat?characterEncoding=utf-8&useSSL=false
    spring.datasource.username=root
    spring.datasource.password=root
    
    #返回json的全局时间格式
    spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
    spring.jackson.time-zone=GMT+8
    
    #mybatis日志
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
    mybatis-plus.mapper-locations=classpath:com/atguigu/ggkt/wechat/mapper/xml/*.xml
    
    # nacos服务地址
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
    
    #公众号id和秘钥
    # 硅谷课堂微信公众平台appId
    wechat.mpAppId: wx09f201e9013e81d8
    # 硅谷课堂微信公众平台api秘钥
    wechat.mpAppSecret: 6c999765c12c51850d28055e8b6e2eda
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    1.5配置网关

    #service-wechat模块配置
    #设置路由id
    spring.cloud.gateway.routes[4].id=service-wechat
    #设置路由的uri
    spring.cloud.gateway.routes[4].uri=lb://service-wechat
    #设置路由断言,代理servicerId为auth-service的/auth/路径
    spring.cloud.gateway.routes[4].predicates= Path=/*/wechat/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.6开发菜单管理接口

    1.6.1编写MenuController

    @RestController
    @RequestMapping("/admin/wechat/menu")
    public class MenuController {
    
        @Autowired
        private MenuService menuService;
    
        //获取所有菜单,按照一级和二级菜单封装
        @GetMapping("findMenuInfo")
        public Result findMenuInfo() {
            List<MenuVo> list = menuService.findMenuInfo();
            return Result.ok(list);
        }
    
        //获取所有一级菜单
        @GetMapping("findOneMenuInfo")
        public Result findOneMenuInfo() {
            List<Menu> list = menuService.findMenuOneInfo();
            return Result.ok(list);
        }
    
        @ApiOperation(value = "获取")
        @GetMapping("get/{id}")
        public Result get(@PathVariable Long id) {
            Menu menu = menuService.getById(id);
            return Result.ok(menu);
        }
    
        @ApiOperation(value = "新增")
        @PostMapping("save")
        public Result save(@RequestBody Menu menu) {
            menuService.save(menu);
            return Result.ok(null);
        }
    
        @ApiOperation(value = "修改")
        @PutMapping("update")
        public Result updateById(@RequestBody Menu menu) {
            menuService.updateById(menu);
            return Result.ok(null);
        }
    
        @ApiOperation(value = "删除")
        @DeleteMapping("remove/{id}")
        public Result remove(@PathVariable Long id) {
            menuService.removeById(id);
            return Result.ok(null);
        }
    
        @ApiOperation(value = "根据id列表删除")
        @DeleteMapping("batchRemove")
        public Result batchRemove(@RequestBody List<Long> idList) {
            menuService.removeByIds(idList);
            return Result.ok(null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    1.6.2serviceImpl层

    package com.jq.wechat.service.impl;
    
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.jq.model.wechat.Menu;
    import com.jq.vo.wechat.MenuVo;
    import com.jq.wechat.mapper.MenuMapper;
    import com.jq.wechat.service.MenuService;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.springframework.beans.BeanUtils;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * 

    * 订单明细 订单明细 服务实现类 *

    * * @author CJQ * @since 2022-09-04 */
    @Service public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService { //获取所有一级菜单 @Override public List<Menu> findMenuOneInfo() { QueryWrapper<Menu>wrapper =new QueryWrapper<>(); wrapper.eq("parent_id",0); List<Menu> list = baseMapper.selectList(wrapper); return list; } //获取所有菜单,按照一级和二级菜单封装 @Override public List<MenuVo> findMenuInfo() { //1.创建list数据集合,用于最终数据封装 List<MenuVo>finalMenuList=new ArrayList<>(); //2.查询所有菜单数据(包含一级和二级) List<Menu> menuList = baseMapper.selectList(null); // 3.从所有菜单数据中获取所有一级菜单数据(parent_id=0) List<Menu> oneMenuList = menuList.stream() .filter(menu -> menu.getParentId().longValue() == 0) .collect(Collectors.toList()); //4. 封装一级菜单数据,封装到最终数据list集合 //遍历一级菜单集合做转换 for (Menu oneMenu :oneMenuList){ //Menu-->MenuVo MenuVo oneMenuVo = new MenuVo(); BeanUtils.copyProperties(oneMenu,oneMenuVo); //5. 封装二级菜单数据,(判断一级菜单和二级菜单parent_id是否相同) //如果相同,把二级菜单数据放到一级菜单里面 List<Menu> twoMenuList = menuList.stream() .filter(menu -> menu.getParentId().longValue() == oneMenu.getId()) .collect(Collectors.toList()); //List
    -->List List<MenuVo>children=new ArrayList<>(); for (Menu twoMenu :twoMenuList){ MenuVo twoMenuVo = new MenuVo(); BeanUtils.copyProperties(twoMenu,twoMenuVo); children.add(twoMenuVo); } //把二级菜单数据放到一级菜单里面 oneMenuVo.setChildren(children); //把oneMenuVo放入最终list集合中 finalMenuList.add(oneMenuVo); } return finalMenuList; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    1.7同步菜单(获取access_token

    1. 调用微信接口,获取access_token
    2. 拿着access_token调用微信接口,公众号菜单同步

    1.7.1接口文档

    进行菜单同步时候,需要获取到公众号的access_token通过access_token进行菜单同步
    接口文档

    1.7.2service_wechat添加配置

    # 硅谷课堂微信公众平台appId
    wechat.mpAppId:
    # 硅谷课堂微信公众平台api秘钥
    wechat.mpAppSecret: 
    
    • 1
    • 2
    • 3
    • 4

    1.7.3添加工具类

    @Component
    public class ConstantPropertiesUtil implements InitializingBean {
    
        @Value("${wechat.mpAppId}")
        private String appid;
    
        @Value("${wechat.mpAppSecret}")
        private String appsecret;
    
        public static String ACCESS_KEY_ID;
        public static String ACCESS_KEY_SECRET;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            ACCESS_KEY_ID = appid;
            ACCESS_KEY_SECRET = appsecret;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1.7.4获取access_token的controller

        //获取access_token
        @GetMapping("getAccessToken")
        public Result getAccessToken(){
            //拼接请求地址
            StringBuffer buffer = new StringBuffer();
            buffer.append("https://api.weixin.qq.com/cgi-bin/token");
            buffer.append("?grant_type=client_credential");
            buffer.append("&appid=%s");
            buffer.append("&secret=%s");
    
            //设置路径中的参数
            String url = String.format(buffer.toString(),
                    ConstantPropertiesUtil.ACCESS_KEY_ID,
                    ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            try {
                String tokenString = HttpClientUtils.get(url);
                //获取access_token
                JSONObject jsonObject = JSONObject.parseObject(tokenString);
                String access_token = jsonObject.getString("access_token");
                return Result.ok(access_token);
            } catch (Exception e) {
                e.printStackTrace();
                throw new GgktException(20001,"获取access_token失败");
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    1.7.5添加配置类

    package com.jq.wechat.config;
    
    import com.jq.wechat.utils.ConstantPropertiesUtil;
    import me.chanjar.weixin.mp.api.WxMpService;
    import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
    import me.chanjar.weixin.mp.config.WxMpConfigStorage;
    import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    @Component
    @Configuration
    public class WeChatMpConfig {
    
        @Autowired
        private ConstantPropertiesUtil constantPropertiesUtil;
    
        @Bean
        public WxMpService wxMpService(){
            WxMpService wxMpService = new WxMpServiceImpl();
            wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
            return wxMpService;
        }
        @Bean
        public WxMpConfigStorage wxMpConfigStorage(){
            WxMpDefaultConfigImpl wxMpConfigStorage = new WxMpDefaultConfigImpl();
            wxMpConfigStorage.setAppId(ConstantPropertiesUtil.ACCESS_KEY_ID);
            wxMpConfigStorage.setSecret(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            return wxMpConfigStorage;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    1.7.6同步菜单方法controller

    @ApiOperation(value = "同步菜单")
    @GetMapping("syncMenu")
    public Result createMenu() throws WxErrorException {
        menuService.syncMenu();
        return Result.ok(null);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.7.7同步菜单方法serviceImpl层

    在这里插入图片描述

    
        //同步菜单方法
        @Override
        public void syncMenu() {
            //获取所有菜单数据
            List<MenuVo> menuVoList = this.findMenuInfo();
            //封装button里面结构,数组格式
            JSONArray buttonList = new JSONArray();
            for(MenuVo oneMenuVo:menuVoList){
                //json对象 一级菜单
                JSONObject one =new JSONObject();
                one.put("name",oneMenuVo.getName());
    
                //json数组,封住二级菜单
                JSONArray subButton =new JSONArray();
                for (MenuVo twoMenuVo:oneMenuVo.getChildren()) {
                    JSONObject view = new JSONObject();
                    view.put("type", twoMenuVo.getType());
                    if(twoMenuVo.getType().equals("view")) {
                        view.put("name", twoMenuVo.getName());
                        view.put("url", "http://ggkt2.vipgz1.91tunnel.com/#"
                                +twoMenuVo.getUrl());
                    } else {
                        view.put("name", twoMenuVo.getName());
                        view.put("key", twoMenuVo.getMeunKey());
                    }
                    subButton.add(view);
                }
                one.put("sub_button",subButton);
                buttonList.add(one);
            }
            //封装最外层的button部分
            JSONObject button =new JSONObject();
            button.put("button",buttonList);
            try {
                String menuId = this.wxMpService.getMenuService().menuCreate(button.toJSONString());
                System.out.println(menuId);
            } catch (WxErrorException e) {
                e.printStackTrace();
                throw new GgktException(20001,"公众号菜单同步失败");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    1.8公众号菜单删除

    
        //公众号菜单删除
        @Override
        public void removeMenu() {
            try {
                wxMpService.getMenuService().menuDelete();
            } catch (WxErrorException e) {
                e.printStackTrace();
                throw new GgktException(20001,"公众号菜单删除失败");
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.9前端

    1.9.1添加路由

    src -> router -> index.js添加路由

    1.9.2定义接口

    src -> api -> wechat -> menu.js定义接口

    1.9.3编写页面

    创建views -> wechat -> menu -> list.vue

    2.公众号普通消息

    3.微信授权登录

  • 相关阅读:
    UE4 设计模式:单例模式(Singleton Pattern)
    Open3D(C++) 点云滤波
    如何在单链表中的任意一个位置插入一个结点
    【JavaWeb】-JDBC详解、数据库连接池的认识
    『时代』杂志:元宇宙将改变世界;健身教练:AI让我丢工作!有话说北欧人工智能夏令营资料大公开;深度学习书籍TOP5 | ShowMeAI资讯日报
    域名公安备案
    小程序中如何访问mysql数据库
    Java程序员常用的Eclipse键盘快捷键,建议收藏
    设计模式 - 行为型模式考点篇:模板方法模式(概念 | 案例实现 | 优缺点 | 使用场景)
    机械工程英语第二版叶邦彦-汉语翻译最多单元版
  • 原文地址:https://blog.csdn.net/qq_45498432/article/details/126689898