上篇讲了通过发送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();
}
}
测试返回成功
{
"errcode": 40007,
"errmsg": "invalid media_id rid: 633806a1-669a8fba-192b1458"
}
菜单删除
http请求方式:GET api.weixin.qq.com/cgi-bin/men…
只要发生送Get请求即可
下一篇:
基础消息能力-接收普通消息被动回复用户消息