上篇讲了通过发送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请求即可
网络异常,图片无法展示
|
下一篇: 基础消息能力-接收普通消息被动回复用户消息