diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxBooleanTypeAdapter.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxBooleanTypeAdapter.java new file mode 100644 index 0000000000..3fbbef4a43 --- /dev/null +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/json/WxBooleanTypeAdapter.java @@ -0,0 +1,47 @@ +package me.chanjar.weixin.common.util.json; + +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import org.apache.commons.lang3.BooleanUtils; + +import java.io.IOException; + +/** + *
+ * Gson 布尔类型类型转换器 + * Created by Binary Wang on 2017-7-8. + *+ * + * @author Binary Wang + */ +public class WxBooleanTypeAdapter extends TypeAdapter
+ * Gson 日期类型转换器 + * Created by Binary Wang on 2017-7-8. + *+ * + * @author Binary Wang + */ +public class WxDateTypeAdapter extends TypeAdapter
* 验证消息的确来自微信服务器 @@ -273,6 +278,24 @@ public interface WxMpService { */ String[] getCallbackIP() throws WxErrorException; + /** + *+ * 获取公众号的自动回复规则 + * http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751299&token=&lang=zh_CN + * 开发者可以通过该接口,获取公众号当前使用的自动回复规则,包括关注后自动回复、消息自动回复(60分钟内触发一次)、关键词自动回复。 + * 请注意: + * 1、第三方平台开发者可以通过本接口,在旗下公众号将业务授权给你后,立即通过本接口检测公众号的自动回复配置,并通过接口再次给公众号设置好自动回复规则,以提升公众号运营者的业务体验。 + * 2、本接口仅能获取公众号在公众平台官网的自动回复功能中设置的自动回复规则,若公众号自行开发实现自动回复,或通过第三方平台开发者来实现,则无法获取。 + * 3、认证/未认证的服务号/订阅号,以及接口测试号,均拥有该接口权限。 + * 4、从第三方平台的公众号登录授权机制上来说,该接口从属于消息与菜单权限集。 + * 5、本接口中返回的图片/语音/视频为临时素材(临时素材每次获取都不同,3天内有效,通过素材管理-获取临时素材接口来获取这些素材),本接口返回的图文消息为永久素材素材(通过素材管理-获取永久素材接口来获取这些素材)。 + * 接口调用请求说明 + * http请求方式: GET(请使用https协议) + * https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info?access_token=ACCESS_TOKEN + *+ */ + WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException; + /** * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求 */ @@ -292,15 +315,10 @@ public interface WxMpService { */T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; - /** - * 获取代理对象 - */ - //HttpHost getRequestHttpProxy(); - /** * * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试 - * 默认:1000ms + * @param retrySleepMillis 默认:1000ms **/ void setRetrySleepMillis(int retrySleepMillis); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java index d3075aa11d..ed93d4936f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java @@ -231,6 +231,11 @@ public String[] getCallbackIP() throws WxErrorException { return ipArray; } + @Override + public WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException { + return WxMpCurrentAutoReplyInfo.fromJson(this.get(GET_CURRENT_AUTOREPLY_INFO_URL, null)); + } + @Override public String get(String url, String queryParam) throws WxErrorException { return execute(SimpleGetRequestExecutor.create(this), url, queryParam); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfo.java new file mode 100644 index 0000000000..6738b8bc4a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfo.java @@ -0,0 +1,359 @@ +package me.chanjar.weixin.mp.bean.result; + +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.json.WxBooleanTypeAdapter; +import me.chanjar.weixin.common.util.json.WxDateTypeAdapter; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.util.Date; +import java.util.List; + +/** + *+ * 公众号的自动回复规则 + * Created by Binary Wang on 2017-7-8. + * @author Binary Wang + *+ */ +public class WxMpCurrentAutoReplyInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + public static WxMpCurrentAutoReplyInfo fromJson(String json) { + return WxMpGsonBuilder.create().fromJson(json, WxMpCurrentAutoReplyInfo.class); + } + + @SerializedName("is_add_friend_reply_open") + @JsonAdapter(WxBooleanTypeAdapter.class) + private Boolean isAddFriendReplyOpen; + + @SerializedName("is_autoreply_open") + @JsonAdapter(WxBooleanTypeAdapter.class) + private Boolean isAutoReplyOpen; + + @SerializedName("add_friend_autoreply_info") + private AutoReplyInfo addFriendAutoReplyInfo; + + @SerializedName("message_default_autoreply_info") + private AutoReplyInfo messageDefaultAutoReplyInfo; + + @SerializedName("keyword_autoreply_info") + private KeywordAutoReplyInfo keywordAutoReplyInfo; + + public Boolean getAddFriendReplyOpen() { + return this.isAddFriendReplyOpen; + } + + public void setAddFriendReplyOpen(Boolean addFriendReplyOpen) { + isAddFriendReplyOpen = addFriendReplyOpen; + } + + public Boolean getAutoReplyOpen() { + return this.isAutoReplyOpen; + } + + public void setAutoReplyOpen(Boolean autoReplyOpen) { + isAutoReplyOpen = autoReplyOpen; + } + + public AutoReplyInfo getAddFriendAutoReplyInfo() { + return this.addFriendAutoReplyInfo; + } + + public void setAddFriendAutoReplyInfo(AutoReplyInfo addFriendAutoReplyInfo) { + this.addFriendAutoReplyInfo = addFriendAutoReplyInfo; + } + + public AutoReplyInfo getMessageDefaultAutoReplyInfo() { + return this.messageDefaultAutoReplyInfo; + } + + public void setMessageDefaultAutoReplyInfo(AutoReplyInfo messageDefaultAutoReplyInfo) { + this.messageDefaultAutoReplyInfo = messageDefaultAutoReplyInfo; + } + + public KeywordAutoReplyInfo getKeywordAutoReplyInfo() { + return this.keywordAutoReplyInfo; + } + + public void setKeywordAutoReplyInfo(KeywordAutoReplyInfo keywordAutoReplyInfo) { + this.keywordAutoReplyInfo = keywordAutoReplyInfo; + } + + public static class AutoReplyRule { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + @SerializedName("rule_name") + private String ruleName; + + @SerializedName("create_time") + @JsonAdapter(WxDateTypeAdapter.class) + private Date createTime; + + @SerializedName("reply_mode") + private String replyMode; + + @SerializedName("keyword_list_info") + private ListkeywordListInfo; + + @SerializedName("reply_list_info") + private List replyListInfo; + + public String getRuleName() { + return this.ruleName; + } + + public void setRuleName(String ruleName) { + this.ruleName = ruleName; + } + + public Date getCreateTime() { + return this.createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getReplyMode() { + return this.replyMode; + } + + public void setReplyMode(String replyMode) { + this.replyMode = replyMode; + } + + public List getKeywordListInfo() { + return this.keywordListInfo; + } + + public void setKeywordListInfo(List keywordListInfo) { + this.keywordListInfo = keywordListInfo; + } + + public List getReplyListInfo() { + return this.replyListInfo; + } + + public void setReplyListInfo(List replyListInfo) { + this.replyListInfo = replyListInfo; + } + } + + public static class ReplyInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + private String type; + private String content; + + @SerializedName("news_info") + private NewsInfo newsInfo; + + public String getType() { + return this.type; + } + + public void setType(String type) { + this.type = type; + } + + public String getContent() { + return this.content; + } + + public void setContent(String content) { + this.content = content; + } + + public NewsInfo getNewsInfo() { + return this.newsInfo; + } + + public void setNewsInfo(NewsInfo newsInfo) { + this.newsInfo = newsInfo; + } + } + + public static class NewsInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + private List list; + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class NewsItem { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + @SerializedName("cover_url") + private String coverUrl; + private String author; + @SerializedName("content_url") + private String contentUrl; + private String digest; + @SerializedName("show_cover") + @JsonAdapter(WxBooleanTypeAdapter.class) + private Boolean showCover; + @SerializedName("source_url") + private String sourceUrl; + private String title; + + public String getCoverUrl() { + return this.coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public String getAuthor() { + return this.author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getContentUrl() { + return this.contentUrl; + } + + public void setContentUrl(String contentUrl) { + this.contentUrl = contentUrl; + } + + public String getDigest() { + return this.digest; + } + + public void setDigest(String digest) { + this.digest = digest; + } + + public Boolean getShowCover() { + return this.showCover; + } + + public void setShowCover(Boolean showCover) { + this.showCover = showCover; + } + + public String getSourceUrl() { + return this.sourceUrl; + } + + public void setSourceUrl(String sourceUrl) { + this.sourceUrl = sourceUrl; + } + + public String getTitle() { + return this.title; + } + + public void setTitle(String title) { + this.title = title; + } + } + + public static class KeywordInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + private String type; + @SerializedName("match_mode") + private String matchMode; + private String content; + + public String getType() { + return this.type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMatchMode() { + return this.matchMode; + } + + public void setMatchMode(String matchMode) { + this.matchMode = matchMode; + } + + public String getContent() { + return this.content; + } + + public void setContent(String content) { + this.content = content; + } + } + + public static class KeywordAutoReplyInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + private List list; + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + } + + public static class AutoReplyInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + private String type; + private String content; + + public String getType() { + return this.type; + } + + public void setType(String type) { + this.type = type; + } + + public String getContent() { + return this.content; + } + + public void setContent(String content) { + this.content = content; + } + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java index d5bf621287..c3f9f69d7b 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java @@ -2,12 +2,16 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.test.ApiTestModule; import me.chanjar.weixin.mp.api.test.TestConfigStorage; +import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo; import org.testng.*; import org.testng.annotations.*; +import static org.testng.Assert.*; + @Test @Guice(modules = ApiTestModule.class) public class WxMpServiceImplTest { @@ -15,6 +19,14 @@ public class WxMpServiceImplTest { @Inject private WxMpService wxService; + @Test + public void testGetCurrentAutoReplyInfo() throws WxErrorException { + WxMpCurrentAutoReplyInfo autoReplyInfo = this.wxService.getCurrentAutoReplyInfo(); + + assertNotNull(autoReplyInfo); + System.out.println(autoReplyInfo); + } + @Test public void testCheckSignature() { Assert.fail("Not yet implemented"); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfoTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfoTest.java new file mode 100644 index 0000000000..da2cddff40 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/WxMpCurrentAutoReplyInfoTest.java @@ -0,0 +1,157 @@ +package me.chanjar.weixin.mp.bean.result; + +import org.testng.annotations.*; + +import static org.testng.Assert.*; + +/** + * + * Created by Binary Wang on 2017-7-8. + * @author Binary Wang + *+ */ +public class WxMpCurrentAutoReplyInfoTest { + @Test + public void testFromJson() throws Exception { + String json = "{ \n" + + " \"is_add_friend_reply_open\": 1, \n" + + " \"is_autoreply_open\": 1, \n" + + " \"add_friend_autoreply_info\": { \n" + + " \"type\": \"text\", \n" + + " \"content\": \"Thanks for your attention!\"\n" + + " }, \n" + + " \"message_default_autoreply_info\": { \n" + + " \"type\": \"text\", \n" + + " \"content\": \"Hello, this is autoreply!\"\n" + + " }, \n" + + " \"keyword_autoreply_info\": { \n" + + " \"list\": [ \n" + + " { \n" + + " \"rule_name\": \"autoreply-news\", \n" + + " \"create_time\": 1423028166, \n" + + " \"reply_mode\": \"reply_all\", \n" + + " \"keyword_list_info\": [ \n" + + " { \n" + + " \"type\": \"text\", \n" + + " \"match_mode\": \"contain\", \n" + + " \"content\": \"news测试\"//此处content即为关键词内容\n" + + " }\n" + + " ], \n" + + " \"reply_list_info\": [ \n" + + " { \n" + + " \"type\": \"news\", \n" + + " \"news_info\": { \n" + + " \"list\": [ \n" + + " { \n" + + " \"title\": \"it's news\", \n" + + " \"author\": \"jim\", \n" + + " \"digest\": \"it's digest\", \n" + + " \"show_cover\": 1, \"cover_url\": \"http://mmbiz.qpic.cn/mmbiz/GE7et87vE9vicuCibqXsX9GPPLuEtBfXfKbE8sWdt2DDcL0dMfQWJWTVn1N8DxI0gcRmrtqBOuwQH\n" + + " euPKmFLK0ZQ/0\", \n" + + " \"content_url\": \"http://mp.weixin.qq.com/s?__biz=MjM5ODUwNTM3Ng==&mid=203929886&idx=1&sn=628f964cf0c6d84c026881b6959aea8b#rd\", \n" + + " \"source_url\": \"http://www.url.com\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " }, \n" + + " { \n" + + " \"type\": \"news\",\n" + + " \"content\":\"KQb_w_Tiz-nSdVLoTV35Psmty8hGBulGhEdbb9SKs-o\", \n" + + " \"news_info\": { \n" + + " \"list\": [ \n" + + " { \n" + + " \"title\": \"MULTI_NEWS\", \n" + + " \"author\": \"JIMZHENG\", \n" + + " \"digest\": \"text\", \n" + + " \"show_cover\": 0, \n" + + " \"cover_url\": \"http://mmbiz.qpic.cn/mmbiz/GE7et87vE9vicuCibqXsX9GPPLuEtBfXfK0HKuBIa1A1cypS0uY1wickv70iaY1gf3I1DTszuJoS3lAVLv\n" + + "hTcm9sDA/0\", \n" + + " \"content_url\": \"http://mp.weixin.qq.com/s?__biz=MjM5ODUwNTM3Ng==&mid=204013432&idx=1&sn=80ce6d9abcb832237bf86c87e50fda15#rd\", \n" + + " \"source_url\": \"\"\n" + + " },\n" + + " { \n" + + " \"title\": \"MULTI_NEWS4\", \n" + + " \"author\": \"JIMZHENG\", \n" + + " \"digest\": \"MULTI_NEWSMULTI_NEWSMULTI_NEWSMULTI_NEWSMULTI_NEWSMULT\", \n" + + " \"show_cover\": 1, \n" + + "\"cover_url\": \"http://mmbiz.qpic.cn/mmbiz/GE7et87vE9vicuCibqXsX9GPPLuEtBfXfKbE8sWdt2DDcL0dMfQWJWTVn1N8DxI0gcRmrtqBOuwQ\n" + + "HeuPKmFLK0ZQ/0\", \n" + + " \"content_url\": \"http://mp.weixin.qq.com/s?__biz=MjM5ODUwNTM3Ng==&mid=204013432&idx=5&sn=b4ef73a915e7c2265e437096582774af#rd\", \n" + + " \"source_url\": \"\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " }\n" + + " ]\n" + + " }, \n" + + " { \n" + + " \"rule_name\": \"autoreply-voice\", \n" + + " \"create_time\": 1423027971, \n" + + " \"reply_mode\": \"random_one\", \n" + + " \"keyword_list_info\": [ \n" + + " { \n" + + " \"type\": \"text\", \n" + + " \"match_mode\": \"contain\", \n" + + " \"content\": \"voice测试\"\n" + + " }\n" + + " ], \n" + + " \"reply_list_info\": [ \n" + + " { \n" + + " \"type\": \"voice\", \n" + + " \"content\": \"NESsxgHEvAcg3egJTtYj4uG1PTL6iPhratdWKDLAXYErhN6oEEfMdVyblWtBY5vp\"\n" + + " }\n" + + " ]\n" + + " }, \n" + + " { \n" + + " \"rule_name\": \"autoreply-text\", \n" + + " \"create_time\": 1423027926, \n" + + " \"reply_mode\": \"random_one\", \n" + + " \"keyword_list_info\": [ \n" + + " { \n" + + " \"type\": \"text\", \n" + + " \"match_mode\": \"contain\", \n" + + " \"content\": \"text测试\"\n" + + " }\n" + + " ], \n" + + " \"reply_list_info\": [ \n" + + " { \n" + + " \"type\": \"text\", \n" + + " \"content\": \"hello!text!\"\n" + + " }\n" + + " ]\n" + + " }, \n" + + " { \n" + + " \"rule_name\": \"autoreply-video\", \n" + + " \"create_time\": 1423027801, \n" + + " \"reply_mode\": \"random_one\", \n" + + " \"keyword_list_info\": [ \n" + + " { \n" + + " \"type\": \"text\", \n" + + " \"match_mode\": \"equal\", \n" + + " \"content\": \"video测试\"\n" + + " }\n" + + " ], \n" + + " \"reply_list_info\": [ \n" + + " { \n" + + " \"type\": \"video\", \n" + + "\"content\": \"http://61.182.133.153/vweixinp.tc.qq.com/1007_114bcede9a2244eeb5ab7f76d951df5f.f10.mp4?vkey=7183E5C952B16C3AB1991BA8138673DE1037CB82A29801A504B64A77F691BF9DF7AD054A9B7FE683&sha=0&save=1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + WxMpCurrentAutoReplyInfo autoReplyInfo = WxMpCurrentAutoReplyInfo.fromJson(json); + + assertNotNull(autoReplyInfo); + assertTrue(autoReplyInfo.getAddFriendReplyOpen()); + assertTrue(autoReplyInfo.getAutoReplyOpen()); + assertNotNull(autoReplyInfo.getAddFriendAutoReplyInfo()); + assertNotNull(autoReplyInfo.getMessageDefaultAutoReplyInfo()); + assertTrue(autoReplyInfo.getKeywordAutoReplyInfo().getList().size() > 0); + + System.out.println(autoReplyInfo); + } + +}