SpringCloud Alibaba 开发微信公众号 (自定义菜单json请求数据封装)

简介: SpringCloud Alibaba 开发微信公众号 (自定义菜单json请求数据封装)

上篇讲了通过发送json格式数据测试自定义菜单功能,这篇讲创建实体类组织上送数据。

1.创建Button 组织上送数据

因为按钮类型比较多,所以创建按钮类型枚举类ButtonType

/**
 * 自定义菜单类型枚举类
 */
public enum ButtonType {
    /**
     * 点击事件
     */
    CLICK("click"),
    /**
     * 跳转URL用户点击view类型按钮后,
     * 微信客户端将会打开开发者在按钮中填写的网页URL,
     * 可与网页授权获取用户基本信息接口结合,获得用户基本信息
     */
    VIEW("view"),
    /**
     * 小程序类型
     */
    MINIPROGRAM("miniprogram"),
    /**
     * 扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),
     * 且会将扫码的结果传给开发者,开发者可以下发消息
     */
    SCANCODE_PUSH("scancode_push"),
    /**
     * 扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,
     * 将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息
     */
    SCANCODE_WAITMSG("scancode_waitmsg"),
    /**
     * 弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,
     * 会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息
     */
    PIC_SYSPHOTO("pic_sysphoto"),
    /**
     * 弹出拍照或者相册发图用户点击按钮后,
     * 微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。
     * 用户选择后即走其他两种流程
     */
    PIC_PHOTO_OR_ALBUM("pic_photo_or_album"),
    /**
     * 弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,
     * 将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息
     */
    PIC_WEIXIN("pic_weixin"),
    /**
     * 弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,
     * 将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
     */
    LOCATION_SELECT("location_select"),
    /**
     * 下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,
     * 永久素材类型可以是图片、音频、视频、图文消息。
     * 请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
     */
    MEDIA_ID("media_id"),
    /**
     * 跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,
     * 永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id
     */
    VIEW_LIMITED("view_limited"),
    /**
     * 空结点类型
     */
    EMPTY(null);
    /**
     * type值
     */
    private final String type;
    ButtonType(String type) {
        this.type = type;
    }
    /**
     * 获取type值
     *
     * @return
     */
    public String type() {
        return this.type;
    }
}
复制代码

创建菜单按钮对象类

说明:

Button()构造方法,将参数进行switch判断,根据按钮类型进行不同的属性赋值

verify()校验类 根据按钮类型校验按钮必输属性

toJson()  将String数据转为Json对象

import cn.org.spring.common.domain.Assert;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
 * 菜单按钮对象类
 */
@Getter
public class Button implements Serializable {
    public static final Button HEAD = new Button(ButtonType.EMPTY, null, null);
    /**
     * 一级菜单数组,个数应为1~3个
     */
    private List<Button> button;
    /**
     * 菜单标题,不超过16个字节,子菜单不超过60个字节
     */
    private String name;
    /**
     * 菜单的响应动作类型,view表示网页类型,
     * click表示点击类型,miniprogram表示小程序类型
     */
    private String type;
    /**
     * 菜单KEY值,用于消息接口推送,不超过128字节
     */
    private String key;
    /**
     * 网页 链接,用户点击菜单可打开链接,不超过1024字节。
     * type为miniprogram时,不支持小程序的老版本客户端将打开本url。
     */
    private String url;
    /**
     * 调用新增永久素材接口返回的合法media_id
     */
    private String media_id;
    /**
     * 小程序的appid(仅认证公众号可配置)
     */
    private String appid;
    /**
     * 小程序的页面路径
     */
    private String pagepath;
    /**
     * 二级菜单数组,个数应为1~5个
     */
    private List<Button> sub_button;
    /**
     * 校验函数
     */
    private void verify(ButtonType typeEnum) {
        switch (typeEnum) {
            case CLICK:
                Assert.nonNull(key, "key");
                Assert.nonNull(name, "name");
                Assert.nonNull(type, "type");
                break;
            case VIEW:
                Assert.nonNull(url, "url");
                Assert.nonNull(name, "name");
                Assert.nonNull(type, "type");
                break;
            case MEDIA_ID:
            case VIEW_LIMITED:
                Assert.nonNull(media_id, "media_id");
                Assert.nonNull(name, "name");
                Assert.nonNull(type, "type");
                break;
            case MINIPROGRAM:
                Assert.nonNull(appid, "appid");
                Assert.nonNull(url, "url");
                Assert.nonNull(pagepath, "pagepath");
                Assert.nonNull(name, "name");
                Assert.nonNull(type, "type");
                break;
            case EMPTY:
                break;
        }
    }
    private Button(ButtonType typeEnum, String name, String param) {
        this.type = typeEnum.type();
        this.name = name;
        switch (typeEnum) {
            case PIC_SYSPHOTO:
            case PIC_PHOTO_OR_ALBUM:
            case LOCATION_SELECT:
            case SCANCODE_PUSH:
            case SCANCODE_WAITMSG:
            case PIC_WEIXIN:
            case CLICK:
                this.key = param;
                break;
            case VIEW:
                this.url = param;
                break;
            case MEDIA_ID:
                this.media_id = param;
                break;
            case MINIPROGRAM:
                this.appid = param;
                break;
        }
        verify(typeEnum);
    }
    public static Button of(Button button, int parent, ButtonType typeEnum, String name, String param) {
        Button menu = new Button(ButtonType.EMPTY, null, null);
        menu.button = new ArrayList<>();
        Button newButton = new Button(typeEnum, name, param);
        if (button != null) {
            Button temp = button.button.get(parent);
            if (temp.sub_button == null) {
                temp.sub_button = new ArrayList<>();
            }
            temp.sub_button.add(newButton);
            return button;
        }
        menu.button.add(newButton);
        return menu;
    }
    public static Button ofOneMenu(Button button, ButtonType typeEnum, String name, String key) {
        Button menu = new Button(typeEnum, name, key);
        if (button.button == null) {
            button.button = new ArrayList<>();
        }
        button.button.add(menu);
        return button;
    }
    public String toJson() {
        return JSON.toJSONString(this);
    }
    public static void main(String[] args) {
        Button one = Button.ofOneMenu(Button.HEAD, ButtonType.CLICK, "拍照", "20");
        Button one1 = Button.ofOneMenu(one, ButtonType.CLICK, "个人中心", "20");
        Button one2 = Button.ofOneMenu(one1, ButtonType.CLICK, "我的会员", "20");
        Button of1 = Button.of(one2, 0, ButtonType.VIEW, "搜索", "http://www.soso.com/");
        Button of2 = Button.of(of1, 1, ButtonType.VIEW, "百度", "http://www.baidu.com/");
        Button of3 = Button.of(of2, 0, ButtonType.VIEW, "搜索1", "http://www.baidu.com/");
        System.out.println(of3.toJson());
    }
}
复制代码

