Comprehensive Java SDK for WeChat Official Account development with complete API coverage for user management, messaging, materials, menus, and WeChat platform features.
—
Create, update, and delete custom menus for WeChat Official Accounts, providing interactive navigation for users.
interface WxMpMenuService {
// Menu operations
String menuCreate(WxMenu menu) throws WxErrorException;
void menuDelete() throws WxErrorException;
WxMenu menuGet() throws WxErrorException;
WxMpGetSelfMenuInfoResult getSelfMenuInfo() throws WxErrorException;
// Conditional menu operations
String menuTryMatch(String userId) throws WxErrorException;
String conditionalMenuCreate(WxMenuConditional menu) throws WxErrorException;
void conditionalMenuDelete(String menuid) throws WxErrorException;
}class WxMenu implements Serializable {
private List<WxMenuButton> buttons;
private WxMenuRule matchRule;
public List<WxMenuButton> getButtons();
public void setButtons(List<WxMenuButton> buttons);
public WxMenuRule getMatchRule();
public void setMatchRule(WxMenuRule matchRule);
}
class WxMenuButton implements Serializable {
private String type;
private String name;
private String key;
private String url;
private String mediaId;
private String appid;
private String pagepath;
private String articleId;
private List<WxMenuButton> subButtons;
public String getType();
public void setType(String type);
public String getName();
public void setName(String name);
public String getKey();
public void setKey(String key);
public String getUrl();
public void setUrl(String url);
public String getMediaId();
public void setMediaId(String mediaId);
public String getAppid();
public void setAppid(String appid);
public String getPagepath();
public void setPagepath(String pagepath);
public String getArticleId();
public void setArticleId(String articleId);
public List<WxMenuButton> getSubButtons();
public void setSubButtons(List<WxMenuButton> subButtons);
}class WxMenuConditional extends WxMenu {
private String menuid;
public String getMenuid();
public void setMenuid(String menuid);
}
class WxMenuRule implements Serializable {
private String tagId;
private String sex;
private String country;
private String province;
private String city;
private String clientPlatformType;
private String language;
public String getTagId();
public void setTagId(String tagId);
public String getSex();
public void setSex(String sex);
public String getCountry();
public void setCountry(String country);
public String getProvince();
public void setProvince(String province);
public String getCity();
public void setCity(String city);
public String getClientPlatformType();
public void setClientPlatformType(String clientPlatformType);
public String getLanguage();
public void setLanguage(String language);
}class WxMpGetSelfMenuInfoResult implements Serializable {
private Boolean isMenuOpen;
private List<WxMpSelfMenuInfo> selfMenuInfo;
public Boolean getIsMenuOpen();
public void setIsMenuOpen(Boolean isMenuOpen);
public List<WxMpSelfMenuInfo> getSelfMenuInfo();
public void setSelfMenuInfo(List<WxMpSelfMenuInfo> selfMenuInfo);
public static class WxMpSelfMenuInfo implements Serializable {
private String type;
private String name;
private String value;
private WxMpSelfMenuInfo newsInfo;
private List<WxMpSelfMenuInfo> subButton;
public String getType();
public void setType(String type);
public String getName();
public void setName(String name);
public String getValue();
public void setValue(String value);
public WxMpSelfMenuInfo getNewsInfo();
public void setNewsInfo(WxMpSelfMenuInfo newsInfo);
public List<WxMpSelfMenuInfo> getSubButton();
public void setSubButton(List<WxMpSelfMenuInfo> subButton);
}
}// Menu button type constants
public static final String BUTTON_TYPE_CLICK = "click";
public static final String BUTTON_TYPE_VIEW = "view";
public static final String BUTTON_TYPE_SCANCODE_PUSH = "scancode_push";
public static final String BUTTON_TYPE_SCANCODE_WAITMSG = "scancode_waitmsg";
public static final String BUTTON_TYPE_PIC_SYSPHOTO = "pic_sysphoto";
public static final String BUTTON_TYPE_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
public static final String BUTTON_TYPE_PIC_WEIXIN = "pic_weixin";
public static final String BUTTON_TYPE_LOCATION_SELECT = "location_select";
public static final String BUTTON_TYPE_MEDIA_ID = "media_id";
public static final String BUTTON_TYPE_VIEW_LIMITED = "view_limited";
public static final String BUTTON_TYPE_MINIPROGRAM = "miniprogram";
public static final String BUTTON_TYPE_ARTICLE_ID = "article_id";
public static final String BUTTON_TYPE_ARTICLE_VIEW_LIMITED = "article_view_limited";import me.chanjar.weixin.mp.bean.menu.WxMenu;
import me.chanjar.weixin.mp.bean.menu.WxMenuButton;
// Create menu
WxMenu menu = new WxMenu();
List<WxMenuButton> buttons = new ArrayList<>();
// First level button - Click type
WxMenuButton button1 = new WxMenuButton();
button1.setType(WxConsts.MenuButtonType.CLICK);
button1.setName("About Us");
button1.setKey("ABOUT_US");
buttons.add(button1);
// First level button - View type (URL)
WxMenuButton button2 = new WxMenuButton();
button2.setType(WxConsts.MenuButtonType.VIEW);
button2.setName("Website");
button2.setUrl("https://www.example.com");
buttons.add(button2);
// First level button with sub-buttons
WxMenuButton button3 = new WxMenuButton();
button3.setName("Services");
List<WxMenuButton> subButtons = new ArrayList<>();
// Sub-button 1
WxMenuButton subButton1 = new WxMenuButton();
subButton1.setType(WxConsts.MenuButtonType.CLICK);
subButton1.setName("Service A");
subButton1.setKey("SERVICE_A");
subButtons.add(subButton1);
// Sub-button 2
WxMenuButton subButton2 = new WxMenuButton();
subButton2.setType(WxConsts.MenuButtonType.VIEW);
subButton2.setName("Service B");
subButton2.setUrl("https://www.example.com/service-b");
subButtons.add(subButton2);
button3.setSubButtons(subButtons);
buttons.add(button3);
menu.setButtons(buttons);
// Create menu
String result = wxService.getMenuService().menuCreate(menu);
System.out.println("Menu created: " + result);WxMenu advancedMenu = new WxMenu();
List<WxMenuButton> buttons = new ArrayList<>();
// Scan QR code button
WxMenuButton scanButton = new WxMenuButton();
scanButton.setType(WxConsts.MenuButtonType.SCANCODE_PUSH);
scanButton.setName("Scan QR");
scanButton.setKey("SCAN_QR");
buttons.add(scanButton);
// Photo button
WxMenuButton photoButton = new WxMenuButton();
photoButton.setType(WxConsts.MenuButtonType.PIC_PHOTO_OR_ALBUM);
photoButton.setName("Upload Photo");
photoButton.setKey("UPLOAD_PHOTO");
buttons.add(photoButton);
// Location button
WxMenuButton locationButton = new WxMenuButton();
locationButton.setType(WxConsts.MenuButtonType.LOCATION_SELECT);
locationButton.setName("Send Location");
locationButton.setKey("SEND_LOCATION");
buttons.add(locationButton);
advancedMenu.setButtons(buttons);
wxService.getMenuService().menuCreate(advancedMenu);WxMenu miniProgramMenu = new WxMenu();
List<WxMenuButton> buttons = new ArrayList<>();
// Mini program button
WxMenuButton miniProgramButton = new WxMenuButton();
miniProgramButton.setType(WxConsts.MenuButtonType.MINIPROGRAM);
miniProgramButton.setName("Mini Program");
miniProgramButton.setUrl("https://fallback.url.com"); // Fallback URL for older versions
miniProgramButton.setAppid("your-miniprogram-appid");
miniProgramButton.setPagepath("pages/index/index");
buttons.add(miniProgramButton);
miniProgramMenu.setButtons(buttons);
wxService.getMenuService().menuCreate(miniProgramMenu);// Upload media first (image/voice)
File mediaFile = new File("path/to/media.jpg");
WxMpMaterialUploadResult uploadResult = wxService.getMaterialService()
.materialFileUpload(WxConsts.MediaFileType.IMAGE, mediaFile);
// Create menu with media button
WxMenu mediaMenu = new WxMenu();
List<WxMenuButton> buttons = new ArrayList<>();
WxMenuButton mediaButton = new WxMenuButton();
mediaButton.setType(WxConsts.MenuButtonType.MEDIA_ID);
mediaButton.setName("View Image");
mediaButton.setMediaId(uploadResult.getMediaId());
buttons.add(mediaButton);
mediaMenu.setButtons(buttons);
wxService.getMenuService().menuCreate(mediaMenu);// Create conditional menu for specific user groups
WxMenuConditional conditionalMenu = new WxMenuConditional();
// Set menu rule (conditions)
WxMenuRule rule = new WxMenuRule();
rule.setTagId("100"); // For users with tag ID 100
rule.setSex("1"); // For male users (1=male, 2=female)
rule.setCountry("China");
rule.setProvince("Beijing");
conditionalMenu.setMatchRule(rule);
// Set menu buttons
List<WxMenuButton> buttons = new ArrayList<>();
WxMenuButton vipButton = new WxMenuButton();
vipButton.setType(WxConsts.MenuButtonType.CLICK);
vipButton.setName("VIP Services");
vipButton.setKey("VIP_SERVICES");
buttons.add(vipButton);
conditionalMenu.setButtons(buttons);
// Create conditional menu
String menuid = wxService.getMenuService().conditionalMenuCreate(conditionalMenu);
System.out.println("Conditional menu created with ID: " + menuid);// Get current menu configuration
WxMenu currentMenu = wxService.getMenuService().menuGet();
if (currentMenu != null && currentMenu.getButtons() != null) {
for (WxMenuButton button : currentMenu.getButtons()) {
System.out.println("Button: " + button.getName() + " - Type: " + button.getType());
if (button.getSubButtons() != null) {
for (WxMenuButton subButton : button.getSubButtons()) {
System.out.println(" Sub-button: " + subButton.getName() +
" - Type: " + subButton.getType());
}
}
}
}// Get detailed menu information including conditionally displayed menus
WxMpGetSelfMenuInfoResult selfMenuInfo = wxService.getMenuService().getSelfMenuInfo();
System.out.println("Menu open: " + selfMenuInfo.getIsMenuOpen());
if (selfMenuInfo.getSelfMenuInfo() != null) {
for (WxMpGetSelfMenuInfoResult.WxMpSelfMenuInfo menuInfo : selfMenuInfo.getSelfMenuInfo()) {
System.out.println("Menu: " + menuInfo.getName() + " - Type: " + menuInfo.getType());
if (menuInfo.getSubButton() != null) {
for (WxMpGetSelfMenuInfoResult.WxMpSelfMenuInfo subMenu : menuInfo.getSubButton()) {
System.out.println(" Sub-menu: " + subMenu.getName() +
" - Type: " + subMenu.getType());
}
}
}
}// Delete current menu
wxService.getMenuService().menuDelete();
System.out.println("Menu deleted successfully");
// Delete conditional menu
wxService.getMenuService().conditionalMenuDelete("menuid");// Test which menu a specific user would see
String userId = "user_openid";
String menuResult = wxService.getMenuService().menuTryMatch(userId);
System.out.println("User would see menu: " + menuResult);// In your message handler
public class MenuClickHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context,
WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
String eventKey = wxMessage.getEventKey();
switch (eventKey) {
case "ABOUT_US":
return TextBuilder.build("About our company...", wxMessage);
case "SERVICE_A":
return buildServiceAResponse(wxMessage);
case "VIP_SERVICES":
return buildVipResponse(wxMessage);
case "SCAN_QR":
return TextBuilder.build("Please scan the QR code", wxMessage);
case "UPLOAD_PHOTO":
return TextBuilder.build("Please upload your photo", wxMessage);
case "SEND_LOCATION":
return TextBuilder.build("Please share your location", wxMessage);
default:
return TextBuilder.build("Menu option not implemented", wxMessage);
}
}
private WxMpXmlOutMessage buildServiceAResponse(WxMpXmlMessage wxMessage) {
// Build rich response for Service A
List<WxMpXmlOutNewsMessage.Item> articles = new ArrayList<>();
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setTitle("Service A Details");
item.setDescription("Complete information about Service A");
item.setUrl("https://www.example.com/service-a");
item.setPicUrl("https://www.example.com/service-a-image.jpg");
articles.add(item);
return NewsBuilder.build(articles, wxMessage);
}
}
// Register menu handler in router
router.rule()
.msgType(WxConsts.XmlMsgType.EVENT)
.event(WxConsts.EventType.CLICK)
.handler(new MenuClickHandler())
.end();public WxMenu createComplexMenu() {
WxMenu menu = new WxMenu();
List<WxMenuButton> buttons = new ArrayList<>();
// Products menu with sub-buttons
WxMenuButton productsButton = new WxMenuButton();
productsButton.setName("Products");
List<WxMenuButton> productSubButtons = new ArrayList<>();
// Product category 1
WxMenuButton product1 = new WxMenuButton();
product1.setType(WxConsts.MenuButtonType.VIEW);
product1.setName("Category A");
product1.setUrl("https://www.example.com/category-a");
productSubButtons.add(product1);
// Product category 2
WxMenuButton product2 = new WxMenuButton();
product2.setType(WxConsts.MenuButtonType.CLICK);
product2.setName("Category B");
product2.setKey("CATEGORY_B");
productSubButtons.add(product2);
// Product catalog
WxMenuButton catalog = new WxMenuButton();
catalog.setType(WxConsts.MenuButtonType.MEDIA_ID);
catalog.setName("Catalog");
catalog.setMediaId("catalog_media_id");
productSubButtons.add(catalog);
productsButton.setSubButtons(productSubButtons);
buttons.add(productsButton);
// Services menu
WxMenuButton servicesButton = new WxMenuButton();
servicesButton.setName("Services");
List<WxMenuButton> serviceSubButtons = new ArrayList<>();
// Customer service
WxMenuButton customerService = new WxMenuButton();
customerService.setType(WxConsts.MenuButtonType.CLICK);
customerService.setName("Customer Service");
customerService.setKey("CUSTOMER_SERVICE");
serviceSubButtons.add(customerService);
// Technical support
WxMenuButton techSupport = new WxMenuButton();
techSupport.setType(WxConsts.MenuButtonType.VIEW);
techSupport.setName("Tech Support");
techSupport.setUrl("https://support.example.com");
serviceSubButtons.add(techSupport);
// FAQ
WxMenuButton faq = new WxMenuButton();
faq.setType(WxConsts.MenuButtonType.ARTICLE_VIEW_LIMITED);
faq.setName("FAQ");
faq.setArticleId("faq_article_id");
serviceSubButtons.add(faq);
servicesButton.setSubButtons(serviceSubButtons);
buttons.add(servicesButton);
// Contact menu
WxMenuButton contactButton = new WxMenuButton();
contactButton.setName("Contact");
List<WxMenuButton> contactSubButtons = new ArrayList<>();
// Phone
WxMenuButton phone = new WxMenuButton();
phone.setType(WxConsts.MenuButtonType.CLICK);
phone.setName("Phone");
phone.setKey("CONTACT_PHONE");
contactSubButtons.add(phone);
// Address
WxMenuButton address = new WxMenuButton();
address.setType(WxConsts.MenuButtonType.LOCATION_SELECT);
address.setName("Address");
address.setKey("CONTACT_ADDRESS");
contactSubButtons.add(address);
// Mini Program
WxMenuButton miniProgram = new WxMenuButton();
miniProgram.setType(WxConsts.MenuButtonType.MINIPROGRAM);
miniProgram.setName("Mini Program");
miniProgram.setUrl("https://www.example.com");
miniProgram.setAppid("miniprogram_appid");
miniProgram.setPagepath("pages/contact/contact");
contactSubButtons.add(miniProgram);
contactButton.setSubButtons(contactSubButtons);
buttons.add(contactButton);
menu.setButtons(buttons);
return menu;
}try {
wxService.getMenuService().menuCreate(menu);
} catch (WxErrorException e) {
int errorCode = e.getError().getErrorCode();
switch (errorCode) {
case 40018:
System.err.println("Invalid button name length");
break;
case 40019:
System.err.println("Invalid button key length");
break;
case 40020:
System.err.println("Invalid button URL");
break;
case 40023:
System.err.println("Invalid sub-menu level");
break;
case 40024:
System.err.println("Too many sub-menu buttons");
break;
case 40025:
System.err.println("Too many main menu buttons");
break;
default:
System.err.println("Menu creation failed: " + e.getError().getErrorMsg());
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-github-binarywang--weixin-java-mp