#68 实现获取公众号的自动回复规则的接口

This commit is contained in:
Binary Wang 2017-07-08 19:22:26 +08:00
parent 166e54c3f5
commit 57f3755a84
7 changed files with 647 additions and 6 deletions

View File

@ -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;
/**
* <pre>
* Gson 布尔类型类型转换器
* Created by Binary Wang on 2017-7-8.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxBooleanTypeAdapter extends TypeAdapter<Boolean> {
@Override
public void write(JsonWriter out, Boolean value) throws IOException {
if (value == null) {
out.nullValue();
} else {
out.value(value);
}
}
@Override
public Boolean read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
switch (peek) {
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
case NUMBER:
return BooleanUtils.toBoolean(in.nextInt());
case STRING:
return BooleanUtils.toBoolean(in.nextString());
default:
throw new JsonParseException("Expected BOOLEAN or NUMBER but was " + peek);
}
}
}

View File

@ -0,0 +1,43 @@
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 java.io.IOException;
import java.util.Date;
/**
* <pre>
* Gson 日期类型转换器
* Created by Binary Wang on 2017-7-8.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxDateTypeAdapter extends TypeAdapter<Date> {
@Override
public void write(JsonWriter out, Date value) throws IOException {
if (value == null) {
out.nullValue();
} else {
out.value(value.getTime() / 1000);
}
}
@Override
public Date read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
switch (peek) {
case NULL:
in.nextNull();
return null;
case NUMBER:
return new Date(in.nextInt() * 1000);
default:
throw new JsonParseException("Expected NUMBER but was " + peek);
}
}
}

View File

@ -77,6 +77,11 @@ public interface WxMpService {
*/
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
/**
* 获取公众号的自动回复规则
*/
String GET_CURRENT_AUTOREPLY_INFO_URL = "https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info";
/**
* <pre>
* 验证消息的确来自微信服务器
@ -273,6 +278,24 @@ public interface WxMpService {
*/
String[] getCallbackIP() throws WxErrorException;
/**
* <pre>
* 获取公众号的自动回复规则
* 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
* </pre>
*/
WxMpCurrentAutoReplyInfo getCurrentAutoReplyInfo() throws WxErrorException;
/**
* 当本Service没有实现某个API的时候可以用这个针对所有微信API中的GET请求
*/
@ -292,15 +315,10 @@ public interface WxMpService {
*/
<T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException;
/**
* 获取代理对象
*/
//HttpHost getRequestHttpProxy();
/**
* <pre>
* 设置当微信系统响应系统繁忙时要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试
* 默认1000ms
* @param retrySleepMillis 默认1000ms
* </pre>
*/
void setRetrySleepMillis(int retrySleepMillis);

View File

@ -231,6 +231,11 @@ public abstract class AbstractWxMpServiceImpl<H, P> implements WxMpService, Requ
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);

View File

@ -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;
/**
* <pre>
* 公众号的自动回复规则
* Created by Binary Wang on 2017-7-8.
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* </pre>
*/
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 List<KeywordInfo> keywordListInfo;
@SerializedName("reply_list_info")
private List<ReplyInfo> 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<KeywordInfo> getKeywordListInfo() {
return this.keywordListInfo;
}
public void setKeywordListInfo(List<KeywordInfo> keywordListInfo) {
this.keywordListInfo = keywordListInfo;
}
public List<ReplyInfo> getReplyListInfo() {
return this.replyListInfo;
}
public void setReplyListInfo(List<ReplyInfo> 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<NewsItem> list;
public List<NewsItem> getList() {
return this.list;
}
public void setList(List<NewsItem> 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<AutoReplyRule> list;
public List<AutoReplyRule> getList() {
return this.list;
}
public void setList(List<AutoReplyRule> 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;
}
}
}

View File

@ -2,12 +2,16 @@ package me.chanjar.weixin.mp.api.impl;
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");

View File

@ -0,0 +1,157 @@
package me.chanjar.weixin.mp.bean.result;
import org.testng.annotations.*;
import static org.testng.Assert.*;
/**
* <pre>
* Created by Binary Wang on 2017-7-8.
* @author <a href="https://github.com/binarywang">Binary Wang</a>
* </pre>
*/
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);
}
}