MenuService

import javax.annotation.Resource;
import java.io.IOException;
/**
 * @Author : lizzu
 * @create 2022/9/25 15:19
 */
@Service
public class MenuService {
    private static final String CREATE_URL = WeCharConstant.CREATE_MENU_URL;
    private static final String DELETE_URL = WeCharConstant.DELETE_MENU_URL;
    @Resource
    private AccessTokenService accessTokenService;
    /**
     * 创建菜单
     *
     * @param json
     * @throws IOException
     */
    public String createMenu(String json) throws IOException {
        return sendPost(json);
    }
    /**
     * 创建菜单
     *
     * @param button
     * @throws IOException
     */
    public String createMenu(Button button) throws IOException {
        return sendPost(button.toJson());
    }
    /**
     * 删除菜单
     *
     * @throws IOException
     */
    public String deleteMenu() throws IOException {
        return HttpClientUtils.get(DELETE_URL.replace("ACCESS_TOKEN", accessTokenService.getAccessToken()));
    }
    /**
     * 发送POST请求
     *
     * @param data 请求数据
     * @return
     * @throws IOException
     */
    private String sendPost(String data) throws IOException {
        return HttpClientUtils.post(CREATE_URL.replace("ACCESS_TOKEN", accessTokenService.getAccessToken()), data);
    }
}
复制代码

MenuController

import com.ctsi.sddx.bean.Button;
import com.ctsi.sddx.bean.ButtonType;
import com.ctsi.sddx.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
 * @Author : lizzu
 * @create 2022/9/25 15:24
 */
@RestController
@RequestMapping("/v1/weChart")
public class MenuController {
    @Autowired
    MenuService menuService;
    @GetMapping("/createMenu")
    public String createMenu() throws IOException {
        Button one = Button.ofOneMenu(Button.HEAD, ButtonType.CLICK, "菜单1", "20");
        Button one1 = Button.ofOneMenu(one, ButtonType.CLICK, "菜单2", "20");
        Button one2 = Button.ofOneMenu(one1, ButtonType.CLICK, "菜单3", "20");
        Button of1 = Button.of(one2, 0, ButtonType.VIEW, "搜索", "http://www.baidu.com/");
        Button of2 = Button.of(of1, 0, ButtonType.SCANCODE_WAITMSG, "扫码带提示", "rselfmenu_0_0");
        Button of3 = Button.of(of2, 0, ButtonType.SCANCODE_PUSH, "扫码推事件", "rselfmenu_0_1");
        Button of4 = Button.of(of3, 1, ButtonType.PIC_SYSPHOTO, "系统拍照发图", "rselfmenu_1_0");
        Button of5 = Button.of(of4, 1, ButtonType.PIC_PHOTO_OR_ALBUM, "拍照或者相册发图", "rselfmenu_1_1");
        Button of6 = Button.of(of5, 1, ButtonType.PIC_WEIXIN, "微信相册发图", "rselfmenu_1_2");
        Button of7 = Button.of(of6, 2, ButtonType.LOCATION_SELECT, "发送位置", "rselfmenu_2_0");
        return menuService.createMenu(of7);
    }
    @GetMapping("/createMenuToJson")
    public String createMenuToJson(String json) throws IOException {
        return menuService.createMenu(json);
    }
    @GetMapping("/deleteMenu")
    public String deleteMenu() throws IOException {
        return menuService.deleteMenu();
    }
}
复制代码

