diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenu.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenu.java index 6b43ed06..4e61a465 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenu.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/menu/WxMenu.java @@ -1,5 +1,8 @@ package me.chanjar.weixin.common.bean.menu; +import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + import java.io.InputStream; import java.io.InputStreamReader; import java.io.Serializable; @@ -7,11 +10,8 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import me.chanjar.weixin.common.bean.menu.WxMenuButton; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; - /** - * 企业号菜单 + * 菜单(公众号和企业号共用的) * * @author Daniel Qian */ @@ -61,9 +61,7 @@ public class WxMenu implements Serializable { @Override public String toString() { - return "WxMenu{" + - "buttons=" + this.buttons + - '}'; + return ToStringUtils.toSimpleString(this); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java index 22217801..94359025 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java @@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.api; import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; /** * 菜单相关操作接口 @@ -56,4 +57,20 @@ public interface WxMpMenuService { */ WxMenu menuTryMatch(String userid) throws WxErrorException; + /** + *
+   * 获取自定义菜单配置接口
+   * 本接口将会提供公众号当前使用的自定义菜单的配置,如果公众号是通过API调用设置的菜单,则返回菜单的开发配置,而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。
+     请注意:
+     1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自定义菜单配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。
+     2、本接口与自定义菜单查询接口的不同之处在于,本接口无论公众号的接口是如何设置的,都能查询到接口,而自定义菜单查询接口则仅能查询到使用API设置的菜单配置。
+     3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。
+     4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。
+     5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。
+   *  接口调用请求说明:
+        http请求方式: GET(请使用https协议)
+        https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
+   *
+ */ + WxMpGetSelfMenuInfoResult getSelfMenuInfo() throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java index 2f40f709..1373c83d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java @@ -1,12 +1,13 @@ package me.chanjar.weixin.mp.api.impl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpMenuService; import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; +import me.chanjar.weixin.mp.bean.menu.WxMpSelfMenuInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Created by Binary Wang on 2016/7/21. @@ -14,7 +15,7 @@ import me.chanjar.weixin.mp.api.WxMpService; public class WxMpMenuServiceImpl implements WxMpMenuService { private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/menu"; private static Logger log = LoggerFactory - .getLogger(WxMpMenuServiceImpl.class); + .getLogger(WxMpMenuServiceImpl.class); private WxMpService wxMpService; @@ -74,10 +75,17 @@ public class WxMpMenuServiceImpl implements WxMpMenuService { } catch (WxErrorException e) { // 46003 不存在的菜单数据 46002 不存在的菜单版本 if (e.getError().getErrorCode() == 46003 - || e.getError().getErrorCode() == 46002) { + || e.getError().getErrorCode() == 46002) { return null; } throw e; } } + + @Override + public WxMpGetSelfMenuInfoResult getSelfMenuInfo() throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info"; + String resultContent = this.wxMpService.get(url, null); + return WxMpGetSelfMenuInfoResult.fromJson(resultContent); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java new file mode 100644 index 00000000..b78d2dc3 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java @@ -0,0 +1,44 @@ +package me.chanjar.weixin.mp.bean.menu; + +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + +/** + *
+ * Created by Binary Wang on 2016-11-25.
+ * @author binarywang(Binary Wang)
+ * 
+ */ +public class WxMpGetSelfMenuInfoResult { + @SerializedName("selfmenu_info") + private WxMpSelfMenuInfo selfMenuInfo; + + @SerializedName("is_menu_open") + private Integer isMenuOpen; + + public static WxMpGetSelfMenuInfoResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, WxMpGetSelfMenuInfoResult.class); + } + + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + public WxMpSelfMenuInfo getSelfMenuInfo() { + return selfMenuInfo; + } + + public void setSelfMenuInfo(WxMpSelfMenuInfo selfMenuInfo) { + this.selfMenuInfo = selfMenuInfo; + } + + public Integer getIsMenuOpen() { + return isMenuOpen; + } + + public void setIsMenuOpen(Integer isMenuOpen) { + this.isMenuOpen = isMenuOpen; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpSelfMenuInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpSelfMenuInfo.java new file mode 100644 index 00000000..f2c0c4ca --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpSelfMenuInfo.java @@ -0,0 +1,288 @@ +package me.chanjar.weixin.mp.bean.menu; + +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.common.util.ToStringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + *
+ * Created by Binary Wang on 2016-11-25.
+ * @author binarywang(Binary Wang)
+ * 
+ */ +public class WxMpSelfMenuInfo { + /** + * 菜单按钮 + */ + @SerializedName("button") + private List buttons; + + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + public static class WxMpSelfMenuButton { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + /** + *
+     * 菜单的类型,公众平台官网上能够设置的菜单类型有view(跳转网页)、text(返回文本,下同)、img、photo、video、voice。
+     * 使用API设置的则有8种,详见《自定义菜单创建接口》
+     * 
+ */ + @SerializedName("type") + private String type; + + /** + * 菜单名称 + */ + @SerializedName("name") + private String name; + + /** + *
+     * 对于不同的菜单类型,value的值意义不同。
+     * 官网上设置的自定义菜单:
+     *  
  • Text:保存文字到value; + *
  • Img、voice:保存mediaID到value; + *
  • Video:保存视频下载链接到value; + *
  • News:保存图文消息到news_info,同时保存mediaID到value; + *
  • View:保存链接到url。
  • + * + * 使用API设置的自定义菜单: + *
  • click、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album、 pic_weixin、location_select:保存值到key; + *
  • view:保存链接到url + *
  • + */ + @SerializedName("key") + private String key; + + /** + * @see #key + */ + @SerializedName("url") + private String url; + + /** + * @see #key + */ + @SerializedName("value") + private String value; + + /** + * 子菜单信息 + */ + @SerializedName("sub_button") + private SubButtons subButtons; + + public SubButtons getSubButtons() { + return subButtons; + } + + public void setSubButtons(SubButtons subButtons) { + this.subButtons = subButtons; + } + + public static class SubButtons { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + @SerializedName("list") + private List subButtons = new ArrayList<>(); + + public List getSubButtons() { + return subButtons; + } + + public void setSubButtons(List subButtons) { + this.subButtons = subButtons; + } + } + + /** + * 图文消息的信息 + */ + @SerializedName("news_info") + private NewsInfo newsInfo; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public NewsInfo getNewsInfo() { + return newsInfo; + } + + public void setNewsInfo(NewsInfo newsInfo) { + this.newsInfo = newsInfo; + } + + public static class NewsInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + @SerializedName("list") + private List news = new ArrayList<>(); + + public List getNews() { + return news; + } + + public void setNews(List news) { + this.news = news; + } + + public static class NewsInButton { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + /** + * 图文消息的标题 + */ + @SerializedName("title") + private String title; + + /** + * 摘要 + */ + @SerializedName("digest") + private String digest; + + /** + * 作者 + */ + @SerializedName("author") + private String author; + + /** + * show_cover + * 是否显示封面,0为不显示,1为显示 + */ + @SerializedName("show_cover") + private Integer showCover; + + /** + * 封面图片的URL + */ + @SerializedName("cover_url") + private String coverUrl; + + /** + * 正文的URL + */ + @SerializedName("content_url") + private String contentUrl; + + /** + * 原文的URL,若置空则无查看原文入口 + */ + @SerializedName("source_url") + private String sourceUrl; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDigest() { + return digest; + } + + public void setDigest(String digest) { + this.digest = digest; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public Integer getShowCover() { + return showCover; + } + + public void setShowCover(Integer showCover) { + this.showCover = showCover; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public String getContentUrl() { + return contentUrl; + } + + public void setContentUrl(String contentUrl) { + this.contentUrl = contentUrl; + } + + public String getSourceUrl() { + return sourceUrl; + } + + public void setSourceUrl(String sourceUrl) { + this.sourceUrl = sourceUrl; + } + } + } + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java index f31a0e4b..a312b15d 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java @@ -1,18 +1,17 @@ package me.chanjar.weixin.mp.api.impl; -import me.chanjar.weixin.mp.api.WxMpService; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; - import com.google.inject.Inject; - import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.menu.WxMenu; import me.chanjar.weixin.common.bean.menu.WxMenuButton; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.menu.WxMpGetSelfMenuInfoResult; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; /** * 测试菜单 @@ -28,11 +27,22 @@ public class WxMpMenuServiceImplTest { protected WxMpService wxService; @Test(dataProvider = "menu") - public void testCreateMenu(WxMenu wxMenu) throws WxErrorException { + public void testMenuCreate(WxMenu wxMenu) throws WxErrorException { System.out.println(wxMenu.toJson()); this.wxService.getMenuService().menuCreate(wxMenu); } + @Test + public void testMenuTryMatch() throws Exception { + //TODO + } + + @Test + public void testGetSelfMenuInfo() throws Exception { + WxMpGetSelfMenuInfoResult selfMenuInfo = this.wxService.getMenuService().getSelfMenuInfo(); + System.out.println(selfMenuInfo); + } + @Test public void testCreateMenu2() throws WxErrorException { String a = "{\n" @@ -77,15 +87,15 @@ public class WxMpMenuServiceImplTest { this.wxService.getMenuService().menuCreate(menu); } - @Test(dependsOnMethods = { "testCreateMenu"}) - public void testGetMenu() throws WxErrorException { + @Test(dependsOnMethods = { "testMenuCreate"}) + public void testMenuGet() throws WxErrorException { WxMenu wxMenu = this.wxService.getMenuService().menuGet(); Assert.assertNotNull(wxMenu); System.out.println(wxMenu.toJson()); } - @Test(dependsOnMethods = { "testGetMenu"}) - public void testDeleteMenu() throws WxErrorException { + @Test(dependsOnMethods = { "testMenuGet"}) + public void testMenuDelete() throws WxErrorException { this.wxService.getMenuService().menuDelete(); }