From 6b2e858a622ba2c81c9e888da1a2f2f90a4b5072 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Thu, 30 Jun 2016 20:24:23 +0800 Subject: [PATCH 01/54] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=B8=BA1.3.6-SNAPSHOT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- spring-demo/pom.xml | 2 +- weixin-java-common/pom.xml | 2 +- weixin-java-cp/pom.xml | 2 +- weixin-java-mp/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index ebbd615583..eee4837c1b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.github.binarywang weixin-java-parent - 1.3.5-SNAPSHOT + 1.3.6-SNAPSHOT pom WeiXin Java Tools - Parent 微信公众号、企业号上级POM diff --git a/spring-demo/pom.xml b/spring-demo/pom.xml index 1ae990ed16..815ce765ce 100644 --- a/spring-demo/pom.xml +++ b/spring-demo/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.5-SNAPSHOT + 1.3.6-SNAPSHOT spring-demo war diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index 38749b9fb0..8adf10cdfb 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.5-SNAPSHOT + 1.3.6-SNAPSHOT weixin-java-common diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml index 38e14fa72e..893eceb33c 100644 --- a/weixin-java-cp/pom.xml +++ b/weixin-java-cp/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.5-SNAPSHOT + 1.3.6-SNAPSHOT weixin-java-cp diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index ada2e442cb..47daf6793d 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.5-SNAPSHOT + 1.3.6-SNAPSHOT weixin-java-mp WeiXin Java Tools - MP From a21f1522a60ce05cc8840806f5ab64fef6d81fbc Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 4 Jul 2016 13:19:24 +0800 Subject: [PATCH 02/54] =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=B8=AD=E5=8E=BB=E6=8E=89=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84?= =?UTF-8?q?=E7=BB=84=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java | 2 +- .../test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java index 7af300c9c3..2b12ac259b 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java @@ -14,7 +14,7 @@ * * @author chanjarster */ -@Test(groups = "qrCodeAPI", dependsOnGroups = { "baseAPI" }) +@Test(groups = "qrCodeAPI") @Guice(modules = ApiTestModule.class) public class WxMpQrCodeAPITest { diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java index fb97f2d4ec..76712ad58a 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java @@ -11,7 +11,7 @@ * * @author chanjarster */ -@Test(groups = "shortURLAPI", dependsOnGroups = { "baseAPI" }) +@Test(groups = "shortURLAPI") @Guice(modules = ApiTestModule.class) public class WxMpShortUrlAPITest { From 8b1f026aa7f581017c1478adbb4622c83affcbaf Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 4 Jul 2016 17:21:00 +0800 Subject: [PATCH 03/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9Bwarni?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/bean/WxMpCustomMessage.java | 33 ++++++++++--------- .../weixin/mp/bean/WxMpXmlOutMessage.java | 16 +++++---- ...pXmlOutTransferCustomerServiceMessage.java | 6 ++-- .../TransferCustomerServiceBuilder.java | 10 +++--- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java index a19b79bd4c..278ac2886f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java @@ -13,7 +13,8 @@ * */ public class WxMpCustomMessage implements Serializable { - + private static final long serialVersionUID = -9196732086954365246L; + private String toUser; private String msgType; private String content; @@ -23,16 +24,16 @@ public class WxMpCustomMessage implements Serializable { private String description; private String musicUrl; private String hqMusicUrl; - private List articles = new ArrayList(); + private List articles = new ArrayList<>(); public String getToUser() { - return toUser; + return this.toUser; } public void setToUser(String toUser) { this.toUser = toUser; } public String getMsgType() { - return msgType; + return this.msgType; } /** @@ -51,49 +52,49 @@ public void setMsgType(String msgType) { this.msgType = msgType; } public String getContent() { - return content; + return this.content; } public void setContent(String content) { this.content = content; } public String getMediaId() { - return mediaId; + return this.mediaId; } public void setMediaId(String mediaId) { this.mediaId = mediaId; } public String getThumbMediaId() { - return thumbMediaId; + return this.thumbMediaId; } public void setThumbMediaId(String thumbMediaId) { this.thumbMediaId = thumbMediaId; } public String getTitle() { - return title; + return this.title; } public void setTitle(String title) { this.title = title; } public String getDescription() { - return description; + return this.description; } public void setDescription(String description) { this.description = description; } public String getMusicUrl() { - return musicUrl; + return this.musicUrl; } public void setMusicUrl(String musicUrl) { this.musicUrl = musicUrl; } public String getHqMusicUrl() { - return hqMusicUrl; + return this.hqMusicUrl; } public void setHqMusicUrl(String hqMusicUrl) { this.hqMusicUrl = hqMusicUrl; } public List getArticles() { - return articles; + return this.articles; } public void setArticles(List articles) { this.articles = articles; @@ -111,25 +112,25 @@ public static class WxArticle { private String picUrl; public String getTitle() { - return title; + return this.title; } public void setTitle(String title) { this.title = title; } public String getDescription() { - return description; + return this.description; } public void setDescription(String description) { this.description = description; } public String getUrl() { - return url; + return this.url; } public void setUrl(String url) { this.url = url; } public String getPicUrl() { - return picUrl; + return this.picUrl; } public void setPicUrl(String picUrl) { this.picUrl = picUrl; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java index bca8c143d8..ba816949d8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java @@ -13,6 +13,8 @@ @XStreamAlias("xml") public abstract class WxMpXmlOutMessage implements Serializable { + private static final long serialVersionUID = -381382011286216263L; + @XStreamAlias("ToUserName") @XStreamConverter(value=XStreamCDataConverter.class) protected String toUserName; @@ -29,7 +31,7 @@ public abstract class WxMpXmlOutMessage implements Serializable { protected String msgType; public String getToUserName() { - return toUserName; + return this.toUserName; } public void setToUserName(String toUserName) { @@ -37,7 +39,7 @@ public void setToUserName(String toUserName) { } public String getFromUserName() { - return fromUserName; + return this.fromUserName; } public void setFromUserName(String fromUserName) { @@ -45,7 +47,7 @@ public void setFromUserName(String fromUserName) { } public Long getCreateTime() { - return createTime; + return this.createTime; } public void setCreateTime(Long createTime) { @@ -53,7 +55,7 @@ public void setCreateTime(Long createTime) { } public String getMsgType() { - return msgType; + return this.msgType; } public void setMsgType(String msgType) { @@ -61,7 +63,7 @@ public void setMsgType(String msgType) { } public String toXml() { - return XStreamTransformer.toXml((Class) this.getClass(), this); + return XStreamTransformer.toXml((Class) this.getClass(), this); } /** @@ -121,9 +123,9 @@ public static MusicBuilder MUSIC() { public static NewsBuilder NEWS() { return new NewsBuilder(); } - /** + + /** * 获得客服消息builder - * * @return */ public static TransferCustomerServiceBuilder TRANSFER_CUSTOMER_SERVICE() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferCustomerServiceMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferCustomerServiceMessage.java index 67c3d28e25..a1a48bbe92 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferCustomerServiceMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferCustomerServiceMessage.java @@ -7,6 +7,8 @@ @XStreamAlias("xml") public class WxMpXmlOutTransferCustomerServiceMessage extends WxMpXmlOutMessage { + private static final long serialVersionUID = 1850903037285841322L; + @XStreamAlias("TransInfo") protected TransInfo transInfo; @@ -15,7 +17,7 @@ public WxMpXmlOutTransferCustomerServiceMessage() { } public TransInfo getTransInfo() { - return transInfo; + return this.transInfo; } public void setTransInfo(TransInfo transInfo) { @@ -30,7 +32,7 @@ public static class TransInfo { private String kfAccount; public String getKfAccount() { - return kfAccount; + return this.kfAccount; } public void setKfAccount(String kfAccount) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/TransferCustomerServiceBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/TransferCustomerServiceBuilder.java index d004eb566a..87ec3a047f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/TransferCustomerServiceBuilder.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/TransferCustomerServiceBuilder.java @@ -14,18 +14,18 @@ public final class TransferCustomerServiceBuilder extends BaseBuilder { private String kfAccount; - public TransferCustomerServiceBuilder kfAccount(String kfAccount) { - this.kfAccount = kfAccount; + public TransferCustomerServiceBuilder kfAccount(String kf) { + this.kfAccount = kf; return this; } - + @Override public WxMpXmlOutTransferCustomerServiceMessage build() { WxMpXmlOutTransferCustomerServiceMessage m = new WxMpXmlOutTransferCustomerServiceMessage(); setCommon(m); - if(StringUtils.isNotBlank(kfAccount)){ + if(StringUtils.isNotBlank(this.kfAccount)){ WxMpXmlOutTransferCustomerServiceMessage.TransInfo transInfo = new WxMpXmlOutTransferCustomerServiceMessage.TransInfo(); - transInfo.setKfAccount(kfAccount); + transInfo.setKfAccount(this.kfAccount); m.setTransInfo(transInfo); } return m; From 1ebcd9c864dd21f5b991ceb84c02e6ccf1e45f19 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 4 Jul 2016 17:31:00 +0800 Subject: [PATCH 04/54] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=87=A0=E4=B8=AA?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=B9=B6=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?parent=20pom=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index eee4837c1b..1fa126e5af 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 com.github.binarywang weixin-java-parent @@ -39,7 +39,7 @@ weixin-java-common weixin-java-cp weixin-java-mp - spring-demo + weixin-java-demo-with-spring @@ -50,6 +50,9 @@ 1.7.10 1.1.2 3.6.7 + 2.7.5 + 2.7 + 3.4 @@ -82,7 +85,7 @@ com.google.code.gson gson - 2.2.2 + ${gson.version} commons-codec @@ -94,8 +97,18 @@ commons-io 2.4 + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - + @@ -149,16 +162,16 @@ - - doclint-java8-disable - - [1.8,) - - - -Xdoclint:none - - - + + doclint-java8-disable + + [1.8,) + + + -Xdoclint:none + + + release From e169bcc2e972424e8b82e165fee4e2a78fd884f3 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 4 Jul 2016 17:31:45 +0800 Subject: [PATCH 05/54] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=9A=E5=AE=A2?= =?UTF-8?q?=E6=9C=8D=E4=B8=AD=E5=AE=A2=E6=9C=8D=E7=AE=A1=E7=90=86=E7=9A=84?= =?UTF-8?q?6=E4=B8=AA=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpBaseChildService.java | 15 ++ .../weixin/mp/api/WxMpKefuService.java | 73 ++++++++++ .../me/chanjar/weixin/mp/api/WxMpService.java | 57 ++++++-- .../weixin/mp/api/WxMpServiceImpl.java | 12 ++ .../mp/api/impl/WxMpKefuServiceImpl.java | 72 ++++++++++ .../request/WxMpKfAccountRequest.java | 133 ++++++++++++++++++ .../customerservice/result/WxMpKfInfo.java | 123 ++++++++++++++++ .../customerservice/result/WxMpKfList.java | 35 +++++ .../result/WxMpKfOnlineList.java | 35 +++++ .../chanjar/weixin/mp/api/ApiTestModule.java | 44 ++++-- .../weixin/mp/api/impl/WxMpKefuImplTest.java | 70 +++++++++ .../mp/bean/result/kefu/WxMpKfListTest.java | 41 ++++++ .../result/kefu/WxMpKfOnlineListTest.java | 39 +++++ 13 files changed, 725 insertions(+), 24 deletions(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java create mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java create mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java create mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java new file mode 100644 index 0000000000..2176af5783 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java @@ -0,0 +1,15 @@ +package me.chanjar.weixin.mp.api; + +/** + * + * @author Binary Wang + * + */ + +public interface WxMpBaseChildService { + /** + * 设置WxMpService对象 + * @return + */ + void setWxMpService(WxMpService wxMpService); +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java new file mode 100644 index 0000000000..8220a6733b --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -0,0 +1,73 @@ +package me.chanjar.weixin.mp.api; + +import java.io.File; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; + +/** + * 客服接口 , + * 命名采用kefu拼音的原因是: + * 其英文CustomerService如果再加上Service后缀显得有点啰嗦, + * 如果不加又显得表意不完整 + * @author Binary Wang + * + */ +public interface WxMpKefuService extends WxMpBaseChildService { + /** + *
+   * 获取客服基本信息
+   * 详情请见:客服管理
+   * https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN
+   * 
+ */ + WxMpKfList kfList() throws WxErrorException; + + /** + *
+   * 获取在线客服接待信息
+   * 详情请见:客服管理
+   * https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN
+   * 
+ */ + WxMpKfOnlineList kfOnlineList() throws WxErrorException; + + /** + *
+   * 添加客服账号
+   * 详情请见:客服管理
+   * https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN
+   * 
+ */ + boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException; + + /** + *
+   * 设置客服信息(更新)
+   * 详情请见:客服管理
+   * https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN
+   * 
+ */ + boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException; + + /** + *
+   * 上传客服头像
+   * 详情请见:客服管理
+   * http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
+   * 
+ */ + + boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException; + + /** + *
+   * 删除客服账号
+   * 详情请见:客服管理
+   * https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
+   * 
+ */ + boolean kfAccountDel(String kfAccount) throws WxErrorException; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index d822fc3348..634f97d23e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -1,14 +1,5 @@ package me.chanjar.weixin.mp.api; -import me.chanjar.weixin.common.bean.WxCardApiSignature; -import me.chanjar.weixin.common.bean.WxMenu; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -17,6 +8,47 @@ import java.util.List; import java.util.Map; +import me.chanjar.weixin.common.bean.WxCardApiSignature; +import me.chanjar.weixin.common.bean.WxJsapiSignature; +import me.chanjar.weixin.common.bean.WxMenu; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.bean.WxMpCustomMessage; +import me.chanjar.weixin.mp.bean.WxMpGroup; +import me.chanjar.weixin.mp.bean.WxMpIndustry; +import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; +import me.chanjar.weixin.mp.bean.WxMpMassNews; +import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; +import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; +import me.chanjar.weixin.mp.bean.WxMpMassVideo; +import me.chanjar.weixin.mp.bean.WxMpMaterial; +import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; +import me.chanjar.weixin.mp.bean.WxMpMaterialNews; +import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; +import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; +import me.chanjar.weixin.mp.bean.result.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpCardResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialFileBatchGetResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialNewsBatchGetResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpPayCallback; +import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult; +import me.chanjar.weixin.mp.bean.result.WxMpPayResult; +import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; +import me.chanjar.weixin.mp.bean.result.WxRedpackResult; + /** * 微信API的Service */ @@ -1001,4 +1033,11 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa * @throws WxErrorException */ WxMpIndustry getIndustry() throws WxErrorException; + + /** + * 返回客服接口方法实现类,以方便调用个其各种接口 + * @return WxMpKefuService + */ + WxMpKefuService getKefuService(); + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index 18fb3aefed..e7242101a9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -74,6 +74,8 @@ public class WxMpServiceImpl implements WxMpService { protected final Object globalCardApiTicketRefreshLock = new Object(); protected WxMpConfigStorage wxMpConfigStorage; + + protected WxMpKefuService kefuService; protected CloseableHttpClient httpClient; @@ -1369,4 +1371,14 @@ public WxMpIndustry getIndustry() throws WxErrorException { String responseContent = execute(new SimpleGetRequestExecutor(), url, null); return WxMpIndustry.fromJson(responseContent); } + + @Override + public WxMpKefuService getKefuService() { + return this.kefuService; + } + + public void setCustomerService(WxMpKefuService kefuService) { + this.kefuService = kefuService; + this.kefuService.setWxMpService(this); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java new file mode 100644 index 0000000000..8efcfdff44 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -0,0 +1,72 @@ +package me.chanjar.weixin.mp.api.impl; + +import java.io.File; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.mp.api.WxMpKefuService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKefuServiceImpl implements WxMpKefuService { + private WxMpService wxMpService; + + @Override + public void setWxMpService(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpKfList kfList() throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"; + String responseContent = this.wxMpService.execute( + new SimpleGetRequestExecutor(), url, null); + return WxMpKfList.fromJson(responseContent); + } + + @Override + public WxMpKfOnlineList kfOnlineList() throws WxErrorException { + String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"; + String responseContent = this.wxMpService.execute( + new SimpleGetRequestExecutor(), url, null); + return WxMpKfOnlineList.fromJson(responseContent); + } + + @Override + public boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/add"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); + return true; + } + + @Override + public boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/update"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); + return true; + } + + @Override + public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?kf_account=" + kfAccount ; + this.wxMpService.execute(new MediaUploadRequestExecutor(), url, imgFile); + return true; + } + + @Override + public boolean kfAccountDel(String kfAccount) throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/del?kf_account=" + kfAccount; + this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); + return true; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java new file mode 100644 index 0000000000..a5d301dad1 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java @@ -0,0 +1,133 @@ +package me.chanjar.weixin.mp.bean.customerservice.request; + +import java.io.Serializable; + +import org.apache.commons.codec.digest.Md5Crypt; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +public class WxMpKfAccountRequest implements Serializable { + private static final long serialVersionUID = -5451863610674856927L; + + /** + * kf_account 完整客服账号,格式为:账号前缀@公众号微信号 + */ + @SerializedName("kf_account") + private String kfAccount; + + /** + * nickname 客服昵称,最长6个汉字或12个英文字符 + */ + @SerializedName("nickname") + private String nickName; + + /** + * password 客服账号登录密码,格式为密码明文的32位加密MD5值 + */ + @SerializedName("password") + private String password; + + /** + * rawPassword 客服账号登录密码,明文密码,仅用于辅助操作 + */ + @SerializedName("rawPassword") + private String rawPassword; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public String toJson() { + return WxMpGsonBuilder.INSTANCE.create().toJson(this); + } + + public String getKfAccount() { + return this.kfAccount; + } + + public void setKfAccount(String kfAccount) { + this.kfAccount = kfAccount; + } + + public String getNickName() { + return this.nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getPassword() { + return this.password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRawPassword() { + return this.rawPassword; + } + + public void setRawPassword(String rawPassword) { + this.rawPassword = rawPassword; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String kfAccount; + private String nickName; + private String password; + private String rawPassword; + + @SuppressWarnings("hiding") + public Builder kfAccount(String kfAccount) { + this.kfAccount = kfAccount; + return this; + } + + @SuppressWarnings("hiding") + public Builder nickName(String nickName) { + this.nickName = nickName; + return this; + } + + @SuppressWarnings("hiding") + public Builder password(String password) { + this.password = password; + return this; + } + + @SuppressWarnings("hiding") + public Builder rawPassword(String rawPassword) { + this.rawPassword = rawPassword; + this.password(Md5Crypt.md5Crypt(rawPassword.getBytes())); + return this; + } + + public Builder from(WxMpKfAccountRequest origin) { + this.kfAccount(origin.kfAccount); + this.nickName(origin.nickName); + this.password(origin.password); + this.rawPassword(origin.rawPassword); + return this; + } + + public WxMpKfAccountRequest build() { + WxMpKfAccountRequest m = new WxMpKfAccountRequest(); + m.kfAccount = this.kfAccount; + m.nickName = this.nickName; + m.password = this.password; + m.rawPassword = this.rawPassword; + return m; + } + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java new file mode 100644 index 0000000000..95b3a96f93 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java @@ -0,0 +1,123 @@ +package me.chanjar.weixin.mp.bean.customerservice.result; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +/** + * 客服基本信息以及客服在线状态信息 + * @author Binary Wang + * + */ +public class WxMpKfInfo implements Serializable { + private static final long serialVersionUID = -5877300750666022290L; + + /** + * kf_account 完整客服账号,格式为:账号前缀@公众号微信号 + */ + @SerializedName("kf_account") + private String account; + + /** + * kf_headimgurl 客服头像地址 + */ + @SerializedName("kf_headimgurl") + private String headImgUrl; + + /** + * kf_id 客服工号 + */ + @SerializedName("kf_id") + private String id; + + /** + * kf_nick 客服昵称 + */ + @SerializedName("kf_nick") + private String nick; + + /** + * status 客服在线状态 1:pc在线,2:手机在线。若pc和手机同时在线则为 1+2=3 + */ + @SerializedName("status") + private Integer status; + + /** + * auto_accept 客服设置的最大自动接入数 + */ + @Expose + @SerializedName("auto_accept") + private Integer autoAccept; + + /** + * accepted_case 客服当前正在接待的会话数 + * @return + */ + @Expose + @SerializedName("accepted_case") + private Integer acceptedCase; + + public Integer getStatus() { + return this.status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getAutoAccept() { + return this.autoAccept; + } + + public void setAutoAccept(Integer autoAccept) { + this.autoAccept = autoAccept; + } + + public Integer getAcceptedCase() { + return this.acceptedCase; + } + + public void setAcceptedCase(Integer acceptedCase) { + this.acceptedCase = acceptedCase; + } + + public String getAccount() { + return this.account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getHeadImgUrl() { + return this.headImgUrl; + } + + public void setHeadImgUrl(String headImgUrl) { + this.headImgUrl = headImgUrl; + } + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public String getNick() { + return this.nick; + } + + public void setNick(String nick) { + this.nick = nick; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java new file mode 100644 index 0000000000..335204fb80 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.mp.bean.customerservice.result; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +/** + * + * @author Binary Wang + * + */ +public class WxMpKfList { + @SerializedName("kf_list") + private List kfList; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public List getKfList() { + return this.kfList; + } + + public void setKfList(List kfList) { + this.kfList = kfList; + } + + public static WxMpKfList fromJson(String json) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpKfList.class); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java new file mode 100644 index 0000000000..949d88490a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.mp.bean.customerservice.result; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +/** + * + * @author Binary Wang + * + */ +public class WxMpKfOnlineList { + @SerializedName("kf_online_list") + private List kfOnlineList; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + + public List getKfOnlineList() { + return this.kfOnlineList; + } + + public void setKfOnlineList(List kfOnlineList) { + this.kfOnlineList = kfOnlineList; + } + + public static WxMpKfOnlineList fromJson(String json) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpKfOnlineList.class); + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java index e6df8e3439..7c3db8e825 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java @@ -1,24 +1,36 @@ package me.chanjar.weixin.mp.api; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.lang3.builder.ToStringBuilder; + import com.google.inject.Binder; import com.google.inject.Module; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; -import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import java.io.InputStream; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl; public class ApiTestModule implements Module { @Override public void configure(Binder binder) { - InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); - WxXmlMpInMemoryConfigStorage config = fromXml(WxXmlMpInMemoryConfigStorage.class, is1); - WxMpServiceImpl wxService = new WxMpServiceImpl(); - wxService.setWxMpConfigStorage(config); + try (InputStream is1 = ClassLoader + .getSystemResourceAsStream("test-config.xml")) { + WxXmlMpInMemoryConfigStorage config = fromXml( + WxXmlMpInMemoryConfigStorage.class, is1); + WxMpServiceImpl wxService = new WxMpServiceImpl(); + wxService.setWxMpConfigStorage(config); + WxMpKefuService customerService = new WxMpKefuServiceImpl(); + wxService.setCustomerService(customerService); - binder.bind(WxMpServiceImpl.class).toInstance(wxService); - binder.bind(WxMpConfigStorage.class).toInstance(config); + binder.bind(WxMpServiceImpl.class).toInstance(wxService); + binder.bind(WxMpConfigStorage.class).toInstance(config); + } catch (IOException e) { + e.printStackTrace(); + } } public static T fromXml(Class clazz, InputStream is) { @@ -29,22 +41,24 @@ public static T fromXml(Class clazz, InputStream is) { } @XStreamAlias("xml") - public static class WxXmlMpInMemoryConfigStorage extends WxMpInMemoryConfigStorage { - + public static class WxXmlMpInMemoryConfigStorage + extends WxMpInMemoryConfigStorage { + protected String openId; public String getOpenId() { - return openId; + return this.openId; } + public void setOpenId(String openId) { this.openId = openId; } + @Override public String toString() { - return "SimpleWxConfigProvider [appId=" + appId + ", secret=" + secret + ", accessToken=" + accessToken - + ", expiresTime=" + expiresTime + ", token=" + token + ", openId=" + openId + "]"; + return ToStringBuilder.reflectionToString(this); } - + } - + } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java new file mode 100644 index 0000000000..f5d4ab0410 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java @@ -0,0 +1,70 @@ +package me.chanjar.weixin.mp.api.impl; + +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import com.google.inject.Inject; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.WxMpServiceImpl; +import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; + +import java.io.File; + +import org.testng.Assert; + +/** + * 测试客服相关接口 + * @author Binary Wang + * + */ +@Test +@Guice(modules = ApiTestModule.class) +public class WxMpKefuImplTest { + private static final String KF_ACCOUNT = "kf2009@youxintest"; + + @Inject + protected WxMpServiceImpl wxService; + + public void testKfList() throws WxErrorException { + WxMpKfList kfList = this.wxService.getKefuService().kfList(); + Assert.assertNotNull(kfList); + System.err.println(kfList); + } + + public void testKfOnlineList() throws WxErrorException { + WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService().kfOnlineList(); + Assert.assertNotNull(kfOnlineList); + System.err.println(kfOnlineList); + } + + public void testKfAccountAdd() throws WxErrorException { + WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() + .kfAccount(KF_ACCOUNT).nickName("我晕").rawPassword("123").build(); + Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request)); + } + + @Test(dependsOnMethods = { "testKfAccountAdd" }) + public void testKfAccountUpdate() throws WxErrorException { + WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() + .kfAccount(KF_ACCOUNT).nickName("我晕").rawPassword("123").build(); + Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request)); + } + + @Test(dependsOnMethods = { "testKfAccountUpdate" }) + public void testKfAccountUploadHeadImg() throws WxErrorException { + File imgFile = new File("src\\test\\resources\\mm.jpeg"); + boolean result = this.wxService.getKefuService().kfAccountUploadHeadImg(KF_ACCOUNT, imgFile); + Assert.assertTrue(result); + } + + @Test(dependsOnMethods = { "testKfAccountUploadHeadImg" }) + public void testKfAccountDel() throws WxErrorException { + boolean result = this.wxService.getKefuService().kfAccountDel(KF_ACCOUNT); + Assert.assertTrue(result); + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java new file mode 100644 index 0000000000..0d3841ef52 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.mp.bean.result.kefu; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.testng.Assert; +import org.testng.annotations.Test; + +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; + +@Test +public class WxMpKfListTest { + + public void testFromJson() { + String json=" {\r\n" + + " \"kf_list\" : [\r\n" + + " {\r\n" + + " \"kf_account\" : \"test1@test\",\r\n" + + " \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" + + " \"kf_id\" : \"1001\",\r\n" + + " \"kf_nick\" : \"ntest1\"\r\n" + + " },\r\n" + + " {\r\n" + + " \"kf_account\" : \"test2@test\",\r\n" + + " \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" + + " \"kf_id\" : \"1002\",\r\n" + + " \"kf_nick\" : \"ntest2\"\r\n" + + " },\r\n" + + " {\r\n" + + " \"kf_account\" : \"test3@test\",\r\n" + + " \"kf_headimgurl\" : \"http://mmbiz.qpic.cn/mmbiz/4whpV1VZl2iccsvYbHvnphkyGtnvjfUS8Ym0GSaLic0FD3vN0V8PILcibEGb2fPfEOmw/0\",\r\n" + + " \"kf_id\" : \"1003\",\r\n" + + " \"kf_nick\" : \"ntest3\"\r\n" + + " }\r\n" + + " ]\r\n" + + " }"; + + WxMpKfList wxMpKfList = WxMpKfList.fromJson(json); + Assert.assertNotNull(wxMpKfList); + System.err.println(ToStringBuilder.reflectionToString(wxMpKfList)); + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java new file mode 100644 index 0000000000..052f8e25d3 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java @@ -0,0 +1,39 @@ +package me.chanjar.weixin.mp.bean.result.kefu; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.testng.Assert; +import org.testng.annotations.Test; + +import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; + +@Test +public class WxMpKfOnlineListTest { + + @Test + public void testFromJson() { + String json = "{\r\n" + + " \"kf_online_list\": [\r\n" + + " {\r\n" + + " \"kf_account\": \"test1@test\", \r\n" + + " \"status\": 1, \r\n" + + " \"kf_id\": \"1001\", \r\n" + + " \"auto_accept\": 0, \r\n" + + " \"accepted_case\": 1\r\n" + + " },\r\n" + + " {\r\n" + + " \"kf_account\": \"test2@test\", \r\n" + + " \"status\": 1, \r\n" + + " \"kf_id\": \"1002\", \r\n" + + " \"auto_accept\": 0, \r\n" + + " \"accepted_case\": 2\r\n" + + " }\r\n" + + " ]\r\n" + + "}"; + + WxMpKfOnlineList wxMpKfOnlineList = WxMpKfOnlineList.fromJson(json); + Assert.assertNotNull(wxMpKfOnlineList); + System.err.println(ToStringBuilder.reflectionToString(wxMpKfOnlineList)); + + } + +} From 244df15d83c35d05ce8f8db98470b2e949c3bf65 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 5 Jul 2016 10:30:41 +0800 Subject: [PATCH 06/54] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E5=AE=A2?= =?UTF-8?q?=E6=9C=8D=E6=8E=A5=E5=8F=A3=E8=8E=B7=E5=8F=96=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=EF=BC=8C=E4=BF=9D=E8=AF=81=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java | 2 +- .../chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java | 8 ++++++++ .../test/java/me/chanjar/weixin/mp/api/ApiTestModule.java | 5 +++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index e7242101a9..7273642d7b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -1377,7 +1377,7 @@ public WxMpKefuService getKefuService() { return this.kefuService; } - public void setCustomerService(WxMpKefuService kefuService) { + public void setKefuService(WxMpKefuService kefuService) { this.kefuService = kefuService; this.kefuService.setWxMpService(this); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index 8efcfdff44..fc49e4ae7e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -20,6 +20,14 @@ public class WxMpKefuServiceImpl implements WxMpKefuService { private WxMpService wxMpService; + public WxMpKefuServiceImpl(){ + + } + + public WxMpKefuServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + @Override public void setWxMpService(WxMpService wxMpService) { this.wxMpService = wxMpService; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java index 7c3db8e825..7dc042f7e7 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java @@ -23,8 +23,9 @@ public void configure(Binder binder) { WxXmlMpInMemoryConfigStorage.class, is1); WxMpServiceImpl wxService = new WxMpServiceImpl(); wxService.setWxMpConfigStorage(config); - WxMpKefuService customerService = new WxMpKefuServiceImpl(); - wxService.setCustomerService(customerService); + + WxMpKefuService kefuService = new WxMpKefuServiceImpl(); + wxService.setKefuService(kefuService); binder.bind(WxMpServiceImpl.class).toInstance(wxService); binder.bind(WxMpConfigStorage.class).toInstance(config); From f9022814fda4cc7025c73d28bf1554c610b41a70 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 5 Jul 2016 10:55:47 +0800 Subject: [PATCH 07/54] =?UTF-8?q?=E7=AE=80=E5=8C=96=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpBaseChildService.java | 15 --------------- .../me/chanjar/weixin/mp/api/WxMpKefuService.java | 2 +- .../me/chanjar/weixin/mp/api/WxMpServiceImpl.java | 7 ++----- .../weixin/mp/api/impl/WxMpKefuServiceImpl.java | 9 --------- .../me/chanjar/weixin/mp/api/ApiTestModule.java | 3 --- 5 files changed, 3 insertions(+), 33 deletions(-) delete mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java deleted file mode 100644 index 2176af5783..0000000000 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpBaseChildService.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.chanjar.weixin.mp.api; - -/** - * - * @author Binary Wang - * - */ - -public interface WxMpBaseChildService { - /** - * 设置WxMpService对象 - * @return - */ - void setWxMpService(WxMpService wxMpService); -} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 8220a6733b..ec9b7af36b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -15,7 +15,7 @@ * @author Binary Wang * */ -public interface WxMpKefuService extends WxMpBaseChildService { +public interface WxMpKefuService { /** *
    * 获取客服基本信息
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index 7273642d7b..2260f48dd9 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -23,6 +23,7 @@
 import me.chanjar.weixin.common.util.json.GsonHelper;
 import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.common.util.xml.XStreamInitializer;
+import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl;
 import me.chanjar.weixin.mp.bean.*;
 import me.chanjar.weixin.mp.bean.result.*;
 import me.chanjar.weixin.mp.util.http.*;
@@ -75,7 +76,7 @@ public class WxMpServiceImpl implements WxMpService {
 
   protected WxMpConfigStorage wxMpConfigStorage;
   
-  protected WxMpKefuService kefuService;
+  protected WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
 
   protected CloseableHttpClient httpClient;
 
@@ -1377,8 +1378,4 @@ public WxMpKefuService getKefuService() {
     return this.kefuService;
   }
   
-  public void setKefuService(WxMpKefuService kefuService) {
-    this.kefuService = kefuService;
-    this.kefuService.setWxMpService(this);
-  }
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
index fc49e4ae7e..91afb73193 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
@@ -20,19 +20,10 @@
 public class WxMpKefuServiceImpl implements WxMpKefuService {
   private WxMpService wxMpService;
 
-  public WxMpKefuServiceImpl(){
-    
-  }
-  
   public WxMpKefuServiceImpl(WxMpService wxMpService) {
     this.wxMpService = wxMpService;
   }
 
-  @Override
-  public void setWxMpService(WxMpService wxMpService) {
-    this.wxMpService = wxMpService;
-  }
-
   @Override
   public WxMpKfList kfList() throws WxErrorException {
     String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist";
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
index 7dc042f7e7..154b06b673 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
@@ -24,9 +24,6 @@ public void configure(Binder binder) {
       WxMpServiceImpl wxService = new WxMpServiceImpl();
       wxService.setWxMpConfigStorage(config);
       
-      WxMpKefuService kefuService = new WxMpKefuServiceImpl();
-      wxService.setKefuService(kefuService);
-
       binder.bind(WxMpServiceImpl.class).toInstance(wxService);
       binder.bind(WxMpConfigStorage.class).toInstance(config);
     } catch (IOException e) {

From 29cfa7762e46dd3af69d0d3914962f7879caaea1 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Tue, 5 Jul 2016 11:45:20 +0800
Subject: [PATCH 08/54] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=A2=E6=9C=8D?=
 =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3=E7=9A=84=E5=8D=95=E5=85=83?=
 =?UTF-8?q?=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/mp/api/WxMpServiceImpl.java        |  4 ++
 .../chanjar/weixin/mp/api/ApiTestModule.java  | 14 ++++--
 .../weixin/mp/api/impl/WxMpKefuImplTest.java  | 50 ++++++++++++-------
 .../src/test/resources/test-config.sample.xml |  1 +
 4 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index 2260f48dd9..8841696de0 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -825,6 +825,10 @@ public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
     this.httpClient = apacheHttpClientBuilder.build();
   }
 
+  public WxMpConfigStorage getWxMpConfigStorage() {
+    return this.wxMpConfigStorage;
+  }
+
   @Override
   public void setRetrySleepMillis(int retrySleepMillis) {
     this.retrySleepMillis = retrySleepMillis;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
index 154b06b673..320751546f 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
@@ -11,7 +11,6 @@
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 
 import me.chanjar.weixin.common.util.xml.XStreamInitializer;
-import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl;
 
 public class ApiTestModule implements Module {
 
@@ -23,7 +22,7 @@ public void configure(Binder binder) {
           WxXmlMpInMemoryConfigStorage.class, is1);
       WxMpServiceImpl wxService = new WxMpServiceImpl();
       wxService.setWxMpConfigStorage(config);
-      
+
       binder.bind(WxMpServiceImpl.class).toInstance(wxService);
       binder.bind(WxMpConfigStorage.class).toInstance(config);
     } catch (IOException e) {
@@ -42,7 +41,8 @@ public static  T fromXml(Class clazz, InputStream is) {
   public static class WxXmlMpInMemoryConfigStorage
       extends WxMpInMemoryConfigStorage {
 
-    protected String openId;
+    private String openId;
+    private String kfAccount;
 
     public String getOpenId() {
       return this.openId;
@@ -57,6 +57,14 @@ public String toString() {
       return ToStringBuilder.reflectionToString(this);
     }
 
+    public String getKfAccount() {
+      return this.kfAccount;
+    }
+
+    public void setKfAccount(String kfAccount) {
+      this.kfAccount = kfAccount;
+    }
+
   }
 
 }
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java
index f5d4ab0410..f2045437ff 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.mp.api.impl;
 
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
@@ -7,6 +8,8 @@
 
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.mp.api.ApiTestModule;
+import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage;
+import me.chanjar.weixin.mp.api.WxMpConfigStorage;
 import me.chanjar.weixin.mp.api.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest;
 import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList;
@@ -24,8 +27,7 @@
 @Test
 @Guice(modules = ApiTestModule.class)
 public class WxMpKefuImplTest {
-  private static final String KF_ACCOUNT = "kf2009@youxintest";
-  
+
   @Inject
   protected WxMpServiceImpl wxService;
 
@@ -36,34 +38,48 @@ public void testKfList() throws WxErrorException {
   }
 
   public void testKfOnlineList() throws WxErrorException {
-    WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService().kfOnlineList();
+    WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService()
+        .kfOnlineList();
     Assert.assertNotNull(kfOnlineList);
     System.err.println(kfOnlineList);
   }
 
-  public void testKfAccountAdd() throws WxErrorException {
+  @DataProvider
+  public Object[][] getKfAccount() {
+    WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService
+        .getWxMpConfigStorage();
+    return new Object[][] { { configStorage.getKfAccount() } };
+  }
+
+  @Test(dataProvider = "getKfAccount")
+  public void testKfAccountAdd(String kfAccount) throws WxErrorException {
     WxMpKfAccountRequest request = WxMpKfAccountRequest.builder()
-        .kfAccount(KF_ACCOUNT).nickName("我晕").rawPassword("123").build();
+        .kfAccount(kfAccount).nickName("我晕").rawPassword("123").build();
     Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request));
   }
-  
-  @Test(dependsOnMethods = { "testKfAccountAdd" })
-  public void testKfAccountUpdate() throws WxErrorException {
+
+  @Test(dependsOnMethods = {
+      "testKfAccountAdd" }, dataProvider = "getKfAccount")
+  public void testKfAccountUpdate(String kfAccount) throws WxErrorException {
     WxMpKfAccountRequest request = WxMpKfAccountRequest.builder()
-        .kfAccount(KF_ACCOUNT).nickName("我晕").rawPassword("123").build();
+        .kfAccount(kfAccount).nickName("我晕").rawPassword("123").build();
     Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request));
   }
-  
-  @Test(dependsOnMethods = { "testKfAccountUpdate" })
-  public void testKfAccountUploadHeadImg() throws WxErrorException {
+
+  @Test(dependsOnMethods = {
+      "testKfAccountUpdate" }, dataProvider = "getKfAccount")
+  public void testKfAccountUploadHeadImg(String kfAccount)
+      throws WxErrorException {
     File imgFile = new File("src\\test\\resources\\mm.jpeg");
-    boolean result = this.wxService.getKefuService().kfAccountUploadHeadImg(KF_ACCOUNT, imgFile);
+    boolean result = this.wxService.getKefuService()
+        .kfAccountUploadHeadImg(kfAccount, imgFile);
     Assert.assertTrue(result);
   }
-  
-  @Test(dependsOnMethods = { "testKfAccountUploadHeadImg" })
-  public void testKfAccountDel() throws WxErrorException {    
-    boolean result = this.wxService.getKefuService().kfAccountDel(KF_ACCOUNT);
+
+  @Test(dependsOnMethods = {
+      "testKfAccountUploadHeadImg" }, dataProvider = "getKfAccount")
+  public void testKfAccountDel(String kfAccount) throws WxErrorException {
+    boolean result = this.wxService.getKefuService().kfAccountDel(kfAccount);
     Assert.assertTrue(result);
   }
 
diff --git a/weixin-java-mp/src/test/resources/test-config.sample.xml b/weixin-java-mp/src/test/resources/test-config.sample.xml
index 6ec4825a99..1f79bea2cc 100644
--- a/weixin-java-mp/src/test/resources/test-config.sample.xml
+++ b/weixin-java-mp/src/test/resources/test-config.sample.xml
@@ -7,4 +7,5 @@
     可以不填写
     某个加你公众号的用户的openId
     网页授权获取用户信息回调地址
+    完整客服账号,格式为:账号前缀@公众号微信号
 

From d29cc984bcddd7738b0e4fed23ad5e3894f5fe5e Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Wed, 6 Jul 2016 16:02:37 +0800
Subject: [PATCH 09/54] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0?=
 =?UTF-8?q?=E4=B8=80=E4=B8=AA=E4=BD=BF=E7=94=A8Spring=E6=A1=86=E6=9E=B6?=
 =?UTF-8?q?=E7=9A=84Demo=20Web=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 spring-demo/pom.xml                           |  25 ----
 weixin-java-demo-with-spring/.gitignore       |   1 +
 weixin-java-demo-with-spring/README.md        |   7 +
 weixin-java-demo-with-spring/pom.xml          |  91 ++++++++++++
 .../demo/spring/aop/ControllerLogAspect.java  |  80 +++++++++++
 .../demo/spring/builder/AbstractBuilder.java  |  21 +++
 .../demo/spring/builder/ImageBuilder.java     |  27 ++++
 .../demo/spring/builder/TextBuilder.java      |  25 ++++
 .../demo/spring/config/WxAccountEnum.java     |  41 ++++++
 .../demo/spring/config/WxConfig.java          |  21 +++
 .../demo/spring/config/WxGzh1Config.java      |  42 ++++++
 .../demo/spring/config/WxGzh2Config.java      |  42 ++++++
 .../AbstractWxPortalController.java           |  62 +++++++++
 .../controller/Gzh1WxPortalController.java    |  26 ++++
 .../controller/Gzh2WxPortalController.java    |  26 ++++
 .../binarywang/demo/spring/dto/WxMenuKey.java |  44 ++++++
 .../demo/spring/handler/AbstractHandler.java  |  23 ++++
 .../demo/spring/handler/LocationHandler.java  |  47 +++++++
 .../demo/spring/handler/MenuHandler.java      |  71 ++++++++++
 .../demo/spring/handler/MsgHandler.java       |  48 +++++++
 .../demo/spring/handler/NullHandler.java      |  34 +++++
 .../demo/spring/handler/ScanHandler.java      |  10 ++
 .../demo/spring/handler/SubscribeHandler.java |  62 +++++++++
 .../spring/handler/UnsubscribeHandler.java    |  27 ++++
 .../demo/spring/service/BaseWxService.java    | 129 ++++++++++++++++++
 .../demo/spring/service/Gzh1WxService.java    |  65 +++++++++
 .../demo/spring/service/Gzh2WxService.java    |  66 +++++++++
 .../src/main/resources/.gitignore             |   2 +
 .../src/main/resources/applicationContext.xml |  17 +++
 .../src/main/resources/log4j.properties       |   8 ++
 .../main/resources/spring-service-bean.xml    |  29 ++++
 .../main/resources/spring-servlet-common.xml  |  43 ++++++
 .../resources/wx-gzh1.properties.template     |   3 +
 .../resources/wx-gzh2.properties.template     |   3 +
 .../src/main/webapp/WEB-INF/web.xml           |   8 --
 35 files changed, 1243 insertions(+), 33 deletions(-)
 delete mode 100644 spring-demo/pom.xml
 create mode 100644 weixin-java-demo-with-spring/.gitignore
 create mode 100644 weixin-java-demo-with-spring/README.md
 create mode 100644 weixin-java-demo-with-spring/pom.xml
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/aop/ControllerLogAspect.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/AbstractBuilder.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/ImageBuilder.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/TextBuilder.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxAccountEnum.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh1WxPortalController.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh2WxPortalController.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/dto/WxMenuKey.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/AbstractHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LocationHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MenuHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/ScanHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/UnsubscribeHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh2WxService.java
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/.gitignore
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/applicationContext.xml
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/log4j.properties
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/spring-service-bean.xml
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/spring-servlet-common.xml
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template
 create mode 100644 weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template
 rename {spring-demo => weixin-java-demo-with-spring}/src/main/webapp/WEB-INF/web.xml (85%)

diff --git a/spring-demo/pom.xml b/spring-demo/pom.xml
deleted file mode 100644
index 815ce765ce..0000000000
--- a/spring-demo/pom.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-  4.0.0    
-  
-        com.github.binarywang
-        weixin-java-parent
-        1.3.6-SNAPSHOT
-    
-  spring-demo
-  war
-  WeiXin Java Tools - demo with spring
-  spring demo
-  https://github.com/binarywang/weixin-java-tools
- 
-  
-    
-        com.github.binarywang
-        weixin-java-common
-        ${project.version}
-    
-  
-
-
diff --git a/weixin-java-demo-with-spring/.gitignore b/weixin-java-demo-with-spring/.gitignore
new file mode 100644
index 0000000000..22f500b062
--- /dev/null
+++ b/weixin-java-demo-with-spring/.gitignore
@@ -0,0 +1 @@
+*.pmd
diff --git a/weixin-java-demo-with-spring/README.md b/weixin-java-demo-with-spring/README.md
new file mode 100644
index 0000000000..1268e693a9
--- /dev/null
+++ b/weixin-java-demo-with-spring/README.md
@@ -0,0 +1,7 @@
+#### 本Demo使用Spring MVC 框架实现微信公众号后台管理功能,支持多公众号,欢迎帮忙维护添加新功能,或提供更好的实现。
+### 1. 配置
+	复制/src/main/resources/wx-gzh1.properties.template 生成wx-gzh1.properties 文件,填写相关配置;
+	复制/src/main/resources/wx-gzh2.properties.template 生成wx-gzh2.properties 文件,填写相关配置.
+		
+### 2. 使用maven运行demo程序
+	mvn jetty:run
diff --git a/weixin-java-demo-with-spring/pom.xml b/weixin-java-demo-with-spring/pom.xml
new file mode 100644
index 0000000000..469ac9e226
--- /dev/null
+++ b/weixin-java-demo-with-spring/pom.xml
@@ -0,0 +1,91 @@
+
+
+  4.0.0
+  
+    com.github.binarywang
+    weixin-java-parent
+    1.3.6-SNAPSHOT
+  
+  weixin-java-demo-with-spring
+  war
+  WeiXin Java Tools - DemoWithSpring
+  spring demo
+  https://github.com/binarywang/weixin-java-tools
+  
+    4.3.0.RELEASE
+    4.1.0.RELEASE
+    19.0
+    1.7.2
+    1.8.9
+    1.2.6
+    3.1
+    9.3.10.v20160621
+  
+
+  
+    
+      com.github.binarywang
+      weixin-java-mp
+      ${project.version}
+    
+
+    
+      com.alibaba
+      fastjson
+      ${fastjson.version}
+    
+    
+      org.apache.commons
+      commons-lang3
+      ${commons-lang3.version}
+    
+    
+      com.google.guava
+      guava
+      ${guava.version}
+    
+    
+      org.slf4j
+      slf4j-log4j12
+      ${slf4j.version}
+    
+    
+      org.springframework
+      spring-webmvc
+      ${spring.version}
+    
+    
+      org.springframework
+      spring-web
+      ${spring.version}
+    
+    
+      org.springframework.security
+      spring-security-core
+      ${spring-security.version}
+    
+
+    
+      org.aspectj
+      aspectjrt
+      ${aspectj.version}
+    
+    
+      org.aspectj
+      aspectjweaver
+      ${aspectj.version}
+    
+  
+
+  
+    
+      
+        org.eclipse.jetty
+        jetty-maven-plugin
+        ${jetty-maven-plugin.version}
+      
+    
+  
+
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/aop/ControllerLogAspect.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/aop/ControllerLogAspect.java
new file mode 100644
index 0000000000..8a836908c5
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/aop/ControllerLogAspect.java
@@ -0,0 +1,80 @@
+package com.github.binarywang.demo.spring.aop;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.CodeSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Aspect
+@Component
+public class ControllerLogAspect {
+    private Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Pointcut("within(com.github.binarywang.demo.spring..*.controller..*)")
+    public void inController() {
+    }
+
+    @Pointcut("execution(public * com.github.binarywang.demo.spring..*.controller..*.*(..))")
+    public void controller() {
+    }
+
+    @Before("inController()")
+    public void writeBeforeLog(JoinPoint jp) {
+        this.debugInController(jp, "Start");
+    }
+
+    @After("inController()")
+    public void writeAfterLog(JoinPoint jp) {
+        this.debugInController(jp, "End");
+    }
+
+    private void debugInController(JoinPoint jp, String msg) {
+        String userName = getLoginUserName();
+
+        this.logger.debug("\n【{}】{}.{}() {} ", userName,
+            jp.getTarget()
+            .getClass().getSimpleName(), jp.getSignature().getName(), msg);
+    }
+
+    private static String getLoginUserName() {
+        Authentication authentication = SecurityContextHolder.getContext()
+            .getAuthentication();
+        if (authentication != null) {
+            return authentication.getName();
+        }
+
+        return "Anonymous";
+    }
+
+    @Before("controller()")
+    public void writeParams(JoinPoint jp) {
+        String[] names = ((CodeSignature) jp.getSignature())
+            .getParameterNames();
+        Object[] args = jp.getArgs();
+
+        if (ArrayUtils.isEmpty(names)) {
+            return;
+        }
+
+        StringBuilder sb = new StringBuilder("Arguments: ");
+        for (int i = 0; i < names.length; i++) {
+            sb.append(names[i] + " = " + args[i] + ",");
+        }
+
+        debugInController(jp, sb.toString());
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/AbstractBuilder.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/AbstractBuilder.java
new file mode 100644
index 0000000000..bf019b4b20
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/AbstractBuilder.java
@@ -0,0 +1,21 @@
+package com.github.binarywang.demo.spring.builder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class AbstractBuilder {
+  protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+  public abstract WxMpXmlOutMessage build(String content,
+      WxMpXmlMessage wxMessage, BaseWxService service) ;
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/ImageBuilder.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/ImageBuilder.java
new file mode 100644
index 0000000000..882671258c
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/ImageBuilder.java
@@ -0,0 +1,27 @@
+package com.github.binarywang.demo.spring.builder;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public class ImageBuilder extends AbstractBuilder {
+
+  @Override
+  public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+      BaseWxService service) {
+
+    WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
+        .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())
+        .build();
+
+    return m;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/TextBuilder.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/TextBuilder.java
new file mode 100644
index 0000000000..551f6ca79a
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/builder/TextBuilder.java
@@ -0,0 +1,25 @@
+package com.github.binarywang.demo.spring.builder;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public class TextBuilder extends AbstractBuilder {
+
+  @Override
+  public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
+      BaseWxService service)   {
+    WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
+        .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())
+        .build();
+    return m;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxAccountEnum.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxAccountEnum.java
new file mode 100644
index 0000000000..c82aab9e42
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxAccountEnum.java
@@ -0,0 +1,41 @@
+package com.github.binarywang.demo.spring.config;
+
+/**
+ * 公众号标识的枚举类
+ * @author Binary Wang
+ *
+ */
+public enum WxAccountEnum {
+    GZH1(1, "公众号1"),
+    GZH2(2, "公众号2");
+
+    private int pubid;
+    private String name;
+
+    private WxAccountEnum(int pubid, String name) {
+        this.name = name;
+        this.pubid = pubid;
+    }
+
+    public int getPubid() {
+        return this.pubid;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public static int queryPubid(String wxCode) {
+        return WxAccountEnum.valueOf(wxCode.toUpperCase()).getPubid();
+    }
+
+    public static String queryWxCode(int pubid) {
+        for (WxAccountEnum e : values()) {
+            if (e.getPubid() == pubid) {
+                return e.name().toLowerCase();
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java
new file mode 100644
index 0000000000..a65d4000ed
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java
@@ -0,0 +1,21 @@
+package com.github.binarywang.demo.spring.config;
+
+/**
+ * 微信配置的抽象实现类
+ * @author Binary Wang
+ *
+ */
+public abstract class WxConfig {
+    public abstract String getToken();
+
+    public abstract String getAppid();
+
+    public abstract String getAppsecret();
+
+    public abstract WxAccountEnum getWxAccountEnum();
+
+    public int getPubId() {
+        return getWxAccountEnum().getPubid();
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java
new file mode 100644
index 0000000000..fee34f431e
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java
@@ -0,0 +1,42 @@
+package com.github.binarywang.demo.spring.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Configuration
+public class WxGzh1Config extends WxConfig {
+    @Value("#{gzh1WxProperties.wx_token}")
+    private String token;
+
+    @Value("#{gzh1WxProperties.wx_appid}")
+    private String appid;
+
+    @Value("#{gzh1WxProperties.wx_appsecret}")
+    private String appsecret;
+
+    @Override
+    public String getToken() {
+        return this.token;
+    }
+
+    @Override
+    public String getAppid() {
+        return this.appid;
+    }
+
+    @Override
+    public String getAppsecret() {
+        return this.appsecret;
+    }
+
+    @Override
+    public WxAccountEnum getWxAccountEnum() {
+        return WxAccountEnum.GZH1;
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java
new file mode 100644
index 0000000000..d284630a8b
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java
@@ -0,0 +1,42 @@
+package com.github.binarywang.demo.spring.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Configuration
+public class WxGzh2Config extends WxConfig {
+    @Value("#{gzh2WxProperties.wx_token}")
+    private String token;
+
+    @Value("#{gzh2WxProperties.wx_appid}")
+    private String appid;
+
+    @Value("#{gzh2WxProperties.wx_appsecret}")
+    private String appsecret;
+
+    @Override
+    public String getToken() {
+        return this.token;
+    }
+
+    @Override
+    public String getAppid() {
+        return this.appid;
+    }
+
+    @Override
+    public String getAppsecret() {
+        return this.appsecret;
+    }
+
+    @Override
+    public WxAccountEnum getWxAccountEnum() {
+        return WxAccountEnum.GZH2;
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java
new file mode 100644
index 0000000000..8bae466956
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java
@@ -0,0 +1,62 @@
+package com.github.binarywang.demo.spring.controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class AbstractWxPortalController {
+  private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+  @RequestMapping(method = RequestMethod.GET, produces = "text/plain;charset=utf-8")
+  public @ResponseBody String authGet(
+      @RequestParam("signature") String signature,
+      @RequestParam("timestamp") String timestamp,
+      @RequestParam("nonce") String nonce,
+      @RequestParam("echostr") String echostr) {
+    this.logger.info("接收到来自微信服务器的认证消息");
+
+    if (this.getWxService().checkSignature(timestamp, nonce, signature)) {
+      return echostr;
+    }
+
+    return "非法请求";
+  }
+
+  @RequestMapping(method = RequestMethod.POST, produces = "application/xml; charset=UTF-8")
+  public @ResponseBody String post(@RequestBody String requestBody) {
+
+    this.logger.debug("\n接收微信请求:{} ", requestBody);
+
+    BaseWxService wxService = this.getWxService();
+
+    WxMpXmlOutMessage out = wxService
+        .route(WxMpXmlMessage.fromXml(requestBody));
+
+    if (out == null) {
+      return "";
+    }
+
+    String outXml = out.toXml();
+
+    this.logger.debug("\n组装回复信息:{}", outXml);
+
+    return outXml;
+  }
+
+  protected abstract BaseWxService getWxService();
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh1WxPortalController.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh1WxPortalController.java
new file mode 100644
index 0000000000..cea1315228
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh1WxPortalController.java
@@ -0,0 +1,26 @@
+package com.github.binarywang.demo.spring.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+import com.github.binarywang.demo.spring.service.Gzh1WxService;
+
+/**
+ * 第一个公众号的微信交互接口
+ * @author Binary Wang
+ *
+ */
+@RestController
+@RequestMapping("/api/gzh1/portal")
+public class Gzh1WxPortalController extends AbstractWxPortalController{
+  @Autowired
+  private Gzh1WxService wxService;
+  
+  @Override
+  protected BaseWxService getWxService() {
+    return this.wxService;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh2WxPortalController.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh2WxPortalController.java
new file mode 100644
index 0000000000..d982ad46b5
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/Gzh2WxPortalController.java
@@ -0,0 +1,26 @@
+package com.github.binarywang.demo.spring.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.github.binarywang.demo.spring.service.BaseWxService;
+import com.github.binarywang.demo.spring.service.Gzh2WxService;
+
+/**
+ * 第二个公众号的微信交互接口
+ * @author Binary Wang
+ *
+ */
+@RestController
+@RequestMapping("/api/gzh2/portal")
+public class Gzh2WxPortalController extends AbstractWxPortalController{
+  @Autowired
+  private Gzh2WxService wxService;
+  
+  @Override
+  protected BaseWxService getWxService() {
+    return this.wxService;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/dto/WxMenuKey.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/dto/WxMenuKey.java
new file mode 100644
index 0000000000..99b4cb680c
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/dto/WxMenuKey.java
@@ -0,0 +1,44 @@
+package com.github.binarywang.demo.spring.dto;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * 菜单的dto对象
+ * @author Binary Wang
+ *
+ */
+public class WxMenuKey {
+  private String type;
+  private String content;
+
+  @Override
+  public String toString() {
+    return ToStringBuilder.reflectionToString(this);
+  }
+
+  public WxMenuKey() {
+
+  }
+
+  public WxMenuKey(String type, String content) {
+    this.type = type;
+    this.content = 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-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/AbstractHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/AbstractHandler.java
new file mode 100644
index 0000000000..7e4e1642df
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/AbstractHandler.java
@@ -0,0 +1,23 @@
+package com.github.binarywang.demo.spring.handler;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.google.gson.Gson;
+
+import me.chanjar.weixin.mp.api.WxMpMessageHandler;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class AbstractHandler implements WxMpMessageHandler {
+
+    protected Logger logger = LoggerFactory.getLogger(getClass());
+    protected final Gson gson = new Gson();
+
+    protected abstract WxConfig getWxConfig();
+    
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LocationHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LocationHandler.java
new file mode 100644
index 0000000000..2a03ee7635
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LocationHandler.java
@@ -0,0 +1,47 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import com.github.binarywang.demo.spring.builder.TextBuilder;
+
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class LocationHandler extends AbstractHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+            Map context, WxMpService wxMpService,
+            WxSessionManager sessionManager) throws WxErrorException {
+        if (wxMessage.getMsgType().equals(WxConsts.XML_MSG_LOCATION)) {
+            //TODO 接收处理用户发送的地理位置消息
+            try {
+                String content = "感谢反馈,您的的地理位置已收到!";
+                return new TextBuilder().build(content, wxMessage, null);
+            } catch (Exception e) {
+                this.logger.error("位置消息接收处理失败", e);
+                return null;
+            }
+        }
+
+        //上报地理位置事件
+        this.logger.info("\n上报地理位置 。。。 ");
+        this.logger.info("\n纬度 : " + wxMessage.getLatitude());
+        this.logger.info("\n经度 : " + wxMessage.getLongitude());
+        this.logger.info("\n精度 : " + String.valueOf(wxMessage.getPrecision()));
+        
+        //TODO  可以将用户地理位置信息保存到本地数据库,以便以后使用
+        
+        return null;
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MenuHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MenuHandler.java
new file mode 100644
index 0000000000..45d5c9788a
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MenuHandler.java
@@ -0,0 +1,71 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+import com.github.binarywang.demo.spring.builder.AbstractBuilder;
+import com.github.binarywang.demo.spring.builder.ImageBuilder;
+import com.github.binarywang.demo.spring.builder.TextBuilder;
+import com.github.binarywang.demo.spring.dto.WxMenuKey;
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class MenuHandler extends AbstractHandler {
+
+  @Override
+  public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+      Map context, WxMpService wxMpService,
+      WxSessionManager sessionManager) {
+    BaseWxService weixinService = (BaseWxService) wxMpService;
+
+    String key = wxMessage.getEventKey();
+    WxMenuKey menuKey = null;
+    try {
+      menuKey = JSON.parseObject(key, WxMenuKey.class);
+    } catch (Exception e) {
+      return WxMpXmlOutMessage.TEXT().content(key)
+          .fromUser(wxMessage.getToUserName())
+          .toUser(wxMessage.getFromUserName()).build();
+    }
+
+    AbstractBuilder builder = null;
+    switch (menuKey.getType()) {
+    case WxConsts.XML_MSG_TEXT:
+      builder = new TextBuilder();
+      break;
+    case WxConsts.XML_MSG_IMAGE:
+      builder = new ImageBuilder();
+      break;
+    case WxConsts.XML_MSG_VOICE:
+      break;
+    case WxConsts.XML_MSG_VIDEO:
+      break;
+    case WxConsts.XML_MSG_NEWS:
+      break;
+    default:
+      break;
+    }
+
+    if (builder != null) {
+      try {
+        return builder.build(menuKey.getContent(), wxMessage, weixinService);
+      } catch (Exception e) {
+        this.logger.error(e.getMessage(), e);
+      }
+    }
+
+    return null;
+
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
new file mode 100644
index 0000000000..47ad929f4b
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
@@ -0,0 +1,48 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.github.binarywang.demo.spring.builder.TextBuilder;
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class MsgHandler extends AbstractHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+            Map context, WxMpService wxMpService,
+            WxSessionManager sessionManager)    {
+
+        BaseWxService weixinService = (BaseWxService) wxMpService;
+
+        if (!wxMessage.getMsgType().equals(WxConsts.XML_MSG_EVENT)) {
+            //TODO 可以选择将消息保存到本地
+        }
+
+        //当用户输入关键词如“你好”,“在吗”等并且有客服在线时,把消息转发给在线客服
+        if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "在吗")
+            && weixinService.isCustomerServiceOnline()) {
+            return WxMpXmlOutMessage
+                .TRANSFER_CUSTOMER_SERVICE().fromUser(wxMessage.getToUserName())
+                .toUser(wxMessage.getFromUserName()).build();
+        }
+
+        //TODO 组装回复消息
+        String content = "回复信息内容";
+        return new TextBuilder().build(content, wxMessage, weixinService);
+
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
new file mode 100644
index 0000000000..ac828f52ab
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
@@ -0,0 +1,34 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Component
+public class NullHandler extends AbstractHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+            Map context, WxMpService wxMpService,
+            WxSessionManager sessionManager) {
+        return null;
+    }
+
+    @Override
+    protected WxConfig getWxConfig() {
+        return null;
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/ScanHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/ScanHandler.java
new file mode 100644
index 0000000000..91267d4d4d
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/ScanHandler.java
@@ -0,0 +1,10 @@
+package com.github.binarywang.demo.spring.handler;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class ScanHandler extends AbstractHandler {
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
new file mode 100644
index 0000000000..f5bd64604f
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
@@ -0,0 +1,62 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import com.github.binarywang.demo.spring.builder.TextBuilder;
+import com.github.binarywang.demo.spring.service.BaseWxService;
+
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class SubscribeHandler extends AbstractHandler {
+
+  @Override
+  public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context, WxMpService wxMpService,
+      WxSessionManager sessionManager) throws WxErrorException {
+
+    this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUserName());
+
+    BaseWxService weixinService = (BaseWxService) wxMpService;
+
+    // 获取微信用户基本信息
+    WxMpUser userWxInfo = weixinService.userInfo(wxMessage.getFromUserName(), null);
+
+    if (userWxInfo != null) {
+      // TODO 可以添加关注用户到本地
+    }
+
+    WxMpXmlOutMessage responsResult = null;
+    try {
+      responsResult = handleSpecial(wxMessage);
+    } catch (Exception e) {
+      this.logger.error(e.getMessage(), e);
+    }
+
+    if (responsResult != null) {
+      return responsResult;
+    }
+
+    try {
+      return new TextBuilder().build("感谢关注", wxMessage, weixinService);
+    } catch (Exception e) {
+      this.logger.error(e.getMessage(), e);
+    }
+
+    return null;
+  }
+
+  /**
+   * 处理特殊请求,比如如果是扫码进来的,可以做相应处理
+   */
+  protected abstract WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) throws Exception;
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/UnsubscribeHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/UnsubscribeHandler.java
new file mode 100644
index 0000000000..44daaa1826
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/UnsubscribeHandler.java
@@ -0,0 +1,27 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class UnsubscribeHandler extends AbstractHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+            Map context, WxMpService wxMpService,
+            WxSessionManager sessionManager) {
+        String openId = wxMessage.getFromUserName();
+        this.logger.info("取消关注用户 OPENID: " + openId);
+        // TODO 可以更新本地数据库为取消关注状态
+        return null;
+    }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
new file mode 100644
index 0000000000..a05abf8c9e
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
@@ -0,0 +1,129 @@
+package com.github.binarywang.demo.spring.service;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.handler.AbstractHandler;
+import com.github.binarywang.demo.spring.handler.MenuHandler;
+import com.github.binarywang.demo.spring.handler.MsgHandler;
+import com.github.binarywang.demo.spring.handler.NullHandler;
+import com.github.binarywang.demo.spring.handler.SubscribeHandler;
+import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParser;
+
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
+import me.chanjar.weixin.mp.api.WxMpMessageRouter;
+import me.chanjar.weixin.mp.api.WxMpServiceImpl;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+public abstract class BaseWxService extends WxMpServiceImpl {
+  private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+  @Autowired
+  protected NullHandler nullHandler;
+
+  private WxMpMessageRouter router;
+
+  protected abstract WxConfig getServerConfig();
+
+  protected abstract MenuHandler getMenuHandler();
+
+  protected abstract SubscribeHandler getSubscribeHandler();
+
+  protected abstract UnsubscribeHandler getUnsubscribeHandler();
+
+  protected abstract AbstractHandler getLocationHandler();
+
+  protected abstract MsgHandler getMsgHandler();
+
+  protected abstract AbstractHandler getScanHandler();
+
+  @PostConstruct
+  public void init() {
+    final WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
+    config.setAppId(this.getServerConfig().getAppid());// 设置微信公众号的appid
+    config.setSecret(this.getServerConfig().getAppsecret());// 设置微信公众号的app corpSecret
+    config.setToken(this.getServerConfig().getToken());// 设置微信公众号的token
+    super.setWxMpConfigStorage(config);
+
+    this.refreshRouter();
+  }
+
+  private void refreshRouter() {
+
+    final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);
+
+    // 自定义菜单事件
+    newRouter.rule().async(false).event(WxConsts.BUTTON_CLICK)
+        .handler(this.getMenuHandler()).end();
+
+    // 点击菜单连接事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.BUTTON_VIEW).handler(this.nullHandler).end();
+
+    // 关注事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.EVT_SUBSCRIBE).handler(this.getSubscribeHandler())
+        .end();
+
+    // 取消关注事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.EVT_UNSUBSCRIBE).handler(this.getUnsubscribeHandler())
+        .end();
+
+    // 上报地理位置事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.EVT_LOCATION).handler(this.getLocationHandler()).end();
+
+    // 接收地理位置消息
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_LOCATION)
+        .handler(this.getLocationHandler()).end();
+
+    // 扫码事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.EVT_SCAN).handler(this.getScanHandler()).end();
+
+    // 默认
+    newRouter.rule().async(false).handler(this.getMsgHandler()).end();
+
+    this.router = newRouter;
+  }
+
+  public WxMpXmlOutMessage route(WxMpXmlMessage message) {
+    try {
+      final WxMpXmlOutMessage responseMessage = this.router.route(message);
+      return responseMessage;
+    } catch (Exception e) {
+      this.logger.error(e.getMessage(), e);
+    }
+
+    return null;
+  }
+
+  public boolean isCustomerServiceOnline() {
+    try {
+      String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist";
+      String executeResult = this.get(url, null);
+      JsonArray jsonArray = new JsonParser().parse(executeResult)
+          .getAsJsonObject().get("kf_online_list").getAsJsonArray();
+      return jsonArray.size() > 0;
+    } catch (Exception e) {
+      this.logger.error("获取客服在线状态异常: " + e.getMessage(), e);
+    }
+
+    return false;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
new file mode 100644
index 0000000000..74e0e5664c
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
@@ -0,0 +1,65 @@
+package com.github.binarywang.demo.spring.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.handler.AbstractHandler;
+import com.github.binarywang.demo.spring.handler.MenuHandler;
+import com.github.binarywang.demo.spring.handler.MsgHandler;
+import com.github.binarywang.demo.spring.handler.SubscribeHandler;
+import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Service
+public class Gzh1WxService extends BaseWxService {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+  
+  @Override
+  protected WxConfig getServerConfig() {
+    return this.wxConfig;
+  }
+
+  @Override
+  protected MenuHandler getMenuHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected SubscribeHandler getSubscribeHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected UnsubscribeHandler getUnsubscribeHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected AbstractHandler getLocationHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected MsgHandler getMsgHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected AbstractHandler getScanHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh2WxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh2WxService.java
new file mode 100644
index 0000000000..beaeafbfa9
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh2WxService.java
@@ -0,0 +1,66 @@
+package com.github.binarywang.demo.spring.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.github.binarywang.demo.spring.config.WxGzh2Config;
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.handler.AbstractHandler;
+import com.github.binarywang.demo.spring.handler.MenuHandler;
+import com.github.binarywang.demo.spring.handler.MsgHandler;
+import com.github.binarywang.demo.spring.handler.SubscribeHandler;
+import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Service
+public class Gzh2WxService extends BaseWxService {
+
+  @Autowired
+  private WxGzh2Config wxConfig;
+
+  @Override
+  protected WxConfig getServerConfig() {
+    return this.wxConfig;
+  }
+
+  @Override
+  protected MenuHandler getMenuHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected SubscribeHandler getSubscribeHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected UnsubscribeHandler getUnsubscribeHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected AbstractHandler getLocationHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected MsgHandler getMsgHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  protected AbstractHandler getScanHandler() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/resources/.gitignore b/weixin-java-demo-with-spring/src/main/resources/.gitignore
new file mode 100644
index 0000000000..a8697d7334
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/.gitignore
@@ -0,0 +1,2 @@
+/wx-gzh1.properties
+/wx-gzh2.properties
diff --git a/weixin-java-demo-with-spring/src/main/resources/applicationContext.xml b/weixin-java-demo-with-spring/src/main/resources/applicationContext.xml
new file mode 100644
index 0000000000..f4954624f8
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/applicationContext.xml
@@ -0,0 +1,17 @@
+
+
+
+  
+
+  
+  
+
+
\ No newline at end of file
diff --git a/weixin-java-demo-with-spring/src/main/resources/log4j.properties b/weixin-java-demo-with-spring/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..0f4d67788d
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/log4j.properties
@@ -0,0 +1,8 @@
+log4j.rootLogger=DEBUG, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.EnhancedPatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} [%t]:%c:%L#%M() %m%n
+
+log4j.logger.org.apache.http.impl.conn.PoolingHttpClientConnectionManager=INFO
\ No newline at end of file
diff --git a/weixin-java-demo-with-spring/src/main/resources/spring-service-bean.xml b/weixin-java-demo-with-spring/src/main/resources/spring-service-bean.xml
new file mode 100644
index 0000000000..bc5bbf9a54
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/spring-service-bean.xml
@@ -0,0 +1,29 @@
+
+
+
+  
+    
+  
+
+  
+    
+      
+        
+          
+            UTF-8
+          
+        
+        
+      
+    
+  
+
+
\ No newline at end of file
diff --git a/weixin-java-demo-with-spring/src/main/resources/spring-servlet-common.xml b/weixin-java-demo-with-spring/src/main/resources/spring-servlet-common.xml
new file mode 100644
index 0000000000..3686b979a8
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/spring-servlet-common.xml
@@ -0,0 +1,43 @@
+
+
+	
+	
+		
+	
+
+	
+		
+			
+			
+		
+	
+
+	
+
+	
+		
+			
+				text/html;charset=UTF-8
+				text/plain;charset=UTF-8
+			
+		
+	
+
+	
+		
+	
+
+	
+
+
diff --git a/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template b/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template
new file mode 100644
index 0000000000..76afcd9eab
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template
@@ -0,0 +1,3 @@
+wx_appid=
+wx_appsecret=
+wx_token=
diff --git a/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template b/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template
new file mode 100644
index 0000000000..76afcd9eab
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template
@@ -0,0 +1,3 @@
+wx_appid=
+wx_appsecret=
+wx_token=
diff --git a/spring-demo/src/main/webapp/WEB-INF/web.xml b/weixin-java-demo-with-spring/src/main/webapp/WEB-INF/web.xml
similarity index 85%
rename from spring-demo/src/main/webapp/WEB-INF/web.xml
rename to weixin-java-demo-with-spring/src/main/webapp/WEB-INF/web.xml
index 6242f8f1f4..fd9cce94ba 100644
--- a/spring-demo/src/main/webapp/WEB-INF/web.xml
+++ b/weixin-java-demo-with-spring/src/main/webapp/WEB-INF/web.xml
@@ -20,14 +20,6 @@
 		encodingFilter
 		/*
 	
-	
-		springSecurityFilterChain
-		org.springframework.web.filter.DelegatingFilterProxy
-	
-	
-		springSecurityFilterChain
-		/v1/admin/*
-	
 	
 	
 		org.springframework.web.context.ContextLoaderListener

From f73a3d85b549528fa3c76835e6c8c3b317455369 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Wed, 6 Jul 2016 17:33:13 +0800
Subject: [PATCH 10/54] =?UTF-8?q?=E5=B0=86demo=E7=A7=BB=E5=87=BA=E5=AD=90?=
 =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=8C=E4=BB=A5=E9=81=BF=E5=85=8D=E4=B8=8D?=
 =?UTF-8?q?=E5=BF=85=E8=A6=81=E7=9A=84=E5=8F=91=E5=B8=83=E7=94=9F=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 1fa126e5af..bbd69cb5f3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,6 @@
     weixin-java-common
     weixin-java-cp
     weixin-java-mp
-    weixin-java-demo-with-spring
   
 
   

From ab8850cd12647ca823b0e37ba0a50e9fcbf934e3 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 7 Jul 2016 20:19:27 +0800
Subject: [PATCH 11/54] =?UTF-8?q?jetty=E7=89=88=E6=9C=AC=E5=8F=B7=E6=8F=90?=
 =?UTF-8?q?=E5=87=BA=E6=9D=A5=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index bbd69cb5f3..9c8bd39ea8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,8 @@
     2.7.5
     2.7
     3.4
+    9.3.0.M0
+    9.3.10.v20160621
   
 
   
@@ -137,13 +139,13 @@
       
         org.eclipse.jetty
         jetty-server
-        9.3.0.M0
+        ${jetty.version}
         test
       
       
         org.eclipse.jetty
         jetty-servlet
-        9.3.0.M0
+        ${jetty.version}
         test
       
     

From 79a41e96d1c5b4abf68c8d48ba25dee00db36ac6 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 7 Jul 2016 20:25:58 +0800
Subject: [PATCH 12/54] =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../demo/spring/handler/LogHandler.java       | 38 +++++++++++++++++++
 .../demo/spring/handler/MsgHandler.java       |  6 +--
 .../demo/spring/service/BaseWxService.java    | 23 ++++++-----
 3 files changed, 54 insertions(+), 13 deletions(-)
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
new file mode 100644
index 0000000000..28aa264b6d
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
@@ -0,0 +1,38 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Component
+public class LogHandler extends AbstractHandler {
+  private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+  @Override
+  public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+      Map context, WxMpService wxMpService,
+      WxSessionManager sessionManager) {
+    this.logger.info("接收到请求消息,内容:【{}】" ,wxMessage.toString());
+    return null;
+  }
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return null;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
index 47ad929f4b..5984749ce4 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
@@ -31,9 +31,9 @@ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
             //TODO 可以选择将消息保存到本地
         }
 
-        //当用户输入关键词如“你好”,“在吗”等并且有客服在线时,把消息转发给在线客服
-        if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "在吗")
-            && weixinService.isCustomerServiceOnline()) {
+        //当用户输入关键词如“是”,“客服”等并且有客服在线时,把消息转发给在线客服
+        if (StringUtils.startsWithAny(wxMessage.getContent(), "是","客服")
+            && weixinService.hasKefuOnline()) {
             return WxMpXmlOutMessage
                 .TRANSFER_CUSTOMER_SERVICE().fromUser(wxMessage.getToUserName())
                 .toUser(wxMessage.getFromUserName()).build();
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
index a05abf8c9e..29b319a975 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
@@ -11,10 +11,9 @@
 import com.github.binarywang.demo.spring.handler.MenuHandler;
 import com.github.binarywang.demo.spring.handler.MsgHandler;
 import com.github.binarywang.demo.spring.handler.NullHandler;
+import com.github.binarywang.demo.spring.handler.LogHandler;
 import com.github.binarywang.demo.spring.handler.SubscribeHandler;
 import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonParser;
 
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
@@ -22,6 +21,7 @@
 import me.chanjar.weixin.mp.api.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
 import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList;
 
 /**
  * 
@@ -31,6 +31,9 @@
 public abstract class BaseWxService extends WxMpServiceImpl {
   private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
+  @Autowired
+  protected LogHandler logHandler;
+
   @Autowired
   protected NullHandler nullHandler;
 
@@ -65,9 +68,12 @@ private void refreshRouter() {
 
     final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);
 
+    //记录所有事件的日志
+    newRouter.rule().handler(this.logHandler).next();
+
     // 自定义菜单事件
-    newRouter.rule().async(false).event(WxConsts.BUTTON_CLICK)
-        .handler(this.getMenuHandler()).end();
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.BUTTON_CLICK).handler(this.getMenuHandler()).end();
 
     // 点击菜单连接事件
     newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
@@ -112,13 +118,10 @@ public WxMpXmlOutMessage route(WxMpXmlMessage message) {
     return null;
   }
 
-  public boolean isCustomerServiceOnline() {
+  public boolean hasKefuOnline() {
     try {
-      String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist";
-      String executeResult = this.get(url, null);
-      JsonArray jsonArray = new JsonParser().parse(executeResult)
-          .getAsJsonObject().get("kf_online_list").getAsJsonArray();
-      return jsonArray.size() > 0;
+      WxMpKfOnlineList kfOnlineList = this.getKefuService().kfOnlineList();
+      return kfOnlineList != null && kfOnlineList.getKfOnlineList().size() > 0;
     } catch (Exception e) {
       this.logger.error("获取客服在线状态异常: " + e.getMessage(), e);
     }

From 1bf35b963b58bd5e45c65f7b3718776f46ee7ed0 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 7 Jul 2016 20:26:09 +0800
Subject: [PATCH 13/54] =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../demo/spring/handler/NullHandler.java      | 34 -------------------
 1 file changed, 34 deletions(-)
 delete mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
deleted file mode 100644
index ac828f52ab..0000000000
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.github.binarywang.demo.spring.handler;
-
-import java.util.Map;
-
-import org.springframework.stereotype.Component;
-
-import com.github.binarywang.demo.spring.config.WxConfig;
-
-import me.chanjar.weixin.common.session.WxSessionManager;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
-
-/**
- * 
- * @author Binary Wang
- *
- */
-@Component
-public class NullHandler extends AbstractHandler {
-
-    @Override
-    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
-            Map context, WxMpService wxMpService,
-            WxSessionManager sessionManager) {
-        return null;
-    }
-
-    @Override
-    protected WxConfig getWxConfig() {
-        return null;
-    }
-
-}

From 62988c11e3cac6a305c594607b5af7ae540505fd Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 7 Jul 2016 20:26:14 +0800
Subject: [PATCH 14/54] =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../demo/spring/handler/NullHandler.java      | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
new file mode 100644
index 0000000000..ac828f52ab
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/NullHandler.java
@@ -0,0 +1,34 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Component
+public class NullHandler extends AbstractHandler {
+
+    @Override
+    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+            Map context, WxMpService wxMpService,
+            WxSessionManager sessionManager) {
+        return null;
+    }
+
+    @Override
+    protected WxConfig getWxConfig() {
+        return null;
+    }
+
+}

From 9d2923edc929a42ae09e408d5d1c94c00f188fd6 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 09:48:59 +0800
Subject: [PATCH 15/54] =?UTF-8?q?=E5=AE=8C=E5=96=84Demo=EF=BC=8C=E4=BF=9D?=
 =?UTF-8?q?=E8=AF=81=E5=85=B6=E4=B8=AD=E4=B8=80=E4=B8=AA=E5=85=AC=E4=BC=97?=
 =?UTF-8?q?=E5=8F=B7=E5=8F=AF=E4=BB=A5=E6=AD=A3=E5=B8=B8=E4=BD=BF=E7=94=A8?=
 =?UTF-8?q?=EF=BC=8Cclose=20#7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../handler/gzh1/Gzh1LocationHandler.java     | 23 +++++++++++
 .../spring/handler/gzh1/Gzh1MenuHadler.java   | 23 +++++++++++
 .../spring/handler/gzh1/Gzh1MsgHadler.java    | 23 +++++++++++
 .../handler/gzh1/Gzh1SubscribeHadler.java     | 32 ++++++++++++++++
 .../handler/gzh1/Gzh1UnSubscribeHadler.java   | 23 +++++++++++
 .../demo/spring/service/Gzh1WxService.java    | 38 +++++++++++++------
 6 files changed, 150 insertions(+), 12 deletions(-)
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1LocationHandler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1LocationHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1LocationHandler.java
new file mode 100644
index 0000000000..efe4a72744
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1LocationHandler.java
@@ -0,0 +1,23 @@
+package com.github.binarywang.demo.spring.handler.gzh1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.handler.LocationHandler;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class Gzh1LocationHandler extends LocationHandler {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return this.wxConfig;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java
new file mode 100644
index 0000000000..4368a60400
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java
@@ -0,0 +1,23 @@
+package com.github.binarywang.demo.spring.handler.gzh1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.handler.MenuHandler;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class Gzh1MenuHadler extends MenuHandler {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return this.wxConfig;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java
new file mode 100644
index 0000000000..59ee6ae1a5
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java
@@ -0,0 +1,23 @@
+package com.github.binarywang.demo.spring.handler.gzh1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.handler.MsgHandler;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class Gzh1MsgHadler extends MsgHandler {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return this.wxConfig;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java
new file mode 100644
index 0000000000..cadfd1fa66
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java
@@ -0,0 +1,32 @@
+package com.github.binarywang.demo.spring.handler.gzh1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.handler.SubscribeHandler;
+
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class Gzh1SubscribeHadler extends SubscribeHandler {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return this.wxConfig;
+  }
+
+  @Override
+  protected WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
+      throws Exception {
+    return null;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java
new file mode 100644
index 0000000000..a4e3a8ed6c
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java
@@ -0,0 +1,23 @@
+package com.github.binarywang.demo.spring.handler.gzh1;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+import com.github.binarywang.demo.spring.config.WxGzh1Config;
+import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
+
+@Component
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class Gzh1UnSubscribeHadler extends UnsubscribeHandler {
+  @Autowired
+  private  WxGzh1Config wxConfig;
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return this.wxConfig;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
index 74e0e5664c..cd809951ea 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java
@@ -10,6 +10,11 @@
 import com.github.binarywang.demo.spring.handler.MsgHandler;
 import com.github.binarywang.demo.spring.handler.SubscribeHandler;
 import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
+import com.github.binarywang.demo.spring.handler.gzh1.Gzh1LocationHandler;
+import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MenuHadler;
+import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MsgHadler;
+import com.github.binarywang.demo.spring.handler.gzh1.Gzh1SubscribeHadler;
+import com.github.binarywang.demo.spring.handler.gzh1.Gzh1UnSubscribeHadler;
 
 /**
  * 
@@ -19,8 +24,23 @@
 @Service
 public class Gzh1WxService extends BaseWxService {
   @Autowired
-  private  WxGzh1Config wxConfig;
+  private WxGzh1Config wxConfig;
+
+  @Autowired
+  private Gzh1LocationHandler locationHandler;
+  
+  @Autowired
+  private Gzh1MenuHadler menuHadler;
+  
+  @Autowired
+  private Gzh1MsgHadler msgHadler;
+  
+  @Autowired
+  private Gzh1UnSubscribeHadler unSubscribeHadler;
   
+  @Autowired
+  private Gzh1SubscribeHadler subscribeHadler;
+
   @Override
   protected WxConfig getServerConfig() {
     return this.wxConfig;
@@ -28,37 +48,31 @@ protected WxConfig getServerConfig() {
 
   @Override
   protected MenuHandler getMenuHandler() {
-    // TODO Auto-generated method stub
-    return null;
+    return this.menuHadler;
   }
 
   @Override
   protected SubscribeHandler getSubscribeHandler() {
-    // TODO Auto-generated method stub
-    return null;
+    return this.subscribeHadler;
   }
 
   @Override
   protected UnsubscribeHandler getUnsubscribeHandler() {
-    // TODO Auto-generated method stub
-    return null;
+    return this.unSubscribeHadler;
   }
 
   @Override
   protected AbstractHandler getLocationHandler() {
-    // TODO Auto-generated method stub
-    return null;
+    return this.locationHandler;
   }
 
   @Override
   protected MsgHandler getMsgHandler() {
-    // TODO Auto-generated method stub
-    return null;
+    return this.msgHadler;
   }
 
   @Override
   protected AbstractHandler getScanHandler() {
-    // TODO Auto-generated method stub
     return null;
   }
 

From c16e2fbe503c2d0ed9fde6a7c0815941d334ce38 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 10:52:42 +0800
Subject: [PATCH 16/54] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/main/java/me/chanjar/weixin/common/api/WxConsts.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
index 85efcd3fa5..ebe5cf986e 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
@@ -20,7 +20,7 @@ public class WxConsts {
   public static final String XML_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
   
   ///////////////////////
-  // 主动发送消息的消息类型
+  // 主动发送消息(即客服消息)的消息类型
   ///////////////////////
   public static final String CUSTOM_MSG_TEXT = "text";
   public static final String CUSTOM_MSG_IMAGE = "image";

From 2ea838fce236f3364c7faa5bf62f684d7736353f Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 11:01:44 +0800
Subject: [PATCH 17/54] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=A2=E6=9C=8D?=
 =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=AE=A1=E7=90=86=E7=9A=84=E4=B8=89=E4=B8=AA?=
 =?UTF-8?q?=E4=BA=8B=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/main/java/me/chanjar/weixin/common/api/WxConsts.java  | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
index ebe5cf986e..c645e30f97 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
@@ -103,6 +103,10 @@ public class WxConsts {
   public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
   public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警
 
+  public static final String EVT_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话
+  public static final String EVT_KF_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话
+  public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话
+
   ///////////////////////
   // 上传多媒体文件的类型
   ///////////////////////

From 3ab7e66b48dea8817a619ec025667bd9f67265c2 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 12:30:48 +0800
Subject: [PATCH 18/54] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=B6=88=E6=81=AF?=
 =?UTF-8?q?=E9=87=8C=E5=A2=9E=E5=8A=A0=E5=AE=A2=E6=9C=8D=E4=BC=9A=E8=AF=9D?=
 =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=9A=84=E4=B8=89=E4=B8=AA=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/mp/bean/WxMpXmlMessage.java        | 300 ++++++++++--------
 1 file changed, 165 insertions(+), 135 deletions(-)

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
index 9f42ffc701..cd86fd0dd3 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
@@ -1,18 +1,22 @@
 package me.chanjar.weixin.mp.bean;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
 import com.thoughtworks.xstream.annotations.XStreamAlias;
 import com.thoughtworks.xstream.annotations.XStreamConverter;
+
 import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
 import me.chanjar.weixin.mp.api.WxMpConfigStorage;
 import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
 import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * 
@@ -28,46 +32,48 @@
 @XStreamAlias("xml")
 public class WxMpXmlMessage implements Serializable {
 
+  private static final long serialVersionUID = -3586245291677274914L;
+
   ///////////////////////
   // 以下都是微信推送过来的消息的xml的element所对应的属性
   ///////////////////////
 
   @XStreamAlias("ToUserName")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String toUserName;
 
   @XStreamAlias("FromUserName")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String fromUserName;
 
   @XStreamAlias("CreateTime")
   private Long createTime;
 
   @XStreamAlias("MsgType")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String msgType;
 
   @XStreamAlias("Content")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String content;
 
   @XStreamAlias("MsgId")
   private Long msgId;
 
   @XStreamAlias("PicUrl")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String picUrl;
 
   @XStreamAlias("MediaId")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String mediaId;
 
   @XStreamAlias("Format")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String format;
 
   @XStreamAlias("ThumbMediaId")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String thumbMediaId;
 
   @XStreamAlias("Location_X")
@@ -80,31 +86,31 @@ public class WxMpXmlMessage implements Serializable {
   private Double scale;
 
   @XStreamAlias("Label")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String label;
 
   @XStreamAlias("Title")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String title;
 
   @XStreamAlias("Description")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String description;
 
   @XStreamAlias("Url")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String url;
 
   @XStreamAlias("Event")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String event;
 
   @XStreamAlias("EventKey")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String eventKey;
 
   @XStreamAlias("Ticket")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String ticket;
 
   @XStreamAlias("Latitude")
@@ -117,7 +123,7 @@ public class WxMpXmlMessage implements Serializable {
   private Double precision;
 
   @XStreamAlias("Recognition")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String recognition;
 
   ///////////////////////////////////////
@@ -127,7 +133,7 @@ public class WxMpXmlMessage implements Serializable {
    * 群发的结果
    */
   @XStreamAlias("Status")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String status;
   /**
    * group_id下粉丝数;或者openid_list中的粉丝数
@@ -150,26 +156,45 @@ public class WxMpXmlMessage implements Serializable {
   @XStreamAlias("ErrorCount")
   private Integer errorCount;
 
+  ///////////////////////////////////////
+  // 客服会话管理相关事件推送
+  ///////////////////////////////////////
+  /**
+   * 创建或关闭客服会话时的客服帐号
+   */
+  @XStreamAlias("KfAccount")
+  private String kfAccount;
+  /**
+   * 转接客服会话时的转入客服帐号
+   */
+  @XStreamAlias("ToKfAccount")
+  private String toKfAccount;
+  /**
+   * 转接客服会话时的转出客服帐号
+   */
+  @XStreamAlias("FromKfAccount")
+  private String fromKfAccount;
+
   ///////////////////////////////////////
   // 卡券相关事件推送
   ///////////////////////////////////////
   @XStreamAlias("CardId")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String cardId;
 
   @XStreamAlias("FriendUserName")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String friendUserName;
 
   @XStreamAlias("IsGiveByFriend")
   private Integer isGiveByFriend; // 是否为转赠,1代表是,0代表否
 
   @XStreamAlias("UserCardCode")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String userCardCode;
 
   @XStreamAlias("OldUserCardCode")
-  @XStreamConverter(value=XStreamCDataConverter.class)
+  @XStreamConverter(value = XStreamCDataConverter.class)
   private String oldUserCardCode;
 
   @XStreamAlias("OuterId")
@@ -185,7 +210,7 @@ public class WxMpXmlMessage implements Serializable {
   private SendLocationInfo sendLocationInfo = new SendLocationInfo();
 
   public String getToUserName() {
-    return toUserName;
+    return this.toUserName;
   }
 
   public void setToUserName(String toUserName) {
@@ -193,7 +218,7 @@ public void setToUserName(String toUserName) {
   }
 
   public Long getCreateTime() {
-    return createTime;
+    return this.createTime;
   }
 
   public void setCreateTime(Long createTime) {
@@ -215,7 +240,7 @@ public void setCreateTime(Long createTime) {
    * @return
    */
   public String getMsgType() {
-    return msgType;
+    return this.msgType;
   }
 
   /**
@@ -236,7 +261,7 @@ public void setMsgType(String msgType) {
   }
 
   public String getContent() {
-    return content;
+    return this.content;
   }
 
   public void setContent(String content) {
@@ -244,7 +269,7 @@ public void setContent(String content) {
   }
 
   public Long getMsgId() {
-    return msgId;
+    return this.msgId;
   }
 
   public void setMsgId(Long msgId) {
@@ -252,7 +277,7 @@ public void setMsgId(Long msgId) {
   }
 
   public String getPicUrl() {
-    return picUrl;
+    return this.picUrl;
   }
 
   public void setPicUrl(String picUrl) {
@@ -260,7 +285,7 @@ public void setPicUrl(String picUrl) {
   }
 
   public String getMediaId() {
-    return mediaId;
+    return this.mediaId;
   }
 
   public void setMediaId(String mediaId) {
@@ -268,7 +293,7 @@ public void setMediaId(String mediaId) {
   }
 
   public String getFormat() {
-    return format;
+    return this.format;
   }
 
   public void setFormat(String format) {
@@ -276,7 +301,7 @@ public void setFormat(String format) {
   }
 
   public String getThumbMediaId() {
-    return thumbMediaId;
+    return this.thumbMediaId;
   }
 
   public void setThumbMediaId(String thumbMediaId) {
@@ -284,7 +309,7 @@ public void setThumbMediaId(String thumbMediaId) {
   }
 
   public Double getLocationX() {
-    return locationX;
+    return this.locationX;
   }
 
   public void setLocationX(Double locationX) {
@@ -292,7 +317,7 @@ public void setLocationX(Double locationX) {
   }
 
   public Double getLocationY() {
-    return locationY;
+    return this.locationY;
   }
 
   public void setLocationY(Double locationY) {
@@ -300,7 +325,7 @@ public void setLocationY(Double locationY) {
   }
 
   public Double getScale() {
-    return scale;
+    return this.scale;
   }
 
   public void setScale(Double scale) {
@@ -308,7 +333,7 @@ public void setScale(Double scale) {
   }
 
   public String getLabel() {
-    return label;
+    return this.label;
   }
 
   public void setLabel(String label) {
@@ -316,7 +341,7 @@ public void setLabel(String label) {
   }
 
   public String getTitle() {
-    return title;
+    return this.title;
   }
 
   public void setTitle(String title) {
@@ -324,7 +349,7 @@ public void setTitle(String title) {
   }
 
   public String getDescription() {
-    return description;
+    return this.description;
   }
 
   public void setDescription(String description) {
@@ -332,7 +357,7 @@ public void setDescription(String description) {
   }
 
   public String getUrl() {
-    return url;
+    return this.url;
   }
 
   public void setUrl(String url) {
@@ -340,7 +365,7 @@ public void setUrl(String url) {
   }
 
   public String getEvent() {
-    return event;
+    return this.event;
   }
 
   public void setEvent(String event) {
@@ -348,7 +373,7 @@ public void setEvent(String event) {
   }
 
   public String getEventKey() {
-    return eventKey;
+    return this.eventKey;
   }
 
   public void setEventKey(String eventKey) {
@@ -356,7 +381,7 @@ public void setEventKey(String eventKey) {
   }
 
   public String getTicket() {
-    return ticket;
+    return this.ticket;
   }
 
   public void setTicket(String ticket) {
@@ -364,7 +389,7 @@ public void setTicket(String ticket) {
   }
 
   public Double getLatitude() {
-    return latitude;
+    return this.latitude;
   }
 
   public void setLatitude(Double latitude) {
@@ -372,7 +397,7 @@ public void setLatitude(Double latitude) {
   }
 
   public Double getLongitude() {
-    return longitude;
+    return this.longitude;
   }
 
   public void setLongitude(Double longitude) {
@@ -380,7 +405,7 @@ public void setLongitude(Double longitude) {
   }
 
   public Double getPrecision() {
-    return precision;
+    return this.precision;
   }
 
   public void setPrecision(Double precision) {
@@ -388,7 +413,7 @@ public void setPrecision(Double precision) {
   }
 
   public String getRecognition() {
-    return recognition;
+    return this.recognition;
   }
 
   public void setRecognition(String recognition) {
@@ -396,7 +421,7 @@ public void setRecognition(String recognition) {
   }
 
   public String getFromUserName() {
-    return fromUserName;
+    return this.fromUserName;
   }
 
   public void setFromUserName(String fromUserName) {
@@ -421,28 +446,28 @@ public static WxMpXmlMessage fromXml(InputStream is) {
    * @param msgSignature
    * @return
    */
-  public static WxMpXmlMessage fromEncryptedXml(
-      String encryptedXml,
-      WxMpConfigStorage wxMpConfigStorage,
-      String timestamp, String nonce, String msgSignature) {
+  public static WxMpXmlMessage fromEncryptedXml(String encryptedXml,
+      WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
+      String msgSignature) {
     WxMpCryptUtil cryptUtil = new WxMpCryptUtil(wxMpConfigStorage);
-    String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml);
+    String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce,
+        encryptedXml);
     return fromXml(plainText);
   }
 
-  public static WxMpXmlMessage fromEncryptedXml(
-      InputStream is,
-      WxMpConfigStorage wxMpConfigStorage,
-      String timestamp, String nonce, String msgSignature) {
+  public static WxMpXmlMessage fromEncryptedXml(InputStream is,
+      WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce,
+      String msgSignature) {
     try {
-      return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxMpConfigStorage, timestamp, nonce, msgSignature);
+      return fromEncryptedXml(IOUtils.toString(is, "UTF-8"), wxMpConfigStorage,
+          timestamp, nonce, msgSignature);
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
   }
 
   public String getStatus() {
-    return status;
+    return this.status;
   }
 
   public void setStatus(String status) {
@@ -450,7 +475,7 @@ public void setStatus(String status) {
   }
 
   public Integer getTotalCount() {
-    return totalCount;
+    return this.totalCount;
   }
 
   public void setTotalCount(Integer totalCount) {
@@ -458,7 +483,7 @@ public void setTotalCount(Integer totalCount) {
   }
 
   public Integer getFilterCount() {
-    return filterCount;
+    return this.filterCount;
   }
 
   public void setFilterCount(Integer filterCount) {
@@ -466,7 +491,7 @@ public void setFilterCount(Integer filterCount) {
   }
 
   public Integer getSentCount() {
-    return sentCount;
+    return this.sentCount;
   }
 
   public void setSentCount(Integer sentCount) {
@@ -474,7 +499,7 @@ public void setSentCount(Integer sentCount) {
   }
 
   public Integer getErrorCount() {
-    return errorCount;
+    return this.errorCount;
   }
 
   public void setErrorCount(Integer errorCount) {
@@ -482,7 +507,7 @@ public void setErrorCount(Integer errorCount) {
   }
 
   public String getCardId() {
-    return cardId;
+    return this.cardId;
   }
 
   public void setCardId(String cardId) {
@@ -490,7 +515,7 @@ public void setCardId(String cardId) {
   }
 
   public String getFriendUserName() {
-    return friendUserName;
+    return this.friendUserName;
   }
 
   public void setFriendUserName(String friendUserName) {
@@ -498,7 +523,7 @@ public void setFriendUserName(String friendUserName) {
   }
 
   public Integer getIsGiveByFriend() {
-    return isGiveByFriend;
+    return this.isGiveByFriend;
   }
 
   public void setIsGiveByFriend(Integer isGiveByFriend) {
@@ -506,7 +531,7 @@ public void setIsGiveByFriend(Integer isGiveByFriend) {
   }
 
   public String getUserCardCode() {
-    return userCardCode;
+    return this.userCardCode;
   }
 
   public void setUserCardCode(String userCardCode) {
@@ -514,7 +539,7 @@ public void setUserCardCode(String userCardCode) {
   }
 
   public String getOldUserCardCode() {
-    return oldUserCardCode;
+    return this.oldUserCardCode;
   }
 
   public void setOldUserCardCode(String oldUserCardCode) {
@@ -522,7 +547,7 @@ public void setOldUserCardCode(String oldUserCardCode) {
   }
 
   public Integer getOuterId() {
-    return outerId;
+    return this.outerId;
   }
 
   public void setOuterId(Integer outerId) {
@@ -530,7 +555,7 @@ public void setOuterId(Integer outerId) {
   }
 
   public WxMpXmlMessage.ScanCodeInfo getScanCodeInfo() {
-    return scanCodeInfo;
+    return this.scanCodeInfo;
   }
 
   public void setScanCodeInfo(WxMpXmlMessage.ScanCodeInfo scanCodeInfo) {
@@ -538,7 +563,7 @@ public void setScanCodeInfo(WxMpXmlMessage.ScanCodeInfo scanCodeInfo) {
   }
 
   public WxMpXmlMessage.SendPicsInfo getSendPicsInfo() {
-    return sendPicsInfo;
+    return this.sendPicsInfo;
   }
 
   public void setSendPicsInfo(WxMpXmlMessage.SendPicsInfo sendPicsInfo) {
@@ -546,22 +571,51 @@ public void setSendPicsInfo(WxMpXmlMessage.SendPicsInfo sendPicsInfo) {
   }
 
   public WxMpXmlMessage.SendLocationInfo getSendLocationInfo() {
-    return sendLocationInfo;
+    return this.sendLocationInfo;
   }
 
-  public void setSendLocationInfo(WxMpXmlMessage.SendLocationInfo sendLocationInfo) {
+  public void setSendLocationInfo(
+      WxMpXmlMessage.SendLocationInfo sendLocationInfo) {
     this.sendLocationInfo = sendLocationInfo;
   }
 
+  public String getKfAccount() {
+    return this.kfAccount;
+  }
+
+  public void setKfAccount(String kfAccount) {
+    this.kfAccount = kfAccount;
+  }
+
+  public String getToKfAccount() {
+    return this.toKfAccount;
+  }
+
+  public void setToKfAccount(String toKfAccount) {
+    this.toKfAccount = toKfAccount;
+  }
+
+  public String getFromKfAccount() {
+    return this.fromKfAccount;
+  }
+
+  public void setFromKfAccount(String fromKfAccount) {
+    this.fromKfAccount = fromKfAccount;
+  }
+
   @XStreamAlias("ScanCodeInfo")
   public static class ScanCodeInfo {
+    @Override
+    public String toString() {
+      return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
+    }
 
     @XStreamAlias("ScanType")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String scanType;
 
     @XStreamAlias("ScanResult")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String scanResult;
 
     /**
@@ -570,7 +624,7 @@ public static class ScanCodeInfo {
      */
     public String getScanType() {
 
-      return scanType;
+      return this.scanType;
     }
 
     public void setScanType(String scanType) {
@@ -582,7 +636,7 @@ public void setScanType(String scanType) {
      * @return
      */
     public String getScanResult() {
-      return scanResult;
+      return this.scanResult;
     }
 
     public void setScanResult(String scanResult) {
@@ -593,15 +647,19 @@ public void setScanResult(String scanResult) {
 
   @XStreamAlias("SendPicsInfo")
   public static class SendPicsInfo {
+    @Override
+    public String toString() {
+      return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
+    }
 
     @XStreamAlias("Count")
     private Long count;
 
     @XStreamAlias("PicList")
-    protected final List picList = new ArrayList();
+    protected final List picList = new ArrayList<>();
 
     public Long getCount() {
-      return count;
+      return this.count;
     }
 
     public void setCount(Long count) {
@@ -609,18 +667,23 @@ public void setCount(Long count) {
     }
 
     public List getPicList() {
-      return picList;
+      return this.picList;
     }
 
     @XStreamAlias("item")
     public static class Item {
+      @Override
+      public String toString() {
+        return ToStringBuilder.reflectionToString(this,
+            ToStringStyle.JSON_STYLE);
+      }
 
       @XStreamAlias("PicMd5Sum")
-      @XStreamConverter(value=XStreamCDataConverter.class)
+      @XStreamConverter(value = XStreamCDataConverter.class)
       private String picMd5Sum;
 
       public String getPicMd5Sum() {
-        return picMd5Sum;
+        return this.picMd5Sum;
       }
 
       public void setPicMd5Sum(String picMd5Sum) {
@@ -633,27 +696,32 @@ public void setPicMd5Sum(String picMd5Sum) {
   public static class SendLocationInfo {
 
     @XStreamAlias("Location_X")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String locationX;
 
     @XStreamAlias("Location_Y")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String locationY;
 
     @XStreamAlias("Scale")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String scale;
 
     @XStreamAlias("Label")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String label;
 
     @XStreamAlias("Poiname")
-    @XStreamConverter(value=XStreamCDataConverter.class)
+    @XStreamConverter(value = XStreamCDataConverter.class)
     private String poiname;
 
+    @Override
+    public String toString() {
+      return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
+    }
+
     public String getLocationX() {
-      return locationX;
+      return this.locationX;
     }
 
     public void setLocationX(String locationX) {
@@ -661,7 +729,7 @@ public void setLocationX(String locationX) {
     }
 
     public String getLocationY() {
-      return locationY;
+      return this.locationY;
     }
 
     public void setLocationY(String locationY) {
@@ -669,7 +737,7 @@ public void setLocationY(String locationY) {
     }
 
     public String getScale() {
-      return scale;
+      return this.scale;
     }
 
     public void setScale(String scale) {
@@ -677,7 +745,7 @@ public void setScale(String scale) {
     }
 
     public String getLabel() {
-      return label;
+      return this.label;
     }
 
     public void setLabel(String label) {
@@ -685,7 +753,7 @@ public void setLabel(String label) {
     }
 
     public String getPoiname() {
-      return poiname;
+      return this.poiname;
     }
 
     public void setPoiname(String poiname) {
@@ -695,44 +763,6 @@ public void setPoiname(String poiname) {
 
   @Override
   public String toString() {
-    return "WxMpXmlMessage{" +
-        "toUserName='" + toUserName + '\'' +
-        ", fromUserName='" + fromUserName + '\'' +
-        ", createTime=" + createTime +
-        ", msgType='" + msgType + '\'' +
-        ", content='" + content + '\'' +
-        ", msgId=" + msgId +
-        ", picUrl='" + picUrl + '\'' +
-        ", mediaId='" + mediaId + '\'' +
-        ", format='" + format + '\'' +
-        ", thumbMediaId='" + thumbMediaId + '\'' +
-        ", locationX=" + locationX +
-        ", locationY=" + locationY +
-        ", scale=" + scale +
-        ", label='" + label + '\'' +
-        ", title='" + title + '\'' +
-        ", description='" + description + '\'' +
-        ", url='" + url + '\'' +
-        ", event='" + event + '\'' +
-        ", eventKey='" + eventKey + '\'' +
-        ", ticket='" + ticket + '\'' +
-        ", latitude=" + latitude +
-        ", longitude=" + longitude +
-        ", precision=" + precision +
-        ", recognition='" + recognition + '\'' +
-        ", status='" + status + '\'' +
-        ", totalCount=" + totalCount +
-        ", filterCount=" + filterCount +
-        ", sentCount=" + sentCount +
-        ", errorCount=" + errorCount +
-        ", cardId='" + cardId + '\'' +
-        ", isGiveByFriend=" + isGiveByFriend +
-        ", userCardCode='" + userCardCode + '\'' +
-        ", oldUserCardCode='" + oldUserCardCode + '\'' +
-        ", outerId=" + outerId +
-        ", scanCodeInfo=" + scanCodeInfo +
-        ", sendPicsInfo=" + sendPicsInfo +
-        ", sendLocationInfo=" + sendLocationInfo +
-        '}';
+    return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
   }
 }

From 06a3ed17d0469161c7cd476919e8429a78fca6cf Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 12:33:50 +0800
Subject: [PATCH 19/54] =?UTF-8?q?demo=E4=B8=AD=E5=A2=9E=E5=8A=A0=E5=AF=B9?=
 =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E4=BC=9A=E8=AF=9D=E7=AE=A1=E7=90=86=E7=9A=84?=
 =?UTF-8?q?=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../demo/spring/handler/KfSessionHandler.java | 36 +++++++++++++++++++
 .../demo/spring/handler/LogHandler.java       |  2 +-
 .../demo/spring/handler/MsgHandler.java       |  4 +--
 .../demo/spring/service/BaseWxService.java    | 21 +++++++++--
 4 files changed, 57 insertions(+), 6 deletions(-)
 create mode 100644 weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/KfSessionHandler.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/KfSessionHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/KfSessionHandler.java
new file mode 100644
index 0000000000..dac1be8057
--- /dev/null
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/KfSessionHandler.java
@@ -0,0 +1,36 @@
+package com.github.binarywang.demo.spring.handler;
+
+import java.util.Map;
+
+import org.springframework.stereotype.Component;
+
+import com.github.binarywang.demo.spring.config.WxConfig;
+
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+
+/**
+ * 
+ * @author Binary Wang
+ *
+ */
+@Component
+public class KfSessionHandler extends AbstractHandler{
+
+  @Override
+  public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
+      Map context, WxMpService wxMpService,
+      WxSessionManager sessionManager) throws WxErrorException {
+    //TODO 对会话做处理
+    return null;
+  }
+
+  @Override
+  protected WxConfig getWxConfig() {
+    return null;
+  }
+
+}
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
index 28aa264b6d..32890f7314 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
@@ -26,7 +26,7 @@ public class LogHandler extends AbstractHandler {
   public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
       Map context, WxMpService wxMpService,
       WxSessionManager sessionManager) {
-    this.logger.info("接收到请求消息,内容:【{}】" ,wxMessage.toString());
+    this.logger.info("接收到请求消息,内容:【{}】", wxMessage.toString());
     return null;
   }
 
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
index 5984749ce4..7519420db8 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/MsgHandler.java
@@ -31,8 +31,8 @@ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
             //TODO 可以选择将消息保存到本地
         }
 
-        //当用户输入关键词如“是”,“客服”等并且有客服在线时,把消息转发给在线客服
-        if (StringUtils.startsWithAny(wxMessage.getContent(), "是","客服")
+        //当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服
+        if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服")
             && weixinService.hasKefuOnline()) {
             return WxMpXmlOutMessage
                 .TRANSFER_CUSTOMER_SERVICE().fromUser(wxMessage.getToUserName())
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
index 29b319a975..a7d851d8f8 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
@@ -8,10 +8,11 @@
 
 import com.github.binarywang.demo.spring.config.WxConfig;
 import com.github.binarywang.demo.spring.handler.AbstractHandler;
+import com.github.binarywang.demo.spring.handler.KfSessionHandler;
+import com.github.binarywang.demo.spring.handler.LogHandler;
 import com.github.binarywang.demo.spring.handler.MenuHandler;
 import com.github.binarywang.demo.spring.handler.MsgHandler;
 import com.github.binarywang.demo.spring.handler.NullHandler;
-import com.github.binarywang.demo.spring.handler.LogHandler;
 import com.github.binarywang.demo.spring.handler.SubscribeHandler;
 import com.github.binarywang.demo.spring.handler.UnsubscribeHandler;
 
@@ -37,6 +38,9 @@ public abstract class BaseWxService extends WxMpServiceImpl {
   @Autowired
   protected NullHandler nullHandler;
 
+  @Autowired
+  protected KfSessionHandler kfSessionHandler;
+
   private WxMpMessageRouter router;
 
   protected abstract WxConfig getServerConfig();
@@ -50,7 +54,7 @@ public abstract class BaseWxService extends WxMpServiceImpl {
   protected abstract AbstractHandler getLocationHandler();
 
   protected abstract MsgHandler getMsgHandler();
-
+  
   protected abstract AbstractHandler getScanHandler();
 
   @PostConstruct
@@ -68,9 +72,19 @@ private void refreshRouter() {
 
     final WxMpMessageRouter newRouter = new WxMpMessageRouter(this);
 
-    //记录所有事件的日志
+    // 记录所有事件的日志
     newRouter.rule().handler(this.logHandler).next();
 
+    // 接收客服会话管理事件
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+        .event(WxConsts.EVT_KF_CREATE_SESSION).handler(this.kfSessionHandler).end();
+    
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+    .event(WxConsts.EVT_KF_CLOSE_SESSION).handler(this.kfSessionHandler).end();
+    
+    newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
+    .event(WxConsts.EVT_KF_SWITCH_SESSION).handler(this.kfSessionHandler).end();
+    
     // 自定义菜单事件
     newRouter.rule().async(false).msgType(WxConsts.XML_MSG_EVENT)
         .event(WxConsts.BUTTON_CLICK).handler(this.getMenuHandler()).end();
@@ -107,6 +121,7 @@ private void refreshRouter() {
     this.router = newRouter;
   }
 
+
   public WxMpXmlOutMessage route(WxMpXmlMessage message) {
     try {
       final WxMpXmlOutMessage responseMessage = this.router.route(message);

From 5d96b00a9397bfd62f0ced1759d61d94d9995fab Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 8 Jul 2016 14:44:58 +0800
Subject: [PATCH 20/54] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E7=88=B6=E7=B1=BB?=
 =?UTF-8?q?=E5=B7=B2=E5=AD=98=E5=9C=A8=E7=9A=84=E5=A4=9A=E4=BD=99=E7=9A=84?=
 =?UTF-8?q?log?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/github/binarywang/demo/spring/handler/LogHandler.java | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
index 32890f7314..87cb09966a 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
@@ -2,8 +2,6 @@
 
 import java.util.Map;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 import com.github.binarywang.demo.spring.config.WxConfig;
@@ -20,8 +18,6 @@
  */
 @Component
 public class LogHandler extends AbstractHandler {
-  private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
   @Override
   public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
       Map context, WxMpService wxMpService,

From 9ad2283d964827942b64d1811fac4512faa90972 Mon Sep 17 00:00:00 2001
From: Binary Wang 
Date: Sun, 10 Jul 2016 23:15:00 +0800
Subject: [PATCH 21/54] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=87=A0=E7=A7=8D?=
 =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=8C=89=E9=92=AE=E7=B1=BB=E5=9E=8B=E7=9A=84?=
 =?UTF-8?q?=E5=91=BD=E5=90=8D=EF=BC=8C=E4=BF=9D=E6=8C=81=E7=BB=9F=E4=B8=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../main/java/me/chanjar/weixin/common/api/WxConsts.java  | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
index c645e30f97..e1f8c8c214 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
@@ -137,13 +137,13 @@ public class WxConsts {
   /** 扫码推事件且弹出“消息接收中”提示框 */
   public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg";
   /** 弹出系统拍照发图 */
-  public static final String PIC_SYSPHOTO = "pic_sysphoto";
+  public static final String BUTTON_PIC_SYSPHOTO = "pic_sysphoto";
   /** 弹出拍照或者相册发图 */
-  public static final String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
+  public static final String BUTTON_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
   /** 弹出微信相册发图器 */
-  public static final String PIC_WEIXIN = "pic_weixin";
+  public static final String BUTTON_PIC_WEIXIN = "pic_weixin";
   /** 弹出地理位置选择器 */
-  public static final String LOCATION_SELECT = "location_select";
+  public static final String BUTTON_LOCATION_SELECT = "location_select";
 
   ///////////////////////
   // oauth2网页授权的scope

From 04b3d596ffe1aa333e45865e3893c62a16713d1a Mon Sep 17 00:00:00 2001
From: miller 
Date: Mon, 11 Jul 2016 10:45:27 +0800
Subject: [PATCH 22/54] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8F=9C=E5=8D=95?=
 =?UTF-8?q?=E6=8C=89=E9=92=AE=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/main/java/me/chanjar/weixin/common/api/WxConsts.java  | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
index e1f8c8c214..aac9d4e9b2 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
@@ -144,6 +144,10 @@ public class WxConsts {
   public static final String BUTTON_PIC_WEIXIN = "pic_weixin";
   /** 弹出地理位置选择器 */
   public static final String BUTTON_LOCATION_SELECT = "location_select";
+  /** 下发消息(除文本消息) */
+  public static final String BUTTON_MEDIA_ID = "media_id";
+  /** 跳转图文消息URL */
+  public static final String BUTTON_VIEW_LIMITED = "view_limited";
 
   ///////////////////////
   // oauth2网页授权的scope

From 2923512a838a4d62fa560b6c90527141cb18a09d Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Mon, 11 Jul 2016 18:00:41 +0800
Subject: [PATCH 23/54] =?UTF-8?q?=E6=8F=90=E5=8F=96pom=E7=89=88=E6=9C=AC?=
 =?UTF-8?q?=E5=8F=B7=E4=B8=BA=E9=85=8D=E7=BD=AE=E9=A1=B9=EF=BC=8C=E5=B9=B6?=
 =?UTF-8?q?=E6=8F=90=E5=8D=87=E5=85=B6=E7=89=88=E6=9C=AC=E5=8F=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9c8bd39ea8..f3bf20a758 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,8 @@
     2.7.5
     2.7
     3.4
+    2.5
+    1.10
     9.3.0.M0
     9.3.10.v20160621
   
@@ -91,12 +93,12 @@
     
       commons-codec
       commons-codec
-      1.9
+      ${commons-codec.version}
     
     
       commons-io
       commons-io
-      2.4
+      ${commons-io.version}
     
     
       org.apache.commons

From 065156e81befd33c2b8ee2fc06283748746c7d62 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Mon, 11 Jul 2016 18:07:05 +0800
Subject: [PATCH 24/54] =?UTF-8?q?=E6=8D=A2=E7=94=A8jdk7=E8=87=AA=E5=B8=A6c?=
 =?UTF-8?q?harset=E5=B8=B8=E9=87=8F=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index 8841696de0..e79ded196c 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -51,6 +51,7 @@
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.security.NoSuchAlgorithmException;
 import java.util.*;
 import java.util.Map.Entry;
@@ -526,7 +527,7 @@ public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErr
     String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
     try {
       String resultUrl = String.format(url, 
-          URLEncoder.encode(ticket, Charsets.UTF_8.name()));
+          URLEncoder.encode(ticket, StandardCharsets.UTF_8.name()));
       if(needShortUrl){
         return this.shortUrl(resultUrl);
       }

From 0c2768dfe7831aaba755d32620a44afa8776654a Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Tue, 12 Jul 2016 09:09:46 +0800
Subject: [PATCH 25/54] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=A4=9A=E5=AE=A2?=
 =?UTF-8?q?=E6=9C=8D=E4=BC=9A=E8=AF=9D=E6=8E=A7=E5=88=B6=E7=9A=84=E6=8E=A5?=
 =?UTF-8?q?=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../demo/spring/service/BaseWxService.java    |   2 +-
 .../weixin/mp/api/WxMpKefuService.java        |  90 ++++++++++---
 .../weixin/mp/api/WxMpServiceImpl.java        | 121 +++++++++++++-----
 .../mp/api/impl/WxMpKefuServiceImpl.java      |  90 +++++++++++--
 .../request/WxMpKfAccountRequest.java         |   2 +-
 .../kefu/request/WxMpKfSessionRequest.java    |  66 ++++++++++
 .../result/WxMpKfInfo.java                    |  17 +--
 .../result/WxMpKfList.java                    |   5 +-
 .../result/WxMpKfOnlineList.java              |   5 +-
 .../mp/bean/kefu/result/WxMpKfSession.java    |  61 +++++++++
 .../kefu/result/WxMpKfSessionGetResult.java   |  53 ++++++++
 .../bean/kefu/result/WxMpKfSessionList.java   |  41 ++++++
 .../result/WxMpKfSessionWaitCaseList.java     |  48 +++++++
 .../weixin/mp/api/impl/WxMpKefuImplTest.java  |  78 +++++++++--
 .../mp/bean/result/kefu/WxMpKfListTest.java   |   2 +-
 .../result/kefu/WxMpKfOnlineListTest.java     |   2 +-
 16 files changed, 592 insertions(+), 91 deletions(-)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/{customerservice => kefu}/request/WxMpKfAccountRequest.java (98%)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/{customerservice => kefu}/result/WxMpKfInfo.java (92%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/{customerservice => kefu}/result/WxMpKfList.java (78%)
 rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/{customerservice => kefu}/result/WxMpKfOnlineList.java (79%)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
index a7d851d8f8..133c7445bd 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java
@@ -22,7 +22,7 @@
 import me.chanjar.weixin.mp.api.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
 import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
-import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
 
 /**
  * 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
index ec9b7af36b..37799d13a5 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
@@ -3,9 +3,12 @@
 import java.io.File;
 
 import me.chanjar.weixin.common.exception.WxErrorException;
-import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest;
-import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList;
-import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList;
+import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList;
+import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList;
 
 /**
  * 客服接口 ,
@@ -15,59 +18,112 @@
  * @author Binary Wang
  *
  */
-public interface WxMpKefuService {  
+public interface WxMpKefuService {
+
+  //*******************客服管理接口***********************//
   /**
    * 
    * 获取客服基本信息
    * 详情请见:客服管理
-   * https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN
+   * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN
    * 
*/ WxMpKfList kfList() throws WxErrorException; - + /** *
    * 获取在线客服接待信息
    * 详情请见:客服管理
-   * https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN
+   * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN
    * 
*/ WxMpKfOnlineList kfOnlineList() throws WxErrorException; - + /** *
    * 添加客服账号
    * 详情请见:客服管理
-   * https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN
+   * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN
    * 
*/ boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException; - + /** *
    * 设置客服信息(更新)
    * 详情请见:客服管理
-   * https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN
+   * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN
    * 
*/ boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException; - + /** *
    * 上传客服头像
    * 详情请见:客服管理
-   * http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
+   * 接口url格式:http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
    * 
*/ - - boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException; - + boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) + throws WxErrorException; + /** *
    * 删除客服账号
    * 详情请见:客服管理
-   * https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
+   * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
    * 
*/ boolean kfAccountDel(String kfAccount) throws WxErrorException; + + //*******************多客服会话控制接口***********************// + /** + *
+   * 创建会话
+   * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
+   * 详情请见:多客服会话控制接口
+   * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN
+   * 
+ */ + boolean kfSessionCreate(String openid, String kfAccount, String text) throws WxErrorException; + + /** + *
+   * 关闭会话
+   * 开发者可以使用本接口,关闭一个会话。
+   * 详情请见:多客服会话控制接口
+   * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN
+   * 
+ */ + boolean kfSessionClose(String openid, String kfAccount, String text) throws WxErrorException; + + /** + *
+   * 获取客户的会话状态
+   * 开发者可以通过本接口获取客户当前的会话状态。
+   * 详情请见:多客服会话控制接口
+   * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID
+   * 
+ */ + WxMpKfSessionGetResult kfSessionGet(String openid) throws WxErrorException; + + /** + *
+   * 获取客服的会话列表
+   * 开发者可以通过本接口获取某个客服正在接待的会话列表。
+   * 详情请见:多客服会话控制接口
+   * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsessionlist?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
+   * 
+ */ + WxMpKfSessionList kfSessionList(String kfAccount) throws WxErrorException; + + /** + *
+   * 获取未接入会话列表
+   * 开发者可以通过本接口获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。
+   * 详情请见:多客服会话控制接口
+   * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getwaitcase?access_token=ACCESS_TOKEN
+   * 
+ */ + WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index e79ded196c..6ea190e480 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -1,10 +1,48 @@ package me.chanjar.weixin.mp.api; -import com.google.gson.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.UUID; + +import org.apache.http.Consts; +import org.apache.http.HttpHost; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.MessageFormatter; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.internal.Streams; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.thoughtworks.xstream.XStream; + import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.WxCardApiSignature; @@ -19,43 +57,62 @@ import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.crypto.WxCryptUtil; import me.chanjar.weixin.common.util.fs.FileUtils; -import me.chanjar.weixin.common.util.http.*; +import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; +import me.chanjar.weixin.common.util.http.DefaultApacheHttpHttpClientBuilder; +import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; +import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; +import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.http.URIUtil; +import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl; -import me.chanjar.weixin.mp.bean.*; -import me.chanjar.weixin.mp.bean.result.*; -import me.chanjar.weixin.mp.util.http.*; +import me.chanjar.weixin.mp.bean.WxMpCustomMessage; +import me.chanjar.weixin.mp.bean.WxMpGroup; +import me.chanjar.weixin.mp.bean.WxMpIndustry; +import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; +import me.chanjar.weixin.mp.bean.WxMpMassNews; +import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; +import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; +import me.chanjar.weixin.mp.bean.WxMpMassVideo; +import me.chanjar.weixin.mp.bean.WxMpMaterial; +import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; +import me.chanjar.weixin.mp.bean.WxMpMaterialNews; +import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; +import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; +import me.chanjar.weixin.mp.bean.result.WxMediaImgUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpCardResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialFileBatchGetResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialNewsBatchGetResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult; +import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpPayCallback; +import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult; +import me.chanjar.weixin.mp.bean.result.WxMpPayResult; +import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; +import me.chanjar.weixin.mp.bean.result.WxRedpackResult; +import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor; +import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.MaterialVideoInfoRequestExecutor; +import me.chanjar.weixin.mp.util.http.MaterialVoiceAndImageDownloadRequestExecutor; +import me.chanjar.weixin.mp.util.http.MediaImgUploadRequestExecutor; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; -import org.apache.commons.io.Charsets; -import org.apache.http.Consts; -import org.apache.http.HttpHost; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.MessageFormatter; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.Map.Entry; - public class WxMpServiceImpl implements WxMpService { protected final Logger log = LoggerFactory.getLogger(WxMpServiceImpl.class); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index 91afb73193..19fdd50887 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -8,9 +8,13 @@ import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import me.chanjar.weixin.mp.api.WxMpKefuService; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * @@ -27,45 +31,103 @@ public WxMpKefuServiceImpl(WxMpService wxMpService) { @Override public WxMpKfList kfList() throws WxErrorException { String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"; - String responseContent = this.wxMpService.execute( - new SimpleGetRequestExecutor(), url, null); + String responseContent = this.wxMpService + .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfList.fromJson(responseContent); } @Override public WxMpKfOnlineList kfOnlineList() throws WxErrorException { String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"; - String responseContent = this.wxMpService.execute( - new SimpleGetRequestExecutor(), url, null); + String responseContent = this.wxMpService + .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfOnlineList.fromJson(responseContent); } @Override - public boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException { + public boolean kfAccountAdd(WxMpKfAccountRequest request) + throws WxErrorException { String url = "https://api.weixin.qq.com/customservice/kfaccount/add"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); + this.wxMpService.execute(new SimplePostRequestExecutor(), url, + request.toJson()); return true; } @Override - public boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException { + public boolean kfAccountUpdate(WxMpKfAccountRequest request) + throws WxErrorException { String url = "https://api.weixin.qq.com/customservice/kfaccount/update"; - this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); + this.wxMpService.execute(new SimplePostRequestExecutor(), url, + request.toJson()); return true; } @Override - public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?kf_account=" + kfAccount ; + public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) + throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?kf_account=" + + kfAccount; this.wxMpService.execute(new MediaUploadRequestExecutor(), url, imgFile); return true; } @Override public boolean kfAccountDel(String kfAccount) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/del?kf_account=" + kfAccount; + String url = "https://api.weixin.qq.com/customservice/kfaccount/del?kf_account=" + + kfAccount; this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); return true; } + @Override + public boolean kfSessionCreate(String openid, String kfAccount, String text) + throws WxErrorException { + WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid, + text); + String url = "https://api.weixin.qq.com/customservice/kfsession/create"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, + request.toJson()); + return true; + } + + @Override + public boolean kfSessionClose(String openid, String kfAccount, String text) + throws WxErrorException { + WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid, + text); + String url = "https://api.weixin.qq.com/customservice/kfsession/close"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, + request.toJson()); + return true; + } + + @Override + public WxMpKfSessionGetResult kfSessionGet(String openid) + throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfsession/getsession?openid=" + + openid; + String responseContent = this.wxMpService + .execute(new SimpleGetRequestExecutor(), url, null); + return WxMpKfSessionGetResult.fromJson(responseContent); + } + + @Override + public WxMpKfSessionList kfSessionList(String kfAccount) + throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfsession/getsessionlist?kf_account=" + + kfAccount; + String responseContent = this.wxMpService + .execute(new SimpleGetRequestExecutor(), url, null); + return WxMpKfSessionList.fromJson(responseContent); + } + + @Override + public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() + throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfsession/getwaitcase"; + String responseContent = this.wxMpService + .execute(new SimpleGetRequestExecutor(), url, null); + return WxMpKfSessionWaitCaseList.fromJson(responseContent); + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java similarity index 98% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java index a5d301dad1..fb5ac41b14 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/request/WxMpKfAccountRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.mp.bean.customerservice.request; +package me.chanjar.weixin.mp.bean.kefu.request; import java.io.Serializable; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java new file mode 100644 index 0000000000..aaf9e98c87 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.mp.bean.kefu.request; + +import java.io.Serializable; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +public class WxMpKfSessionRequest implements Serializable { + private static final long serialVersionUID = -5451863610674856927L; + + /** + * kf_account 完整客服账号,格式为:账号前缀@公众号微信号 + */ + @SerializedName("kf_account") + private String kfAccount; + + /** + * openid 客户openid + */ + @SerializedName("openid") + private String openid; + + /** + * text 附加信息,文本会展示在客服人员的多客服客户端 + * 目前看起来无用,主要是老版的多客服客户端使用 + */ + @SerializedName("text") + @Deprecated + private String text; + + public WxMpKfSessionRequest(String kfAccount, String openid, String text) { + this.kfAccount = kfAccount; + this.openid = openid; + this.text = text; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public String toJson() { + return WxMpGsonBuilder.INSTANCE.create().toJson(this); + } + + public String getKfAccount() { + return this.kfAccount; + } + + public void setKfAccount(String kfAccount) { + this.kfAccount = kfAccount; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java similarity index 92% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java index 95b3a96f93..39e27f2278 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java @@ -1,8 +1,9 @@ -package me.chanjar.weixin.mp.bean.customerservice.result; +package me.chanjar.weixin.mp.bean.kefu.result; import java.io.Serializable; import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -20,38 +21,38 @@ public class WxMpKfInfo implements Serializable { */ @SerializedName("kf_account") private String account; - + /** * kf_headimgurl 客服头像地址 */ @SerializedName("kf_headimgurl") private String headImgUrl; - + /** * kf_id 客服工号 */ @SerializedName("kf_id") private String id; - + /** * kf_nick 客服昵称 */ @SerializedName("kf_nick") private String nick; - + /** * status 客服在线状态 1:pc在线,2:手机在线。若pc和手机同时在线则为 1+2=3 */ @SerializedName("status") private Integer status; - + /** * auto_accept 客服设置的最大自动接入数 */ @Expose @SerializedName("auto_accept") private Integer autoAccept; - + /** * accepted_case 客服当前正在接待的会话数 * @return @@ -118,6 +119,6 @@ public void setNick(String nick) { @Override public String toString() { - return ToStringBuilder.reflectionToString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java similarity index 78% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java index 335204fb80..062ff9ac9b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java @@ -1,8 +1,9 @@ -package me.chanjar.weixin.mp.bean.customerservice.result; +package me.chanjar.weixin.mp.bean.kefu.result; import java.util.List; import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import com.google.gson.annotations.SerializedName; @@ -18,7 +19,7 @@ public class WxMpKfList { @Override public String toString() { - return ToStringBuilder.reflectionToString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } public List getKfList() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java similarity index 79% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java index 949d88490a..b4a418f671 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/customerservice/result/WxMpKfOnlineList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java @@ -1,8 +1,9 @@ -package me.chanjar.weixin.mp.bean.customerservice.result; +package me.chanjar.weixin.mp.bean.kefu.result; import java.util.List; import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import com.google.gson.annotations.SerializedName; @@ -18,7 +19,7 @@ public class WxMpKfOnlineList { @Override public String toString() { - return ToStringBuilder.reflectionToString(this); + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } public List getKfOnlineList() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java new file mode 100644 index 0000000000..9cc3d50f42 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java @@ -0,0 +1,61 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKfSession { + /** + * kf_account 正在接待的客服,为空表示没有人在接待 + */ + @SerializedName("kf_account") + private String kfAccount; + + /** + * createtime 会话接入的时间 或者 来访时间,UNIX时间戳 + */ + @SerializedName("createtime") + private long createTime; + + /** + * openid 客户openid + */ + @SerializedName("openid") + private String openid; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public String getKfAccount() { + return this.kfAccount; + } + + public void setKfAccount(String kfAccount) { + this.kfAccount = kfAccount; + } + + public long getCreateTime() { + return this.createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getOpenid() { + return this.openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java new file mode 100644 index 0000000000..22a6cf24ac --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java @@ -0,0 +1,53 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKfSessionGetResult { + /** + * kf_account 正在接待的客服,为空表示没有人在接待 + */ + @SerializedName("kf_account") + private String kfAccount; + + /** + * createtime 会话接入的时间 ,UNIX时间戳 + */ + @SerializedName("createtime") + private long createTime; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public static WxMpKfSessionGetResult fromJson(String json) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpKfSessionGetResult.class); + } + + public String getKfAccount() { + return this.kfAccount; + } + + public void setKfAccount(String kfAccount) { + this.kfAccount = kfAccount; + } + + public long getCreateTime() { + return this.createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java new file mode 100644 index 0000000000..dea7e2434e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKfSessionList { + /** + * 会话列表 + */ + @SerializedName("sessionlist") + private List kfSessionList; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public static WxMpKfSessionList fromJson(String json) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(json, + WxMpKfSessionList.class); + } + + public List getKfSessionList() { + return this.kfSessionList; + } + + public void setKfSessionList(List kfSessionList) { + this.kfSessionList = kfSessionList; + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java new file mode 100644 index 0000000000..dc2ab06b4e --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java @@ -0,0 +1,48 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import java.util.List; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import com.google.gson.annotations.SerializedName; + +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +/** + * + * @author Binary Wang + * + */ +public class WxMpKfSessionWaitCaseList { + /** + * count 未接入会话数量 + */ + @SerializedName("count") + private Long count; + + /** + * waitcaselist 未接入会话列表,最多返回100条数据 + */ + @SerializedName("waitcaselist") + private List kfSessionWaitCaseList; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public static WxMpKfSessionWaitCaseList fromJson(String json) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(json, + WxMpKfSessionWaitCaseList.class); + } + + public List getKfSessionWaitCaseList() { + return this.kfSessionWaitCaseList; + } + + public void setKfSessionWaitCaseList(List kfSessionWaitCaseList) { + this.kfSessionWaitCaseList = kfSessionWaitCaseList; + } + +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java index f2045437ff..120a3c036d 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java @@ -1,5 +1,8 @@ package me.chanjar.weixin.mp.api.impl; +import java.io.File; + +import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; @@ -9,15 +12,14 @@ import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; -import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpServiceImpl; -import me.chanjar.weixin.mp.bean.customerservice.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; - -import java.io.File; - -import org.testng.Assert; +import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * 测试客服相关接口 @@ -34,14 +36,18 @@ public class WxMpKefuImplTest { public void testKfList() throws WxErrorException { WxMpKfList kfList = this.wxService.getKefuService().kfList(); Assert.assertNotNull(kfList); - System.err.println(kfList); + for (WxMpKfInfo k : kfList.getKfList()) { + System.err.println(k); + } } public void testKfOnlineList() throws WxErrorException { WxMpKfOnlineList kfOnlineList = this.wxService.getKefuService() .kfOnlineList(); Assert.assertNotNull(kfOnlineList); - System.err.println(kfOnlineList); + for (WxMpKfInfo k : kfOnlineList.getKfOnlineList()) { + System.err.println(k); + } } @DataProvider @@ -76,11 +82,59 @@ public void testKfAccountUploadHeadImg(String kfAccount) Assert.assertTrue(result); } - @Test(dependsOnMethods = { - "testKfAccountUploadHeadImg" }, dataProvider = "getKfAccount") + @Test(dataProvider = "getKfAccount") public void testKfAccountDel(String kfAccount) throws WxErrorException { boolean result = this.wxService.getKefuService().kfAccountDel(kfAccount); Assert.assertTrue(result); } + @DataProvider + public Object[][] getKfAccountAndOpenid() { + WxXmlMpInMemoryConfigStorage configStorage = (WxXmlMpInMemoryConfigStorage) this.wxService + .getWxMpConfigStorage(); + return new Object[][] { + { configStorage.getKfAccount(), configStorage.getOpenId() } }; + } + + @Test(dataProvider = "getKfAccountAndOpenid") + public void testKfSessionCreate(String kfAccount, String openid) + throws WxErrorException { + boolean result = this.wxService.getKefuService().kfSessionCreate(openid, + kfAccount, "welcome"); + Assert.assertTrue(result); + } + + @Test(dataProvider = "getKfAccountAndOpenid") + public void testKfSessionClose(String kfAccount, String openid) + throws WxErrorException { + boolean result = this.wxService.getKefuService().kfSessionClose(openid, + kfAccount, "bye bye"); + Assert.assertTrue(result); + } + + @Test(dataProvider = "getKfAccountAndOpenid") + public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount, + String openid) throws WxErrorException { + WxMpKfSessionGetResult result = this.wxService.getKefuService() + .kfSessionGet(openid); + Assert.assertNotNull(result); + System.err.println(result); + } + + @Test(dataProvider = "getKfAccount") + public void testKfSessionList(String kfAccount) throws WxErrorException { + WxMpKfSessionList result = this.wxService.getKefuService() + .kfSessionList(kfAccount); + Assert.assertNotNull(result); + System.err.println(result); + } + + @Test + public void testKfSessionGetWaitCase() throws WxErrorException { + WxMpKfSessionWaitCaseList result = this.wxService.getKefuService() + .kfSessionGetWaitCase(); + Assert.assertNotNull(result); + System.err.println(result); + } + } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java index 0d3841ef52..cc782250ff 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfListTest.java @@ -4,7 +4,7 @@ import org.testng.Assert; import org.testng.annotations.Test; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; @Test public class WxMpKfListTest { diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java index 052f8e25d3..ab04e8e00c 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/result/kefu/WxMpKfOnlineListTest.java @@ -4,7 +4,7 @@ import org.testng.Assert; import org.testng.annotations.Test; -import me.chanjar.weixin.mp.bean.customerservice.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; @Test public class WxMpKfOnlineListTest { From 5d957582e309022ab8f6b46ec1851fab27d63cf7 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 09:33:08 +0800 Subject: [PATCH 26/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9Bwarni?= =?UTF-8?q?ng=EF=BC=8C=E5=B0=A4=E5=85=B6=E6=98=AF=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=89=93=E5=8C=85warning=E7=9A=84=E4=B8=8D=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E6=88=96=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84javadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cp/util/xml/XStreamTransformer.java | 7 -- .../weixin/mp/api/WxMpMessageMatcher.java | 1 - .../weixin/mp/api/WxMpMessageRouter.java | 1 - .../weixin/mp/api/WxMpMessageRouterRule.java | 74 +++-------- .../me/chanjar/weixin/mp/api/WxMpService.java | 119 +----------------- .../weixin/mp/bean/WxMpCustomMessage.java | 5 - .../mp/bean/WxMpMassOpenIdsMessage.java | 12 +- .../weixin/mp/bean/WxMpXmlMessage.java | 4 - .../weixin/mp/bean/WxMpXmlOutMessage.java | 8 -- .../mp/bean/kefu/result/WxMpKfInfo.java | 1 - 10 files changed, 22 insertions(+), 210 deletions(-) diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java index 12dd89921e..9bcd5edacb 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/util/xml/XStreamTransformer.java @@ -14,10 +14,6 @@ public class XStreamTransformer { /** * xml -> pojo - * - * @param clazz - * @param xml - * @return */ @SuppressWarnings("unchecked") public static T fromXml(Class clazz, String xml) { @@ -43,9 +39,6 @@ public static void register(Class clz,XStream xStream){ /** * pojo -> xml * - * @param clazz - * @param object - * @return */ public static String toXml(Class clazz, T object) { return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java index 3d913f7819..c4e3c456e3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java @@ -10,7 +10,6 @@ public interface WxMpMessageMatcher { /** * 消息是否匹配某种模式 * @param message - * @return */ public boolean match(WxMpXmlMessage message); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java index 4cc7df21dd..73d0cabe7f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java @@ -124,7 +124,6 @@ List getRules() { /** * 开始一个新的Route规则 - * @return */ public WxMpMessageRouterRule rule() { return new WxMpMessageRouterRule(this); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java index 3113a19ced..ae2b161658 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java @@ -34,9 +34,9 @@ public class WxMpMessageRouterRule { private boolean reEnter = false; - private List handlers = new ArrayList(); + private List handlers = new ArrayList<>(); - private List interceptors = new ArrayList(); + private List interceptors = new ArrayList<>(); public WxMpMessageRouterRule(WxMpMessageRouter routerBuilder) { this.routerBuilder = routerBuilder; @@ -44,9 +44,6 @@ public WxMpMessageRouterRule(WxMpMessageRouter routerBuilder) { /** * 设置是否异步执行,默认是true - * - * @param async - * @return */ public WxMpMessageRouterRule async(boolean async) { this.async = async; @@ -55,9 +52,6 @@ public WxMpMessageRouterRule async(boolean async) { /** * 如果msgType等于某值 - * - * @param msgType - * @return */ public WxMpMessageRouterRule msgType(String msgType) { this.msgType = msgType; @@ -66,9 +60,6 @@ public WxMpMessageRouterRule msgType(String msgType) { /** * 如果event等于某值 - * - * @param event - * @return */ public WxMpMessageRouterRule event(String event) { this.event = event; @@ -77,9 +68,6 @@ public WxMpMessageRouterRule event(String event) { /** * 如果eventKey等于某值 - * - * @param eventKey - * @return */ public WxMpMessageRouterRule eventKey(String eventKey) { this.eventKey = eventKey; @@ -88,9 +76,6 @@ public WxMpMessageRouterRule eventKey(String eventKey) { /** * 如果content等于某值 - * - * @param content - * @return */ public WxMpMessageRouterRule content(String content) { this.content = content; @@ -99,9 +84,6 @@ public WxMpMessageRouterRule content(String content) { /** * 如果content匹配该正则表达式 - * - * @param regex - * @return */ public WxMpMessageRouterRule rContent(String regex) { this.rContent = regex; @@ -110,9 +92,6 @@ public WxMpMessageRouterRule rContent(String regex) { /** * 如果fromUser等于某值 - * - * @param fromUser - * @return */ public WxMpMessageRouterRule fromUser(String fromUser) { this.fromUser = fromUser; @@ -121,9 +100,6 @@ public WxMpMessageRouterRule fromUser(String fromUser) { /** * 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候 - * - * @param matcher - * @return */ public WxMpMessageRouterRule matcher(WxMpMessageMatcher matcher) { this.matcher = matcher; @@ -132,9 +108,6 @@ public WxMpMessageRouterRule matcher(WxMpMessageMatcher matcher) { /** * 设置微信消息拦截器 - * - * @param interceptor - * @return */ public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor) { return interceptor(interceptor, (WxMpMessageInterceptor[]) null); @@ -142,10 +115,6 @@ public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor) { /** * 设置微信消息拦截器 - * - * @param interceptor - * @param otherInterceptors - * @return */ public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor, WxMpMessageInterceptor... otherInterceptors) { this.interceptors.add(interceptor); @@ -159,9 +128,6 @@ public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor, WxM /** * 设置微信消息处理器 - * - * @param handler - * @return */ public WxMpMessageRouterRule handler(WxMpMessageHandler handler) { return handler(handler, (WxMpMessageHandler[]) null); @@ -169,10 +135,6 @@ public WxMpMessageRouterRule handler(WxMpMessageHandler handler) { /** * 设置微信消息处理器 - * - * @param handler - * @param otherHandlers - * @return */ public WxMpMessageRouterRule handler(WxMpMessageHandler handler, WxMpMessageHandler... otherHandlers) { this.handlers.add(handler); @@ -186,8 +148,6 @@ public WxMpMessageRouterRule handler(WxMpMessageHandler handler, WxMpMessageHand /** * 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则 - * - * @return */ public WxMpMessageRouter end() { this.routerBuilder.getRules().add(this); @@ -196,8 +156,6 @@ public WxMpMessageRouter end() { /** * 规则结束,但是消息还会进入其他规则 - * - * @return */ public WxMpMessageRouter next() { this.reEnter = true; @@ -207,8 +165,6 @@ public WxMpMessageRouter next() { /** * 将微信自定义的事件修正为不区分大小写, * 比如框架定义的事件常量为click,但微信传递过来的却是CLICK - * @param wxMessage - * @return */ protected boolean test(WxMpXmlMessage wxMessage) { return @@ -243,7 +199,7 @@ protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage, try { - Map context = new HashMap(); + Map context = new HashMap<>(); // 如果拦截器不通过 for (WxMpMessageInterceptor interceptor : this.interceptors) { if (!interceptor.intercept(wxMessage, context, wxMpService, sessionManager)) { @@ -266,11 +222,11 @@ protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage, } public WxMpMessageRouter getRouterBuilder() { - return routerBuilder; + return this.routerBuilder; } public boolean isAsync() { - return async; + return this.async; } public void setAsync(boolean async) { @@ -278,7 +234,7 @@ public void setAsync(boolean async) { } public String getFromUser() { - return fromUser; + return this.fromUser; } public void setFromUser(String fromUser) { @@ -286,7 +242,7 @@ public void setFromUser(String fromUser) { } public String getMsgType() { - return msgType; + return this.msgType; } public void setMsgType(String msgType) { @@ -294,7 +250,7 @@ public void setMsgType(String msgType) { } public String getEvent() { - return event; + return this.event; } public void setEvent(String event) { @@ -302,7 +258,7 @@ public void setEvent(String event) { } public String getEventKey() { - return eventKey; + return this.eventKey; } public void setEventKey(String eventKey) { @@ -310,7 +266,7 @@ public void setEventKey(String eventKey) { } public String getContent() { - return content; + return this.content; } public void setContent(String content) { @@ -318,7 +274,7 @@ public void setContent(String content) { } public String getrContent() { - return rContent; + return this.rContent; } public void setrContent(String rContent) { @@ -326,7 +282,7 @@ public void setrContent(String rContent) { } public WxMpMessageMatcher getMatcher() { - return matcher; + return this.matcher; } public void setMatcher(WxMpMessageMatcher matcher) { @@ -334,7 +290,7 @@ public void setMatcher(WxMpMessageMatcher matcher) { } public boolean isReEnter() { - return reEnter; + return this.reEnter; } public void setReEnter(boolean reEnter) { @@ -342,7 +298,7 @@ public void setReEnter(boolean reEnter) { } public List getHandlers() { - return handlers; + return this.handlers; } public void setHandlers(List handlers) { @@ -350,7 +306,7 @@ public void setHandlers(List handlers) { } public List getInterceptors() { - return interceptors; + return this.interceptors; } public void setInterceptors(List interceptors) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 634f97d23e..c9308d7cee 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -60,18 +60,12 @@ public interface WxMpService { * 验证推送过来的消息的正确性 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=验证消息真实性 *
- * @param timestamp - * @param nonce - * @param signature - * @return */ public boolean checkSignature(String timestamp, String nonce, String signature); /** * 获取access_token, 不强制刷新access_token * @see #getAccessToken(boolean) - * @return - * @throws WxErrorException */ public String getAccessToken() throws WxErrorException; @@ -87,16 +81,12 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token *
* @param forceRefresh 强制刷新 - * @return - * @throws me.chanjar.weixin.common.exception.WxErrorException */ public String getAccessToken(boolean forceRefresh) throws WxErrorException; /** * 获得jsapi_ticket,不强制刷新jsapi_ticket * @see #getJsapiTicket(boolean) - * @return - * @throws WxErrorException */ public String getJsapiTicket() throws WxErrorException; @@ -108,8 +98,6 @@ public interface WxMpService { * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 * * @param forceRefresh 强制刷新 - * @return - * @throws WxErrorException */ public String getJsapiTicket(boolean forceRefresh) throws WxErrorException; @@ -119,8 +107,6 @@ public interface WxMpService { * * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 * - * @param url url - * @return */ public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; @@ -158,8 +144,6 @@ public interface WxMpService { * * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} * @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial} - * @return - * @throws WxErrorException */ public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException; @@ -170,8 +154,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html * * @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews} - * @return - * @throws WxErrorException */ public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException; @@ -182,8 +164,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * * @param media_id 永久素材的id - * @return - * @throws WxErrorException */ public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException; @@ -194,8 +174,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * * @param media_id 永久素材的id - * @return - * @throws WxErrorException */ public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException; @@ -206,8 +184,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * * @param media_id 永久素材的id - * @return - * @throws WxErrorException */ public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException; @@ -218,8 +194,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html * * @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate} - * @return - * @throws WxErrorException */ public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException; @@ -230,8 +204,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html * * @param media_id 永久素材的id - * @return - * @throws WxErrorException */ public boolean materialDelete(String media_id) throws WxErrorException; @@ -241,8 +213,6 @@ public interface WxMpService { * * 详情请见: http://mp.weixin.qq.com/wiki/16/8cc64f8c189674b421bee3ed403993b8.html * - * @return - * @throws WxErrorException */ public WxMpMaterialCountResult materialCount() throws WxErrorException; @@ -254,8 +224,6 @@ public interface WxMpService { * * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 * @param count 返回素材的数量,取值在1到20之间 - * @return - * @throws WxErrorException */ public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException; @@ -268,8 +236,6 @@ public interface WxMpService { * @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 * @param count 返回素材的数量,取值在1到20之间 - * @return - * @throws WxErrorException */ public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException; @@ -300,8 +266,6 @@ public interface WxMpService { * 发送客服消息 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=发送客服消息 * - * @param message - * @throws WxErrorException */ public void customMessageSend(WxMpCustomMessage message) throws WxErrorException; @@ -323,8 +287,6 @@ public interface WxMpService { * 上传群发用的视频,上传后才能群发视频消息 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口 * - * @return - * @throws WxErrorException * @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassGroupMessage) * @see #massOpenIdsMessageSend(me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage) */ @@ -337,9 +299,6 @@ public interface WxMpService { * 如果发送视频消息,必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id,然后再发送 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口 * - * @param message - * @throws WxErrorException - * @return */ public WxMpMassSendResult massGroupMessageSend(WxMpMassGroupMessage message) throws WxErrorException; @@ -350,9 +309,6 @@ public interface WxMpService { * 如果发送视频消息,必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id,然后再发送 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口 * - * @param message - * @return - * @throws WxErrorException */ public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException; @@ -363,8 +319,6 @@ public interface WxMpService { * 如果要创建个性化菜单,请设置matchrule属性 * 详情请见:http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html * - * @param menu - * @throws WxErrorException */ public void menuCreate(WxMenu menu) throws WxErrorException; @@ -373,7 +327,6 @@ public interface WxMpService { * 自定义菜单删除接口 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单删除接口 * - * @throws WxErrorException */ public void menuDelete() throws WxErrorException; @@ -383,7 +336,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html * * @param menuid - * @throws WxErrorException */ public void menuDelete(String menuid) throws WxErrorException; @@ -392,8 +344,6 @@ public interface WxMpService { * 自定义菜单查询接口 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单查询接口 * - * @return - * @throws WxErrorException */ public WxMenu menuGet() throws WxErrorException; @@ -403,7 +353,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html * * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 - * @throws WxErrorException */ public WxMenu menuTryMatch(String userid) throws WxErrorException; @@ -414,7 +363,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 * * @param name 分组名字(30个字符以内) - * @throws WxErrorException */ public WxMpGroup groupCreate(String name) throws WxErrorException; @@ -424,7 +372,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 * * @return - * @throws WxErrorException */ public List groupGet() throws WxErrorException; @@ -434,7 +381,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 * * @param openid 微信用户的openid - * @throws WxErrorException */ public long userGetGroup(String openid) throws WxErrorException; @@ -446,7 +392,6 @@ public interface WxMpService { * 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误 * * @param group 要更新的group,group的id,name必须设置 - * @throws WxErrorException */ public void groupUpdate(WxMpGroup group) throws WxErrorException; @@ -459,7 +404,6 @@ public interface WxMpService { * * @param openid 用户openid * @param to_groupid 移动到的分组id - * @throws WxErrorException */ public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException; @@ -470,7 +414,6 @@ public interface WxMpService { * * @param openid 用户openid * @param remark 备注名 - * @throws WxErrorException */ public void userUpdateRemark(String openid, String remark) throws WxErrorException; @@ -481,8 +424,6 @@ public interface WxMpService { * * @param openid 用户openid * @param lang 语言,zh_CN 简体(默认),zh_TW 繁体,en 英语 - * @return - * @throws WxErrorException */ public WxMpUser userInfo(String openid, String lang) throws WxErrorException; @@ -492,8 +433,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表 * * @param next_openid 可选,第一个拉取的OPENID,null为从头开始拉取 - * @return - * @throws WxErrorException */ public WxMpUserList userList(String next_openid) throws WxErrorException; @@ -504,8 +443,6 @@ public interface WxMpService { * * @param scene_id 参数。 * @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒 - * @return - * @throws WxErrorException */ public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException; @@ -515,8 +452,6 @@ public interface WxMpService { * 详情请见: 生成带参数的二维码 * * @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000) - * @return - * @throws WxErrorException */ public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException; @@ -527,8 +462,6 @@ public interface WxMpService { * * * @param scene_str 参数。字符串类型长度现在为1到64 - * @return - * @throws WxErrorException */ public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException; @@ -538,8 +471,6 @@ public interface WxMpService { * 详情请见: 生成带参数的二维码 * * @param ticket 二维码ticket - * @return - * @throws WxErrorException */ public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException; @@ -550,8 +481,6 @@ public interface WxMpService { * * @param ticket 二维码ticket * @param needShortUrl 是否需要压缩的二维码地址 - * @return - * @throws WxErrorException */ public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException; /** @@ -560,8 +489,6 @@ public interface WxMpService { * 详情请见: 生成带参数的二维码 * * @param ticket 二维码ticket - * @return - * @throws WxErrorException */ public String qrCodePictureUrl(String ticket) throws WxErrorException; @@ -571,8 +498,6 @@ public interface WxMpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口 * * @param long_url - * @return - * @throws WxErrorException */ public String shortUrl(String long_url) throws WxErrorException; @@ -592,9 +517,6 @@ public interface WxMpService { * 语义查询接口 * 详情请见:http://mp.weixin.qq.com/wiki/index.php?title=语义理解 * - * @param semanticQuery - * @return - * @throws WxErrorException */ WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException; @@ -621,13 +543,12 @@ public interface WxMpService { * @return url */ public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state); + /** *
    * 用code换取oauth2的access token
    * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
    * 
- * @param code - * @return */ public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException; @@ -635,8 +556,6 @@ public interface WxMpService { *
    * 刷新oauth2的access token
    * 
- * @param refreshToken - * @return */ public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException; @@ -663,8 +582,6 @@ public interface WxMpService { * 获取微信服务器IP地址 * http://mp.weixin.qq.com/wiki/0/2ad4b6bfd29f30f71d39616c2a0fcedc.html * - * @return - * @throws WxErrorException */ String[] getCallbackIP() throws WxErrorException; @@ -675,8 +592,6 @@ public interface WxMpService { * * @param beginDate 最大时间跨度7天 * @param endDate endDate不能早于begingDate - * @return - * @throws WxErrorException */ List getUserSummary(Date beginDate, Date endDate) throws WxErrorException; @@ -687,26 +602,16 @@ public interface WxMpService { * * @param beginDate 最大时间跨度7天 * @param endDate endDate不能早于begingDate - * @return - * @throws WxErrorException */ List getUserCumulate(Date beginDate, Date endDate) throws WxErrorException; /** * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求 - * @param url - * @param queryParam - * @return - * @throws WxErrorException */ String get(String url, String queryParam) throws WxErrorException; /** * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求 - * @param url - * @param postData - * @return - * @throws WxErrorException */ String post(String url, String postData) throws WxErrorException; @@ -716,19 +621,11 @@ public interface WxMpService { * 比{@link #get}和{@link #post}方法更灵活,可以自己构造RequestExecutor用来处理不同的参数和不同的返回类型。 * 可以参考,{@link me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor}的实现方法 * - * @param executor - * @param uri - * @param data - * @param - * @param - * @return - * @throws WxErrorException */ public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; /** * 注入 {@link WxMpConfigStorage} 的实现 - * @param wxConfigProvider */ public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider); @@ -737,7 +634,6 @@ public interface WxMpService { * 设置当微信系统响应系统繁忙时,要等待多少 retrySleepMillis(ms) * 2^(重试次数 - 1) 再发起重试 * 默认:1000ms * - * @param retrySleepMillis */ void setRetrySleepMillis(int retrySleepMillis); @@ -746,7 +642,6 @@ public interface WxMpService { * 设置当微信系统响应系统繁忙时,最大重试次数 * 默认:5次 * - * @param maxRetryTimes */ void setMaxRetryTimes(int maxRetryTimes); @@ -760,7 +655,6 @@ public interface WxMpService { * @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP * @param ip 发起支付的客户端IP * @param notifyUrl 通知地址 - * @return * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map) instead */ @Deprecated @@ -772,7 +666,6 @@ public interface WxMpService { * * @param parameters * All required/optional parameters for weixin payment - * @return * @throws IllegalArgumentException */ WxMpPrepayIdResult getPrepayId(Map parameters); @@ -782,8 +675,6 @@ public interface WxMpService { * 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 * @param parameters * the required or optional parameters - * @return - * @throws WxErrorException */ Map getPayInfo(Map parameters) throws WxErrorException; @@ -797,8 +688,6 @@ public interface WxMpService { * @param body 商品描述 * @param ip 发起支付的客户端IP * @param notifyUrl 通知地址 - * @return - * @throws WxErrorException * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map) instead */ @Deprecated @@ -814,8 +703,6 @@ public interface WxMpService { * @param body 商品描述 * @param ip 发起支付的客户端IP * @param notifyUrl 通知地址 - * @return - * @throws WxErrorException * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map) instead */ @Deprecated @@ -833,7 +720,6 @@ public interface WxMpService { * 读取支付结果通知 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 * @param xmlData - * @return */ WxMpPayCallback getJSSDKCallbackData(String xmlData); @@ -858,7 +744,6 @@ public interface WxMpService { * * @param kvm * @param signature - * @return */ public boolean checkJSSDKCallbackDataSignature(Map kvm, String signature); @@ -882,8 +767,6 @@ public interface WxMpService { * 商户平台设置的API密钥 * * @param parameters - * @return - * @throws WxErrorException */ public WxRedpackResult sendRedpack(Map parameters) throws WxErrorException; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java index 278ac2886f..061aa2cea9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java @@ -140,7 +140,6 @@ public void setPicUrl(String picUrl) { /** * 获得文本消息builder - * @return */ public static TextBuilder TEXT() { return new TextBuilder(); @@ -148,7 +147,6 @@ public static TextBuilder TEXT() { /** * 获得图片消息builder - * @return */ public static ImageBuilder IMAGE() { return new ImageBuilder(); @@ -164,7 +162,6 @@ public static VoiceBuilder VOICE() { /** * 获得视频消息builder - * @return */ public static VideoBuilder VIDEO() { return new VideoBuilder(); @@ -172,7 +169,6 @@ public static VideoBuilder VIDEO() { /** * 获得音乐消息builder - * @return */ public static MusicBuilder MUSIC() { return new MusicBuilder(); @@ -180,7 +176,6 @@ public static MusicBuilder MUSIC() { /** * 获得图文消息builder - * @return */ public static NewsBuilder NEWS() { return new NewsBuilder(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java index 7ef2535ca3..38bd8ea7f0 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassOpenIdsMessage.java @@ -12,8 +12,9 @@ * @author chanjarster */ public class WxMpMassOpenIdsMessage implements Serializable { + private static final long serialVersionUID = -8022910911104788999L; - private List toUsers = new ArrayList(); + private List toUsers = new ArrayList<>(); private String msgType; private String content; private String mediaId; @@ -23,7 +24,7 @@ public WxMpMassOpenIdsMessage() { } public String getMsgType() { - return msgType; + return this.msgType; } /** @@ -43,7 +44,7 @@ public void setMsgType(String msgType) { } public String getContent() { - return content; + return this.content; } public void setContent(String content) { @@ -51,7 +52,7 @@ public void setContent(String content) { } public String getMediaId() { - return mediaId; + return this.mediaId; } public void setMediaId(String mediaId) { @@ -64,10 +65,9 @@ public String toJson() { /** * OpenId列表,最多支持10,000个 - * @return */ public List getToUsers() { - return toUsers; + return this.toUsers; } /** diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java index cd86fd0dd3..047961ea87 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java @@ -237,7 +237,6 @@ public void setCreateTime(Long createTime) { * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_EVENT} * * - * @return */ public String getMsgType() { return this.msgType; @@ -444,7 +443,6 @@ public static WxMpXmlMessage fromXml(InputStream is) { * @param timestamp * @param nonce * @param msgSignature - * @return */ public static WxMpXmlMessage fromEncryptedXml(String encryptedXml, WxMpConfigStorage wxMpConfigStorage, String timestamp, String nonce, @@ -620,7 +618,6 @@ public String toString() { /** * 扫描类型,一般是qrcode - * @return */ public String getScanType() { @@ -633,7 +630,6 @@ public void setScanType(String scanType) { /** * 扫描结果,即二维码对应的字符串信息 - * @return */ public String getScanResult() { return this.scanResult; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java index ba816949d8..2eb6818b30 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java @@ -68,7 +68,6 @@ public String toXml() { /** * 转换成加密的xml格式 - * @return */ public String toEncryptedXml(WxMpConfigStorage wxMpConfigStorage) { String plainXml = toXml(); @@ -78,7 +77,6 @@ public String toEncryptedXml(WxMpConfigStorage wxMpConfigStorage) { /** * 获得文本消息builder - * @return */ public static TextBuilder TEXT() { return new TextBuilder(); @@ -86,7 +84,6 @@ public static TextBuilder TEXT() { /** * 获得图片消息builder - * @return */ public static ImageBuilder IMAGE() { return new ImageBuilder(); @@ -94,7 +91,6 @@ public static ImageBuilder IMAGE() { /** * 获得语音消息builder - * @return */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); @@ -102,7 +98,6 @@ public static VoiceBuilder VOICE() { /** * 获得视频消息builder - * @return */ public static VideoBuilder VIDEO() { return new VideoBuilder(); @@ -110,7 +105,6 @@ public static VideoBuilder VIDEO() { /** * 获得音乐消息builder - * @return */ public static MusicBuilder MUSIC() { return new MusicBuilder(); @@ -118,7 +112,6 @@ public static MusicBuilder MUSIC() { /** * 获得图文消息builder - * @return */ public static NewsBuilder NEWS() { return new NewsBuilder(); @@ -126,7 +119,6 @@ public static NewsBuilder NEWS() { /** * 获得客服消息builder - * @return */ public static TransferCustomerServiceBuilder TRANSFER_CUSTOMER_SERVICE() { return new TransferCustomerServiceBuilder(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java index 39e27f2278..7e9b54251e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java @@ -55,7 +55,6 @@ public class WxMpKfInfo implements Serializable { /** * accepted_case 客服当前正在接待的会话数 - * @return */ @Expose @SerializedName("accepted_case") From 55e0653521ad9c339a6ef495b56b3d199623e0e8 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 10:02:26 +0800 Subject: [PATCH 27/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E7=9A=84warning=EF=BC=8C=E5=B0=A4=E5=85=B6=E6=98=AF=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=89=93=E5=8C=85warning=E7=9A=84=E4=B8=8D=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E6=88=96=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84javadoc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../me/chanjar/weixin/common/bean/WxMenu.java | 14 +-- .../common/session/WxSessionManager.java | 5 - .../weixin/common/util/crypto/SHA1.java | 6 - .../common/util/crypto/WxCryptUtil.java | 105 +++++++++--------- .../weixin/common/util/fs/FileUtils.java | 4 - .../util/http/ApacheHttpClientBuilder.java | 5 - .../common/util/http/RequestExecutor.java | 1 - .../weixin/cp/api/WxCpMessageMatcher.java | 2 - .../weixin/cp/api/WxCpMessageRouter.java | 1 - .../weixin/cp/api/WxCpMessageRouterRule.java | 15 --- .../me/chanjar/weixin/cp/api/WxCpService.java | 29 +---- .../weixin/cp/api/WxCpServiceImpl.java | 6 - .../chanjar/weixin/cp/bean/WxCpMessage.java | 28 ++--- .../weixin/cp/bean/WxCpXmlMessage.java | 4 - .../weixin/cp/bean/WxCpXmlOutMessage.java | 18 +-- .../me/chanjar/weixin/mp/api/WxMpService.java | 4 +- .../weixin/mp/api/WxMpServiceImpl.java | 6 - .../weixin/mp/bean/WxMpCustomMessage.java | 1 - .../mp/util/xml/XStreamTransformer.java | 8 -- 19 files changed, 79 insertions(+), 183 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxMenu.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxMenu.java index 7df05a48db..d236f62b3f 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxMenu.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/bean/WxMenu.java @@ -1,14 +1,14 @@ package me.chanjar.weixin.common.bean; -import me.chanjar.weixin.common.util.json.WxGsonBuilder; -import org.apache.commons.codec.Charsets; - import java.io.InputStream; import java.io.InputStreamReader; import java.io.Serializable; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import me.chanjar.weixin.common.util.json.WxGsonBuilder; + /** * 企业号菜单 * @author Daniel Qian @@ -45,8 +45,6 @@ public String toJson() { /** * 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化 * 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu - * @param json - * @return */ public static WxMenu fromJson(String json) { return WxGsonBuilder.create().fromJson(json, WxMenu.class); @@ -55,11 +53,9 @@ public static WxMenu fromJson(String json) { /** * 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化 * 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式,外层多套了一个menu - * @param is - * @return */ public static WxMenu fromJson(InputStream is) { - return WxGsonBuilder.create().fromJson(new InputStreamReader(is, Charsets.UTF_8), WxMenu.class); + return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class); } @Override @@ -195,7 +191,7 @@ public void setLanguage(String language) { this.language = language; } - @Override + @Override public String toString() { return "matchrule:{" + "tag_id='" + tagId + '\'' + diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java index 262d9fe4f9..9f74162eef 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/session/WxSessionManager.java @@ -4,16 +4,11 @@ public interface WxSessionManager { /** * 获取某个sessionId对应的session,如果sessionId没有对应的session,则新建一个并返回。 - * @param sessionId - * @return */ public WxSession getSession(String sessionId); /** * 获取某个sessionId对应的session,如果sessionId没有对应的session,若create为true则新建一个,否则返回null。 - * @param sessionId - * @param create - * @return */ public WxSession getSession(String sessionId, boolean create); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java index bd6ec15eeb..38a6c28db6 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java @@ -12,9 +12,6 @@ public class SHA1 { /** * 串接arr参数,生成sha1 digest - * - * @param arr - * @return */ public static String gen(String... arr) throws NoSuchAlgorithmException { Arrays.sort(arr); @@ -27,9 +24,6 @@ public static String gen(String... arr) throws NoSuchAlgorithmException { /** * 用&串接arr参数,生成sha1 digest - * - * @param arr - * @return */ public static String genWithAmple(String... arr) throws NoSuchAlgorithmException { Arrays.sort(arr); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java index a8fa9e15f7..874133349f 100755 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java @@ -35,16 +35,16 @@ public class WxCryptUtil { private static final Base64 base64 = new Base64(); private static final Charset CHARSET = Charset.forName("utf-8"); - private static final ThreadLocal builderLocal = - new ThreadLocal() { - @Override protected DocumentBuilder initialValue() { - try { - return DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } catch (ParserConfigurationException exc) { - throw new IllegalArgumentException(exc); - } - } - }; + private static final ThreadLocal builderLocal = new ThreadLocal() { + @Override + protected DocumentBuilder initialValue() { + try { + return DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (ParserConfigurationException exc) { + throw new IllegalArgumentException(exc); + } + } + }; protected byte[] aesKey; protected String token; @@ -61,7 +61,8 @@ public WxCryptUtil() { * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey * @param appidOrCorpid 公众平台appid/corpid */ - public WxCryptUtil(String token, String encodingAesKey, String appidOrCorpid) { + public WxCryptUtil(String token, String encodingAesKey, + String appidOrCorpid) { this.token = token; this.appidOrCorpid = appidOrCorpid; this.aesKey = Base64.decodeBase64(encodingAesKey + "="); @@ -105,7 +106,8 @@ protected String encrypt(String randomStr, String plainText) { ByteGroup byteCollector = new ByteGroup(); byte[] randomStringBytes = randomStr.getBytes(CHARSET); byte[] plainTextBytes = plainText.getBytes(CHARSET); - byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(plainTextBytes.length); + byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder( + plainTextBytes.length); byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET); // randomStr + networkBytesOrder + text + appid @@ -154,7 +156,8 @@ protected String encrypt(String randomStr, String plainText) { * @param encryptedXml 密文,对应POST请求的数据 * @return 解密后的原文 */ - public String decrypt(String msgSignature, String timeStamp, String nonce, String encryptedXml) { + public String decrypt(String msgSignature, String timeStamp, String nonce, + String encryptedXml) { // 密钥,公众账号的app corpSecret // 提取密文 String cipherText = extractEncryptPart(encryptedXml); @@ -186,7 +189,8 @@ public String decrypt(String cipherText) { // 设置解密模式为AES的CBC模式 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES"); - IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); + IvParameterSpec iv = new IvParameterSpec( + Arrays.copyOfRange(aesKey, 0, 16)); cipher.init(Cipher.DECRYPT_MODE, key_spec, iv); // 使用BASE64对密文进行解码 @@ -208,9 +212,10 @@ public String decrypt(String cipherText) { int xmlLength = bytesNetworkOrder2Number(networkOrder); - xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET); - from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), + xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET); + from_appid = new String( + Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); } catch (Exception e) { throw new RuntimeException(e); } @@ -224,34 +229,32 @@ public String decrypt(String cipherText) { } - /** - * 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3) - * @param packageParams 原始参数 - * @param signKey 加密Key(即 商户Key) - * @param charset 编码 - * @return 签名字符串 - */ - public static String createSign(Map packageParams, String signKey) { - SortedMap sortedMap = new TreeMap(); - sortedMap.putAll(packageParams); - - List keys = new ArrayList(packageParams.keySet()); - Collections.sort(keys); - - - StringBuffer toSign = new StringBuffer(); - for (String key : keys) { - String value = packageParams.get(key); - if (null != value && !"".equals(value) && !"sign".equals(key) - && !"key".equals(key)) { - toSign.append(key + "=" + value + "&"); - } - } - toSign.append("key=" + signKey); - String sign = DigestUtils.md5Hex(toSign.toString()) - .toUpperCase(); - return sign; + /** + * 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3) + * @param packageParams 原始参数 + * @param signKey 加密Key(即 商户Key) + * @return 签名字符串 + */ + public static String createSign(Map packageParams, + String signKey) { + SortedMap sortedMap = new TreeMap(); + sortedMap.putAll(packageParams); + + List keys = new ArrayList(packageParams.keySet()); + Collections.sort(keys); + + StringBuffer toSign = new StringBuffer(); + for (String key : keys) { + String value = packageParams.get(key); + if (null != value && !"".equals(value) && !"sign".equals(key) + && !"key".equals(key)) { + toSign.append(key + "=" + value + "&"); + } } + toSign.append("key=" + signKey); + String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase(); + return sign; + } /** * 将一个数字转换成生成4个字节的网络字节序bytes数组 @@ -283,8 +286,6 @@ private int bytesNetworkOrder2Number(byte[] bytesInNetworkOrder) { /** * 随机生成16位字符串 - * - * @return */ private String genRandomStr() { String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; @@ -306,14 +307,12 @@ private String genRandomStr() { * @param nonce 随机字符串 * @return 生成的xml字符串 */ - private String generateXml(String encrypt, String signature, String timestamp, String nonce) { - String format = - "\n" - + "\n" - + "\n" - + "%3$s\n" - + "\n" - + ""; + private String generateXml(String encrypt, String signature, String timestamp, + String nonce) { + String format = "\n" + "\n" + + "\n" + + "%3$s\n" + "\n" + + ""; return String.format(format, encrypt, signature, timestamp, nonce); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java index 718f33e631..35c50e3ff9 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java @@ -14,8 +14,6 @@ public class FileUtils { * @param name 文件名 * @param ext 扩展名 * @param tmpDirFile 临时文件夹目录 - * @return - * @throws IOException */ public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException { FileOutputStream fos = null; @@ -56,8 +54,6 @@ public static File createTmpFile(InputStream inputStream, String name, String ex * @param inputStream * @param name 文件名 * @param ext 扩展名 - * @return - * @throws IOException */ public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException { return createTmpFile(inputStream, name, ext, null); diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java index 1bd6a98cbe..c821d86c60 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/ApacheHttpClientBuilder.java @@ -17,35 +17,30 @@ public interface ApacheHttpClientBuilder { /** * 代理服务器地址 * @param httpProxyHost - * @return */ ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); /** * 代理服务器端口 * @param httpProxyPort - * @return */ ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); /** * 代理服务器用户名 * @param httpProxyUsername - * @return */ ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); /** * 代理服务器密码 * @param httpProxyPassword - * @return */ ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); /** * ssl连接socket工厂 * @param sslConnectionSocketFactory - * @return */ ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); } diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java index b0d498a345..1172a2fcbf 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/RequestExecutor.java @@ -22,7 +22,6 @@ public interface RequestExecutor { * @param httpProxy http代理对象,如果没有配置代理则为空 * @param uri uri * @param data 数据 - * @return * @throws WxErrorException * @throws ClientProtocolException * @throws IOException diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageMatcher.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageMatcher.java index 184a5324cb..09fbdd2103 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageMatcher.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageMatcher.java @@ -9,8 +9,6 @@ public interface WxCpMessageMatcher { /** * 消息是否匹配某种模式 - * @param message - * @return */ public boolean match(WxCpXmlMessage message); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java index 2c3722f469..96b4e77de5 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouter.java @@ -124,7 +124,6 @@ List getRules() { /** * 开始一个新的Route规则 - * @return */ public WxCpMessageRouterRule rule() { return new WxCpMessageRouterRule(this); diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouterRule.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouterRule.java index cf453938ef..6d68332309 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouterRule.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpMessageRouterRule.java @@ -48,7 +48,6 @@ protected WxCpMessageRouterRule(WxCpMessageRouter routerBuilder) { * 设置是否异步执行,默认是true * * @param async - * @return */ public WxCpMessageRouterRule async(boolean async) { this.async = async; @@ -59,7 +58,6 @@ public WxCpMessageRouterRule async(boolean async) { * 如果agentId匹配 * * @param agentId - * @return */ public WxCpMessageRouterRule agentId(Integer agentId) { this.agentId = agentId; @@ -70,7 +68,6 @@ public WxCpMessageRouterRule agentId(Integer agentId) { * 如果msgType等于某值 * * @param msgType - * @return */ public WxCpMessageRouterRule msgType(String msgType) { this.msgType = msgType; @@ -81,7 +78,6 @@ public WxCpMessageRouterRule msgType(String msgType) { * 如果event等于某值 * * @param event - * @return */ public WxCpMessageRouterRule event(String event) { this.event = event; @@ -92,7 +88,6 @@ public WxCpMessageRouterRule event(String event) { * 如果eventKey等于某值 * * @param eventKey - * @return */ public WxCpMessageRouterRule eventKey(String eventKey) { this.eventKey = eventKey; @@ -103,7 +98,6 @@ public WxCpMessageRouterRule eventKey(String eventKey) { * 如果content等于某值 * * @param content - * @return */ public WxCpMessageRouterRule content(String content) { this.content = content; @@ -114,7 +108,6 @@ public WxCpMessageRouterRule content(String content) { * 如果content匹配该正则表达式 * * @param regex - * @return */ public WxCpMessageRouterRule rContent(String regex) { this.rContent = regex; @@ -125,7 +118,6 @@ public WxCpMessageRouterRule rContent(String regex) { * 如果fromUser等于某值 * * @param fromUser - * @return */ public WxCpMessageRouterRule fromUser(String fromUser) { this.fromUser = fromUser; @@ -136,7 +128,6 @@ public WxCpMessageRouterRule fromUser(String fromUser) { * 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候 * * @param matcher - * @return */ public WxCpMessageRouterRule matcher(WxCpMessageMatcher matcher) { this.matcher = matcher; @@ -147,7 +138,6 @@ public WxCpMessageRouterRule matcher(WxCpMessageMatcher matcher) { * 设置微信消息拦截器 * * @param interceptor - * @return */ public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor) { return interceptor(interceptor, (WxCpMessageInterceptor[]) null); @@ -158,7 +148,6 @@ public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor) { * * @param interceptor * @param otherInterceptors - * @return */ public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor, WxCpMessageInterceptor... otherInterceptors) { this.interceptors.add(interceptor); @@ -174,7 +163,6 @@ public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor, WxC * 设置微信消息处理器 * * @param handler - * @return */ public WxCpMessageRouterRule handler(WxCpMessageHandler handler) { return handler(handler, (WxCpMessageHandler[]) null); @@ -185,7 +173,6 @@ public WxCpMessageRouterRule handler(WxCpMessageHandler handler) { * * @param handler * @param otherHandlers - * @return */ public WxCpMessageRouterRule handler(WxCpMessageHandler handler, WxCpMessageHandler... otherHandlers) { this.handlers.add(handler); @@ -200,7 +187,6 @@ public WxCpMessageRouterRule handler(WxCpMessageHandler handler, WxCpMessageHand /** * 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则 * - * @return */ public WxCpMessageRouter end() { this.routerBuilder.getRules().add(this); @@ -210,7 +196,6 @@ public WxCpMessageRouter end() { /** * 规则结束,但是消息还会进入其他规则 * - * @return */ public WxCpMessageRouter next() { this.reEnter = true; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 78e75a7603..33de577d00 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -32,7 +32,6 @@ public interface WxCpService { * @param timestamp * @param nonce * @param data 微信传输过来的数据,有可能是echoStr,有可能是xml消息 - * @return */ boolean checkSignature(String msgSignature, String timestamp, String nonce, String data); @@ -49,7 +48,6 @@ public interface WxCpService { /** * 获取access_token, 不强制刷新access_token * @see #getAccessToken(boolean) - * @return * @throws WxErrorException */ String getAccessToken() throws WxErrorException; @@ -63,7 +61,6 @@ public interface WxCpService { * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token * * @param forceRefresh 强制刷新 - * @return * @throws me.chanjar.weixin.common.exception.WxErrorException */ String getAccessToken(boolean forceRefresh) throws WxErrorException; @@ -71,7 +68,6 @@ public interface WxCpService { /** * 获得jsapi_ticket,不强制刷新jsapi_ticket * @see #getJsapiTicket(boolean) - * @return * @throws WxErrorException */ public String getJsapiTicket() throws WxErrorException; @@ -84,7 +80,6 @@ public interface WxCpService { * 详情请见:http://qydev.weixin.qq.com/wiki/index.php?title=微信JS接口#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 * * @param forceRefresh 强制刷新 - * @return * @throws WxErrorException */ public String getJsapiTicket(boolean forceRefresh) throws WxErrorException; @@ -96,7 +91,6 @@ public interface WxCpService { * 详情请见:http://qydev.weixin.qq.com/wiki/index.php?title=微信JS接口#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 * * @param url url - * @return */ public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; @@ -136,7 +130,7 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * * @return 保存到本地的临时文件 * @throws WxErrorException - * @params media_id + * @param media_id */ File mediaDownload(String media_id) throws WxErrorException; @@ -216,7 +210,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * * @see #menuGet(String) * - * @return * @throws WxErrorException */ WxMenu menuGet() throws WxErrorException; @@ -231,7 +224,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * @see #menuGet() * * @param agentId 企业号应用的id - * @return * @throws WxErrorException */ WxMenu menuGet(String agentId) throws WxErrorException; @@ -255,7 +247,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=部门管理接口 * * - * @return * @throws WxErrorException */ List departGet() throws WxErrorException; @@ -291,7 +282,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * @param departId 必填。部门id * @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员 * @param status 非必填。0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加 - * @return * @throws WxErrorException */ List userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; @@ -306,7 +296,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * @param departId 必填。部门id * @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员 * @param status 非必填。0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加 - * @return * @throws WxErrorException */ List departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException; @@ -350,7 +339,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 获取用户 * * @param userid - * @return * @throws WxErrorException */ WxCpUser userGet(String userid) throws WxErrorException; @@ -359,7 +347,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 创建标签 * * @param tagName - * @return */ String tagCreate(String tagName) throws WxErrorException; @@ -381,7 +368,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i /** * 获得标签列表 * - * @return */ List tagGet() throws WxErrorException; @@ -389,7 +375,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 获取标签成员 * * @param tagId - * @return */ List tagGetUsers(String tagId) throws WxErrorException; @@ -478,7 +463,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求 * @param url * @param queryParam - * @return * @throws WxErrorException */ String get(String url, String queryParam) throws WxErrorException; @@ -487,7 +471,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求 * @param url * @param postData - * @return * @throws WxErrorException */ String post(String url, String postData) throws WxErrorException; @@ -503,7 +486,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * @param data * @param * @param - * @return * @throws WxErrorException */ T execute(RequestExecutor executor, String uri, E data) throws WxErrorException; @@ -536,7 +518,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i /** * 获取某个sessionId对应的session,如果sessionId没有对应的session,则新建一个并返回。 * @param id id可以为任意字符串,建议使用FromUserName作为id - * @return */ WxSession getSession(String id); @@ -544,7 +525,6 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * 获取某个sessionId对应的session,如果sessionId没有对应的session,若create为true则新建一个,否则返回null。 * @param id id可以为任意字符串,建议使用FromUserName作为id * @param create - * @return */ WxSession getSession(String id, boolean create); @@ -556,25 +536,24 @@ WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream i * @param sessionManager */ void setSessionManager(WxSessionManager sessionManager); - + /** * 上传部门列表覆盖企业号上的部门信息 * @param mediaId * @throws WxErrorException */ String replaceParty(String mediaId) throws WxErrorException; - + /** * 上传用户列表覆盖企业号上的用户信息 * @param mediaId * @throws WxErrorException */ String replaceUser(String mediaId) throws WxErrorException; - + /** * 获取异步任务结果 * @param joinId - * @return * @throws WxErrorException */ String getTaskResult(String joinId) throws WxErrorException; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java index 46e5692920..1cf517abd7 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpServiceImpl.java @@ -510,12 +510,6 @@ public String post(String url, String postData) throws WxErrorException { /** * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - * - * @param executor - * @param uri - * @param data - * @return - * @throws WxErrorException */ public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { int retryTimes = 0; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java index 8e69027a46..25734aef85 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpMessage.java @@ -28,7 +28,7 @@ public class WxCpMessage implements Serializable { private String hqMusicUrl; private String safe; private List articles = new ArrayList(); - + public String getToUser() { return toUser; } @@ -63,7 +63,7 @@ public void setAgentId(String agentId) { public String getMsgType() { return msgType; } - + public String getSafe() { return safe; } @@ -135,18 +135,18 @@ public List getArticles() { public void setArticles(List articles) { this.articles = articles; } - + public String toJson() { return WxCpGsonBuilder.INSTANCE.create().toJson(this); } - + public static class WxArticle { - + private String title; private String description; private String url; private String picUrl; - + public String getTitle() { return title; } @@ -171,12 +171,11 @@ public String getPicUrl() { public void setPicUrl(String picUrl) { this.picUrl = picUrl; } - + } - + /** * 获得文本消息builder - * @return */ public static TextBuilder TEXT() { return new TextBuilder(); @@ -184,7 +183,6 @@ public static TextBuilder TEXT() { /** * 获得图片消息builder - * @return */ public static ImageBuilder IMAGE() { return new ImageBuilder(); @@ -192,23 +190,20 @@ public static ImageBuilder IMAGE() { /** * 获得语音消息builder - * @return */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); } - + /** * 获得视频消息builder - * @return */ public static VideoBuilder VIDEO() { return new VideoBuilder(); } - + /** * 获得图文消息builder - * @return */ public static NewsBuilder NEWS() { return new NewsBuilder(); @@ -216,10 +211,9 @@ public static NewsBuilder NEWS() { /** * 获得文件消息builder - * @return */ public static FileBuilder FILE() { return new FileBuilder(); } - + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java index 469bb0bdb3..eaf926e2a2 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlMessage.java @@ -198,7 +198,6 @@ public void setCreateTime(Long createTime) { * {@link me.chanjar.weixin.common.api.WxConsts#XML_MSG_EVENT} * * - * @return */ public String getMsgType() { return msgType; @@ -404,7 +403,6 @@ protected static WxCpXmlMessage fromXml(InputStream is) { * @param timestamp * @param nonce * @param msgSignature - * @return */ public static WxCpXmlMessage fromEncryptedXml( String encryptedXml, @@ -542,7 +540,6 @@ public static class ScanCodeInfo { /** * 扫描类型,一般是qrcode - * @return */ public String getScanType() { @@ -555,7 +552,6 @@ public void setScanType(String scanType) { /** * 扫描结果,即二维码对应的字符串信息 - * @return */ public String getScanResult() { return scanResult; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java index 641a572d4b..eccfbecd39 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/WxCpXmlOutMessage.java @@ -14,14 +14,14 @@ public abstract class WxCpXmlOutMessage { @XStreamAlias("ToUserName") @XStreamConverter(value=XStreamCDataConverter.class) protected String toUserName; - + @XStreamAlias("FromUserName") @XStreamConverter(value=XStreamCDataConverter.class) protected String fromUserName; - + @XStreamAlias("CreateTime") protected Long createTime; - + @XStreamAlias("MsgType") @XStreamConverter(value=XStreamCDataConverter.class) protected String msgType; @@ -57,14 +57,13 @@ public String getMsgType() { public void setMsgType(String msgType) { this.msgType = msgType; } - + protected String toXml() { return XStreamTransformer.toXml((Class)this.getClass(), this); } /** * 转换成加密的xml格式 - * @return */ public String toEncryptedXml(WxCpConfigStorage wxCpConfigStorage) { String plainXml = toXml(); @@ -74,7 +73,6 @@ public String toEncryptedXml(WxCpConfigStorage wxCpConfigStorage) { /** * 获得文本消息builder - * @return */ public static TextBuilder TEXT() { return new TextBuilder(); @@ -82,7 +80,6 @@ public static TextBuilder TEXT() { /** * 获得图片消息builder - * @return */ public static ImageBuilder IMAGE() { return new ImageBuilder(); @@ -90,23 +87,20 @@ public static ImageBuilder IMAGE() { /** * 获得语音消息builder - * @return */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); } - + /** * 获得视频消息builder - * @return */ public static VideoBuilder VIDEO() { return new VideoBuilder(); } - + /** * 获得图文消息builder - * @return */ public static NewsBuilder NEWS() { return new NewsBuilder(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index c9308d7cee..7e9e0d928a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -255,7 +255,7 @@ public interface WxMpService { * 根据微信文档,视频文件下载不了,会返回null * 详情请见: 获取临时素材 * - * @params media_id + * @param media_id * @return 保存到本地的临时文件 * @throws WxErrorException */ @@ -371,7 +371,6 @@ public interface WxMpService { * 分组管理接口 - 查询所有分组 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口 * - * @return */ public List groupGet() throws WxErrorException; @@ -573,7 +572,6 @@ public interface WxMpService { * 验证oauth2的access token是否有效 * * @param oAuth2AccessToken - * @return */ public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index 6ea190e480..b9fa37aa9f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -785,12 +785,6 @@ public String post(String url, String postData) throws WxErrorException { /** * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - * - * @param executor - * @param uri - * @param data - * @return - * @throws WxErrorException */ @Override public T execute(RequestExecutor executor, String uri, E data) throws WxErrorException { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java index 061aa2cea9..61a268b0a5 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java @@ -154,7 +154,6 @@ public static ImageBuilder IMAGE() { /** * 获得语音消息builder - * @return */ public static VoiceBuilder VOICE() { return new VoiceBuilder(); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java index 254f2147ce..472bac55b9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/xml/XStreamTransformer.java @@ -14,10 +14,6 @@ public class XStreamTransformer { /** * xml -> pojo - * - * @param clazz - * @param xml - * @return */ @SuppressWarnings("unchecked") public static T fromXml(Class clazz, String xml) { @@ -43,10 +39,6 @@ public static void register(Class clz,XStream xStream){ /** * pojo -> xml - * - * @param clazz - * @param object - * @return */ public static String toXml(Class clazz, T object) { return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object); From 754e09ea02eec5fa783b824a3fb2c99bf05433e8 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 14:46:49 +0800 Subject: [PATCH 28/54] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E7=B1=BB=E7=9A=84=E5=91=BD?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{WxMpKefuImplTest.java => WxMpKefuServiceImplTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/{WxMpKefuImplTest.java => WxMpKefuServiceImplTest.java} (99%) diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java similarity index 99% rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index 120a3c036d..bc44e9aa57 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -28,7 +28,7 @@ */ @Test @Guice(modules = ApiTestModule.class) -public class WxMpKefuImplTest { +public class WxMpKefuServiceImplTest { @Inject protected WxMpServiceImpl wxService; From 3534234d917b883266fc88ba00fccb3ace97bb5e Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 18:00:30 +0800 Subject: [PATCH 29/54] =?UTF-8?q?=E6=8C=89=E7=85=A7=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=AF=B9=E5=AE=A2=E6=9C=8D=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpKefuService.java | 23 ++++-- .../mp/api/impl/WxMpKefuServiceImpl.java | 8 +++ .../kefu/request/WxMpKfAccountRequest.java | 56 +++++---------- .../mp/bean/kefu/result/WxMpKfInfo.java | 71 +++++++++++++++---- .../mp/api/impl/WxMpKefuServiceImplTest.java | 12 +++- 5 files changed, 106 insertions(+), 64 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 37799d13a5..6233e6768c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -24,7 +24,7 @@ public interface WxMpKefuService { /** *
    * 获取客服基本信息
-   * 详情请见:客服管理
+   * 详情请见:客服管理
    * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN
    * 
*/ @@ -33,7 +33,7 @@ public interface WxMpKefuService { /** *
    * 获取在线客服接待信息
-   * 详情请见:客服管理
+   * 详情请见:客服管理
    * 接口url格式:https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN
    * 
*/ @@ -42,7 +42,7 @@ public interface WxMpKefuService { /** *
    * 添加客服账号
-   * 详情请见:客服管理
+   * 详情请见:客服管理
    * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN
    * 
*/ @@ -50,17 +50,26 @@ public interface WxMpKefuService { /** *
-   * 设置客服信息(更新)
-   * 详情请见:客服管理
+   * 设置客服信息(即更新客服信息)
+   * 详情请见:客服管理
    * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN
    * 
*/ boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException; + /** + *
+   * 设置客服信息(即更新客服信息)
+   * 详情请见:客服管理
+   * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=ACCESS_TOKEN
+   * 
+ */ + boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException; + /** *
    * 上传客服头像
-   * 详情请见:客服管理
+   * 详情请见:客服管理
    * 接口url格式:http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
    * 
*/ @@ -70,7 +79,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) /** *
    * 删除客服账号
-   * 详情请见:客服管理
+   * 详情请见:客服管理
    * 接口url格式:https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
    * 
*/ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index 19fdd50887..12eec6c0e0 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -62,6 +62,14 @@ public boolean kfAccountUpdate(WxMpKfAccountRequest request) return true; } + @Override + public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException { + String url = "https://api.weixin.qq.com/customservice/kfaccount/inviteworker"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, + request.toJson()); + return true; + } + @Override public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java index fb5ac41b14..dabdcb76da 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java @@ -23,18 +23,12 @@ public class WxMpKfAccountRequest implements Serializable { */ @SerializedName("nickname") private String nickName; - - /** - * password 客服账号登录密码,格式为密码明文的32位加密MD5值 - */ - @SerializedName("password") - private String password; - + /** - * rawPassword 客服账号登录密码,明文密码,仅用于辅助操作 + * invite_wx 接收绑定邀请的客服微信号 */ - @SerializedName("rawPassword") - private String rawPassword; + @SerializedName("invite_wx") + private String inviteWx; @Override public String toString() { @@ -61,31 +55,22 @@ public void setNickName(String nickName) { this.nickName = nickName; } - public String getPassword() { - return this.password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getRawPassword() { - return this.rawPassword; + public static Builder builder() { + return new Builder(); } - public void setRawPassword(String rawPassword) { - this.rawPassword = rawPassword; + public String getInviteWx() { + return this.inviteWx; } - public static Builder builder() { - return new Builder(); + public void setInviteWx(String inviteWx) { + this.inviteWx = inviteWx; } public static class Builder { private String kfAccount; private String nickName; - private String password; - private String rawPassword; + private String inviteWx; @SuppressWarnings("hiding") public Builder kfAccount(String kfAccount) { @@ -100,23 +85,15 @@ public Builder nickName(String nickName) { } @SuppressWarnings("hiding") - public Builder password(String password) { - this.password = password; - return this; - } - - @SuppressWarnings("hiding") - public Builder rawPassword(String rawPassword) { - this.rawPassword = rawPassword; - this.password(Md5Crypt.md5Crypt(rawPassword.getBytes())); - return this; + public Builder inviteWx(String inviteWx) { + this.inviteWx = inviteWx; + return this; } public Builder from(WxMpKfAccountRequest origin) { this.kfAccount(origin.kfAccount); this.nickName(origin.nickName); - this.password(origin.password); - this.rawPassword(origin.rawPassword); + this.inviteWx(origin.inviteWx); return this; } @@ -124,8 +101,7 @@ public WxMpKfAccountRequest build() { WxMpKfAccountRequest m = new WxMpKfAccountRequest(); m.kfAccount = this.kfAccount; m.nickName = this.nickName; - m.password = this.password; - m.rawPassword = this.rawPassword; + m.inviteWx = this.inviteWx; return m; } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java index 7e9b54251e..37154aa4ba 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfInfo.java @@ -41,17 +41,34 @@ public class WxMpKfInfo implements Serializable { private String nick; /** - * status 客服在线状态 1:pc在线,2:手机在线。若pc和手机同时在线则为 1+2=3 + * kf_wx 如果客服帐号已绑定了客服人员微信号,则此处显示微信号 */ - @SerializedName("status") - private Integer status; + @SerializedName("kf_wx") + private String wxAccount; /** - * auto_accept 客服设置的最大自动接入数 + * invite_wx 如果客服帐号尚未绑定微信号,但是已经发起了一个绑定邀请,则此处显示绑定邀请的微信号 */ - @Expose - @SerializedName("auto_accept") - private Integer autoAccept; + @SerializedName("invite_wx") + private String inviteWx; + + /** + * invite_expire_time 如果客服帐号尚未绑定微信号,但是已经发起过一个绑定邀请,则此处显示为邀请的过期时间,为unix 时间戳 + */ + @SerializedName("invite_expire_time") + private Long inviteExpireTime; + + /** + * invite_status 邀请的状态,有等待确认“waiting”,被拒绝“rejected”,过期“expired” + */ + @SerializedName("invite_status") + private String inviteStatus; + + /** + * status 客服在线状态,目前为:1、web 在线 + */ + @SerializedName("status") + private Integer status; /** * accepted_case 客服当前正在接待的会话数 @@ -68,14 +85,6 @@ public void setStatus(Integer status) { this.status = status; } - public Integer getAutoAccept() { - return this.autoAccept; - } - - public void setAutoAccept(Integer autoAccept) { - this.autoAccept = autoAccept; - } - public Integer getAcceptedCase() { return this.acceptedCase; } @@ -120,4 +129,36 @@ public void setNick(String nick) { public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); } + + public String getWxAccount() { + return this.wxAccount; + } + + public void setWxAccount(String wxAccount) { + this.wxAccount = wxAccount; + } + + public String getInviteWx() { + return this.inviteWx; + } + + public void setInviteWx(String inviteWx) { + this.inviteWx = inviteWx; + } + + public Long getInviteExpireTime() { + return this.inviteExpireTime; + } + + public void setInviteExpireTime(Long inviteExpireTime) { + this.inviteExpireTime = inviteExpireTime; + } + + public String getInviteStatus() { + return this.inviteStatus; + } + + public void setInviteStatus(String inviteStatus) { + this.inviteStatus = inviteStatus; + } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index bc44e9aa57..8007b8759c 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -60,7 +60,7 @@ public Object[][] getKfAccount() { @Test(dataProvider = "getKfAccount") public void testKfAccountAdd(String kfAccount) throws WxErrorException { WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() - .kfAccount(kfAccount).nickName("我晕").rawPassword("123").build(); + .kfAccount(kfAccount).nickName("我晕").build(); Assert.assertTrue(this.wxService.getKefuService().kfAccountAdd(request)); } @@ -68,10 +68,18 @@ public void testKfAccountAdd(String kfAccount) throws WxErrorException { "testKfAccountAdd" }, dataProvider = "getKfAccount") public void testKfAccountUpdate(String kfAccount) throws WxErrorException { WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() - .kfAccount(kfAccount).nickName("我晕").rawPassword("123").build(); + .kfAccount(kfAccount).nickName("我晕").build(); Assert.assertTrue(this.wxService.getKefuService().kfAccountUpdate(request)); } + @Test(dependsOnMethods = { + "testKfAccountAdd" }, dataProvider = "getKfAccount") + public void testKfAccountInviteWorker(String kfAccount) throws WxErrorException { + WxMpKfAccountRequest request = WxMpKfAccountRequest.builder() + .kfAccount(kfAccount).inviteWx("www_ucredit_com").build(); + Assert.assertTrue(this.wxService.getKefuService().kfAccountInviteWorker(request)); + } + @Test(dependsOnMethods = { "testKfAccountUpdate" }, dataProvider = "getKfAccount") public void testKfAccountUploadHeadImg(String kfAccount) From 78f44b2bb00cc7d17762722258d979ebb1e3e634 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 18:35:42 +0800 Subject: [PATCH 30/54] =?UTF-8?q?=E6=8C=89=E7=85=A7=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=AE=98=E6=96=B9=E6=96=87=E6=A1=A3=E5=AF=B9?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E4=BC=9A=E8=AF=9D=E6=8E=A7=E5=88=B6=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/mp/api/WxMpKefuService.java | 14 +++++++------- .../mp/bean/kefu/result/WxMpKfSession.java | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 6233e6768c..a5d6321571 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -85,12 +85,12 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) */ boolean kfAccountDel(String kfAccount) throws WxErrorException; - //*******************多客服会话控制接口***********************// + //*******************客服会话控制接口***********************// /** *
    * 创建会话
    * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
-   * 详情请见:多客服会话控制接口
+   * 详情请见:客服会话控制接口
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN
    * 
*/ @@ -100,7 +100,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
    * 关闭会话
    * 开发者可以使用本接口,关闭一个会话。
-   * 详情请见:多客服会话控制接口
+   * 详情请见:客服会话控制接口
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN
    * 
*/ @@ -109,8 +109,8 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) /** *
    * 获取客户的会话状态
-   * 开发者可以通过本接口获取客户当前的会话状态。
-   * 详情请见:多客服会话控制接口
+   * 此接口获取一个客户的会话,如果不存在,则kf_account为空。
+   * 详情请见:客服会话控制
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID
    * 
*/ @@ -120,7 +120,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
    * 获取客服的会话列表
    * 开发者可以通过本接口获取某个客服正在接待的会话列表。
-   * 详情请见:多客服会话控制接口
+   * 详情请见:客服会话控制
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsessionlist?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT
    * 
*/ @@ -130,7 +130,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
    * 获取未接入会话列表
    * 开发者可以通过本接口获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。
-   * 详情请见:多客服会话控制接口
+   * 详情请见:客服会话控制
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getwaitcase?access_token=ACCESS_TOKEN
    * 
*/ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java index 9cc3d50f42..e29f45b802 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java @@ -18,11 +18,19 @@ public class WxMpKfSession { private String kfAccount; /** - * createtime 会话接入的时间 或者 来访时间,UNIX时间戳 + * createtime 会话接入的时间,UNIX时间戳 + * 该返回值 存在于 获取客服会话列表接口 */ @SerializedName("createtime") private long createTime; + /** + * latest_time 粉丝的最后一条消息的时间,UNIX时间戳 + * 该返回值 存在于 获取未接入会话列表接口 + */ + @SerializedName("latest_time") + private long latestTime; + /** * openid 客户openid */ @@ -58,4 +66,11 @@ public void setOpenid(String openid) { this.openid = openid; } + public long getLatestTime() { + return this.latestTime; + } + + public void setLatestTime(long latestTime) { + this.latestTime = latestTime; + } } From 560ae27a45aefb3774904a33403aeeef42fdd35e Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 12 Jul 2016 18:40:30 +0800 Subject: [PATCH 31/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86javad?= =?UTF-8?q?oc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index a5d6321571..7e2a41128e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -89,7 +89,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) /** *
    * 创建会话
-   * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
+   * 此接口在客服和用户之间创建一个会话,如果该客服和用户会话已存在,则直接返回0。指定的客服帐号必须已经绑定微信号且在线。
    * 详情请见:客服会话控制接口
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN
    * 
@@ -100,7 +100,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
    * 关闭会话
    * 开发者可以使用本接口,关闭一个会话。
-   * 详情请见:客服会话控制接口
+   * 详情请见:客服会话控制接口
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN
    * 
*/ @@ -110,7 +110,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
    * 获取客户的会话状态
    * 此接口获取一个客户的会话,如果不存在,则kf_account为空。
-   * 详情请见:客服会话控制
+   * 详情请见:客服会话控制接口
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID
    * 
*/ From c13b8ac485c848520af161d6fbb6457a1e81f141 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Wed, 13 Jul 2016 15:58:01 +0800 Subject: [PATCH 32/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dhandler=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E6=97=B6=E5=AF=BC=E8=87=B4=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java index ae2b161658..eb02c6414b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java @@ -211,6 +211,9 @@ protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage, WxMpXmlOutMessage res = null; for (WxMpMessageHandler handler : this.handlers) { // 返回最后handler的结果 + if(handler == null){ + continue; + } res = handler.handle(wxMessage, context, wxMpService, sessionManager); } return res; From 42ce9a19189a511c8076f786ee514513b1e368d9 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Wed, 13 Jul 2016 16:05:04 +0800 Subject: [PATCH 33/54] =?UTF-8?q?demo=20=E5=A2=9E=E5=8A=A0=E5=AF=B9aes?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=8A=A0=E5=AF=86=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-demo-with-spring/pom.xml | 2 +- .../demo/spring/config/WxConfig.java | 2 + .../demo/spring/config/WxGzh1Config.java | 8 +++ .../demo/spring/config/WxGzh2Config.java | 8 +++ .../AbstractWxPortalController.java | 50 +++++++++++++------ .../demo/spring/service/BaseWxService.java | 1 + .../resources/wx-gzh1.properties.template | 1 + .../resources/wx-gzh2.properties.template | 1 + 8 files changed, 56 insertions(+), 17 deletions(-) diff --git a/weixin-java-demo-with-spring/pom.xml b/weixin-java-demo-with-spring/pom.xml index 469ac9e226..5178468614 100644 --- a/weixin-java-demo-with-spring/pom.xml +++ b/weixin-java-demo-with-spring/pom.xml @@ -20,7 +20,7 @@ 1.7.2 1.8.9 1.2.6 - 3.1 + 3.4 9.3.10.v20160621 diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java index a65d4000ed..782f240510 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxConfig.java @@ -12,6 +12,8 @@ public abstract class WxConfig { public abstract String getAppsecret(); + public abstract String getAesKey(); + public abstract WxAccountEnum getWxAccountEnum(); public int getPubId() { diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java index fee34f431e..c1cfc01c72 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh1Config.java @@ -19,6 +19,9 @@ public class WxGzh1Config extends WxConfig { @Value("#{gzh1WxProperties.wx_appsecret}") private String appsecret; + @Value("#{gzh1WxProperties.wx_aeskey}") + private String aesKey; + @Override public String getToken() { return this.token; @@ -34,6 +37,11 @@ public String getAppsecret() { return this.appsecret; } + @Override + public String getAesKey() { + return this.aesKey; + } + @Override public WxAccountEnum getWxAccountEnum() { return WxAccountEnum.GZH1; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java index d284630a8b..8c593909c6 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/config/WxGzh2Config.java @@ -19,6 +19,9 @@ public class WxGzh2Config extends WxConfig { @Value("#{gzh2WxProperties.wx_appsecret}") private String appsecret; + @Value("#{gzh2WxProperties.wx_aeskey}") + private String aesKey; + @Override public String getToken() { return this.token; @@ -34,6 +37,11 @@ public String getAppsecret() { return this.appsecret; } + @Override + public String getAesKey() { + return this.aesKey; + } + @Override public WxAccountEnum getWxAccountEnum() { return WxAccountEnum.GZH2; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java index 8bae466956..dba3f84066 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/controller/AbstractWxPortalController.java @@ -1,5 +1,6 @@ package com.github.binarywang.demo.spring.controller; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestBody; @@ -27,7 +28,8 @@ public abstract class AbstractWxPortalController { @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr) { - this.logger.info("接收到来自微信服务器的认证消息"); + this.logger.info("\n接收到来自微信服务器的认证消息:[{},{},{},{}]", + signature, timestamp, nonce, echostr); if (this.getWxService().checkSignature(timestamp, nonce, signature)) { return echostr; @@ -37,24 +39,40 @@ public abstract class AbstractWxPortalController { } @RequestMapping(method = RequestMethod.POST, produces = "application/xml; charset=UTF-8") - public @ResponseBody String post(@RequestBody String requestBody) { - - this.logger.debug("\n接收微信请求:{} ", requestBody); - - BaseWxService wxService = this.getWxService(); - - WxMpXmlOutMessage out = wxService - .route(WxMpXmlMessage.fromXml(requestBody)); - - if (out == null) { - return ""; + public @ResponseBody String post(@RequestBody String requestBody, + @RequestParam("signature") String signature, + @RequestParam("encrypt_type") String encType, + @RequestParam("msg_signature") String msgSignature, + @RequestParam("timestamp") String timestamp, + @RequestParam("nonce") String nonce) { + this.logger.info("\n接收微信请求:[{},{},{},{},{}]\n{} ", + signature, encType, msgSignature, timestamp, nonce, requestBody); + + String out = null; + if (encType == null) { + // 明文传输的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody); + WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage); + if (outMessage == null) { + return ""; + } + out = outMessage.toXml(); + }else if ("aes".equals(encType)) { + // aes加密的消息 + WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, + this.getWxService().getWxMpConfigStorage(), timestamp, nonce, msgSignature); + this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString()); + WxMpXmlOutMessage outMessage = this.getWxService().route(inMessage); + if (outMessage == null) { + return ""; + } + + out = outMessage.toEncryptedXml(this.getWxService().getWxMpConfigStorage()); } - String outXml = out.toXml(); - - this.logger.debug("\n组装回复信息:{}", outXml); + this.logger.debug("\n组装回复信息:{}", out); - return outXml; + return out; } protected abstract BaseWxService getWxService(); diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java index 133c7445bd..ac61bea0b3 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java @@ -63,6 +63,7 @@ public void init() { config.setAppId(this.getServerConfig().getAppid());// 设置微信公众号的appid config.setSecret(this.getServerConfig().getAppsecret());// 设置微信公众号的app corpSecret config.setToken(this.getServerConfig().getToken());// 设置微信公众号的token + config.setAesKey(this.getServerConfig().getAesKey());// 设置消息加解密密钥 super.setWxMpConfigStorage(config); this.refreshRouter(); diff --git a/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template b/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template index 76afcd9eab..302903e552 100644 --- a/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template +++ b/weixin-java-demo-with-spring/src/main/resources/wx-gzh1.properties.template @@ -1,3 +1,4 @@ wx_appid= wx_appsecret= wx_token= +wx_aeskey= diff --git a/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template b/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template index 76afcd9eab..302903e552 100644 --- a/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template +++ b/weixin-java-demo-with-spring/src/main/resources/wx-gzh2.properties.template @@ -1,3 +1,4 @@ wx_appid= wx_appsecret= wx_token= +wx_aeskey= From 72c46d1beca40d0c71544f042f479c4d84a63289 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Wed, 13 Jul 2016 18:20:24 +0800 Subject: [PATCH 34/54] =?UTF-8?q?=E6=8C=89=E7=85=A7=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=AE=98=E6=96=B9=E6=96=87=E6=A1=A3=E5=AF=B9?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E4=BC=9A=E8=AF=9D=E6=8E=A7=E5=88=B6=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=BF=9B=E8=A1=8C=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpKefuService.java | 4 ++-- .../mp/api/impl/WxMpKefuServiceImpl.java | 10 ++++----- .../kefu/request/WxMpKfSessionRequest.java | 21 ++----------------- .../mp/api/impl/WxMpKefuServiceImplTest.java | 4 ++-- 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 7e2a41128e..fc927bc4f2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -94,7 +94,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/create?access_token=ACCESS_TOKEN * */ - boolean kfSessionCreate(String openid, String kfAccount, String text) throws WxErrorException; + boolean kfSessionCreate(String openid, String kfAccount) throws WxErrorException; /** *
@@ -104,7 +104,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
    * 接口url格式: https://api.weixin.qq.com/customservice/kfsession/close?access_token=ACCESS_TOKEN
    * 
*/ - boolean kfSessionClose(String openid, String kfAccount, String text) throws WxErrorException; + boolean kfSessionClose(String openid, String kfAccount) throws WxErrorException; /** *
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
index 12eec6c0e0..c78c873da5 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java
@@ -88,10 +88,9 @@ public boolean kfAccountDel(String kfAccount) throws WxErrorException {
   }
 
   @Override
-  public boolean kfSessionCreate(String openid, String kfAccount, String text)
+  public boolean kfSessionCreate(String openid, String kfAccount)
       throws WxErrorException {
-    WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid,
-        text);
+    WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid);
     String url = "https://api.weixin.qq.com/customservice/kfsession/create";
     this.wxMpService.execute(new SimplePostRequestExecutor(), url,
         request.toJson());
@@ -99,10 +98,9 @@ public boolean kfSessionCreate(String openid, String kfAccount, String text)
   }
 
   @Override
-  public boolean kfSessionClose(String openid, String kfAccount, String text)
+  public boolean kfSessionClose(String openid, String kfAccount)
       throws WxErrorException {
-    WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid,
-        text);
+    WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid);
     String url = "https://api.weixin.qq.com/customservice/kfsession/close";
     this.wxMpService.execute(new SimplePostRequestExecutor(), url,
         request.toJson());
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java
index aaf9e98c87..e821916efe 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfSessionRequest.java
@@ -23,19 +23,10 @@ public class WxMpKfSessionRequest implements Serializable {
    */
   @SerializedName("openid")
   private String openid;
-  
-  /**
-   * text 附加信息,文本会展示在客服人员的多客服客户端
-   * 目前看起来无用,主要是老版的多客服客户端使用
-   */
-  @SerializedName("text")
-  @Deprecated
-  private String text;
-  
-  public WxMpKfSessionRequest(String kfAccount, String openid, String text) {
+
+  public WxMpKfSessionRequest(String kfAccount, String openid) {
     this.kfAccount = kfAccount;
     this.openid = openid;
-    this.text = text;
   }
 
   @Override
@@ -55,12 +46,4 @@ public void setKfAccount(String kfAccount) {
     this.kfAccount = kfAccount;
   }
 
-  public String getText() {
-    return this.text;
-  }
-
-  public void setText(String text) {
-    this.text = text;
-  }
-
 }
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java
index 8007b8759c..f02649cc88 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java
@@ -108,7 +108,7 @@ public Object[][] getKfAccountAndOpenid() {
   public void testKfSessionCreate(String kfAccount, String openid)
       throws WxErrorException {
     boolean result = this.wxService.getKefuService().kfSessionCreate(openid,
-        kfAccount, "welcome");
+        kfAccount);
     Assert.assertTrue(result);
   }
 
@@ -116,7 +116,7 @@ public void testKfSessionCreate(String kfAccount, String openid)
   public void testKfSessionClose(String kfAccount, String openid)
       throws WxErrorException {
     boolean result = this.wxService.getKefuService().kfSessionClose(openid,
-        kfAccount, "bye bye");
+        kfAccount);
     Assert.assertTrue(result);
   }
 

From 95cf37baa42ddc7d6da461f78f8cd87543b7ef94 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Wed, 13 Jul 2016 18:55:48 +0800
Subject: [PATCH 35/54] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=BE=AE=E4=BF=A1?=
 =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=B8=AD=E6=97=B6=E9=97=B4=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E7=9A=84=E5=BA=8F=E5=88=97=E5=8C=96=E8=BD=AC=E6=8D=A2=E7=B1=BB?=
 =?UTF-8?q?=EF=BC=8C=E4=BE=9B=E8=BD=AC=E6=8D=A2json=E4=BD=BF=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pom.xml                                       |  2 +-
 .../weixin/mp/bean/WxMpXmlMessage.java        |  3 +++
 .../util/json/WxLongTimeJsonSerializer.java   | 24 +++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java

diff --git a/pom.xml b/pom.xml
index f3bf20a758..d80a752f8a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,7 +49,7 @@
     1.7.10
     1.1.2
     3.6.7
-    2.7.5
+    2.8.0
     2.7
     3.4
     2.5
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
index 047961ea87..823558fe79 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
@@ -6,6 +6,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import me.chanjar.weixin.mp.util.json.WxLongTimeJsonSerializer;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
@@ -47,6 +49,7 @@ public class WxMpXmlMessage implements Serializable {
   private String fromUserName;
 
   @XStreamAlias("CreateTime")
+  @JsonSerialize(using = WxLongTimeJsonSerializer.class)
   private Long createTime;
 
   @XStreamAlias("MsgType")
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java
new file mode 100644
index 0000000000..576b1be35d
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java
@@ -0,0 +1,24 @@
+package me.chanjar.weixin.mp.util.json;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+/**
+ * Created by Binary Wang on 2016/7/13.
+ */
+public class WxLongTimeJsonSerializer extends JsonSerializer {
+  private static SimpleDateFormat DF = new SimpleDateFormat(
+      "yyyy-MM-dd hh:mm:ss");
+
+  @Override
+  public void serialize(Long value, JsonGenerator gen,
+      SerializerProvider serializers)
+      throws IOException, JsonProcessingException {
+    gen.writeString(DF.format(value * 1000));
+  }
+}

From 0c723bbf5c751a76e3c533403ff16cdc6a0087dd Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Fri, 15 Jul 2016 16:24:35 +0800
Subject: [PATCH 36/54] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=B6=88=E6=81=AF?=
 =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=A2=9E=E5=8A=A0=E5=B0=8F=E8=A7=86=E9=A2=91?=
 =?UTF-8?q?=E7=9A=84=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/main/java/me/chanjar/weixin/common/api/WxConsts.java     | 1 +
 1 file changed, 1 insertion(+)

diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
index aac9d4e9b2..0c9661d2f0 100644
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
@@ -11,6 +11,7 @@ public class WxConsts {
   public static final String XML_MSG_TEXT = "text";
   public static final String XML_MSG_IMAGE = "image";
   public static final String XML_MSG_VOICE = "voice";
+  public static final String XML_MSG_SHORTVIDEO = "shortvideo";
   public static final String XML_MSG_VIDEO = "video";
   public static final String XML_MSG_NEWS = "news";
   public static final String XML_MSG_MUSIC = "music";

From c040ba3929415f3de1609792af8119101f747451 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Mon, 18 Jul 2016 12:10:12 +0800
Subject: [PATCH 37/54] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9F=A5=E7=9C=8B?=
 =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95=E7=9A=84?=
 =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20#5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 weixin-java-mp/pom.xml                        |  6 ++
 .../weixin/mp/api/WxMpKefuService.java        | 26 ++++--
 .../mp/api/impl/WxMpKefuServiceImpl.java      | 56 +++++++-----
 .../mp/bean/kefu/result/WxMpKfMsgList.java    | 55 ++++++++++++
 .../mp/bean/kefu/result/WxMpKfMsgRecord.java  | 87 +++++++++++++++++++
 .../mp/api/impl/WxMpKefuServiceImplTest.java  | 22 +++--
 6 files changed, 220 insertions(+), 32 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java

diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml
index 47daf6793d..a338ff5c57 100644
--- a/weixin-java-mp/pom.xml
+++ b/weixin-java-mp/pom.xml
@@ -47,6 +47,12 @@
             org.eclipse.jetty
             jetty-servlet
             test
+        
+        
+            joda-time
+            joda-time
+            2.9.4
+            test
         
     
 
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
index fc927bc4f2..38eaa8a009 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java
@@ -1,14 +1,11 @@
 package me.chanjar.weixin.mp.api;
 
 import java.io.File;
+import java.util.Date;
 
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
-import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList;
-import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList;
-import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult;
-import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList;
-import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList;
+import me.chanjar.weixin.mp.bean.kefu.result.*;
 
 /**
  * 客服接口 ,
@@ -135,4 +132,23 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
    * 
*/ WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException; + + //*******************获取聊天记录的接口***********************// + /** + *
+   * 获取聊天记录
+   * 此接口返回的聊天记录中,对于图片、语音、视频,分别展示成文本格式的[image]、[voice]、[video]
+   * 详情请见:获取聊天记录
+   * 接口url格式: https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token=ACCESS_TOKEN
+   * 
+ * + * @param startTime 起始时间 + * @param endTime 结束时间 + * @param msgId 消息id顺序从小到大,从1开始 + * @param number 每次获取条数,最多10000条 + * @return 聊天记录对象 + * @throws WxErrorException + */ + WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException; + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index c78c873da5..d385770072 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -1,7 +1,10 @@ package me.chanjar.weixin.mp.api.impl; import java.io.File; +import java.util.Date; +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; @@ -10,11 +13,7 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; +import me.chanjar.weixin.mp.bean.kefu.result.*; /** * @@ -22,6 +21,7 @@ * */ public class WxMpKefuServiceImpl implements WxMpKefuService { + public static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; private WxMpService wxMpService; public WxMpKefuServiceImpl(WxMpService wxMpService) { @@ -30,7 +30,7 @@ public WxMpKefuServiceImpl(WxMpService wxMpService) { @Override public WxMpKfList kfList() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"; + String url = API_URL_PREFIX + "/getkflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfList.fromJson(responseContent); @@ -38,7 +38,7 @@ public WxMpKfList kfList() throws WxErrorException { @Override public WxMpKfOnlineList kfOnlineList() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"; + String url = API_URL_PREFIX + "/getonlinekflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfOnlineList.fromJson(responseContent); @@ -47,7 +47,7 @@ public WxMpKfOnlineList kfOnlineList() throws WxErrorException { @Override public boolean kfAccountAdd(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/add"; + String url = API_URL_PREFIX + "/kfaccount/add"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -56,7 +56,7 @@ public boolean kfAccountAdd(WxMpKfAccountRequest request) @Override public boolean kfAccountUpdate(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/update"; + String url = API_URL_PREFIX + "/kfaccount/update"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -64,7 +64,7 @@ public boolean kfAccountUpdate(WxMpKfAccountRequest request) @Override public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/inviteworker"; + String url = API_URL_PREFIX + "/kfaccount/inviteworker"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -73,16 +73,14 @@ public boolean kfAccountInviteWorker(WxMpKfAccountRequest request) throws WxErro @Override public boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfaccount/uploadheadimg?kf_account=" + kfAccount; this.wxMpService.execute(new MediaUploadRequestExecutor(), url, imgFile); return true; } @Override public boolean kfAccountDel(String kfAccount) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfaccount/del?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfaccount/del?kf_account=" + kfAccount; this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); return true; } @@ -91,7 +89,7 @@ public boolean kfAccountDel(String kfAccount) throws WxErrorException { public boolean kfSessionCreate(String openid, String kfAccount) throws WxErrorException { WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = "https://api.weixin.qq.com/customservice/kfsession/create"; + String url = API_URL_PREFIX + "/kfsession/create"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -101,7 +99,7 @@ public boolean kfSessionCreate(String openid, String kfAccount) public boolean kfSessionClose(String openid, String kfAccount) throws WxErrorException { WxMpKfSessionRequest request = new WxMpKfSessionRequest(kfAccount, openid); - String url = "https://api.weixin.qq.com/customservice/kfsession/close"; + String url = API_URL_PREFIX + "/kfsession/close"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, request.toJson()); return true; @@ -110,8 +108,7 @@ public boolean kfSessionClose(String openid, String kfAccount) @Override public WxMpKfSessionGetResult kfSessionGet(String openid) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getsession?openid=" - + openid; + String url = API_URL_PREFIX + "/kfsession/getsession?openid=" + openid; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionGetResult.fromJson(responseContent); @@ -120,8 +117,7 @@ public WxMpKfSessionGetResult kfSessionGet(String openid) @Override public WxMpKfSessionList kfSessionList(String kfAccount) throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getsessionlist?kf_account=" - + kfAccount; + String url = API_URL_PREFIX + "/kfsession/getsessionlist?kf_account=" + kfAccount; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionList.fromJson(responseContent); @@ -130,10 +126,28 @@ public WxMpKfSessionList kfSessionList(String kfAccount) @Override public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException { - String url = "https://api.weixin.qq.com/customservice/kfsession/getwaitcase"; + String url = API_URL_PREFIX + "/kfsession/getwaitcase"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfSessionWaitCaseList.fromJson(responseContent); } + @Override + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException { + if(startTime.after(endTime)){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("起始时间不能晚于结束时间!").build()); + } + + String url = API_URL_PREFIX + "/msgrecord/getmsglist"; + + JsonObject param = new JsonObject(); + param.addProperty("starttime", startTime.getTime() / 1000); //starttime 起始时间,unix时间戳 + param.addProperty("endtime", endTime.getTime() / 1000); //endtime 结束时间,unix时间戳,每次查询时段不能超过24小时 + param.addProperty("msgid", msgId); //msgid 消息id顺序从小到大,从1开始 + param.addProperty("number", number); //number 每次获取条数,最多10000条 + + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, param.toString()); + return WxMpKfMsgList.fromJson(responseContent); + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java new file mode 100644 index 0000000000..5078a2e5cf --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java @@ -0,0 +1,55 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +/** + * Created by Binary Wang on 2016/7/15. + */ +public class WxMpKfMsgList { + @SerializedName("recordlist") + private List records; + + @SerializedName("number") + private Integer number; + + @SerializedName("msgid") + private Long msgId; + + public List getRecords() { + return records; + } + + public void setRecords(List records) { + this.records = records; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public Long getMsgId() { + return msgId; + } + + public void setMsgId(Long msgId) { + this.msgId = msgId; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + + public static WxMpKfMsgList fromJson(String responseContent) { + return WxMpGsonBuilder.INSTANCE.create().fromJson(responseContent, WxMpKfMsgList.class); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java new file mode 100644 index 0000000000..00b7771e5a --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java @@ -0,0 +1,87 @@ +package me.chanjar.weixin.mp.bean.kefu.result; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.gson.annotations.SerializedName; +import me.chanjar.weixin.mp.util.json.WxLongTimeJsonSerializer; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Created by Binary Wang on 2016/7/18. + */ +public class WxMpKfMsgRecord { + /** + * worker 完整客服帐号,格式为:帐号前缀@公众号微信号 + */ + @SerializedName("worker") + private String worker; + + /** + * openid 用户标识 + */ + @SerializedName("openid") + private String openid; + + /** + * opercode 操作码,2002(客服发送信息),2003(客服接收消息) + */ + @SerializedName("opercode") + private Integer operateCode; + + /** + * text 聊天记录 + */ + @SerializedName("text") + private String text; + + /** + * time 操作时间,unix时间戳 + */ + @SerializedName("time") + @JsonSerialize(using = WxLongTimeJsonSerializer.class) + private Long time; + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE); + } + public String getWorker() { + return worker; + } + + public void setWorker(String worker) { + this.worker = worker; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Long getTime() { + return time; + } + + public void setTime(Long time) { + this.time = time; + } + + public Integer getOperateCode() { + return operateCode; + } + + public void setOperateCode(Integer operateCode) { + this.operateCode = operateCode; + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index f02649cc88..3f3e32dd65 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -1,7 +1,13 @@ package me.chanjar.weixin.mp.api.impl; import java.io.File; +import java.util.Date; +import ch.qos.logback.classic.BasicConfigurator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import me.chanjar.weixin.mp.bean.kefu.result.*; +import org.joda.time.DateTime; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; @@ -14,12 +20,6 @@ import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; -import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * 测试客服相关接口 @@ -145,4 +145,14 @@ public void testKfSessionGetWaitCase() throws WxErrorException { System.err.println(result); } + @Test + public void testKfMsgList() throws WxErrorException, JsonProcessingException { + BasicConfigurator.configureDefaultContext(); + Date startTime = DateTime.now().minusDays(1).toDate(); + Date endTime = DateTime.now().toDate(); + WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime, 0, 20); + Assert.assertNotNull(result); + System.err.println(new ObjectMapper().writeValueAsString(result)); + } + } From 21dcf17a360ff8d390dd14fb712c64fd3f7ad4a1 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 18 Jul 2016 14:36:15 +0800 Subject: [PATCH 38/54] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95=E7=9A=84?= =?UTF-8?q?=E9=87=8D=E8=BD=BD=E6=96=B9=E6=B3=95=EF=BC=8C=E6=96=B9=E4=BE=BF?= =?UTF-8?q?=E4=B8=80=E6=AC=A1=E6=80=A7=E8=8E=B7=E5=8F=96=E4=B8=80=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E9=97=B4=E9=9A=94=E5=86=85=E7=9A=84=E6=89=80?= =?UTF-8?q?=E6=9C=89=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpKefuService.java | 19 ++++++++++++-- .../mp/api/impl/WxMpKefuServiceImpl.java | 25 ++++++++++++++++++- .../mp/api/impl/WxMpKefuServiceImplTest.java | 13 +++++++--- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 38eaa8a009..7e14cb8f33 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -136,7 +136,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) //*******************获取聊天记录的接口***********************// /** *
-   * 获取聊天记录
+   * 获取聊天记录(原始接口)
    * 此接口返回的聊天记录中,对于图片、语音、视频,分别展示成文本格式的[image]、[voice]、[video]
    * 详情请见:获取聊天记录
    * 接口url格式: https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token=ACCESS_TOKEN
@@ -149,6 +149,21 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
    * @return 聊天记录对象
    * @throws WxErrorException
    */
-  WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException;
+  WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException;
+
+  /**
+   * 
+   * 获取聊天记录(优化接口,返回指定时间段内所有的聊天记录)
+   * 此接口返回的聊天记录中,对于图片、语音、视频,分别展示成文本格式的[image]、[voice]、[video]
+   * 详情请见:获取聊天记录
+   * 接口url格式: https://api.weixin.qq.com/customservice/msgrecord/getmsglist?access_token=ACCESS_TOKEN
+   * 
+ * + * @param startTime 起始时间 + * @param endTime 结束时间 + * @return 聊天记录对象 + * @throws WxErrorException + */ + WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index d385770072..f3df9af057 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -133,7 +133,11 @@ public WxMpKfSessionWaitCaseList kfSessionGetWaitCase() } @Override - public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Integer number) throws WxErrorException { + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer number) throws WxErrorException { + if(number > 10000){ + throw new WxErrorException(WxError.newBuilder().setErrorMsg("非法参数请求,每次最多查询10000条记录!").build()); + } + if(startTime.after(endTime)){ throw new WxErrorException(WxError.newBuilder().setErrorMsg("起始时间不能晚于结束时间!").build()); } @@ -150,4 +154,23 @@ public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Integer msgId, Inte return WxMpKfMsgList.fromJson(responseContent); } + @Override + public WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException { + int number = 10000; + WxMpKfMsgList result = this.kfMsgList(startTime,endTime, 1L, number); + Long msgId = result.getMsgId(); + + if(result != null && result.getNumber() >= number){ + WxMpKfMsgList followingResult = this.kfMsgList(startTime,endTime, msgId, number); + while(followingResult != null && followingResult.getRecords().size() > 0){ + result.getRecords().addAll(followingResult.getRecords()); + result.setNumber(result.getNumber() + followingResult.getNumber()); + result.setMsgId(followingResult.getMsgId()); + followingResult = this.kfMsgList(startTime,endTime, followingResult.getMsgId(), number); + } + } + + return result; + } + } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index 3f3e32dd65..edfdc0b6b8 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -147,12 +147,19 @@ public void testKfSessionGetWaitCase() throws WxErrorException { @Test public void testKfMsgList() throws WxErrorException, JsonProcessingException { - BasicConfigurator.configureDefaultContext(); Date startTime = DateTime.now().minusDays(1).toDate(); - Date endTime = DateTime.now().toDate(); - WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime, 0, 20); + Date endTime = DateTime.now().minusDays(0).toDate(); + WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime, 1L, 50); Assert.assertNotNull(result); System.err.println(new ObjectMapper().writeValueAsString(result)); } + @Test + public void testKfMsgListAll() throws WxErrorException, JsonProcessingException { + Date startTime = DateTime.now().minusDays(1).toDate(); + Date endTime = DateTime.now().minusDays(0).toDate(); + WxMpKfMsgList result = this.wxService.getKefuService().kfMsgList(startTime,endTime); + Assert.assertNotNull(result); + System.err.println(new ObjectMapper().writeValueAsString(result)); + } } From 48f032ca61b6b1c410bfdb51ac64e11f1046971a Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 18 Jul 2016 14:45:12 +0800 Subject: [PATCH 39/54] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index f3df9af057..e3ea3f6ad3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -21,7 +21,7 @@ * */ public class WxMpKefuServiceImpl implements WxMpKefuService { - public static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/customservice"; private WxMpService wxMpService; public WxMpKefuServiceImpl(WxMpService wxMpService) { @@ -158,9 +158,9 @@ public WxMpKfMsgList kfMsgList(Date startTime, Date endTime, Long msgId, Integer public WxMpKfMsgList kfMsgList(Date startTime, Date endTime) throws WxErrorException { int number = 10000; WxMpKfMsgList result = this.kfMsgList(startTime,endTime, 1L, number); - Long msgId = result.getMsgId(); - - if(result != null && result.getNumber() >= number){ + + if(result != null && result.getNumber() == number){ + Long msgId = result.getMsgId(); WxMpKfMsgList followingResult = this.kfMsgList(startTime,endTime, msgId, number); while(followingResult != null && followingResult.getRecords().size() > 0){ result.getRecords().addAll(followingResult.getRecords()); From 34d4fa523c013fa4c6efd94bc616e394bf56bc08 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Mon, 18 Jul 2016 14:52:54 +0800 Subject: [PATCH 40/54] =?UTF-8?q?=E7=BC=96=E8=AF=91=E6=89=93=E5=8C=85?= =?UTF-8?q?=E6=97=B6=E9=BB=98=E8=AE=A4=E8=B7=B3=E8=BF=87test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index d80a752f8a..691a394a6d 100644 --- a/pom.xml +++ b/pom.xml @@ -236,6 +236,9 @@ org.apache.maven.plugins maven-surefire-plugin 2.17 + + true + From fe9ed76f6f2c9f5db3ca870d3e09557f7481b0ad Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Tue, 19 Jul 2016 14:50:49 +0800 Subject: [PATCH 41/54] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E6=9C=89=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E7=9A=84=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java index d0d9cde23c..f07b09e67f 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java @@ -12,7 +12,7 @@ * @author chanjarster * */ -@Test(groups="customMessageAPI", dependsOnGroups = "baseAPI") +@Test(groups="customMessageAPI") @Guice(modules = ApiTestModule.class) public class WxMpCustomMessageAPITest { From ff801044c237bc4a6d3586f1fb7690c736b36d53 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Tue, 19 Jul 2016 15:21:33 +0800 Subject: [PATCH 42/54] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bean/kefu/request/WxMpKfAccountRequest.java | 4 ---- .../mp/api/impl/WxMpKefuServiceImplTest.java | 15 ++++++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java index dabdcb76da..b1f0fac8f0 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/request/WxMpKfAccountRequest.java @@ -2,7 +2,6 @@ import java.io.Serializable; -import org.apache.commons.codec.digest.Md5Crypt; import org.apache.commons.lang3.builder.ToStringBuilder; import com.google.gson.annotations.SerializedName; @@ -72,19 +71,16 @@ public static class Builder { private String nickName; private String inviteWx; - @SuppressWarnings("hiding") public Builder kfAccount(String kfAccount) { this.kfAccount = kfAccount; return this; } - @SuppressWarnings("hiding") public Builder nickName(String nickName) { this.nickName = nickName; return this; } - @SuppressWarnings("hiding") public Builder inviteWx(String inviteWx) { this.inviteWx = inviteWx; return this; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index edfdc0b6b8..b63fa8413a 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -3,16 +3,14 @@ import java.io.File; import java.util.Date; -import ch.qos.logback.classic.BasicConfigurator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import me.chanjar.weixin.mp.bean.kefu.result.*; import org.joda.time.DateTime; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; @@ -20,6 +18,13 @@ import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * 测试客服相关接口 @@ -121,7 +126,7 @@ public void testKfSessionClose(String kfAccount, String openid) } @Test(dataProvider = "getKfAccountAndOpenid") - public void testKfSessionGet(@SuppressWarnings("unused") String kfAccount, + public void testKfSessionGet(String kfAccount, String openid) throws WxErrorException { WxMpKfSessionGetResult result = this.wxService.getKefuService() .kfSessionGet(openid); From b88560d9af1dff3a1fc9b6baf318b99fa00bfc59 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Tue, 19 Jul 2016 15:32:12 +0800 Subject: [PATCH 43/54] =?UTF-8?q?=E5=8F=91=E9=80=81=E5=AE=A2=E6=9C=8D?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=8E=A5=E5=8F=A3=E6=94=AF=E6=8C=81=E4=BB=A5?= =?UTF-8?q?=E6=9F=90=E4=B8=AA=E5=AE=A2=E6=9C=8D=E7=9A=84=E5=90=8D=E4=B9=89?= =?UTF-8?q?=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chanjar/weixin/mp/bean/WxMpCustomMessage.java | 9 +++++++++ .../mp/util/json/WxMpCustomMessageGsonAdapter.java | 8 ++++++++ .../weixin/mp/api/WxMpCustomMessageAPITest.java | 13 ++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java index 61a268b0a5..5fce97a3f3 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCustomMessage.java @@ -24,6 +24,7 @@ public class WxMpCustomMessage implements Serializable { private String description; private String musicUrl; private String hqMusicUrl; + private String kfAccount; private List articles = new ArrayList<>(); public String getToUser() { @@ -180,4 +181,12 @@ public static NewsBuilder NEWS() { return new NewsBuilder(); } + public String getKfAccount() { + return kfAccount; + } + + public void setKfAccount(String kfAccount) { + this.kfAccount = kfAccount; + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCustomMessageGsonAdapter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCustomMessageGsonAdapter.java index 3dc0515d59..4e72752a6f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCustomMessageGsonAdapter.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxMpCustomMessageGsonAdapter.java @@ -14,6 +14,8 @@ import java.lang.reflect.Type; +import org.apache.commons.lang3.StringUtils; + public class WxMpCustomMessageGsonAdapter implements JsonSerializer { public JsonElement serialize(WxMpCustomMessage message, Type typeOfSrc, JsonSerializationContext context) { @@ -73,6 +75,12 @@ public JsonElement serialize(WxMpCustomMessage message, Type typeOfSrc, JsonSeri messageJson.add("news", newsJsonObject); } + if (StringUtils.isNotBlank(message.getKfAccount())){ + JsonObject newsJsonObject = new JsonObject(); + newsJsonObject.addProperty("kf_account", message.getKfAccount()); + messageJson.add("customservice", newsJsonObject); + } + return messageJson; } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java index f07b09e67f..92a641dfec 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java @@ -26,7 +26,18 @@ public void testSendCustomMessage() throws WxErrorException { message.setToUser(configStorage.getOpenId()); message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); - wxService.customMessageSend(message); + this.wxService.customMessageSend(message); + } + + public void testSendCustomMessageWithKfAccount() throws WxErrorException { + ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; + WxMpCustomMessage message = new WxMpCustomMessage(); + message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); + message.setToUser(configStorage.getOpenId()); + message.setKfAccount(configStorage.getKfAccount()); + message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); + + this.wxService.customMessageSend(message); } } From fd3844428be2118dd3598960232b1c968779b573 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Tue, 19 Jul 2016 18:05:25 +0800 Subject: [PATCH 44/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E7=9A=84=E6=8E=A5=E5=8F=A3=E6=A0=BC=E5=BC=8F=E6=B7=B7=E4=B9=B1?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81=E6=9C=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/impl/WxMpKefuServiceImpl.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java index e3ea3f6ad3..6d6cf14c95 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImpl.java @@ -4,6 +4,7 @@ import java.util.Date; import com.google.gson.JsonObject; + import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; @@ -13,7 +14,12 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfSessionRequest; -import me.chanjar.weixin.mp.bean.kefu.result.*; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfMsgList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionGetResult; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionList; +import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfSessionWaitCaseList; /** * @@ -30,7 +36,7 @@ public WxMpKefuServiceImpl(WxMpService wxMpService) { @Override public WxMpKfList kfList() throws WxErrorException { - String url = API_URL_PREFIX + "/getkflist"; + String url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfList.fromJson(responseContent); @@ -38,7 +44,7 @@ public WxMpKfList kfList() throws WxErrorException { @Override public WxMpKfOnlineList kfOnlineList() throws WxErrorException { - String url = API_URL_PREFIX + "/getonlinekflist"; + String url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"; String responseContent = this.wxMpService .execute(new SimpleGetRequestExecutor(), url, null); return WxMpKfOnlineList.fromJson(responseContent); From b0334905608ef2b1984b9d0da2faa6cce15f5e49 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Wed, 20 Jul 2016 09:07:10 +0800 Subject: [PATCH 45/54] Update WxLongTimeJsonSerializer.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复错误的日期格式 --- .../chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java index 576b1be35d..309c4b119c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/json/WxLongTimeJsonSerializer.java @@ -13,7 +13,7 @@ */ public class WxLongTimeJsonSerializer extends JsonSerializer { private static SimpleDateFormat DF = new SimpleDateFormat( - "yyyy-MM-dd hh:mm:ss"); + "yyyy-MM-dd HH:mm:ss"); @Override public void serialize(Long value, JsonGenerator gen, From 73bf3b0364da400790bb02dd34a85b738730d963 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Thu, 21 Jul 2016 12:35:45 +0800 Subject: [PATCH 46/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=B0=86=E7=B4=A0=E6=9D=90=E7=AE=A1=E7=90=86=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=9A=84=E6=8E=A5=E5=8F=A3=E7=A7=BB=E5=88=B0=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E4=B8=80=E4=B8=AA=E7=B1=BB=E4=B8=AD=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/WxMpMaterialService.java | 182 ++++++++++++++++++ .../me/chanjar/weixin/mp/api/WxMpService.java | 175 ++--------------- .../weixin/mp/api/WxMpServiceImpl.java | 128 +----------- .../mp/api/impl/WxMpMaterialServiceImpl.java | 155 +++++++++++++++ .../weixin/mp/api/WxMpMassMessageAPITest.java | 8 +- .../weixin/mp/api/WxMpMediaAPITest.java | 73 ------- .../WxMpMaterialServiceImplTest.java} | 134 ++++++++----- .../weixin/mp/demo/DemoImageHandler.java | 2 +- weixin-java-mp/src/test/resources/testng.xml | 7 +- 9 files changed, 454 insertions(+), 410 deletions(-) create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java delete mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMediaAPITest.java rename weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/{WxMpMaterialAPITest.java => impl/WxMpMaterialServiceImplTest.java} (63%) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java new file mode 100644 index 0000000000..a4b1864377 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java @@ -0,0 +1,182 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by Binary Wang on 2016/7/21. + * 素材管理的相关接口,包括媒体管理的接口, + * 即以https://api.weixin.qq.com/cgi-bin/material + * 和 https://api.weixin.qq.com/cgi-bin/media开头的接口 + */ +public interface WxMpMaterialService { + + /** + * 新增临时素材 + * @see #mediaUpload(String, String, InputStream) + * @param mediaType + * @param file + * @throws WxErrorException + */ + public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException; + + /** + *
+   * 获取临时素材
+   * 本接口即为原“下载多媒体文件”接口。
+   * 根据微信文档,视频文件下载不了,会返回null
+   * 详情请见: 获取临时素材
+   * 
+ * @param media_id + * @return 保存到本地的临时文件 + * @throws WxErrorException + */ + public File mediaDownload(String media_id) throws WxErrorException; + + /** + *
+   * 上传图文消息内的图片获取URL
+   * 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E5.86.85.E7.9A.84.E5.9B.BE.E7.89.87.E8.8E.B7.E5.8F.96URL.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
+   * 
+ * @param file + * @return WxMediaImgUploadResult 返回图片url + * @throws WxErrorException + */ + public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException; + + /** + *
+   * 新增临时素材
+   * 本接口即为原“上传多媒体文件”接口。
+   *
+   * 上传的多媒体文件有格式和大小限制,如下:
+   *   图片(image): 1M,支持JPG格式
+   *   语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
+   *   视频(video):10MB,支持MP4格式
+   *   缩略图(thumb):64KB,支持JPG格式
+   *
+   * 详情请见: 新增临时素材
+   * 
+ * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param inputStream 输入流 + * @throws WxErrorException + */ + public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; + + /** + *
+   * 上传非图文永久素材
+   *
+   * 上传的多媒体文件有格式和大小限制,如下:
+   *   图片(image): 图片大小不超过2M,支持bmp/png/jpeg/jpg/gif格式
+   *   语音(voice):语音大小不超过5M,长度不超过60秒,支持mp3/wma/wav/amr格式
+   *   视频(video):在上传视频素材时需要POST另一个表单,id为description,包含素材的描述信息,内容格式为JSON
+   *   缩略图(thumb):文档未说明
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
+   * 
+ * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial} + */ + public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException; + + /** + *
+   * 上传永久图文素材
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
+   * 
+ * @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews} + */ + public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException; + + /** + *
+   * 下载声音或者图片永久素材
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
+   * 
+ * @param media_id 永久素材的id + */ + public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException; + + /** + *
+   * 获取视频永久素材的信息和下载地址
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
+   * 
+ * @param media_id 永久素材的id + */ + public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException; + + /** + *
+   * 获取图文永久素材的信息
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
+   * 
+ * @param media_id 永久素材的id + */ + public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException; + + /** + *
+   * 更新图文永久素材
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html
+   * 
+ * @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate} + */ + public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException; + + /** + *
+   * 删除永久素材
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html
+   * 
+ * @param media_id 永久素材的id + */ + public boolean materialDelete(String media_id) throws WxErrorException; + + /** + *
+   * 获取各类素材总数
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/16/8cc64f8c189674b421bee3ed403993b8.html
+   * 
+ */ + public WxMpMaterialCountResult materialCount() throws WxErrorException; + + /** + *
+   * 分页获取图文素材列表
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
+   * 
+ * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 + * @param count 返回素材的数量,取值在1到20之间 + */ + public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException; + + /** + *
+   * 分页获取其他媒体素材列表
+   *
+   * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
+   * 
+ * @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 + * @param count 返回素材的数量,取值在1到20之间 + */ + public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 7e9e0d928a..3779c3c7c2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -110,157 +110,6 @@ public interface WxMpService { */ public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; - /** - *
-   * 新增临时素材
-   * 本接口即为原“上传多媒体文件”接口。
-   *
-   * 上传的多媒体文件有格式和大小限制,如下:
-   *   图片(image): 1M,支持JPG格式
-   *   语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
-   *   视频(video):10MB,支持MP4格式
-   *   缩略图(thumb):64KB,支持JPG格式
-   *
-   * 详情请见: 新增临时素材
-   * 
- * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param inputStream 输入流 - * @throws WxErrorException - */ - public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; - - /** - *
-   * 上传非图文永久素材
-   *
-   * 上传的多媒体文件有格式和大小限制,如下:
-   *   图片(image): 图片大小不超过2M,支持bmp/png/jpeg/jpg/gif格式
-   *   语音(voice):语音大小不超过5M,长度不超过60秒,支持mp3/wma/wav/amr格式
-   *   视频(video):在上传视频素材时需要POST另一个表单,id为description,包含素材的描述信息,内容格式为JSON
-   *   缩略图(thumb):文档未说明
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
-   * 
- * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial} - */ - public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException; - - /** - *
-   * 上传永久图文素材
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html
-   * 
- * @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews} - */ - public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException; - - /** - *
-   * 下载声音或者图片永久素材
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
-   * 
- * @param media_id 永久素材的id - */ - public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException; - - /** - *
-   * 获取视频永久素材的信息和下载地址
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
-   * 
- * @param media_id 永久素材的id - */ - public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException; - - /** - *
-   * 获取图文永久素材的信息
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html
-   * 
- * @param media_id 永久素材的id - */ - public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException; - - /** - *
-   * 更新图文永久素材
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html
-   * 
- * @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate} - */ - public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException; - - /** - *
-   * 删除永久素材
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html
-   * 
- * @param media_id 永久素材的id - */ - public boolean materialDelete(String media_id) throws WxErrorException; - - /** - *
-   * 获取各类素材总数
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/16/8cc64f8c189674b421bee3ed403993b8.html
-   * 
- */ - public WxMpMaterialCountResult materialCount() throws WxErrorException; - - /** - *
-   * 分页获取图文素材列表
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
-   * 
- * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 - * @param count 返回素材的数量,取值在1到20之间 - */ - public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException; - - /** - *
-   * 分页获取其他媒体素材列表
-   *
-   * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html
-   * 
- * @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 - * @param count 返回素材的数量,取值在1到20之间 - */ - public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException; - - /** - * 新增临时素材 - * @see #mediaUpload(String, String, InputStream) - * @param mediaType - * @param file - * @throws WxErrorException - */ - public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException; - - /** - *
-   * 获取临时素材
-   * 本接口即为原“下载多媒体文件”接口。
-   * 根据微信文档,视频文件下载不了,会返回null
-   * 详情请见: 获取临时素材
-   * 
- * @param media_id - * @return 保存到本地的临时文件 - * @throws WxErrorException - */ - public File mediaDownload(String media_id) throws WxErrorException; - /** *
    * 发送客服消息
@@ -881,17 +730,6 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa
      */
   public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception;
 
-  /**
-     * 
-     * 上传图文消息内的图片获取URL
-     * 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E5.86.85.E7.9A.84.E5.9B.BE.E7.89.87.E8.8E.B7.E5.8F.96URL.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
-     * 
- * @param file - * @return WxMediaImgUploadResult 返回图片url - * @throws WxErrorException - */ - public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException; - /** *
      * 设置所属行业
@@ -920,5 +758,16 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa
    * @return WxMpKefuService
    */ 
   WxMpKefuService getKefuService();
-  
+
+  /**
+   * 返回客服接口方法实现类,以方便调用个其各种接口
+   * @return WxMpMaterialService
+   */
+  WxMpMaterialService getMaterialService();
+
+  /**
+   * 获取WxMpConfigStorage 对象
+   * @return WxMpConfigStorage
+   */
+  WxMpConfigStorage getWxMpConfigStorage();
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index b9fa37aa9f..8b7997a50a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -18,6 +18,7 @@
 import java.util.TreeMap;
 import java.util.UUID;
 
+import me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImpl;
 import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.ClientProtocolException;
@@ -136,6 +137,8 @@ public class WxMpServiceImpl implements WxMpService {
   
   protected WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
 
+  protected WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);
+
   protected CloseableHttpClient httpClient;
 
   protected HttpHost httpProxy;
@@ -309,119 +312,6 @@ public WxMenu menuTryMatch(String userid) throws WxErrorException {
     }
   }
 
-  @Override
-  public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
-    return mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
-  }
-
-  @Override
-  public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
-    return execute(new MediaUploadRequestExecutor(), url, file);
-  }
-
-  @Override
-  public File mediaDownload(String media_id) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/media/get";
-    return execute(new MediaDownloadRequestExecutor(this.wxMpConfigStorage.getTmpDirFile()), url, "media_id=" + media_id);
-  }
-
-  @Override
-  public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=" + mediaType;
-    return execute(new MaterialUploadRequestExecutor(), url, material);
-  }
-
-  @Override
-  public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException {
-    if (news == null || news.isEmpty()) {
-      throw new IllegalArgumentException("news is empty!");
-    }
-    String url = "https://api.weixin.qq.com/cgi-bin/material/add_news";
-    String responseContent = post(url, news.toJson());
-    return WxMpMaterialUploadResult.fromJson(responseContent);
-  }
-
-  @Override
-  public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
-    return execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpConfigStorage.getTmpDirFile()), url, media_id);
-  }
-
-  @Override
-  public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
-    return execute(new MaterialVideoInfoRequestExecutor(), url, media_id);
-  }
-
-  @Override
-  public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
-    return execute(new MaterialNewsInfoRequestExecutor(), url, media_id);
-  }
-
-  @Override
-  public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/update_news";
-    String responseText = post(url, wxMpMaterialArticleUpdate.toJson());
-    WxError wxError = WxError.fromJson(responseText);
-    if (wxError.getErrorCode() == 0) {
-      return true;
-    } else {
-      throw new WxErrorException(wxError);
-    }
-  }
-
-  @Override
-  public boolean materialDelete(String media_id) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/del_material";
-    return execute(new MaterialDeleteRequestExecutor(), url, media_id);
-  }
-
-  @Override
-  public WxMpMaterialCountResult materialCount() throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount";
-    String responseText = get(url, null);
-    WxError wxError = WxError.fromJson(responseText);
-    if (wxError.getErrorCode() == 0) {
-      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialCountResult.class);
-    } else {
-      throw new WxErrorException(wxError);
-    }
-  }
-
-  @Override
-  public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
-    Map params = new HashMap<>();
-    params.put("type", WxConsts.MATERIAL_NEWS);
-    params.put("offset", offset);
-    params.put("count", count);
-    String responseText = post(url, WxGsonBuilder.create().toJson(params));
-    WxError wxError = WxError.fromJson(responseText);
-    if (wxError.getErrorCode() == 0) {
-      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialNewsBatchGetResult.class);
-    } else {
-      throw new WxErrorException(wxError);
-    }
-  }
-
-  @Override
-  public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
-    Map params = new HashMap<>();
-    params.put("type", type);
-    params.put("offset", offset);
-    params.put("count", count);
-    String responseText = post(url, WxGsonBuilder.create().toJson(params));
-    WxError wxError = WxError.fromJson(responseText);
-    if (wxError.getErrorCode() == 0) {
-      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialFileBatchGetResult.class);
-    } else {
-      throw new WxErrorException(wxError);
-    }
-  }
-
   @Override
   public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException {
     String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
@@ -877,6 +767,7 @@ public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
     this.httpClient = apacheHttpClientBuilder.build();
   }
 
+  @Override
   public WxMpConfigStorage getWxMpConfigStorage() {
     return this.wxMpConfigStorage;
   }
@@ -1406,12 +1297,6 @@ public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPrev
     return WxMpMassSendResult.fromJson(responseContent);
   }
 
-  @Override
-  public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg";
-    return execute(new MediaImgUploadRequestExecutor(), url, file);
-  }
-
   @Override
   public String setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException {
     if (null == wxMpIndustry.getPrimaryIndustry() || null == wxMpIndustry.getPrimaryIndustry().getId()
@@ -1433,5 +1318,10 @@ public WxMpIndustry getIndustry() throws WxErrorException {
   public WxMpKefuService getKefuService() {
     return this.kefuService;
   }
+
+  @Override
+  public WxMpMaterialService getMaterialService() {
+    return this.materialService;
+  }
   
 }
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java
new file mode 100644
index 0000000000..6befcc2bb1
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java
@@ -0,0 +1,155 @@
+package me.chanjar.weixin.mp.api.impl;
+
+import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.bean.result.WxError;
+import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.util.fs.FileUtils;
+import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor;
+import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
+import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
+import me.chanjar.weixin.common.util.json.WxGsonBuilder;
+import me.chanjar.weixin.mp.api.WxMpMaterialService;
+import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.*;
+import me.chanjar.weixin.mp.bean.result.*;
+import me.chanjar.weixin.mp.util.http.*;
+import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Created by Binary Wang on 2016/7/21.
+ */
+public class WxMpMaterialServiceImpl implements WxMpMaterialService {
+  private WxMpService wxMpService;
+
+  public WxMpMaterialServiceImpl(WxMpService wxMpService) {
+    this.wxMpService = wxMpService;
+  }
+
+  @Override
+  public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
+    return this.mediaUpload(mediaType, FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
+  }
+
+  @Override
+  public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
+    return this.wxMpService.execute(new MediaUploadRequestExecutor(), url, file);
+  }
+
+  @Override
+  public File mediaDownload(String media_id) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/media/get";
+    return this.wxMpService.execute(new MediaDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, "media_id=" + media_id);
+  }
+
+  @Override
+  public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=" + mediaType;
+    return this.wxMpService.execute(new MaterialUploadRequestExecutor(), url, material);
+  }
+
+  @Override
+  public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException {
+    if (news == null || news.isEmpty()) {
+      throw new IllegalArgumentException("news is empty!");
+    }
+    String url = "https://api.weixin.qq.com/cgi-bin/material/add_news";
+    String responseContent = this.wxMpService.post(url, news.toJson());
+    return WxMpMaterialUploadResult.fromJson(responseContent);
+  }
+
+  @Override
+  public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
+    return this.wxMpService.execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, media_id);
+  }
+
+  @Override
+  public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
+    return this.wxMpService.execute(new MaterialVideoInfoRequestExecutor(), url, media_id);
+  }
+
+  @Override
+  public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/get_material";
+    return this.wxMpService.execute(new MaterialNewsInfoRequestExecutor(), url, media_id);
+  }
+
+  @Override
+  public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/update_news";
+    String responseText = this.wxMpService.post(url, wxMpMaterialArticleUpdate.toJson());
+    WxError wxError = WxError.fromJson(responseText);
+    if (wxError.getErrorCode() == 0) {
+      return true;
+    } else {
+      throw new WxErrorException(wxError);
+    }
+  }
+
+  @Override
+  public boolean materialDelete(String media_id) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/del_material";
+    return this.wxMpService.execute(new MaterialDeleteRequestExecutor(), url, media_id);
+  }
+
+  @Override
+  public WxMpMaterialCountResult materialCount() throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount";
+    String responseText = this.wxMpService.get(url, null);
+    WxError wxError = WxError.fromJson(responseText);
+    if (wxError.getErrorCode() == 0) {
+      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialCountResult.class);
+    } else {
+      throw new WxErrorException(wxError);
+    }
+  }
+
+  @Override
+  public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
+    Map params = new HashMap<>();
+    params.put("type", WxConsts.MATERIAL_NEWS);
+    params.put("offset", offset);
+    params.put("count", count);
+    String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params));
+    WxError wxError = WxError.fromJson(responseText);
+    if (wxError.getErrorCode() == 0) {
+      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialNewsBatchGetResult.class);
+    } else {
+      throw new WxErrorException(wxError);
+    }
+  }
+
+  @Override
+  public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material";
+    Map params = new HashMap<>();
+    params.put("type", type);
+    params.put("offset", offset);
+    params.put("count", count);
+    String responseText = this.wxMpService.post(url, WxGsonBuilder.create().toJson(params));
+    WxError wxError = WxError.fromJson(responseText);
+    if (wxError.getErrorCode() == 0) {
+      return WxMpGsonBuilder.create().fromJson(responseText, WxMpMaterialFileBatchGetResult.class);
+    } else {
+      throw new WxErrorException(wxError);
+    }
+  }
+
+  @Override
+  public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg";
+    return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file);
+  }
+
+}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java
index 73ebd1e2d3..6d276efd9c 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java
@@ -91,7 +91,7 @@ public Object[][] massMessages() throws WxErrorException, IOException {
     {
       // 上传视频到媒体库
       InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.mp4");
-      WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, inputStream);
+      WxMediaUploadResult uploadMediaRes = wxService.getMaterialService().mediaUpload(WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, inputStream);
       Assert.assertNotNull(uploadMediaRes);
       Assert.assertNotNull(uploadMediaRes.getMediaId());
       
@@ -110,7 +110,7 @@ public Object[][] massMessages() throws WxErrorException, IOException {
      */
     {
       InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg");
-      WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
+      WxMediaUploadResult uploadMediaRes = wxService.getMaterialService().mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
       Assert.assertNotNull(uploadMediaRes);
       Assert.assertNotNull(uploadMediaRes.getMediaId());
       messages[1] = new Object[] { WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMediaId() };
@@ -120,7 +120,7 @@ public Object[][] massMessages() throws WxErrorException, IOException {
      */
     {
       InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.mp3");
-      WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, inputStream);
+      WxMediaUploadResult uploadMediaRes = wxService.getMaterialService().mediaUpload(WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, inputStream);
       Assert.assertNotNull(uploadMediaRes);
       Assert.assertNotNull(uploadMediaRes.getMediaId());
       messages[2] = new Object[] { WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMediaId() };
@@ -131,7 +131,7 @@ public Object[][] massMessages() throws WxErrorException, IOException {
     {
       // 上传照片到媒体库
       InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg");
-      WxMediaUploadResult uploadMediaRes = wxService.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
+      WxMediaUploadResult uploadMediaRes = wxService.getMaterialService().mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
       Assert.assertNotNull(uploadMediaRes);
       Assert.assertNotNull(uploadMediaRes.getMediaId());
       
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMediaAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMediaAPITest.java
deleted file mode 100644
index b2fbc85144..0000000000
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMediaAPITest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package me.chanjar.weixin.mp.api;
-
-import com.google.inject.Inject;
-import me.chanjar.weixin.common.api.WxConsts;
-import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
-import me.chanjar.weixin.common.exception.WxErrorException;
-import org.testng.Assert;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Guice;
-import org.testng.annotations.Test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 测试多媒体文件上传下载
- * @author chanjarster
- *
- */
-@Test(groups="mediaAPI", dependsOnGroups="baseAPI")
-@Guice(modules = ApiTestModule.class)
-public class WxMpMediaAPITest {
-
-  @Inject
-  protected WxMpServiceImpl wxService;
-
-  private List media_ids = new ArrayList<>();
-  
-  @Test(dataProvider="uploadMedia")
-  public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
-    try(InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName)){
-      WxMediaUploadResult res = this.wxService.mediaUpload(mediaType, fileType, inputStream);
-      Assert.assertNotNull(res.getType());
-      Assert.assertNotNull(res.getCreatedAt());
-      Assert.assertTrue(res.getMediaId() != null || res.getThumbMediaId() != null);
-      
-      if (res.getMediaId() != null) {
-        this.media_ids.add(res.getMediaId());
-      }
-      
-      if (res.getThumbMediaId() != null) {
-        this.media_ids.add(res.getThumbMediaId());
-      }
-    }
-  }
-  
-  @DataProvider
-  public Object[][] uploadMedia() {
-    return new Object[][] {
-        new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg" },
-        new Object[] { WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3" },
-        new Object[] { WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4" },
-        new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg" }
-    };
-  }
-  
-  @Test(dependsOnMethods = { "testUploadMedia" }, dataProvider="downloadMedia")
-  public void testDownloadMedia(String media_id) throws WxErrorException {
-    this.wxService.mediaDownload(media_id);
-  }
-  
-  @DataProvider
-  public Object[][] downloadMedia() {
-    Object[][] params = new Object[this.media_ids.size()][];
-    for (int i = 0; i < this.media_ids.size(); i++) {
-      params[i] = new Object[] { this.media_ids.get(i) };
-    }
-    return params;
-  }
-  
-}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMaterialAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java
similarity index 63%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMaterialAPITest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java
index 8e145e15c3..abe962211c 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMaterialAPITest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java
@@ -1,9 +1,12 @@
-package me.chanjar.weixin.mp.api;
+package me.chanjar.weixin.mp.api.impl;
 
 import com.google.inject.Inject;
 import me.chanjar.weixin.common.api.WxConsts;
+import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.common.util.fs.FileUtils;
+import me.chanjar.weixin.mp.api.ApiTestModule;
+import me.chanjar.weixin.mp.api.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.WxMpMaterial;
 import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate;
 import me.chanjar.weixin.mp.bean.WxMpMaterialNews;
@@ -20,14 +23,15 @@
 import java.util.*;
 
 /**
- * 测试多媒体文件上传下载
+ * 素材管理相关接口的测试
  *
+ * @author chanjarster
  * @author codepiano
+ * @author Binary Wang
  */
 @Test(groups = "materialAPI")
 @Guice(modules = ApiTestModule.class)
-public class WxMpMaterialAPITest {
-
+public class WxMpMaterialServiceImplTest {
   @Inject
   protected WxMpServiceImpl wxService;
 
@@ -41,10 +45,20 @@ public class WxMpMaterialAPITest {
   // 先查询保存测试开始前永久素材数据
   private WxMpMaterialCountResult wxMaterialCountResultBeforeTest;
 
-  @Test(dataProvider = "uploadMaterial")
+  @DataProvider
+  public Object[][] uploadMedia() {
+    return new Object[][] {
+            new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg" },
+            new Object[] { WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3" },
+            new Object[] { WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4" },
+            new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg" }
+    };
+  }
+
+  @Test(dataProvider = "uploadMedia")
   public void testUploadMaterial(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
     if (wxMaterialCountResultBeforeTest == null) {
-      wxMaterialCountResultBeforeTest = wxService.materialCount();
+      wxMaterialCountResultBeforeTest = this.wxService.getMaterialService().materialCount();
     }
     InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
     File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType);
@@ -55,7 +69,7 @@ public void testUploadMaterial(String mediaType, String fileType, String fileNam
       wxMaterial.setVideoTitle("title");
       wxMaterial.setVideoIntroduction("test video description");
     }
-    WxMpMaterialUploadResult res = wxService.materialFileUpload(mediaType, wxMaterial);
+    WxMpMaterialUploadResult res = this.wxService.getMaterialService().materialFileUpload(mediaType, wxMaterial);
     Assert.assertNotNull(res.getMediaId());
     if (WxConsts.MEDIA_IMAGE.equals(mediaType) || WxConsts.MEDIA_THUMB.equals(mediaType)) {
       Assert.assertNotNull(res.getUrl());
@@ -69,6 +83,8 @@ public void testUploadMaterial(String mediaType, String fileType, String fileNam
     materialInfo.put("length", tempFile.length());
     materialInfo.put("filename", tempFile.getName());
     media_ids.put(res.getMediaId(), materialInfo);
+
+    System.out.println(res);
   }
 
   @Test(dependsOnMethods = {"testUploadMaterial"})
@@ -88,14 +104,14 @@ public void testAddNews() throws WxErrorException {
 
     // 多图文消息
     WxMpMaterialNews wxMpMaterialNewsMultiple = new WxMpMaterialNews();
-    WxMpMaterialNews.WxMpMaterialNewsArticle wxMpMaterialNewsArticleMutiple1 = new WxMpMaterialNews.WxMpMaterialNewsArticle();
-    wxMpMaterialNewsArticleMutiple1.setAuthor("author1");
-    wxMpMaterialNewsArticleMutiple1.setThumbMediaId(thumbMediaId);
-    wxMpMaterialNewsArticleMutiple1.setTitle("multi title1");
-    wxMpMaterialNewsArticleMutiple1.setContent("content 1");
-    wxMpMaterialNewsArticleMutiple1.setContentSourceUrl("content url");
-    wxMpMaterialNewsArticleMutiple1.setShowCoverPic(true);
-    wxMpMaterialNewsArticleMutiple1.setDigest("");
+    WxMpMaterialNews.WxMpMaterialNewsArticle wxMpMaterialNewsArticleMultiple1 = new WxMpMaterialNews.WxMpMaterialNewsArticle();
+    wxMpMaterialNewsArticleMultiple1.setAuthor("author1");
+    wxMpMaterialNewsArticleMultiple1.setThumbMediaId(thumbMediaId);
+    wxMpMaterialNewsArticleMultiple1.setTitle("multi title1");
+    wxMpMaterialNewsArticleMultiple1.setContent("content 1");
+    wxMpMaterialNewsArticleMultiple1.setContentSourceUrl("content url");
+    wxMpMaterialNewsArticleMultiple1.setShowCoverPic(true);
+    wxMpMaterialNewsArticleMultiple1.setDigest("");
 
     WxMpMaterialNews.WxMpMaterialNewsArticle wxMpMaterialNewsArticleMultiple2 = new WxMpMaterialNews.WxMpMaterialNewsArticle();
     wxMpMaterialNewsArticleMultiple2.setAuthor("author2");
@@ -106,18 +122,18 @@ public void testAddNews() throws WxErrorException {
     wxMpMaterialNewsArticleMultiple2.setShowCoverPic(true);
     wxMpMaterialNewsArticleMultiple2.setDigest("");
 
-    wxMpMaterialNewsMultiple.addArticle(wxMpMaterialNewsArticleMutiple1);
+    wxMpMaterialNewsMultiple.addArticle(wxMpMaterialNewsArticleMultiple1);
     wxMpMaterialNewsMultiple.addArticle(wxMpMaterialNewsArticleMultiple2);
 
-    WxMpMaterialUploadResult resSingle = wxService.materialNewsUpload(wxMpMaterialNewsSingle);
+    WxMpMaterialUploadResult resSingle = this.wxService.getMaterialService().materialNewsUpload(wxMpMaterialNewsSingle);
     singleNewsMediaId = resSingle.getMediaId();
-    WxMpMaterialUploadResult resMulti = wxService.materialNewsUpload(wxMpMaterialNewsMultiple);
+    WxMpMaterialUploadResult resMulti = this.wxService.getMaterialService().materialNewsUpload(wxMpMaterialNewsMultiple);
     multiNewsMediaId = resMulti.getMediaId();
   }
 
   @Test(dependsOnMethods = {"testAddNews"})
   public void testMaterialCount() throws WxErrorException {
-    WxMpMaterialCountResult wxMaterialCountResult = wxService.materialCount();
+    WxMpMaterialCountResult wxMaterialCountResult = this.wxService.getMaterialService().materialCount();
     // 测试上传过程中添加了一个音频,一个视频,两个图片,两个图文消息
     Assert.assertEquals(wxMaterialCountResultBeforeTest.getVoiceCount() + 1, wxMaterialCountResult.getVoiceCount());
     Assert.assertEquals(wxMaterialCountResultBeforeTest.getVideoCount() + 1, wxMaterialCountResult.getVideoCount());
@@ -125,29 +141,18 @@ public void testMaterialCount() throws WxErrorException {
     Assert.assertEquals(wxMaterialCountResultBeforeTest.getNewsCount() + 2, wxMaterialCountResult.getNewsCount());
   }
 
-
-  @DataProvider
-  public Object[][] uploadMaterial() {
-    return new Object[][]{
-        new Object[]{WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg"},
-        new Object[]{WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3"},
-        new Object[]{WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4"},
-        new Object[]{WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg"}
-    };
-  }
-
   @Test(dependsOnMethods = {"testMaterialCount"}, dataProvider = "downloadMaterial")
   public void testDownloadMaterial(String media_id) throws WxErrorException, IOException {
     Map materialInfo = media_ids.get(media_id);
     Assert.assertNotNull(materialInfo);
     String filename = materialInfo.get("filename").toString();
     if (filename.endsWith(".mp3") || filename.endsWith(".jpeg")) {
-      InputStream inputStream = wxService.materialImageOrVoiceDownload(media_id);
+      InputStream inputStream = this.wxService.getMaterialService().materialImageOrVoiceDownload(media_id);
       Assert.assertNotNull(inputStream);
       IOUtils.closeQuietly(inputStream);
     }
     if (filename.endsWith("mp4")) {
-      WxMpMaterialVideoInfoResult wxMaterialVideoInfoResult = wxService.materialVideoInfo(media_id);
+      WxMpMaterialVideoInfoResult wxMaterialVideoInfoResult = this.wxService.getMaterialService().materialVideoInfo(media_id);
       Assert.assertNotNull(wxMaterialVideoInfoResult);
       Assert.assertNotNull(wxMaterialVideoInfoResult.getDownUrl());
     }
@@ -155,15 +160,15 @@ public void testDownloadMaterial(String media_id) throws WxErrorException, IOExc
 
   @Test(dependsOnMethods = {"testAddNews"})
   public void testGetNewsInfo() throws WxErrorException {
-    WxMpMaterialNews wxMpMaterialNewsSingle = wxService.materialNewsInfo(singleNewsMediaId);
-    WxMpMaterialNews wxMpMaterialNewsMultiple = wxService.materialNewsInfo(multiNewsMediaId);
+    WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService.getMaterialService().materialNewsInfo(singleNewsMediaId);
+    WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService.getMaterialService().materialNewsInfo(multiNewsMediaId);
     Assert.assertNotNull(wxMpMaterialNewsSingle);
     Assert.assertNotNull(wxMpMaterialNewsMultiple);
   }
 
   @Test(dependsOnMethods = {"testGetNewsInfo"})
   public void testUpdateNewsInfo() throws WxErrorException {
-    WxMpMaterialNews wxMpMaterialNewsSingle = wxService.materialNewsInfo(singleNewsMediaId);
+    WxMpMaterialNews wxMpMaterialNewsSingle = this.wxService.getMaterialService().materialNewsInfo(singleNewsMediaId);
     Assert.assertNotNull(wxMpMaterialNewsSingle);
     WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateSingle = new WxMpMaterialArticleUpdate();
     WxMpMaterialNews.WxMpMaterialNewsArticle articleSingle = wxMpMaterialNewsSingle.getArticles().get(0);
@@ -171,13 +176,13 @@ public void testUpdateNewsInfo() throws WxErrorException {
     wxMpMaterialArticleUpdateSingle.setMediaId(singleNewsMediaId);
     wxMpMaterialArticleUpdateSingle.setArticles(articleSingle);
     wxMpMaterialArticleUpdateSingle.setIndex(0);
-    boolean resultSingle = wxService.materialNewsUpdate(wxMpMaterialArticleUpdateSingle);
+    boolean resultSingle = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateSingle);
     Assert.assertTrue(resultSingle);
-    wxMpMaterialNewsSingle = wxService.materialNewsInfo(singleNewsMediaId);
+    wxMpMaterialNewsSingle = this.wxService.getMaterialService().materialNewsInfo(singleNewsMediaId);
     Assert.assertNotNull(wxMpMaterialNewsSingle);
     Assert.assertEquals("content single update", wxMpMaterialNewsSingle.getArticles().get(0).getContent());
 
-    WxMpMaterialNews wxMpMaterialNewsMultiple = wxService.materialNewsInfo(multiNewsMediaId);
+    WxMpMaterialNews wxMpMaterialNewsMultiple = this.wxService.getMaterialService().materialNewsInfo(multiNewsMediaId);
     Assert.assertNotNull(wxMpMaterialNewsMultiple);
     WxMpMaterialArticleUpdate wxMpMaterialArticleUpdateMulti = new WxMpMaterialArticleUpdate();
     WxMpMaterialNews.WxMpMaterialNewsArticle articleMulti = wxMpMaterialNewsMultiple.getArticles().get(1);
@@ -185,31 +190,30 @@ public void testUpdateNewsInfo() throws WxErrorException {
     wxMpMaterialArticleUpdateMulti.setMediaId(multiNewsMediaId);
     wxMpMaterialArticleUpdateMulti.setArticles(articleMulti);
     wxMpMaterialArticleUpdateMulti.setIndex(1);
-    boolean resultMulti = wxService.materialNewsUpdate(wxMpMaterialArticleUpdateMulti);
+    boolean resultMulti = this.wxService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdateMulti);
     Assert.assertTrue(resultMulti);
-    wxMpMaterialNewsMultiple = wxService.materialNewsInfo(multiNewsMediaId);
+    wxMpMaterialNewsMultiple = this.wxService.getMaterialService().materialNewsInfo(multiNewsMediaId);
     Assert.assertNotNull(wxMpMaterialNewsMultiple);
     Assert.assertEquals("content 2 update", wxMpMaterialNewsMultiple.getArticles().get(1).getContent());
   }
 
-
   @Test(dependsOnMethods = {"testUpdateNewsInfo"})
   public void testMaterialNewsList() throws WxErrorException {
-    WxMpMaterialNewsBatchGetResult wxMpMaterialNewsBatchGetResult = wxService.materialNewsBatchGet(0, 20);
+    WxMpMaterialNewsBatchGetResult wxMpMaterialNewsBatchGetResult = this.wxService.getMaterialService().materialNewsBatchGet(0, 20);
     return;
   }
 
   @Test(dependsOnMethods = {"testMaterialNewsList"})
   public void testMaterialFileList() throws WxErrorException {
-    WxMpMaterialFileBatchGetResult wxMpMaterialVoiceBatchGetResult = wxService.materialFileBatchGet(WxConsts.MATERIAL_VOICE, 0, 20);
-    WxMpMaterialFileBatchGetResult wxMpMaterialVideoBatchGetResult = wxService.materialFileBatchGet(WxConsts.MATERIAL_VIDEO, 0, 20);
-    WxMpMaterialFileBatchGetResult wxMpMaterialImageBatchGetResult = wxService.materialFileBatchGet(WxConsts.MATERIAL_IMAGE, 0, 20);
+    WxMpMaterialFileBatchGetResult wxMpMaterialVoiceBatchGetResult = this.wxService.getMaterialService().materialFileBatchGet(WxConsts.MATERIAL_VOICE, 0, 20);
+    WxMpMaterialFileBatchGetResult wxMpMaterialVideoBatchGetResult = this.wxService.getMaterialService().materialFileBatchGet(WxConsts.MATERIAL_VIDEO, 0, 20);
+    WxMpMaterialFileBatchGetResult wxMpMaterialImageBatchGetResult = this.wxService.getMaterialService().materialFileBatchGet(WxConsts.MATERIAL_IMAGE, 0, 20);
     return;
   }
 
   @Test(dependsOnMethods = {"testMaterialFileList"}, dataProvider = "allTestMaterial")
   public void testDeleteMaterial(String mediaId) throws WxErrorException {
-    boolean result = wxService.materialDelete(mediaId);
+    boolean result = this.wxService.getMaterialService().materialDelete(mediaId);
     Assert.assertTrue(result);
   }
 
@@ -234,4 +238,42 @@ public Iterator allTestMaterial() {
     params.add(new Object[]{this.multiNewsMediaId});
     return params.iterator();
   }
+
+  // 以下为media接口的测试
+  private List mediaIds = new ArrayList<>();
+  @Test(dataProvider="uploadMedia")
+  public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
+    try(InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName)){
+      WxMediaUploadResult res = this.wxService.getMaterialService().mediaUpload(mediaType, fileType, inputStream);
+      Assert.assertNotNull(res.getType());
+      Assert.assertNotNull(res.getCreatedAt());
+      Assert.assertTrue(res.getMediaId() != null || res.getThumbMediaId() != null);
+
+      if (res.getMediaId() != null) {
+        this.mediaIds.add(res.getMediaId());
+      }
+
+      if (res.getThumbMediaId() != null) {
+        this.mediaIds.add(res.getThumbMediaId());
+      }
+
+      System.out.println(res);
+    }
+  }
+
+  @Test(dependsOnMethods = { "testUploadMedia" }, dataProvider="downloadMedia")
+  public void testDownloadMedia(String media_id) throws WxErrorException {
+    File file = this.wxService.getMaterialService().mediaDownload(media_id);
+    Assert.assertNotNull(file);
+    System.out.println(file.getAbsolutePath());
+  }
+
+  @DataProvider
+  public Object[][] downloadMedia() {
+    Object[][] params = new Object[this.mediaIds.size()][];
+    for (int i = 0; i < this.mediaIds.size(); i++) {
+      params[i] = new Object[] { this.mediaIds.get(i) };
+    }
+    return params;
+  }
 }
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
index 8cc505427c..a22f28d79d 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
@@ -18,7 +18,7 @@ public class DemoImageHandler implements WxMpMessageHandler {
   public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map context,
       WxMpService wxMpService, WxSessionManager sessionManager) {
     try {
-      WxMediaUploadResult wxMediaUploadResult = wxMpService
+      WxMediaUploadResult wxMediaUploadResult = wxMpService.getMaterialService()
           .mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
       WxMpXmlOutImageMessage m
           = WxMpXmlOutMessage
diff --git a/weixin-java-mp/src/test/resources/testng.xml b/weixin-java-mp/src/test/resources/testng.xml
index cb1263d317..003af42822 100644
--- a/weixin-java-mp/src/test/resources/testng.xml
+++ b/weixin-java-mp/src/test/resources/testng.xml
@@ -3,19 +3,18 @@
 
 	
 		
-      
+      		
 			
 			
 			
 			
 			
-			
 			
 			
 			
 			
-      
-      
+			
+			
 		
 	
 

From a3fcaa0198431de6f70d9eb753d82ebfdae9318f Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 21 Jul 2016 12:36:49 +0800
Subject: [PATCH 47/54] =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=B0=8F=E7=9A=84?=
 =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../github/binarywang/demo/spring/handler/LogHandler.java | 2 +-
 .../binarywang/demo/spring/handler/SubscribeHandler.java  | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
index 87cb09966a..7d9bc02c25 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/LogHandler.java
@@ -22,7 +22,7 @@ public class LogHandler extends AbstractHandler {
   public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
       Map context, WxMpService wxMpService,
       WxSessionManager sessionManager) {
-    this.logger.info("接收到请求消息,内容:【{}】", wxMessage.toString());
+    this.logger.info("\n接收到请求消息,内容:【{}】", wxMessage.toString());
     return null;
   }
 
diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
index f5bd64604f..27455b375e 100644
--- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
+++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java
@@ -34,15 +34,15 @@ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map co
       // TODO 可以添加关注用户到本地
     }
 
-    WxMpXmlOutMessage responsResult = null;
+    WxMpXmlOutMessage responseResult = null;
     try {
-      responsResult = handleSpecial(wxMessage);
+      responseResult = handleSpecial(wxMessage);
     } catch (Exception e) {
       this.logger.error(e.getMessage(), e);
     }
 
-    if (responsResult != null) {
-      return responsResult;
+    if (responseResult != null) {
+      return responseResult;
     }
 
     try {

From 175bf9bbbab76f320e6d779cc36de6a29574179b Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 21 Jul 2016 15:15:16 +0800
Subject: [PATCH 48/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=EF=BC=8C=E5=B0=86=E8=8F=9C=E5=8D=95=E7=AE=A1=E7=90=86=E7=9B=B8?=
 =?UTF-8?q?=E5=85=B3=E7=9A=84=E6=8E=A5=E5=8F=A3=E7=A7=BB=E5=88=B0=E5=8D=95?=
 =?UTF-8?q?=E7=8B=AC=E4=B8=80=E4=B8=AA=E7=B1=BB=E4=B8=AD=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/mp/api/WxMpMenuService.java        | 62 +++++++++++++
 .../me/chanjar/weixin/mp/api/WxMpService.java | 65 ++------------
 .../weixin/mp/api/WxMpServiceImpl.java        | 89 +++----------------
 .../mp/api/impl/WxMpMenuServiceImpl.java      | 73 +++++++++++++++
 .../WxMpMenuServiceImplTest.java}             | 19 ++--
 weixin-java-mp/src/test/resources/testng.xml  |  2 +-
 6 files changed, 165 insertions(+), 145 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java
 rename weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/{WxMpMenuAPITest.java => impl/WxMpMenuServiceImplTest.java} (87%)

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
new file mode 100644
index 0000000000..865bfb008e
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMenuService.java
@@ -0,0 +1,62 @@
+package me.chanjar.weixin.mp.api;
+
+import me.chanjar.weixin.common.bean.WxMenu;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest;
+import me.chanjar.weixin.mp.bean.kefu.result.*;
+
+import java.io.File;
+import java.util.Date;
+
+/**
+ * 菜单相关操作接口
+ * @author Binary Wang
+ *
+ */
+public interface WxMpMenuService {
+
+  /**
+   * 
+   * 自定义菜单创建接口
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口
+   * 如果要创建个性化菜单,请设置matchrule属性
+   * 详情请见:http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+   * 
+ */ + public void menuCreate(WxMenu menu) throws WxErrorException; + + /** + *
+   * 自定义菜单删除接口
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单删除接口
+   * 
+ */ + public void menuDelete() throws WxErrorException; + + /** + *
+   * 删除个性化菜单接口
+   * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+   * 
+ * @param menuid + */ + public void menuDelete(String menuid) throws WxErrorException; + + /** + *
+   * 自定义菜单查询接口
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单查询接口
+   * 
+ */ + public WxMenu menuGet() throws WxErrorException; + + /** + *
+   * 测试个性化菜单匹配结果
+   * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
+   * 
+ * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 + */ + public WxMenu menuTryMatch(String userid) throws WxErrorException; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 3779c3c7c2..2dc9426079 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -1,8 +1,6 @@ package me.chanjar.weixin.mp.api; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; @@ -10,8 +8,6 @@ import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature; -import me.chanjar.weixin.common.bean.WxMenu; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.mp.bean.WxMpCustomMessage; @@ -22,20 +18,11 @@ import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; import me.chanjar.weixin.mp.bean.WxMpMassVideo; -import me.chanjar.weixin.mp.bean.WxMpMaterial; -import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; -import me.chanjar.weixin.mp.bean.WxMpMaterialNews; import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; -import me.chanjar.weixin.mp.bean.result.WxMediaImgUploadResult; import me.chanjar.weixin.mp.bean.result.WxMpCardResult; import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult; -import me.chanjar.weixin.mp.bean.result.WxMpMaterialFileBatchGetResult; -import me.chanjar.weixin.mp.bean.result.WxMpMaterialNewsBatchGetResult; -import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import me.chanjar.weixin.mp.bean.result.WxMpPayCallback; import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult; @@ -161,50 +148,6 @@ public interface WxMpService { */ public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException; - /** - *
-   * 自定义菜单创建接口
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口
-   * 如果要创建个性化菜单,请设置matchrule属性
-   * 详情请见:http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
-   * 
- */ - public void menuCreate(WxMenu menu) throws WxErrorException; - - /** - *
-   * 自定义菜单删除接口
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单删除接口
-   * 
- */ - public void menuDelete() throws WxErrorException; - - /** - *
-   * 删除个性化菜单接口
-   * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
-   * 
- * @param menuid - */ - public void menuDelete(String menuid) throws WxErrorException; - - /** - *
-   * 自定义菜单查询接口
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单查询接口
-   * 
- */ - public WxMenu menuGet() throws WxErrorException; - - /** - *
-   * 测试个性化菜单匹配结果
-   * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html
-   * 
- * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 - */ - public WxMenu menuTryMatch(String userid) throws WxErrorException; - /** *
    * 分组管理接口 - 创建分组
@@ -760,11 +703,17 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa
   WxMpKefuService getKefuService();
 
   /**
-   * 返回客服接口方法实现类,以方便调用个其各种接口
+   * 返回素材相关接口的方法实现类,以方便调用个其各种接口
    * @return WxMpMaterialService
    */
   WxMpMaterialService getMaterialService();
 
+  /**
+   * 返回素材相关接口的方法实现类,以方便调用个其各种接口
+   * @return WxMpMenuService
+   */
+  WxMpMenuService getMenuService();
+
   /**
    * 获取WxMpConfigStorage 对象
    * @return WxMpConfigStorage
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
index 8b7997a50a..c7ab51c89b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
@@ -2,7 +2,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
@@ -16,9 +15,7 @@
 import java.util.Map.Entry;
 import java.util.SortedMap;
 import java.util.TreeMap;
-import java.util.UUID;
 
-import me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImpl;
 import org.apache.http.Consts;
 import org.apache.http.HttpHost;
 import org.apache.http.client.ClientProtocolException;
@@ -44,33 +41,28 @@
 import com.google.gson.stream.JsonReader;
 import com.thoughtworks.xstream.XStream;
 
-import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.bean.WxAccessToken;
 import me.chanjar.weixin.common.bean.WxCardApiSignature;
 import me.chanjar.weixin.common.bean.WxJsapiSignature;
-import me.chanjar.weixin.common.bean.WxMenu;
 import me.chanjar.weixin.common.bean.result.WxError;
-import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
 import me.chanjar.weixin.common.exception.WxErrorException;
 import me.chanjar.weixin.common.session.StandardSessionManager;
 import me.chanjar.weixin.common.session.WxSessionManager;
 import me.chanjar.weixin.common.util.RandomUtils;
 import me.chanjar.weixin.common.util.crypto.SHA1;
 import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
-import me.chanjar.weixin.common.util.fs.FileUtils;
 import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder;
 import me.chanjar.weixin.common.util.http.DefaultApacheHttpHttpClientBuilder;
-import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor;
-import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
 import me.chanjar.weixin.common.util.http.RequestExecutor;
 import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
 import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
 import me.chanjar.weixin.common.util.http.URIUtil;
 import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
 import me.chanjar.weixin.common.util.json.GsonHelper;
-import me.chanjar.weixin.common.util.json.WxGsonBuilder;
 import me.chanjar.weixin.common.util.xml.XStreamInitializer;
 import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl;
+import me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImpl;
+import me.chanjar.weixin.mp.api.impl.WxMpMenuServiceImpl;
 import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
 import me.chanjar.weixin.mp.bean.WxMpGroup;
 import me.chanjar.weixin.mp.bean.WxMpIndustry;
@@ -79,20 +71,11 @@
 import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
 import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage;
 import me.chanjar.weixin.mp.bean.WxMpMassVideo;
-import me.chanjar.weixin.mp.bean.WxMpMaterial;
-import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate;
-import me.chanjar.weixin.mp.bean.WxMpMaterialNews;
 import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
 import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;
-import me.chanjar.weixin.mp.bean.result.WxMediaImgUploadResult;
 import me.chanjar.weixin.mp.bean.result.WxMpCardResult;
 import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
 import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult;
-import me.chanjar.weixin.mp.bean.result.WxMpMaterialCountResult;
-import me.chanjar.weixin.mp.bean.result.WxMpMaterialFileBatchGetResult;
-import me.chanjar.weixin.mp.bean.result.WxMpMaterialNewsBatchGetResult;
-import me.chanjar.weixin.mp.bean.result.WxMpMaterialUploadResult;
-import me.chanjar.weixin.mp.bean.result.WxMpMaterialVideoInfoResult;
 import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
 import me.chanjar.weixin.mp.bean.result.WxMpPayCallback;
 import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult;
@@ -105,12 +88,6 @@
 import me.chanjar.weixin.mp.bean.result.WxMpUserList;
 import me.chanjar.weixin.mp.bean.result.WxMpUserSummary;
 import me.chanjar.weixin.mp.bean.result.WxRedpackResult;
-import me.chanjar.weixin.mp.util.http.MaterialDeleteRequestExecutor;
-import me.chanjar.weixin.mp.util.http.MaterialNewsInfoRequestExecutor;
-import me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor;
-import me.chanjar.weixin.mp.util.http.MaterialVideoInfoRequestExecutor;
-import me.chanjar.weixin.mp.util.http.MaterialVoiceAndImageDownloadRequestExecutor;
-import me.chanjar.weixin.mp.util.http.MediaImgUploadRequestExecutor;
 import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor;
 import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
 
@@ -139,6 +116,8 @@ public class WxMpServiceImpl implements WxMpService {
 
   protected WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);
 
+  protected WxMpMenuService menuService = new WxMpMenuServiceImpl(this);
+
   protected CloseableHttpClient httpClient;
 
   protected HttpHost httpProxy;
@@ -259,59 +238,6 @@ public void customMessageSend(WxMpCustomMessage message) throws WxErrorException
     execute(new SimplePostRequestExecutor(), url, message.toJson());
   }
 
-  @Override
-  public void menuCreate(WxMenu menu) throws WxErrorException {
-    if (menu.getMatchRule() != null) {
-      String url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional";
-      execute(new SimplePostRequestExecutor(), url, menu.toJson());
-    } else {
-      String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
-      execute(new SimplePostRequestExecutor(), url, menu.toJson());
-    }
-  }
-
-  @Override
-  public void menuDelete() throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
-    execute(new SimpleGetRequestExecutor(), url, null);
-  }
-  
-  @Override
-  public void menuDelete(String menuid) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional";
-    execute(new SimpleGetRequestExecutor(), url, "menuid=" + menuid);
-  }
-
-  @Override
-  public WxMenu menuGet() throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
-    try {
-      String resultContent = execute(new SimpleGetRequestExecutor(), url, null);
-      return WxMenu.fromJson(resultContent);
-    } catch (WxErrorException e) {
-      // 46003 不存在的菜单数据
-      if (e.getError().getErrorCode() == 46003) {
-        return null;
-      }
-      throw e;
-    }
-  }
-  
-  @Override
-  public WxMenu menuTryMatch(String userid) throws WxErrorException {
-    String url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch";
-    try {
-      String resultContent = execute(new SimpleGetRequestExecutor(), url, "user_id=" + userid);
-      return WxMenu.fromJson(resultContent);
-    } catch (WxErrorException e) {
-      // 46003 不存在的菜单数据     46002 不存在的菜单版本
-      if (e.getError().getErrorCode() == 46003 || e.getError().getErrorCode() == 46002) {
-        return null;
-      }
-      throw e;
-    }
-  }
-
   @Override
   public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException {
     String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
@@ -1323,5 +1249,10 @@ public WxMpKefuService getKefuService() {
   public WxMpMaterialService getMaterialService() {
     return this.materialService;
   }
-  
+
+  @Override
+  public WxMpMenuService getMenuService() {
+    return this.menuService;
+  }
+
 }
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
new file mode 100644
index 0000000000..5ecb0d93a3
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImpl.java
@@ -0,0 +1,73 @@
+package me.chanjar.weixin.mp.api.impl;
+
+import me.chanjar.weixin.common.bean.WxMenu;
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
+import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
+import me.chanjar.weixin.mp.api.WxMpMenuService;
+import me.chanjar.weixin.mp.api.WxMpService;
+
+/**
+ * Created by Binary Wang on 2016/7/21.
+ */
+public class WxMpMenuServiceImpl implements WxMpMenuService {
+
+  private WxMpService wxMpService;
+
+  public WxMpMenuServiceImpl(WxMpService wxMpService) {
+    this.wxMpService = wxMpService;
+  }
+
+  @Override
+  public void menuCreate(WxMenu menu) throws WxErrorException {
+    if (menu.getMatchRule() != null) {
+      String url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional";
+      this.wxMpService.execute(new SimplePostRequestExecutor(), url, menu.toJson());
+    } else {
+      String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
+      this.wxMpService.execute(new SimplePostRequestExecutor(), url, menu.toJson());
+    }
+  }
+
+  @Override
+  public void menuDelete() throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
+    this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null);
+  }
+
+  @Override
+  public void menuDelete(String menuid) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional";
+    this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "menuid=" + menuid);
+  }
+
+  @Override
+  public WxMenu menuGet() throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
+    try {
+      String resultContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null);
+      return WxMenu.fromJson(resultContent);
+    } catch (WxErrorException e) {
+      // 46003 不存在的菜单数据
+      if (e.getError().getErrorCode() == 46003) {
+        return null;
+      }
+      throw e;
+    }
+  }
+
+  @Override
+  public WxMenu menuTryMatch(String userid) throws WxErrorException {
+    String url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch";
+    try {
+      String resultContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "user_id=" + userid);
+      return WxMenu.fromJson(resultContent);
+    } catch (WxErrorException e) {
+      // 46003 不存在的菜单数据     46002 不存在的菜单版本
+      if (e.getError().getErrorCode() == 46003 || e.getError().getErrorCode() == 46002) {
+        return null;
+      }
+      throw e;
+    }
+  }
+}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMenuAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java
similarity index 87%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMenuAPITest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java
index 581c67eef7..10e050ea42 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMenuAPITest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java
@@ -1,10 +1,12 @@
-package me.chanjar.weixin.mp.api;
+package me.chanjar.weixin.mp.api.impl;
 
 import com.google.inject.Inject;
 import me.chanjar.weixin.common.api.WxConsts;
 import me.chanjar.weixin.common.bean.WxMenu;
 import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
 import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.mp.api.ApiTestModule;
+import me.chanjar.weixin.mp.api.WxMpServiceImpl;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Guice;
@@ -13,11 +15,12 @@
 /**
  * 测试菜单
  * @author chanjarster
+ * @author Binary Wang
  *
  */
-@Test(groups="menuAPI", dependsOnGroups="baseAPI")
+@Test(groups="menuAPI")
 @Guice(modules = ApiTestModule.class)
-public class WxMpMenuAPITest {
+public class WxMpMenuServiceImplTest {
 
   @Inject
   protected WxMpServiceImpl wxService;
@@ -25,7 +28,7 @@ public class WxMpMenuAPITest {
   @Test(dataProvider = "menu")
   public void testCreateMenu(WxMenu wxMenu) throws WxErrorException {
     System.out.println(wxMenu.toJson());
-    wxService.menuCreate(wxMenu);
+    this.wxService.getMenuService().menuCreate(wxMenu);
   }
 
   @Test
@@ -69,17 +72,19 @@ public void testCreateMenu2() throws WxErrorException {
 
     WxMenu menu = WxMenu.fromJson(a);
     System.out.println(menu.toJson());
-    wxService.menuCreate(menu);
+    this.wxService.getMenuService().menuCreate(menu);
   }
 
   @Test(dependsOnMethods = { "testCreateMenu"})
   public void testGetMenu() throws WxErrorException {
-    Assert.assertNotNull(wxService.menuGet());
+    WxMenu wxMenu = this.wxService.getMenuService().menuGet();
+    Assert.assertNotNull(wxMenu);
+    System.out.println(wxMenu.toJson());
   }
   
   @Test(dependsOnMethods = { "testGetMenu"})
   public void testDeleteMenu() throws WxErrorException {
-    wxService.menuDelete();
+    this.wxService.getMenuService().menuDelete();
   }
   
   @DataProvider(name="menu")
diff --git a/weixin-java-mp/src/test/resources/testng.xml b/weixin-java-mp/src/test/resources/testng.xml
index 003af42822..09184112c0 100644
--- a/weixin-java-mp/src/test/resources/testng.xml
+++ b/weixin-java-mp/src/test/resources/testng.xml
@@ -6,7 +6,7 @@
       		
 			
 			
-			
+			
 			
 			
 			

From fcbdc8686e0cace26be70a8c17eb72852cd47621 Mon Sep 17 00:00:00 2001
From: BinaryWang 
Date: Thu, 21 Jul 2016 17:19:56 +0800
Subject: [PATCH 49/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?=
 =?UTF-8?q?=EF=BC=8C=E5=B0=86=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86=E3=80=81?=
 =?UTF-8?q?=E5=88=86=E7=BB=84=E7=AE=A1=E7=90=86=E4=BB=A5=E5=8F=8A=E4=BA=8C?=
 =?UTF-8?q?=E7=BB=B4=E7=A0=81=E7=9B=B8=E5=85=B3=E7=9A=84=E6=8E=A5=E5=8F=A3?=
 =?UTF-8?q?=E5=88=86=E5=88=AB=E7=A7=BB=E5=88=B0=E5=8D=95=E7=8B=AC=E7=B1=BB?=
 =?UTF-8?q?=E4=B8=AD=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/mp/api/WxMpGroupService.java       |  69 +++
 .../weixin/mp/api/WxMpKefuService.java        |  21 +-
 .../weixin/mp/api/WxMpMaterialService.java    |  47 +-
 .../weixin/mp/api/WxMpMenuService.java        |   9 +-
 .../weixin/mp/api/WxMpQrcodeService.java      |  77 ++++
 .../me/chanjar/weixin/mp/api/WxMpService.java | 434 ++++++------------
 .../weixin/mp/api/WxMpServiceImpl.java        | 299 ++----------
 .../weixin/mp/api/WxMpUserService.java        |  72 +++
 .../mp/api/impl/WxMpGroupServiceImpl.java     |  85 ++++
 .../mp/api/impl/WxMpMaterialServiceImpl.java  |  43 +-
 .../mp/api/impl/WxMpQrcodeServiceImpl.java    | 102 ++++
 .../mp/api/impl/WxMpUserServiceImpl.java      |  83 ++++
 .../mp/bean/result/WxMpQrCodeTicket.java      |   5 +
 .../weixin/mp/bean/result/WxMpUserList.java   |   5 +
 .../weixin/mp/api/WxMpMassMessageAPITest.java |   4 +-
 .../weixin/mp/api/WxMpMiscAPITest.java        |  40 +-
 .../weixin/mp/api/WxMpUserAPITest.java        |  53 ---
 .../WxMpGroupServiceImplTest.java}            |  14 +-
 .../WxMpQrCodeServiceImplTest.java}           |  22 +-
 .../mp/api/impl/WxMpUserServiceImplTest.java  |  85 ++++
 weixin-java-mp/src/test/resources/testng.xml  |   6 +-
 21 files changed, 877 insertions(+), 698 deletions(-)
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java
 create mode 100644 weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java
 delete mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java
 rename weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/{WxMpGroupAPITest.java => impl/WxMpGroupServiceImplTest.java} (70%)
 rename weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/{WxMpQrCodeAPITest.java => impl/WxMpQrCodeServiceImplTest.java} (56%)
 create mode 100644 weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java

diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java
new file mode 100644
index 0000000000..80cadd55e9
--- /dev/null
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpGroupService.java
@@ -0,0 +1,69 @@
+package me.chanjar.weixin.mp.api;
+
+import me.chanjar.weixin.common.exception.WxErrorException;
+import me.chanjar.weixin.mp.bean.WxMpGroup;
+
+import java.util.List;
+
+/**
+ * 用户分组相关操作接口
+ * @author Binary Wang
+ *
+ */
+public interface WxMpGroupService {
+
+
+  /**
+   * 
+   * 分组管理接口 - 创建分组
+   * 最多支持创建500个分组
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
+   * 
+ * + * @param name 分组名字(30个字符以内) + */ + public WxMpGroup groupCreate(String name) throws WxErrorException; + + /** + *
+   * 分组管理接口 - 查询所有分组
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
+   * 
+ */ + public List groupGet() throws WxErrorException; + + /** + *
+   * 分组管理接口 - 查询用户所在分组
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
+   * 
+ * + * @param openid 微信用户的openid + */ + public long userGetGroup(String openid) throws WxErrorException; + + /** + *
+   * 分组管理接口 - 修改分组名
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
+   *
+   * 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
+   * 
+ * + * @param group 要更新的group,group的id,name必须设置 + */ + public void groupUpdate(WxMpGroup group) throws WxErrorException; + + /** + *
+   * 分组管理接口 - 移动用户分组
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
+   *
+   * 如果to_groupid为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
+   * 
+ * + * @param openid 用户openid + * @param to_groupid 移动到的分组id + */ + public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java index 7e14cb8f33..c4731cb524 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpKefuService.java @@ -1,23 +1,24 @@ package me.chanjar.weixin.mp.api; -import java.io.File; -import java.util.Date; - import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.result.*; +import java.io.File; +import java.util.Date; + /** * 客服接口 , * 命名采用kefu拼音的原因是: * 其英文CustomerService如果再加上Service后缀显得有点啰嗦, * 如果不加又显得表意不完整 - * @author Binary Wang * + * @author Binary Wang */ public interface WxMpKefuService { //*******************客服管理接口***********************// + /** *
    * 获取客服基本信息
@@ -71,7 +72,7 @@ public interface WxMpKefuService {
    * 
*/ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) - throws WxErrorException; + throws WxErrorException; /** *
@@ -83,6 +84,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
   boolean kfAccountDel(String kfAccount) throws WxErrorException;
 
   //*******************客服会话控制接口***********************//
+
   /**
    * 
    * 创建会话
@@ -134,6 +136,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
   WxMpKfSessionWaitCaseList kfSessionGetWaitCase() throws WxErrorException;
 
   //*******************获取聊天记录的接口***********************//
+
   /**
    * 
    * 获取聊天记录(原始接口)
@@ -143,9 +146,9 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile)
    * 
* * @param startTime 起始时间 - * @param endTime 结束时间 - * @param msgId 消息id顺序从小到大,从1开始 - * @param number 每次获取条数,最多10000条 + * @param endTime 结束时间 + * @param msgId 消息id顺序从小到大,从1开始 + * @param number 每次获取条数,最多10000条 * @return 聊天记录对象 * @throws WxErrorException */ @@ -160,7 +163,7 @@ boolean kfAccountUploadHeadImg(String kfAccount, File imgFile) *
* * @param startTime 起始时间 - * @param endTime 结束时间 + * @param endTime 结束时间 * @return 聊天记录对象 * @throws WxErrorException */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java index a4b1864377..7254a0080d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMaterialService.java @@ -19,10 +19,11 @@ public interface WxMpMaterialService { /** * 新增临时素材 - * @see #mediaUpload(String, String, InputStream) + * * @param mediaType * @param file * @throws WxErrorException + * @see #mediaUpload(String, String, InputStream) */ public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException; @@ -33,6 +34,7 @@ public interface WxMpMaterialService { * 根据微信文档,视频文件下载不了,会返回null * 详情请见: 获取临时素材 *
+ * * @param media_id * @return 保存到本地的临时文件 * @throws WxErrorException @@ -44,6 +46,7 @@ public interface WxMpMaterialService { * 上传图文消息内的图片获取URL * 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E4.B8.8A.E4.BC.A0.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF.E5.86.85.E7.9A.84.E5.9B.BE.E7.89.87.E8.8E.B7.E5.8F.96URL.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91 *
+ * * @param file * @return WxMediaImgUploadResult 返回图片url * @throws WxErrorException @@ -63,9 +66,10 @@ public interface WxMpMaterialService { * * 详情请见: 新增临时素材 *
- * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param inputStream 输入流 + * + * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param fileType 文件类型,请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param inputStream 输入流 * @throws WxErrorException */ public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; @@ -82,8 +86,9 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html *
- * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial} + * + * @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param material 上传的素材, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterial} */ public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException; @@ -93,7 +98,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html *
- * @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews} + * + * @param news 上传的图文消息, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialNews} */ public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws WxErrorException; @@ -103,7 +109,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * - * @param media_id 永久素材的id + * + * @param media_id 永久素材的id */ public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException; @@ -113,7 +120,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * - * @param media_id 永久素材的id + * + * @param media_id 永久素材的id */ public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException; @@ -123,7 +131,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html * - * @param media_id 永久素材的id + * + * @param media_id 永久素材的id */ public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException; @@ -133,7 +142,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html * - * @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate} + * + * @param wxMpMaterialArticleUpdate 用来更新图文素材的bean, 请看{@link me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate} */ public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException; @@ -143,7 +153,8 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html * - * @param media_id 永久素材的id + * + * @param media_id 永久素材的id */ public boolean materialDelete(String media_id) throws WxErrorException; @@ -162,8 +173,9 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html * - * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 - * @param count 返回素材的数量,取值在1到20之间 + * + * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 + * @param count 返回素材的数量,取值在1到20之间 */ public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException; @@ -173,9 +185,10 @@ public interface WxMpMaterialService { * * 详情请见: http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html * - * @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} - * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 - * @param count 返回素材的数量,取值在1到20之间 + * + * @param type 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts} + * @param offset 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 + * @param count 返回素材的数量,取值在1到20之间 */ public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException; 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 865bfb008e..670921dbc8 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,16 +2,11 @@ import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; -import me.chanjar.weixin.mp.bean.kefu.result.*; - -import java.io.File; -import java.util.Date; /** * 菜单相关操作接口 - * @author Binary Wang * + * @author Binary Wang */ public interface WxMpMenuService { @@ -38,6 +33,7 @@ public interface WxMpMenuService { * 删除个性化菜单接口 * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html * + * * @param menuid */ public void menuDelete(String menuid) throws WxErrorException; @@ -55,6 +51,7 @@ public interface WxMpMenuService { * 测试个性化菜单匹配结果 * 详情请见: http://mp.weixin.qq.com/wiki/0/c48ccd12b69ae023159b4bfaa7c39c20.html * + * * @param userid 可以是粉丝的OpenID,也可以是粉丝的微信号。 */ public WxMenu menuTryMatch(String userid) throws WxErrorException; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java new file mode 100644 index 0000000000..2015ae1b66 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java @@ -0,0 +1,77 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; + +import java.io.File; + +/** + * 二维码相关操作接口 + * + * @author Binary Wang + */ +public interface WxMpQrcodeService { + + /** + *
+   * 换取临时二维码ticket
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param scene_id 参数。 + * @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒 + */ + public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException; + + /** + *
+   * 换取永久二维码ticket
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000) + */ + public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException; + + /** + *
+   * 换取永久字符串二维码ticket
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param scene_str 参数。字符串类型长度现在为1到64 + */ + public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException; + + /** + *
+   * 换取二维码图片文件,jpg格式
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param ticket 二维码ticket + */ + public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException; + + /** + *
+   * 换取二维码图片url地址(可以选择是否生成压缩的网址)
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param ticket 二维码ticket + * @param needShortUrl 是否需要压缩的二维码地址 + */ + public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException; + + /** + *
+   * 换取二维码图片url地址
+   * 详情请见: 生成带参数的二维码
+   * 
+ * + * @param ticket 二维码ticket + */ + public String qrCodePictureUrl(String ticket) throws WxErrorException; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 2dc9426079..7bff302733 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -1,40 +1,14 @@ package me.chanjar.weixin.mp.api; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Map; - import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.mp.bean.WxMpCustomMessage; -import me.chanjar.weixin.mp.bean.WxMpGroup; -import me.chanjar.weixin.mp.bean.WxMpIndustry; -import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; -import me.chanjar.weixin.mp.bean.WxMpMassNews; -import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; -import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; -import me.chanjar.weixin.mp.bean.WxMpMassVideo; -import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; -import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; -import me.chanjar.weixin.mp.bean.result.WxMpCardResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; -import me.chanjar.weixin.mp.bean.result.WxMpPayCallback; -import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult; -import me.chanjar.weixin.mp.bean.result.WxMpPayResult; -import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; -import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; -import me.chanjar.weixin.mp.bean.result.WxMpUser; -import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; -import me.chanjar.weixin.mp.bean.result.WxMpUserList; -import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; -import me.chanjar.weixin.mp.bean.result.WxRedpackResult; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; + +import java.text.SimpleDateFormat; +import java.util.Map; /** * 微信API的Service @@ -42,6 +16,7 @@ public interface WxMpService { public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); + /** *
    * 验证推送过来的消息的正确性
@@ -52,6 +27,7 @@ public interface WxMpService {
 
   /**
    * 获取access_token, 不强制刷新access_token
+   *
    * @see #getAccessToken(boolean)
    */
   public String getAccessToken() throws WxErrorException;
@@ -64,15 +40,17 @@ public interface WxMpService {
    * 另:本service的所有方法都会在access_token过期是调用此方法
    *
    * 程序员在非必要情况下尽量不要主动调用此方法
-
+   *
    * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取access_token
    * 
+ * * @param forceRefresh 强制刷新 */ public String getAccessToken(boolean forceRefresh) throws WxErrorException; /** * 获得jsapi_ticket,不强制刷新jsapi_ticket + * * @see #getJsapiTicket(boolean) */ public String getJsapiTicket() throws WxErrorException; @@ -84,6 +62,7 @@ public interface WxMpService { * * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 * + * * @param forceRefresh 强制刷新 */ public String getJsapiTicket(boolean forceRefresh) throws WxErrorException; @@ -111,6 +90,7 @@ public interface WxMpService { * * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口 * + * * @param news * @throws WxErrorException * @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassGroupMessage) @@ -123,6 +103,7 @@ public interface WxMpService { * 上传群发用的视频,上传后才能群发视频消息 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口 * + * * @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassGroupMessage) * @see #massOpenIdsMessageSend(me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage) */ @@ -148,146 +129,12 @@ public interface WxMpService { */ public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException; - /** - *
-   * 分组管理接口 - 创建分组
-   * 最多支持创建500个分组
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
-   * 
- * @param name 分组名字(30个字符以内) - */ - public WxMpGroup groupCreate(String name) throws WxErrorException; - - /** - *
-   * 分组管理接口 - 查询所有分组
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
-   * 
- */ - public List groupGet() throws WxErrorException; - - /** - *
-   * 分组管理接口 - 查询用户所在分组
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
-   * 
- * @param openid 微信用户的openid - */ - public long userGetGroup(String openid) throws WxErrorException; - - /** - *
-   * 分组管理接口 - 修改分组名
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
-   *
-   * 如果id为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
-   * 
- * @param group 要更新的group,group的id,name必须设置 - */ - public void groupUpdate(WxMpGroup group) throws WxErrorException; - - /** - *
-   * 分组管理接口 - 移动用户分组
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=分组管理接口
-   *
-   * 如果to_groupid为0(未分组),1(黑名单),2(星标组),或者不存在的id,微信会返回系统繁忙的错误
-   * 
- * @param openid 用户openid - * @param to_groupid 移动到的分组id - */ - public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException; - - /** - *
-   * 设置用户备注名接口
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=设置用户备注名接口
-   * 
- * @param openid 用户openid - * @param remark 备注名 - */ - public void userUpdateRemark(String openid, String remark) throws WxErrorException; - - /** - *
-   * 获取用户基本信息
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取用户基本信息
-   * 
- * @param openid 用户openid - * @param lang 语言,zh_CN 简体(默认),zh_TW 繁体,en 英语 - */ - public WxMpUser userInfo(String openid, String lang) throws WxErrorException; - - /** - *
-   * 获取关注者列表
-   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表
-   * 
- * @param next_openid 可选,第一个拉取的OPENID,null为从头开始拉取 - */ - public WxMpUserList userList(String next_openid) throws WxErrorException; - - /** - *
-   * 换取临时二维码ticket
-   * 详情请见: 生成带参数的二维码
-   * 
- * @param scene_id 参数。 - * @param expire_seconds 过期秒数,默认60秒,最小60秒,最大1800秒 - */ - public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException; - - /** - *
-   * 换取永久二维码ticket
-   * 详情请见: 生成带参数的二维码
-   * 
- * @param scene_id 参数。永久二维码时最大值为100000(目前参数只支持1--100000) - */ - public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException; - - /** - *
-   * 换取永久字符串二维码ticket
-   * 详情请见: 生成带参数的二维码
-   * 
- * - * @param scene_str 参数。字符串类型长度现在为1到64 - */ - public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException; - - /** - *
-   * 换取二维码图片文件,jpg格式
-   * 详情请见: 生成带参数的二维码
-   * 
- * @param ticket 二维码ticket - */ - public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException; - - /** - *
-   * 换取二维码图片url地址(可以选择是否生成压缩的网址)
-   * 详情请见: 生成带参数的二维码
-   * 
- * @param ticket 二维码ticket - * @param needShortUrl 是否需要压缩的二维码地址 - */ - public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException; - /** - *
-   * 换取二维码图片url地址
-   * 详情请见: 生成带参数的二维码
-   * 
- * @param ticket 二维码ticket - */ - public String qrCodePictureUrl(String ticket) throws WxErrorException; - /** *
    * 长链接转短链接接口
    * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=长链接转短链接接口
    * 
+ * * @param long_url */ public String shortUrl(String long_url) throws WxErrorException; @@ -297,9 +144,10 @@ public interface WxMpService { * 发送模板消息 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=模板消息接口 * + * * @param templateMessage - * @throws WxErrorException * @return msgid + * @throws WxErrorException */ public String templateSend(WxMpTemplateMessage templateMessage) throws WxErrorException; @@ -316,6 +164,7 @@ public interface WxMpService { * 构造oauth2授权的url连接 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息 * + * * @param scope * @param state * @return url @@ -327,8 +176,8 @@ public interface WxMpService { * 构造oauth2授权的url连接 * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息 * - * @param redirectURI - * 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode + * + * @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode * @param scope * @param state * @return url @@ -354,8 +203,9 @@ public interface WxMpService { *
    * 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以
    * 
+ * * @param oAuth2AccessToken - * @param lang zh_CN, zh_TW, en + * @param lang zh_CN, zh_TW, en */ public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException; @@ -363,6 +213,7 @@ public interface WxMpService { *
    * 验证oauth2的access token是否有效
    * 
+ * * @param oAuth2AccessToken */ public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken); @@ -375,26 +226,6 @@ public interface WxMpService { */ String[] getCallbackIP() throws WxErrorException; - /** - *
-   * 获取用户增减数据
-   * http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
-   * 
- * @param beginDate 最大时间跨度7天 - * @param endDate endDate不能早于begingDate - */ - List getUserSummary(Date beginDate, Date endDate) throws WxErrorException; - - /** - *
-   * 获取累计用户数据
-   * http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
-   * 
- * @param beginDate 最大时间跨度7天 - * @param endDate endDate不能早于begingDate - */ - List getUserCumulate(Date beginDate, Date endDate) throws WxErrorException; - /** * 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求 */ @@ -438,13 +269,14 @@ public interface WxMpService { /** * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" - * @param openId 支付人openId + * + * @param openId 支付人openId * @param outTradeNo 商户端对应订单号 - * @param amt 金额(单位元) - * @param body 商品描述 - * @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP - * @param ip 发起支付的客户端IP - * @param notifyUrl 通知地址 + * @param amt 金额(单位元) + * @param body 商品描述 + * @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP + * @param ip 发起支付的客户端IP + * @param notifyUrl 通知地址 * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map) instead */ @Deprecated @@ -454,8 +286,7 @@ public interface WxMpService { * 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" * - * @param parameters - * All required/optional parameters for weixin payment + * @param parameters All required/optional parameters for weixin payment * @throws IllegalArgumentException */ WxMpPrepayIdResult getPrepayId(Map parameters); @@ -463,21 +294,22 @@ public interface WxMpService { /** * 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数 * 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 - * @param parameters - * the required or optional parameters + * + * @param parameters the required or optional parameters */ - Map getPayInfo(Map parameters) throws WxErrorException; - + Map getPayInfo(Map parameters) throws WxErrorException; + /** * 该接口调用“统一下单”接口,并拼装NATIVE发起支付请求需要的参数 * 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 - * tradeType 交易类型 NATIVE (其他交易类型JSAPI,APP,WAP) - * @param productId 商户商品ID + * tradeType 交易类型 NATIVE (其他交易类型JSAPI,APP,WAP) + * + * @param productId 商户商品ID * @param outTradeNo 商户端对应订单号 - * @param amt 金额(单位元) - * @param body 商品描述 - * @param ip 发起支付的客户端IP - * @param notifyUrl 通知地址 + * @param amt 金额(单位元) + * @param body 商品描述 + * @param ip 发起支付的客户端IP + * @param notifyUrl 通知地址 * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map) instead */ @Deprecated @@ -487,12 +319,13 @@ public interface WxMpService { * 该接口调用“统一下单”接口,并拼装JSAPI发起支付请求需要的参数 * 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 * tradeType 交易类型 JSAPI(其他交易类型NATIVE,APP,WAP) - * @param openId 支付人openId + * + * @param openId 支付人openId * @param outTradeNo 商户端对应订单号 - * @param amt 金额(单位元) - * @param body 商品描述 - * @param ip 发起支付的客户端IP - * @param notifyUrl 通知地址 + * @param amt 金额(单位元) + * @param body 商品描述 + * @param ip 发起支付的客户端IP + * @param notifyUrl 通知地址 * @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map) instead */ @Deprecated @@ -501,6 +334,7 @@ public interface WxMpService { /** * 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2 + * * @param transactionId * @param outTradeNo */ @@ -509,6 +343,7 @@ public interface WxMpService { /** * 读取支付结果通知 * 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 + * * @param xmlData */ WxMpPayCallback getJSSDKCallbackData(String xmlData); @@ -516,12 +351,13 @@ public interface WxMpService { /** * 微信支付-申请退款 * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4 + * * @param parameters 需要传入的退款参数的Map。以下几项为参数的必须项:
- *
  • transaction_id - *
  • out_trade_no (仅在上述transaction_id为空时是必须项) - *
  • out_refund_no - *
  • total_fee - *
  • refund_fee + *
  • transaction_id + *
  • out_trade_no (仅在上述transaction_id为空时是必须项) + *
  • out_refund_no + *
  • total_fee + *
  • refund_fee * @return 退款操作结果 * @throws WxErrorException */ @@ -532,39 +368,41 @@ public interface WxMpService { * 计算Map键值对是否和签名相符, * 按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的 格式(即 key1=value1&key2=value2...)拼接成字符串 * + * * @param kvm * @param signature */ public boolean checkJSSDKCallbackDataSignature(Map kvm, String signature); /** - * 发送微信红包给个人用户 - * - * 需要传入的必填参数如下: - * mch_billno//商户订单号 - * send_name//商户名称 - * re_openid//用户openid - * total_amount//红包总额 - * total_num//红包发放总人数 - * wishing//红包祝福语 - * client_ip//服务器Ip地址 - * act_name//活动名称 - * remark //备注 - * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5 - * - * 使用现金红包功能需要在xml配置文件中额外设置: - * 微信商户平台ID - * 商户平台设置的API密钥 - * - * @param parameters - */ + * 发送微信红包给个人用户 + *

    + * 需要传入的必填参数如下: + * mch_billno//商户订单号 + * send_name//商户名称 + * re_openid//用户openid + * total_amount//红包总额 + * total_num//红包发放总人数 + * wishing//红包祝福语 + * client_ip//服务器Ip地址 + * act_name//活动名称 + * remark //备注 + * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5 + *

    + * 使用现金红包功能需要在xml配置文件中额外设置: + * 微信商户平台ID + * 商户平台设置的API密钥 + * + * @param parameters + */ public WxRedpackResult sendRedpack(Map parameters) throws WxErrorException; /** * 获得卡券api_ticket,不强制刷新卡券api_ticket - * @see #getCardApiTicket(boolean) + * * @return 卡券api_ticket * @throws WxErrorException + * @see #getCardApiTicket(boolean) */ public String getCardApiTicket() throws WxErrorException; @@ -575,6 +413,7 @@ public interface WxMpService { * * 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94.9F.E6.88.90.E7.AE.97.E6.B3.95 * + * * @param forceRefresh 强制刷新 * @return 卡券api_ticket * @throws WxErrorException @@ -591,15 +430,16 @@ public interface WxMpService { * * * @param optionalSignParam 参与签名的参数数组。 - * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id - *
    注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空 + * 可以为下列字段:app_id, card_id, card_type, code, openid, location_id + *
    注意:当做wx.chooseCard调用时,必须传入app_id参与签名,否则会造成签名失败导致拉取卡券列表为空 * @return 卡券Api签名对象 */ public WxCardApiSignature createCardApiSignature(String... optionalSignParam) throws - WxErrorException; + WxErrorException; /** * 卡券Code解码 + * * @param encryptCode 加密Code,通过JSSDK的chooseCard接口获得 * @return 解密后的Code * @throws WxErrorException @@ -608,14 +448,15 @@ public WxCardApiSignature createCardApiSignature(String... optionalSignParam) th /** * 卡券Code查询 - * @param cardId 卡券ID代表一类卡券 - * @param code 单张卡券的唯一标准 + * + * @param cardId 卡券ID代表一类卡券 + * @param code 单张卡券的唯一标准 * @param checkConsume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 * @return WxMpCardResult对象 * @throws WxErrorException */ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkConsume) - throws WxErrorException; + throws WxErrorException; /** * 卡券Code核销。核销失败会抛出异常 @@ -638,51 +479,55 @@ public WxMpCardResult queryCardCode(String cardId, String code, boolean checkCon */ public String consumeCardCode(String code, String cardId) throws WxErrorException; - /** - * 卡券Mark接口。 - * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), - * 才能进一步调用核销接口,否则报错。 - * @param code 卡券的code码 - * @param cardId 卡券的ID - * @param openId 用券用户的openid - * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 - * @throws WxErrorException - */ + /** + * 卡券Mark接口。 + * 开发者在帮助消费者核销卡券之前,必须帮助先将此code(卡券串码)与一个openid绑定(即mark住), + * 才能进一步调用核销接口,否则报错。 + * + * @param code 卡券的code码 + * @param cardId 卡券的ID + * @param openId 用券用户的openid + * @param isMark 是否要mark(占用)这个code,填写true或者false,表示占用或解除占用 + * @throws WxErrorException + */ public void markCardCode(String code, String cardId, String openId, boolean isMark) throws - WxErrorException; + WxErrorException; /** * 查看卡券详情接口 * 详见 https://mp.weixin.qq.com/wiki/14/8dd77aeaee85f922db5f8aa6386d385e.html#.E6.9F.A5.E7.9C.8B.E5.8D.A1.E5.88.B8.E8.AF.A6.E6.83.85 + * * @param cardId 卡券的ID * @return 返回的卡券详情JSON字符串 - *
    [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。 - *
    可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。 + *
    [注] 由于返回的JSON格式过于复杂,难以定义其对应格式的Bean并且难以维护,因此只返回String格式的JSON串。 + *
    可由 com.google.gson.JsonParser#parse 等方法直接取JSON串中的某个字段。 * @throws WxErrorException */ public String getCardDetail(String cardId) throws WxErrorException; /** - *

    -     * 预览接口
    -     * 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E9.A2.84.E8.A7.88.E6.8E.A5.E5.8F.A3.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
    -     * 
    - * @param wxMpMassPreviewMessage - * @return wxMpMassSendResult - * @throws WxErrorException - */ + *
    +   * 预览接口
    +   * 详情请见:http://mp.weixin.qq.com/wiki/15/40b6865b893947b764e2de8e4a1fb55f.html#.E9.A2.84.E8.A7.88.E6.8E.A5.E5.8F.A3.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91
    +   * 
    + * + * @param wxMpMassPreviewMessage + * @return wxMpMassSendResult + * @throws WxErrorException + */ public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception; /** - *
    -     * 设置所属行业
    -     * 官方文档中暂未告知响应内容
    -     * 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A
    -     * 
    - * @param wxMpIndustry - * @return JsonObject - * @throws WxErrorException - */ + *
    +   * 设置所属行业
    +   * 官方文档中暂未告知响应内容
    +   * 详情请见:http://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html#.E8.AE.BE.E7.BD.AE.E6.89.80.E5.B1.9E.E8.A1.8C.E4.B8.9A
    +   * 
    + * + * @param wxMpIndustry + * @return JsonObject + * @throws WxErrorException + */ String setIndustry(WxMpIndustry wxMpIndustry) throws WxErrorException; /*** @@ -695,28 +540,53 @@ public void markCardCode(String code, String cardId, String openId, boolean isMa * @throws WxErrorException */ WxMpIndustry getIndustry() throws WxErrorException; - + + /** + * 获取WxMpConfigStorage 对象 + * + * @return WxMpConfigStorage + */ + WxMpConfigStorage getWxMpConfigStorage(); + /** * 返回客服接口方法实现类,以方便调用个其各种接口 + * * @return WxMpKefuService - */ + */ WxMpKefuService getKefuService(); /** * 返回素材相关接口的方法实现类,以方便调用个其各种接口 + * * @return WxMpMaterialService */ WxMpMaterialService getMaterialService(); /** - * 返回素材相关接口的方法实现类,以方便调用个其各种接口 + * 返回菜单相关接口的方法实现类,以方便调用个其各种接口 + * * @return WxMpMenuService */ WxMpMenuService getMenuService(); /** - * 获取WxMpConfigStorage 对象 - * @return WxMpConfigStorage + * 返回用户相关接口的方法实现类,以方便调用个其各种接口 + * + * @return WxMpUserService */ - WxMpConfigStorage getWxMpConfigStorage(); + WxMpUserService getUserService(); + + /** + * 返回用户分组相关接口的方法实现类,以方便调用个其各种接口 + * + * @return WxMpGroupService + */ + WxMpGroupService getGroupService(); + + /** + * 返回二维码相关接口的方法实现类,以方便调用个其各种接口 + * + * @return WxMpQrcodeService + */ + WxMpQrcodeService getQrcodeService(); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java index c7ab51c89b..5e8809d73c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java @@ -1,46 +1,10 @@ package me.chanjar.weixin.mp.api; -import java.io.File; -import java.io.IOException; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.apache.http.Consts; -import org.apache.http.HttpHost; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.BasicResponseHandler; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.helpers.MessageFormatter; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; +import com.google.gson.*; import com.google.gson.internal.Streams; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.thoughtworks.xstream.XStream; - import me.chanjar.weixin.common.bean.WxAccessToken; import me.chanjar.weixin.common.bean.WxCardApiSignature; import me.chanjar.weixin.common.bean.WxJsapiSignature; @@ -51,45 +15,32 @@ import me.chanjar.weixin.common.util.RandomUtils; import me.chanjar.weixin.common.util.crypto.SHA1; import me.chanjar.weixin.common.util.crypto.WxCryptUtil; -import me.chanjar.weixin.common.util.http.ApacheHttpClientBuilder; -import me.chanjar.weixin.common.util.http.DefaultApacheHttpHttpClientBuilder; -import me.chanjar.weixin.common.util.http.RequestExecutor; -import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; -import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; -import me.chanjar.weixin.common.util.http.URIUtil; -import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; -import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.mp.api.impl.WxMpKefuServiceImpl; -import me.chanjar.weixin.mp.api.impl.WxMpMaterialServiceImpl; -import me.chanjar.weixin.mp.api.impl.WxMpMenuServiceImpl; -import me.chanjar.weixin.mp.bean.WxMpCustomMessage; -import me.chanjar.weixin.mp.bean.WxMpGroup; -import me.chanjar.weixin.mp.bean.WxMpIndustry; -import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; -import me.chanjar.weixin.mp.bean.WxMpMassNews; -import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; -import me.chanjar.weixin.mp.bean.WxMpMassPreviewMessage; -import me.chanjar.weixin.mp.bean.WxMpMassVideo; -import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; -import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; -import me.chanjar.weixin.mp.bean.result.WxMpCardResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; -import me.chanjar.weixin.mp.bean.result.WxMpPayCallback; -import me.chanjar.weixin.mp.bean.result.WxMpPayRefundResult; -import me.chanjar.weixin.mp.bean.result.WxMpPayResult; -import me.chanjar.weixin.mp.bean.result.WxMpPrepayIdResult; -import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; -import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; -import me.chanjar.weixin.mp.bean.result.WxMpUser; -import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; -import me.chanjar.weixin.mp.bean.result.WxMpUserList; -import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; -import me.chanjar.weixin.mp.bean.result.WxRedpackResult; -import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; +import me.chanjar.weixin.mp.api.impl.*; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.*; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import org.apache.http.Consts; +import org.apache.http.HttpHost; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.MessageFormatter; + +import java.io.IOException; +import java.io.StringReader; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.Map.Entry; public class WxMpServiceImpl implements WxMpService { @@ -118,6 +69,12 @@ public class WxMpServiceImpl implements WxMpService { protected WxMpMenuService menuService = new WxMpMenuServiceImpl(this); + protected WxMpUserService userService = new WxMpUserServiceImpl(this); + + protected WxMpGroupService groupService = new WxMpGroupServiceImpl(this); + + protected WxMpQrcodeService qrCodeService = new WxMpQrcodeServiceImpl(this); + protected CloseableHttpClient httpClient; protected HttpHost httpProxy; @@ -266,158 +223,6 @@ public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) return WxMpMassSendResult.fromJson(responseContent); } - @Override - public WxMpGroup groupCreate(String name) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/groups/create"; - JsonObject json = new JsonObject(); - JsonObject groupJson = new JsonObject(); - json.add("group", groupJson); - groupJson.addProperty("name", name); - - String responseContent = execute( - new SimplePostRequestExecutor(), - url, - json.toString()); - return WxMpGroup.fromJson(responseContent); - } - - @Override - public List groupGet() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/groups/get"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, null); - /* - * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } - * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } - */ - JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); - return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("groups"), - new TypeToken>() { - }.getType()); - } - - @Override - public long userGetGroup(String openid) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/groups/getid"; - JsonObject o = new JsonObject(); - o.addProperty("openid", openid); - String responseContent = execute(new SimplePostRequestExecutor(), url, o.toString()); - JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); - return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid")); - } - - @Override - public void groupUpdate(WxMpGroup group) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/groups/update"; - execute(new SimplePostRequestExecutor(), url, group.toJson()); - } - - @Override - public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/groups/members/update"; - JsonObject json = new JsonObject(); - json.addProperty("openid", openid); - json.addProperty("to_groupid", to_groupid); - execute(new SimplePostRequestExecutor(), url, json.toString()); - } - - @Override - public void userUpdateRemark(String openid, String remark) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark"; - JsonObject json = new JsonObject(); - json.addProperty("openid", openid); - json.addProperty("remark", remark); - execute(new SimplePostRequestExecutor(), url, json.toString()); - } - - @Override - public WxMpUser userInfo(String openid, String lang) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/user/info"; - lang = lang == null ? "zh_CN" : lang; - String responseContent = execute(new SimpleGetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang); - return WxMpUser.fromJson(responseContent); - } - - @Override - public WxMpUserList userList(String next_openid) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/user/get"; - String responseContent = execute(new SimpleGetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid); - return WxMpUserList.fromJson(responseContent); - } - - @Override - public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_SCENE"); - if (expire_seconds != null) { - json.addProperty("expire_seconds", expire_seconds); - } - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_id", scene_id); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_LIMIT_SCENE"); - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_id", scene_id); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create"; - JsonObject json = new JsonObject(); - json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); - JsonObject actionInfo = new JsonObject(); - JsonObject scene = new JsonObject(); - scene.addProperty("scene_str", scene_str); - actionInfo.add("scene", scene); - json.add("action_info", actionInfo); - String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString()); - return WxMpQrCodeTicket.fromJson(responseContent); - } - - @Override - public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException { - String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode"; - return execute(new QrCodeRequestExecutor(), url, ticket); - } - - @Override - public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException { - String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; - try { - String resultUrl = String.format(url, - URLEncoder.encode(ticket, StandardCharsets.UTF_8.name())); - if(needShortUrl){ - return this.shortUrl(resultUrl); - } - - return resultUrl; - } catch (UnsupportedEncodingException e) { - WxError error = WxError.newBuilder().setErrorCode(-1) - .setErrorMsg(e.getMessage()).build(); - throw new WxErrorException(error); - } - } - - @Override - public String qrCodePictureUrl(String ticket) throws WxErrorException { - return qrCodePictureUrl(ticket, false); - } - @Override public String shortUrl(String long_url) throws WxErrorException { String url = "https://api.weixin.qq.com/cgi-bin/shorturl"; @@ -562,33 +367,6 @@ public String[] getCallbackIP() throws WxErrorException { return ipArray; } - - @Override - public List getUserSummary(Date beginDate, Date endDate) throws WxErrorException { - String url = "https://api.weixin.qq.com/datacube/getusersummary"; - JsonObject param = new JsonObject(); - param.addProperty("begin_date", SIMPLE_DATE_FORMAT.format(beginDate)); - param.addProperty("end_date", SIMPLE_DATE_FORMAT.format(endDate)); - String responseContent = post(url, param.toString()); - JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); - return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"), - new TypeToken>() { - }.getType()); - } - - @Override - public List getUserCumulate(Date beginDate, Date endDate) throws WxErrorException { - String url = "https://api.weixin.qq.com/datacube/getusercumulate"; - JsonObject param = new JsonObject(); - param.addProperty("begin_date", SIMPLE_DATE_FORMAT.format(beginDate)); - param.addProperty("end_date", SIMPLE_DATE_FORMAT.format(endDate)); - String responseContent = post(url, param.toString()); - JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); - return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"), - new TypeToken>() { - }.getType()); - } - @Override public String get(String url, String queryParam) throws WxErrorException { return execute(new SimpleGetRequestExecutor(), url, queryParam); @@ -1255,4 +1033,19 @@ public WxMpMenuService getMenuService() { return this.menuService; } + @Override + public WxMpUserService getUserService() { + return this.userService; + } + + @Override + public WxMpGroupService getGroupService() { + return this.groupService; + } + + @Override + public WxMpQrcodeService getQrcodeService() { + return this.qrCodeService; + } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java new file mode 100644 index 0000000000..818087b4a4 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserService.java @@ -0,0 +1,72 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; + +import java.util.Date; +import java.util.List; + +/** + * 用户管理和统计相关操作接口 + * + * @author Binary Wang + */ +public interface WxMpUserService { + + /** + *
    +   * 设置用户备注名接口
    +   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=设置用户备注名接口
    +   * 
    + * + * @param openid 用户openid + * @param remark 备注名 + */ + public void userUpdateRemark(String openid, String remark) throws WxErrorException; + + /** + *
    +   * 获取用户基本信息
    +   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取用户基本信息
    +   * 
    + * + * @param openid 用户openid + * @param lang 语言,zh_CN 简体(默认),zh_TW 繁体,en 英语 + */ + public WxMpUser userInfo(String openid, String lang) throws WxErrorException; + + /** + *
    +   * 获取关注者列表
    +   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=获取关注者列表
    +   * 
    + * + * @param next_openid 可选,第一个拉取的OPENID,null为从头开始拉取 + */ + public WxMpUserList userList(String next_openid) throws WxErrorException; + + /** + *
    +   * 获取用户增减数据
    +   * http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
    +   * 
    + * + * @param beginDate 最大时间跨度7天 + * @param endDate endDate不能早于begingDate + */ + List dataCubeUserSummary(Date beginDate, Date endDate) throws WxErrorException; + + /** + *
    +   * 获取累计用户数据
    +   * http://mp.weixin.qq.com/wiki/3/ecfed6e1a0a03b5f35e5efac98e864b7.html
    +   * 
    + * + * @param beginDate 最大时间跨度7天 + * @param endDate endDate不能早于begingDate + */ + List dataCubeUserCumulate(Date beginDate, Date endDate) throws WxErrorException; +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java new file mode 100644 index 0000000000..ea388dea11 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImpl.java @@ -0,0 +1,85 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.mp.api.WxMpGroupService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.WxMpGroup; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.StringReader; +import java.util.List; + +/** + * Created by Binary Wang on 2016/7/21. + */ +public class WxMpGroupServiceImpl implements WxMpGroupService { + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/groups"; + private WxMpService wxMpService; + + public WxMpGroupServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpGroup groupCreate(String name) throws WxErrorException { + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + JsonObject groupJson = new JsonObject(); + json.add("group", groupJson); + groupJson.addProperty("name", name); + + String responseContent = this.wxMpService.execute( + new SimplePostRequestExecutor(), + url, + json.toString()); + return WxMpGroup.fromJson(responseContent); + } + + @Override + public List groupGet() throws WxErrorException { + String url = API_URL_PREFIX + "/get"; + String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); + /* + * 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} } + * 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] } + */ + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("groups"), + new TypeToken>() { + }.getType()); + } + + @Override + public long userGetGroup(String openid) throws WxErrorException { + String url = API_URL_PREFIX + "/getid"; + JsonObject o = new JsonObject(); + o.addProperty("openid", openid); + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, o.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + return GsonHelper.getAsLong(tmpJsonElement.getAsJsonObject().get("groupid")); + } + + @Override + public void groupUpdate(WxMpGroup group) throws WxErrorException { + String url = API_URL_PREFIX + "/update"; + this.wxMpService.execute(new SimplePostRequestExecutor(), url, group.toJson()); + } + + @Override + public void userUpdateGroup(String openid, long to_groupid) throws WxErrorException { + String url = API_URL_PREFIX + "/members/update"; + JsonObject json = new JsonObject(); + json.addProperty("openid", openid); + json.addProperty("to_groupid", to_groupid); + this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString()); + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java index 6befcc2bb1..398d6e29f2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java @@ -7,11 +7,12 @@ import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; -import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; import me.chanjar.weixin.common.util.json.WxGsonBuilder; import me.chanjar.weixin.mp.api.WxMpMaterialService; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.WxMpMaterial; +import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; +import me.chanjar.weixin.mp.bean.WxMpMaterialNews; import me.chanjar.weixin.mp.bean.result.*; import me.chanjar.weixin.mp.util.http.*; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; @@ -27,6 +28,8 @@ * Created by Binary Wang on 2016/7/21. */ public class WxMpMaterialServiceImpl implements WxMpMaterialService { + private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; + private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; private WxMpService wxMpService; public WxMpMaterialServiceImpl(WxMpService wxMpService) { @@ -40,19 +43,25 @@ public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputS @Override public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType; + String url = MEDIA_API_URL_PREFIX + "/upload?type=" + mediaType; return this.wxMpService.execute(new MediaUploadRequestExecutor(), url, file); } @Override public File mediaDownload(String media_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/get"; + String url = MEDIA_API_URL_PREFIX + "/get"; return this.wxMpService.execute(new MediaDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, "media_id=" + media_id); } + @Override + public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException { + String url = MEDIA_API_URL_PREFIX + "/uploadimg"; + return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file); + } + @Override public WxMpMaterialUploadResult materialFileUpload(String mediaType, WxMpMaterial material) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=" + mediaType; + String url = MATERIAL_API_URL_PREFIX + "/add_material?type=" + mediaType; return this.wxMpService.execute(new MaterialUploadRequestExecutor(), url, material); } @@ -61,32 +70,32 @@ public WxMpMaterialUploadResult materialNewsUpload(WxMpMaterialNews news) throws if (news == null || news.isEmpty()) { throw new IllegalArgumentException("news is empty!"); } - String url = "https://api.weixin.qq.com/cgi-bin/material/add_news"; + String url = MATERIAL_API_URL_PREFIX + "/add_news"; String responseContent = this.wxMpService.post(url, news.toJson()); return WxMpMaterialUploadResult.fromJson(responseContent); } @Override public InputStream materialImageOrVoiceDownload(String media_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/get_material"; + String url = MATERIAL_API_URL_PREFIX + "/get_material"; return this.wxMpService.execute(new MaterialVoiceAndImageDownloadRequestExecutor(this.wxMpService.getWxMpConfigStorage().getTmpDirFile()), url, media_id); } @Override public WxMpMaterialVideoInfoResult materialVideoInfo(String media_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/get_material"; + String url = MATERIAL_API_URL_PREFIX + "/get_material"; return this.wxMpService.execute(new MaterialVideoInfoRequestExecutor(), url, media_id); } @Override public WxMpMaterialNews materialNewsInfo(String media_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/get_material"; + String url = MATERIAL_API_URL_PREFIX + "/get_material"; return this.wxMpService.execute(new MaterialNewsInfoRequestExecutor(), url, media_id); } @Override public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/update_news"; + String url = MATERIAL_API_URL_PREFIX + "/update_news"; String responseText = this.wxMpService.post(url, wxMpMaterialArticleUpdate.toJson()); WxError wxError = WxError.fromJson(responseText); if (wxError.getErrorCode() == 0) { @@ -98,13 +107,13 @@ public boolean materialNewsUpdate(WxMpMaterialArticleUpdate wxMpMaterialArticleU @Override public boolean materialDelete(String media_id) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/del_material"; + String url = MATERIAL_API_URL_PREFIX + "/del_material"; return this.wxMpService.execute(new MaterialDeleteRequestExecutor(), url, media_id); } @Override public WxMpMaterialCountResult materialCount() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount"; + String url = MATERIAL_API_URL_PREFIX + "/get_materialcount"; String responseText = this.wxMpService.get(url, null); WxError wxError = WxError.fromJson(responseText); if (wxError.getErrorCode() == 0) { @@ -116,7 +125,7 @@ public WxMpMaterialCountResult materialCount() throws WxErrorException { @Override public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material"; + String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; Map params = new HashMap<>(); params.put("type", WxConsts.MATERIAL_NEWS); params.put("offset", offset); @@ -132,7 +141,7 @@ public WxMpMaterialNewsBatchGetResult materialNewsBatchGet(int offset, int count @Override public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material"; + String url = MATERIAL_API_URL_PREFIX + "/batchget_material"; Map params = new HashMap<>(); params.put("type", type); params.put("offset", offset); @@ -146,10 +155,4 @@ public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offs } } - @Override - public WxMediaImgUploadResult mediaImgUpload(File file) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg"; - return this.wxMpService.execute(new MediaImgUploadRequestExecutor(), url, file); - } - } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java new file mode 100644 index 0000000000..bb0e112cec --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java @@ -0,0 +1,102 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.bean.result.WxError; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.mp.api.WxMpQrcodeService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; +import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * Created by Binary Wang on 2016/7/21. + */ +public class WxMpQrcodeServiceImpl implements WxMpQrcodeService { + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; + private WxMpService wxMpService; + + public WxMpQrcodeServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpQrCodeTicket qrCodeCreateTmpTicket(int scene_id, Integer expire_seconds) throws WxErrorException { + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_SCENE"); + if (expire_seconds != null) { + json.addProperty("expire_seconds", expire_seconds); + } + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_id", scene_id); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorException { + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_LIMIT_SCENE"); + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_id", scene_id); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException { + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_str", scene_str); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override + public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException { + String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode"; + return this.wxMpService.execute(new QrCodeRequestExecutor(), url, ticket); + } + + @Override + public String qrCodePictureUrl(String ticket, boolean needShortUrl) throws WxErrorException { + String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s"; + try { + String resultUrl = String.format(url, + URLEncoder.encode(ticket, StandardCharsets.UTF_8.name())); + if (needShortUrl) { + return this.wxMpService.shortUrl(resultUrl); + } + + return resultUrl; + } catch (UnsupportedEncodingException e) { + WxError error = WxError.newBuilder().setErrorCode(-1) + .setErrorMsg(e.getMessage()).build(); + throw new WxErrorException(error); + } + } + + @Override + public String qrCodePictureUrl(String ticket) throws WxErrorException { + return qrCodePictureUrl(ticket, false); + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java new file mode 100644 index 0000000000..f2ceac3460 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImpl.java @@ -0,0 +1,83 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; +import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.WxMpUserService; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; +import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; + +import java.io.StringReader; +import java.util.Date; +import java.util.List; + +/** + * Created by Binary Wang on 2016/7/21. + */ +public class WxMpUserServiceImpl implements WxMpUserService { + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/user"; + private WxMpService wxMpService; + + public WxMpUserServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public void userUpdateRemark(String openid, String remark) throws WxErrorException { + String url = API_URL_PREFIX + "/info/updateremark"; + JsonObject json = new JsonObject(); + json.addProperty("openid", openid); + json.addProperty("remark", remark); + this.wxMpService.execute(new SimplePostRequestExecutor(), url, json.toString()); + } + + @Override + public WxMpUser userInfo(String openid, String lang) throws WxErrorException { + String url = API_URL_PREFIX + "/info"; + lang = lang == null ? "zh_CN" : lang; + String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "openid=" + openid + "&lang=" + lang); + return WxMpUser.fromJson(responseContent); + } + + @Override + public WxMpUserList userList(String next_openid) throws WxErrorException { + String url = API_URL_PREFIX + "/get"; + String responseContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, next_openid == null ? null : "next_openid=" + next_openid); + return WxMpUserList.fromJson(responseContent); + } + + @Override + public List dataCubeUserSummary(Date beginDate, Date endDate) throws WxErrorException { + String url = "https://api.weixin.qq.com/datacube/getusersummary"; + JsonObject param = new JsonObject(); + param.addProperty("begin_date", WxMpService.SIMPLE_DATE_FORMAT.format(beginDate)); + param.addProperty("end_date", WxMpService.SIMPLE_DATE_FORMAT.format(endDate)); + String responseContent = this.wxMpService.post(url, param.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"), + new TypeToken>() { + }.getType()); + } + + @Override + public List dataCubeUserCumulate(Date beginDate, Date endDate) throws WxErrorException { + String url = "https://api.weixin.qq.com/datacube/getusercumulate"; + JsonObject param = new JsonObject(); + param.addProperty("begin_date", WxMpService.SIMPLE_DATE_FORMAT.format(beginDate)); + param.addProperty("end_date", WxMpService.SIMPLE_DATE_FORMAT.format(endDate)); + String responseContent = this.wxMpService.post(url, param.toString()); + JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent))); + return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement.getAsJsonObject().get("list"), + new TypeToken>() { + }.getType()); + } +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java index 562820c374..537b771c5c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpQrCodeTicket.java @@ -45,4 +45,9 @@ public void setUrl(String url) { public static WxMpQrCodeTicket fromJson(String json) { return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpQrCodeTicket.class); } + + @Override + public String toString() { + return WxMpGsonBuilder.INSTANCE.create().toJson(this); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java index 489d5bedb1..842f13270d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpUserList.java @@ -44,4 +44,9 @@ public void setNextOpenId(String nextOpenId) { public static WxMpUserList fromJson(String json) { return WxMpGsonBuilder.INSTANCE.create().fromJson(json, WxMpUserList.class); } + + @Override + public String toString() { + return WxMpGsonBuilder.INSTANCE.create().toJson(this); + } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java index 6d276efd9c..565de65fcc 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java @@ -63,7 +63,7 @@ public void testTextMassGroupMessageSend() throws WxErrorException { WxMpMassGroupMessage massMessage = new WxMpMassGroupMessage(); massMessage.setMsgtype(WxConsts.MASS_MSG_TEXT); massMessage.setContent("测试群发消息\n欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); - massMessage.setGroupId(wxService.groupGet().get(0).getId()); + massMessage.setGroupId(wxService.getGroupService().groupGet().get(0).getId()); WxMpMassSendResult massResult = wxService.massGroupMessageSend(massMessage); Assert.assertNotNull(massResult); @@ -75,7 +75,7 @@ public void testMediaMassGroupMessageSend(String massMsgType, String mediaId) th WxMpMassGroupMessage massMessage = new WxMpMassGroupMessage(); massMessage.setMsgtype(massMsgType); massMessage.setMediaId(mediaId); - massMessage.setGroupId(wxService.groupGet().get(0).getId()); + massMessage.setGroupId(wxService.getGroupService().groupGet().get(0).getId()); WxMpMassSendResult massResult = wxService.massGroupMessageSend(massMessage); Assert.assertNotNull(massResult); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java index 5f2a73926d..8440828223 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java @@ -1,37 +1,19 @@ package me.chanjar.weixin.mp.api; import com.google.inject.Inject; -import me.chanjar.weixin.common.api.WxConsts; -import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.common.session.WxSession; -import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; -import me.chanjar.weixin.mp.bean.WxMpMassNews; -import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; -import me.chanjar.weixin.mp.bean.WxMpMassVideo; -import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; -import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; -import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; -import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; import org.testng.Assert; -import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; -import java.io.IOException; -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Date; -import java.util.List; /** * * @author chanjarster * */ -@Test(groups = "miscAPI", dependsOnGroups = { "baseAPI"}) +@Test(groups = "miscAPI") @Guice(modules = ApiTestModule.class) public class WxMpMiscAPITest { @@ -46,24 +28,4 @@ public void testGetCallbackIP() throws WxErrorException { Assert.assertNotEquals(ipArray.length, 0); } - @Test - public void testGetUserSummary() throws WxErrorException, ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date beginDate = simpleDateFormat.parse("2015-01-01"); - Date endDate = simpleDateFormat.parse("2015-01-02"); - List summaries = wxService.getUserSummary(beginDate, endDate); - System.out.println(summaries); - Assert.assertNotNull(summaries); - } - - @Test - public void testGetUserCumulate() throws WxErrorException, ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date beginDate = simpleDateFormat.parse("2015-01-01"); - Date endDate = simpleDateFormat.parse("2015-01-02"); - List cumulates = wxService.getUserCumulate(beginDate, endDate); - System.out.println(cumulates); - Assert.assertNotNull(cumulates); - } - } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java deleted file mode 100644 index fa978c57bc..0000000000 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpUserAPITest.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.chanjar.weixin.mp.api; - -import com.google.inject.Inject; -import me.chanjar.weixin.common.exception.WxErrorException; -import me.chanjar.weixin.mp.bean.result.WxMpUser; -import me.chanjar.weixin.mp.bean.result.WxMpUserList; -import org.testng.Assert; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; - -/** - * 测试用户相关的接口 - * @author chanjarster - * - */ -@Test(groups = "userAPI", dependsOnGroups = { "baseAPI", "groupAPI" }) -@Guice(modules = ApiTestModule.class) -public class WxMpUserAPITest { - - @Inject - protected WxMpServiceImpl wxService; - - public void testUserUpdateRemark() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; - wxService.userUpdateRemark(configProvider.getOpenId(), "测试备注名"); - } - - public void testUserInfo() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; - WxMpUser user = wxService.userInfo(configProvider.getOpenId(), null); - Assert.assertNotNull(user); - } - - public void testUserList() throws WxErrorException { - WxMpUserList wxMpUserList = wxService.userList(null); - Assert.assertNotNull(wxMpUserList); - Assert.assertFalse(wxMpUserList.getCount() == -1); - Assert.assertFalse(wxMpUserList.getTotal() == -1); - Assert.assertFalse(wxMpUserList.getOpenIds().size() == -1); - } - - public void testGroupQueryUserGroup() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; - long groupid = wxService.userGetGroup(configStorage.getOpenId()); - Assert.assertTrue(groupid != -1l); - } - - public void getGroupMoveUser() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; - wxService.userUpdateGroup(configStorage.getOpenId(), wxService.groupGet().get(3).getId()); - } - -} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpGroupAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java similarity index 70% rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpGroupAPITest.java rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java index 4397e05701..4bcf8d9fe0 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpGroupAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java @@ -1,7 +1,9 @@ -package me.chanjar.weixin.mp.api; +package me.chanjar.weixin.mp.api.impl; import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpGroup; import org.testng.Assert; import org.testng.annotations.Guice; @@ -14,9 +16,9 @@ * * @author chanjarster */ -@Test(groups = "groupAPI", dependsOnGroups = "baseAPI") +@Test(groups = "groupAPI") @Guice(modules = ApiTestModule.class) -public class WxMpGroupAPITest { +public class WxMpGroupServiceImplTest { @Inject protected WxMpServiceImpl wxService; @@ -24,13 +26,13 @@ public class WxMpGroupAPITest { protected WxMpGroup group; public void testGroupCreate() throws WxErrorException { - WxMpGroup res = wxService.groupCreate("测试分组1"); + WxMpGroup res = this.wxService.getGroupService().groupCreate("测试分组1"); Assert.assertEquals(res.getName(), "测试分组1"); } @Test(dependsOnMethods="testGroupCreate") public void testGroupGet() throws WxErrorException { - List groupList = wxService.groupGet(); + List groupList = this.wxService.getGroupService().groupGet(); Assert.assertNotNull(groupList); Assert.assertTrue(groupList.size() > 0); for (WxMpGroup g : groupList) { @@ -42,7 +44,7 @@ public void testGroupGet() throws WxErrorException { @Test(dependsOnMethods={"testGroupGet", "testGroupCreate"}) public void getGroupUpdate() throws WxErrorException { group.setName("分组改名"); - wxService.groupUpdate(group); + this.wxService.getGroupService().groupUpdate(group); } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java similarity index 56% rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java index 2b12ac259b..4600b07dbf 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpQrCodeAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java @@ -1,7 +1,9 @@ -package me.chanjar.weixin.mp.api; +package me.chanjar.weixin.mp.api.impl; import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import org.testng.Assert; import org.testng.annotations.Guice; @@ -16,35 +18,39 @@ */ @Test(groups = "qrCodeAPI") @Guice(modules = ApiTestModule.class) -public class WxMpQrCodeAPITest { +public class WxMpQrCodeServiceImplTest { @Inject protected WxMpServiceImpl wxService; public void testQrCodeCreateTmpTicket() throws WxErrorException { - WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateTmpTicket(1, null); + WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateTmpTicket(1, null); Assert.assertNotNull(ticket.getUrl()); Assert.assertNotNull(ticket.getTicket()); Assert.assertTrue(ticket.getExpire_seconds() != -1); + System.out.println(ticket); } public void testQrCodeCreateLastTicket() throws WxErrorException { - WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1); + WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1); Assert.assertNotNull(ticket.getUrl()); Assert.assertNotNull(ticket.getTicket()); Assert.assertTrue(ticket.getExpire_seconds() == -1); + System.out.println(ticket); } public void testQrCodePicture() throws WxErrorException { - WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1); - File file = this.wxService.qrCodePicture(ticket); + WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1); + File file = this.wxService.getQrcodeService().qrCodePicture(ticket); Assert.assertNotNull(file); + System.out.println(file.getAbsolutePath()); } public void testQrCodePictureUrl() throws WxErrorException { - WxMpQrCodeTicket ticket = this.wxService.qrCodeCreateLastTicket(1); - String url = this.wxService.qrCodePictureUrl(ticket.getTicket()); + WxMpQrCodeTicket ticket = this.wxService.getQrcodeService().qrCodeCreateLastTicket(1); + String url = this.wxService.getQrcodeService().qrCodePictureUrl(ticket.getTicket()); Assert.assertNotNull(url); + System.out.println(url); } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java new file mode 100644 index 0000000000..5fc3dd9b58 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java @@ -0,0 +1,85 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.inject.Inject; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.WxMpServiceImpl; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; +import me.chanjar.weixin.mp.bean.result.WxMpUserList; +import me.chanjar.weixin.mp.bean.result.WxMpUserSummary; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * 测试用户相关的接口 + * + * @author chanjarster + * @author Binary Wang + */ +@Test(groups = "userAPI") +@Guice(modules = ApiTestModule.class) +public class WxMpUserServiceImplTest { + + @Inject + protected WxMpServiceImpl wxService; + + public void testUserUpdateRemark() throws WxErrorException { + ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); + this.wxService.getUserService().userUpdateRemark(configProvider.getOpenId(), "测试备注名"); + } + + public void testUserInfo() throws WxErrorException { + ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); + WxMpUser user = this.wxService.getUserService().userInfo(configProvider.getOpenId(), null); + Assert.assertNotNull(user); + System.out.println(user); + } + + public void testUserList() throws WxErrorException { + WxMpUserList wxMpUserList = this.wxService.getUserService().userList(null); + Assert.assertNotNull(wxMpUserList); + Assert.assertFalse(wxMpUserList.getCount() == -1); + Assert.assertFalse(wxMpUserList.getTotal() == -1); + Assert.assertFalse(wxMpUserList.getOpenIds().size() == -1); + System.out.println(wxMpUserList); + } + + public void testGroupQueryUserGroup() throws WxErrorException { + ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); + long groupid = this.wxService.getGroupService().userGetGroup(configStorage.getOpenId()); + Assert.assertTrue(groupid != -1l); + } + + public void testGroupMoveUser() throws WxErrorException { + ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); + this.wxService.getGroupService().userUpdateGroup(configStorage.getOpenId(), this.wxService.getGroupService().groupGet().get(3).getId()); + } + + @Test + public void testGetUserSummary() throws WxErrorException, ParseException { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date beginDate = simpleDateFormat.parse("2015-01-01"); + Date endDate = simpleDateFormat.parse("2015-01-02"); + List summaries = this.wxService.getUserService().dataCubeUserSummary(beginDate, endDate); + Assert.assertNotNull(summaries); + System.out.println(summaries); + } + + @Test + public void testGetUserCumulate() throws WxErrorException, ParseException { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date beginDate = simpleDateFormat.parse("2015-01-01"); + Date endDate = simpleDateFormat.parse("2015-01-02"); + List cumulates = this.wxService.getUserService().dataCubeUserCumulate(beginDate, endDate); + Assert.assertNotNull(cumulates); + System.out.println(cumulates); + } + +} diff --git a/weixin-java-mp/src/test/resources/testng.xml b/weixin-java-mp/src/test/resources/testng.xml index 09184112c0..d821e398f6 100644 --- a/weixin-java-mp/src/test/resources/testng.xml +++ b/weixin-java-mp/src/test/resources/testng.xml @@ -7,10 +7,10 @@ - + - - + + From 1d2f2e298534c124eb55f2339b299415cf5f3e8b Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Thu, 21 Jul 2016 17:23:36 +0800 Subject: [PATCH 50/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=90=8E=E7=9A=84=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../binarywang/demo/spring/handler/SubscribeHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java index 27455b375e..78049f4419 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/SubscribeHandler.java @@ -1,10 +1,7 @@ package com.github.binarywang.demo.spring.handler; -import java.util.Map; - import com.github.binarywang.demo.spring.builder.TextBuilder; import com.github.binarywang.demo.spring.service.BaseWxService; - import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpService; @@ -12,6 +9,8 @@ import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.result.WxMpUser; +import java.util.Map; + /** * * @author Binary Wang @@ -28,7 +27,7 @@ public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map co BaseWxService weixinService = (BaseWxService) wxMpService; // 获取微信用户基本信息 - WxMpUser userWxInfo = weixinService.userInfo(wxMessage.getFromUserName(), null); + WxMpUser userWxInfo = weixinService.getUserService().userInfo(wxMessage.getFromUserName(), null); if (userWxInfo != null) { // TODO 可以添加关注用户到本地 From bcbc10d2779f7569b43cc07d74d24618e02cef6e Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Fri, 22 Jul 2016 10:30:35 +0800 Subject: [PATCH 51/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=B8=BB?= =?UTF-8?q?=E8=A6=81=E6=98=AFapi=E7=9A=84url=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/mp/api/impl/WxMpMaterialServiceImpl.java | 4 ++-- .../weixin/mp/api/impl/WxMpMenuServiceImpl.java | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java index 398d6e29f2..c6825815cd 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImpl.java @@ -28,8 +28,8 @@ * Created by Binary Wang on 2016/7/21. */ public class WxMpMaterialServiceImpl implements WxMpMaterialService { - private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; - private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/qrcode"; + private static final String MEDIA_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/media"; + private static final String MATERIAL_API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/material"; private WxMpService wxMpService; public WxMpMaterialServiceImpl(WxMpService wxMpService) { 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 5ecb0d93a3..bfad1e06a9 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 @@ -11,6 +11,7 @@ * Created by Binary Wang on 2016/7/21. */ public class WxMpMenuServiceImpl implements WxMpMenuService { + private static final String API_URL_PREFIX = "https://api.weixin.qq.com/cgi-bin/menu"; private WxMpService wxMpService; @@ -21,29 +22,29 @@ public WxMpMenuServiceImpl(WxMpService wxMpService) { @Override public void menuCreate(WxMenu menu) throws WxErrorException { if (menu.getMatchRule() != null) { - String url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional"; + String url = API_URL_PREFIX + "/addconditional"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, menu.toJson()); } else { - String url = "https://api.weixin.qq.com/cgi-bin/menu/create"; + String url = API_URL_PREFIX + "/create"; this.wxMpService.execute(new SimplePostRequestExecutor(), url, menu.toJson()); } } @Override public void menuDelete() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/menu/delete"; + String url = API_URL_PREFIX + "/delete"; this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); } @Override public void menuDelete(String menuid) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional"; + String url = API_URL_PREFIX + "/delconditional"; this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "menuid=" + menuid); } @Override public WxMenu menuGet() throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/menu/get"; + String url = API_URL_PREFIX + "/get"; try { String resultContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, null); return WxMenu.fromJson(resultContent); @@ -58,7 +59,7 @@ public WxMenu menuGet() throws WxErrorException { @Override public WxMenu menuTryMatch(String userid) throws WxErrorException { - String url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch"; + String url = API_URL_PREFIX + "/trymatch"; try { String resultContent = this.wxMpService.execute(new SimpleGetRequestExecutor(), url, "user_id=" + userid); return WxMenu.fromJson(resultContent); From d8828a2c4e906bbeb4a45e878177ca809e3fa315 Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Fri, 22 Jul 2016 10:37:47 +0800 Subject: [PATCH 52/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=8C=85=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E5=AE=9E=E7=8E=B0=E7=B1=BB=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E6=94=BE=E5=85=A5impl=E5=8C=85=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/binarywang/demo/spring/service/BaseWxService.java | 2 +- .../me/chanjar/weixin/mp/api/{ => impl}/WxMpServiceImpl.java | 4 ++-- .../test/java/me/chanjar/weixin/mp/api/ApiTestModule.java | 1 + .../test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java | 3 ++- .../java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java | 1 + .../me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java | 5 +++-- .../test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java | 3 +-- .../me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java | 5 +++-- .../test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java | 1 + .../java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java | 1 + .../chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java | 1 - .../chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java | 1 - .../weixin/mp/api/impl/WxMpMaterialServiceImplTest.java | 1 - .../chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java | 1 - .../weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java | 1 - .../chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java | 1 - .../test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java | 1 + 17 files changed, 17 insertions(+), 16 deletions(-) rename weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/{ => impl}/WxMpServiceImpl.java (99%) diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java index ac61bea0b3..23b3ded5ae 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java @@ -19,7 +19,7 @@ import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpMessageRouter; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java similarity index 99% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java index 5e8809d73c..8c29dd8b7d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java @@ -1,4 +1,4 @@ -package me.chanjar.weixin.mp.api; +package me.chanjar.weixin.mp.api.impl; import com.google.gson.*; import com.google.gson.internal.Streams; @@ -17,7 +17,7 @@ import me.chanjar.weixin.common.util.crypto.WxCryptUtil; import me.chanjar.weixin.common.util.http.*; import me.chanjar.weixin.common.util.xml.XStreamInitializer; -import me.chanjar.weixin.mp.api.impl.*; +import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.result.*; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java index 320751546f..4980facad3 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.apache.commons.lang3.builder.ToStringBuilder; import com.google.inject.Binder; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java index 49d056af2f..7caaee5078 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBaseAPITest.java @@ -3,6 +3,7 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.StringUtils; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; @@ -20,7 +21,7 @@ public class WxMpBaseAPITest { protected WxMpServiceImpl wxService; public void testRefreshAccessToken() throws WxErrorException { - WxMpConfigStorage configStorage = this.wxService.wxMpConfigStorage; + WxMpConfigStorage configStorage = this.wxService.getWxMpConfigStorage(); String before = configStorage.getAccessToken(); this.wxService.getAccessToken(false); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java index 2e16723aed..c9edbdc534 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpBusyRetryTest.java @@ -3,6 +3,7 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.http.RequestExecutor; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java index 92a641dfec..4cca2e3c67 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpCustomMessageAPITest.java @@ -3,6 +3,7 @@ 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.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpCustomMessage; import org.testng.annotations.Guice; import org.testng.annotations.Test; @@ -20,7 +21,7 @@ public class WxMpCustomMessageAPITest { protected WxMpServiceImpl wxService; public void testSendCustomMessage() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; + ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); WxMpCustomMessage message = new WxMpCustomMessage(); message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); message.setToUser(configStorage.getOpenId()); @@ -30,7 +31,7 @@ public void testSendCustomMessage() throws WxErrorException { } public void testSendCustomMessageWithKfAccount() throws WxErrorException { - ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; + ApiTestModule.WxXmlMpInMemoryConfigStorage configStorage = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); WxMpCustomMessage message = new WxMpCustomMessage(); message.setMsgType(WxConsts.CUSTOM_MSG_TEXT); message.setToUser(configStorage.getOpenId()); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java index 16506caa9f..dacc2ab8a7 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpJsAPITest.java @@ -3,13 +3,12 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.crypto.SHA1; -import me.chanjar.weixin.mp.bean.WxMpGroup; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; import java.security.NoSuchAlgorithmException; -import java.util.List; /** * 测试jsapi ticket接口 diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java index 565de65fcc..5b50b5a44e 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMassMessageAPITest.java @@ -4,6 +4,7 @@ import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; import me.chanjar.weixin.mp.bean.WxMpMassNews; import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; @@ -33,7 +34,7 @@ public class WxMpMassMessageAPITest { @Test public void testTextMassOpenIdsMessageSend() throws WxErrorException { // 发送群发消息 - ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; + ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage(); massMessage.setMsgType(WxConsts.MASS_MSG_TEXT); massMessage.setContent("测试群发消息\n欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); @@ -47,7 +48,7 @@ public void testTextMassOpenIdsMessageSend() throws WxErrorException { @Test(dataProvider="massMessages") public void testMediaMassOpenIdsMessageSend(String massMsgType, String mediaId) throws WxErrorException, IOException { // 发送群发消息 - ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.wxMpConfigStorage; + ApiTestModule.WxXmlMpInMemoryConfigStorage configProvider = (ApiTestModule.WxXmlMpInMemoryConfigStorage) wxService.getWxMpConfigStorage(); WxMpMassOpenIdsMessage massMessage = new WxMpMassOpenIdsMessage(); massMessage.setMsgType(massMsgType); massMessage.setMediaId(mediaId); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java index 8440828223..3d80836f9f 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpMiscAPITest.java @@ -2,6 +2,7 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java index 76712ad58a..091f62eeb4 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/WxMpShortUrlAPITest.java @@ -2,6 +2,7 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.testng.Assert; import org.testng.annotations.Guice; import org.testng.annotations.Test; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java index 4bcf8d9fe0..f2dd8f645f 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpGroupServiceImplTest.java @@ -3,7 +3,6 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpGroup; import org.testng.Assert; import org.testng.annotations.Guice; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java index b63fa8413a..c1812ab064 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpKefuServiceImplTest.java @@ -16,7 +16,6 @@ import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.kefu.request.WxMpKfAccountRequest; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfInfo; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfList; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java index abe962211c..6ab7c7c477 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMaterialServiceImplTest.java @@ -6,7 +6,6 @@ import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.mp.api.ApiTestModule; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.WxMpMaterial; import me.chanjar.weixin.mp.bean.WxMpMaterialArticleUpdate; import me.chanjar.weixin.mp.bean.WxMpMaterialNews; 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 10e050ea42..0cbae4db1b 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 @@ -6,7 +6,6 @@ import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java index 4600b07dbf..d2ed01dad3 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpQrCodeServiceImplTest.java @@ -3,7 +3,6 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import org.testng.Assert; import org.testng.annotations.Guice; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java index 5fc3dd9b58..af5289f0c1 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpUserServiceImplTest.java @@ -3,7 +3,6 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.mp.api.ApiTestModule; -import me.chanjar.weixin.mp.api.WxMpServiceImpl; import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUserCumulate; import me.chanjar.weixin.mp.bean.result.WxMpUserList; diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java index e92bd98655..b89b279610 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpDemoServer.java @@ -2,6 +2,7 @@ import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.mp.api.*; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; From c8c0284a2bda39f2e778351443b36a4c010ccc7d Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Fri, 22 Jul 2016 11:10:09 +0800 Subject: [PATCH 53/54] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=B8=BA=202.0.0-SNAPSHOT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- weixin-java-common/pom.xml | 2 +- weixin-java-cp/pom.xml | 2 +- weixin-java-demo-with-spring/pom.xml | 2 +- weixin-java-mp/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 691a394a6d..deccbf833f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.github.binarywang weixin-java-parent - 1.3.6-SNAPSHOT + 2.0.0-SNAPSHOT pom WeiXin Java Tools - Parent 微信公众号、企业号上级POM diff --git a/weixin-java-common/pom.xml b/weixin-java-common/pom.xml index 8adf10cdfb..517fc604f3 100644 --- a/weixin-java-common/pom.xml +++ b/weixin-java-common/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.6-SNAPSHOT + 2.0.0-SNAPSHOT weixin-java-common diff --git a/weixin-java-cp/pom.xml b/weixin-java-cp/pom.xml index 893eceb33c..654ba365fb 100644 --- a/weixin-java-cp/pom.xml +++ b/weixin-java-cp/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.6-SNAPSHOT + 2.0.0-SNAPSHOT weixin-java-cp diff --git a/weixin-java-demo-with-spring/pom.xml b/weixin-java-demo-with-spring/pom.xml index 5178468614..e416798ef8 100644 --- a/weixin-java-demo-with-spring/pom.xml +++ b/weixin-java-demo-with-spring/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.6-SNAPSHOT + 2.0.0-SNAPSHOT weixin-java-demo-with-spring war diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index a338ff5c57..3aa28ed046 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -6,7 +6,7 @@ com.github.binarywang weixin-java-parent - 1.3.6-SNAPSHOT + 2.0.0-SNAPSHOT weixin-java-mp WeiXin Java Tools - MP From 2207497a6cd90cad59a6eadb0e457ba29b88ce3d Mon Sep 17 00:00:00 2001 From: BinaryWang Date: Fri, 22 Jul 2016 11:35:07 +0800 Subject: [PATCH 54/54] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8D=95=E8=AF=8D=E7=9A=84=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...h1MenuHadler.java => Gzh1MenuHandler.java} | 2 +- ...Gzh1MsgHadler.java => Gzh1MsgHandler.java} | 2 +- ...eHadler.java => Gzh1SubscribeHandler.java} | 2 +- ...adler.java => Gzh1UnSubscribeHandler.java} | 2 +- .../demo/spring/service/BaseWxService.java | 24 ++++++------------- .../demo/spring/service/Gzh1WxService.java | 24 +++++++++---------- 6 files changed, 23 insertions(+), 33 deletions(-) rename weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/{Gzh1MenuHadler.java => Gzh1MenuHandler.java} (92%) rename weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/{Gzh1MsgHadler.java => Gzh1MsgHandler.java} (93%) rename weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/{Gzh1SubscribeHadler.java => Gzh1SubscribeHandler.java} (93%) rename weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/{Gzh1UnSubscribeHadler.java => Gzh1UnSubscribeHandler.java} (91%) diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHandler.java similarity index 92% rename from weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java rename to weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHandler.java index 4368a60400..33382366f2 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHadler.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MenuHandler.java @@ -11,7 +11,7 @@ @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class Gzh1MenuHadler extends MenuHandler { +public class Gzh1MenuHandler extends MenuHandler { @Autowired private WxGzh1Config wxConfig; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHandler.java similarity index 93% rename from weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java rename to weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHandler.java index 59ee6ae1a5..8810b64358 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHadler.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1MsgHandler.java @@ -11,7 +11,7 @@ @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class Gzh1MsgHadler extends MsgHandler { +public class Gzh1MsgHandler extends MsgHandler { @Autowired private WxGzh1Config wxConfig; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHandler.java similarity index 93% rename from weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java rename to weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHandler.java index cadfd1fa66..367a5d8b43 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHadler.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1SubscribeHandler.java @@ -14,7 +14,7 @@ @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class Gzh1SubscribeHadler extends SubscribeHandler { +public class Gzh1SubscribeHandler extends SubscribeHandler { @Autowired private WxGzh1Config wxConfig; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHandler.java similarity index 91% rename from weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java rename to weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHandler.java index a4e3a8ed6c..f55d39d448 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHadler.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/handler/gzh1/Gzh1UnSubscribeHandler.java @@ -11,7 +11,7 @@ @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) -public class Gzh1UnSubscribeHadler extends UnsubscribeHandler { +public class Gzh1UnSubscribeHandler extends UnsubscribeHandler { @Autowired private WxGzh1Config wxConfig; diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java index 23b3ded5ae..4b629eaa6c 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/BaseWxService.java @@ -1,21 +1,7 @@ package com.github.binarywang.demo.spring.service; -import javax.annotation.PostConstruct; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - import com.github.binarywang.demo.spring.config.WxConfig; -import com.github.binarywang.demo.spring.handler.AbstractHandler; -import com.github.binarywang.demo.spring.handler.KfSessionHandler; -import com.github.binarywang.demo.spring.handler.LogHandler; -import com.github.binarywang.demo.spring.handler.MenuHandler; -import com.github.binarywang.demo.spring.handler.MsgHandler; -import com.github.binarywang.demo.spring.handler.NullHandler; -import com.github.binarywang.demo.spring.handler.SubscribeHandler; -import com.github.binarywang.demo.spring.handler.UnsubscribeHandler; - +import com.github.binarywang.demo.spring.handler.*; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpMessageRouter; @@ -23,6 +9,11 @@ import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.kefu.result.WxMpKfOnlineList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.PostConstruct; /** * @@ -125,8 +116,7 @@ private void refreshRouter() { public WxMpXmlOutMessage route(WxMpXmlMessage message) { try { - final WxMpXmlOutMessage responseMessage = this.router.route(message); - return responseMessage; + return this.router.route(message); } catch (Exception e) { this.logger.error(e.getMessage(), e); } diff --git a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java index cd809951ea..1bad76ec34 100644 --- a/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java +++ b/weixin-java-demo-with-spring/src/main/java/com/github/binarywang/demo/spring/service/Gzh1WxService.java @@ -11,10 +11,10 @@ import com.github.binarywang.demo.spring.handler.SubscribeHandler; import com.github.binarywang.demo.spring.handler.UnsubscribeHandler; import com.github.binarywang.demo.spring.handler.gzh1.Gzh1LocationHandler; -import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MenuHadler; -import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MsgHadler; -import com.github.binarywang.demo.spring.handler.gzh1.Gzh1SubscribeHadler; -import com.github.binarywang.demo.spring.handler.gzh1.Gzh1UnSubscribeHadler; +import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MenuHandler; +import com.github.binarywang.demo.spring.handler.gzh1.Gzh1MsgHandler; +import com.github.binarywang.demo.spring.handler.gzh1.Gzh1SubscribeHandler; +import com.github.binarywang.demo.spring.handler.gzh1.Gzh1UnSubscribeHandler; /** * @@ -30,16 +30,16 @@ public class Gzh1WxService extends BaseWxService { private Gzh1LocationHandler locationHandler; @Autowired - private Gzh1MenuHadler menuHadler; + private Gzh1MenuHandler menuHandler; @Autowired - private Gzh1MsgHadler msgHadler; + private Gzh1MsgHandler msgHandler; @Autowired - private Gzh1UnSubscribeHadler unSubscribeHadler; + private Gzh1UnSubscribeHandler unSubscribeHandler; @Autowired - private Gzh1SubscribeHadler subscribeHadler; + private Gzh1SubscribeHandler subscribeHandler; @Override protected WxConfig getServerConfig() { @@ -48,17 +48,17 @@ protected WxConfig getServerConfig() { @Override protected MenuHandler getMenuHandler() { - return this.menuHadler; + return this.menuHandler; } @Override protected SubscribeHandler getSubscribeHandler() { - return this.subscribeHadler; + return this.subscribeHandler; } @Override protected UnsubscribeHandler getUnsubscribeHandler() { - return this.unSubscribeHadler; + return this.unSubscribeHandler; } @Override @@ -68,7 +68,7 @@ protected AbstractHandler getLocationHandler() { @Override protected MsgHandler getMsgHandler() { - return this.msgHadler; + return this.msgHandler; } @Override