测试返回成功console-docs.apipost.cn/preview/4c1…

{ "errcode": 40007, "errmsg": "invalid media_id rid: 633806a1-669a8fba-192b1458" }

网络异常,图片无法展示
|

网络异常,图片无法展示
|

菜单删除

http请求方式:GET api.weixin.qq.com/cgi-bin/men…只要发生送Get请求即可

网络异常,图片无法展示
|

下一篇: 基础消息能力-接收普通消息被动回复用户消息


相关文章
|
10天前
|
小程序 前端开发 测试技术
微信小程序的开发完整流程是什么?
微信小程序的开发完整流程是什么?
48 7
|
5天前
|
小程序 前端开发 数据安全/隐私保护
微信小程序全栈开发中的身份认证与授权机制
【10月更文挑战第3天】随着移动互联网的发展,微信小程序凭借便捷的用户体验和强大的社交传播能力,成为企业拓展业务的新渠道。本文探讨了小程序全栈开发中的身份认证与授权机制,包括手机号码验证、微信登录、第三方登录及角色权限控制等方法,并强调了安全性、用户体验和合规性的重要性,帮助开发者更好地理解和应用这一关键技术。
26 5
|
5天前
|
小程序 前端开发 JavaScript
微信小程序全栈开发中的PWA技术应用
【10月更文挑战第3天】微信小程序作为新兴应用形态,凭借便捷体验与社交传播能力,成为企业拓展业务的新渠道。本文探讨了微信小程序全栈开发中的PWA技术应用,包括离线访问、后台运行、桌面图标及原生体验等方面,助力开发者提升小程序性能与用户体验。PWA技术在不同平台的兼容性、性能优化及用户体验是实践中需注意的关键点。
22 5
|
1天前
|
小程序 JavaScript API
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
这篇文章介绍了如何在uni-app和微信小程序中实现将图片保存到用户手机相册的功能。
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
|
21天前
|
小程序 JavaScript API
微信小程序开发学习之页面导航(声明式导航和编程式导航)
这篇文章介绍了微信小程序中页面导航的两种方式:声明式导航和编程式导航,包括如何导航到tabBar页面、非tabBar页面、后退导航,以及如何在导航过程中传递参数和获取传递的参数。
微信小程序开发学习之页面导航(声明式导航和编程式导航)
|
2月前
|
小程序 JavaScript Java
微信小程序的后端开发需要使用什么语言?
【8月更文挑战第22天】微信小程序的后端开发需要使用什么语言?
448 65
ly~
|
21天前
|
存储 供应链 小程序
除了微信小程序,PHP 还可以用于开发哪些类型的小程序?
除了微信小程序,PHP 还可用于开发多种类型的小程序,包括支付宝小程序、百度智能小程序、抖音小程序、企业内部小程序及行业特定小程序。在电商、生活服务、资讯、工具、娱乐、营销等领域,PHP 能有效管理商品信息、订单处理、支付接口、内容抓取、复杂计算、游戏数据、活动规则等多种业务。同时,在企业内部,PHP 可提升工作效率,实现审批流程、文件共享、生产计划等功能;在医疗和教育等行业,PHP 能管理患者信息、在线问诊、课程资源、成绩查询等重要数据。
ly~
60 6
|
2月前
|
小程序 JavaScript
Taro@3.x+Vue@3.x+TS开发微信小程序,使用轮播图
本文介绍了使用 Taro 和 Vue 创建轮播组件的两种方法:一是通过 `&lt;swiper&gt;` 实现,二是利用 Nut UI 的 `&lt;nut-swiper&gt;` 组件实现。
Taro@3.x+Vue@3.x+TS开发微信小程序,使用轮播图
|
1月前
|
存储 移动开发 监控
微信支付开发避坑指南
【9月更文挑战第11天】在进行微信支付开发时,需遵循官方文档,确保权限和参数配置正确。开发中应注重安全,验证用户输入,合理安排接口调用顺序,并处理异常。上线后需实时监控支付状态,定期检查配置,关注安全更新,确保系统稳定运行。
|
1月前
|
移动开发 小程序 JavaScript
uni-app开发微信小程序
本文详细介绍如何使用 uni-app 开发微信小程序,涵盖需求分析、架构思路及实施方案。主要功能包括用户登录、商品列表展示、商品详情、购物车及订单管理。技术栈采用 uni-app、uView UI 和 RESTful API。文章通过具体示例代码展示了从初始化项目、配置全局样式到实现各页面组件及 API 接口的全过程,并提供了完整的文件结构和配置文件示例。此外,还介绍了微信授权登录及后端接口模拟方法,确保项目的稳定性和安全性。通过本教程,读者可快速掌握使用 uni-app 开发微信小程序的方法。
76 3

热门文章

最新文章