diff --git a/src/main/java/chanjarster/weixin/api/WxService.java b/src/main/java/chanjarster/weixin/api/WxService.java index 1de320039..fffc5c696 100644 --- a/src/main/java/chanjarster/weixin/api/WxService.java +++ b/src/main/java/chanjarster/weixin/api/WxService.java @@ -5,11 +5,12 @@ import java.io.IOException; import java.io.InputStream; import chanjarster.weixin.bean.WxCustomMessage; -import chanjarster.weixin.bean.WxMassMessage; +import chanjarster.weixin.bean.WxMassGroupMessage; import chanjarster.weixin.bean.WxMassNews; +import chanjarster.weixin.bean.WxMassOpenIdsMessage; import chanjarster.weixin.bean.WxMassVideo; import chanjarster.weixin.bean.WxMenu; -import chanjarster.weixin.bean.result.WxMassMaterialUploadResult; +import chanjarster.weixin.bean.result.WxMassUploadResult; import chanjarster.weixin.bean.result.WxMassSendResult; import chanjarster.weixin.bean.result.WxMediaUploadResult; import chanjarster.weixin.exception.WxErrorException; @@ -104,7 +105,7 @@ public interface WxService { * @param news * @throws WxErrorException */ - public WxMassMaterialUploadResult uploadMassNews(WxMassNews news) throws WxErrorException; + public WxMassUploadResult uploadMassNews(WxMassNews news) throws WxErrorException; /** *
@@ -114,11 +115,11 @@ public interface WxService {
* @return
* @throws WxErrorException
*/
- public WxMassMaterialUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException;
+ public WxMassUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException;
/**
*
- * 群发消息
+ * 分组群发消息
* 如果发送图文消息,必须先使用 {@link #uploadMassNews(WxMassNews)} 获得media_id,然后再发送
* 如果发送视频消息,必须先使用 {@link #uploadMassVideo(WxMassVideo)} 获得media_id,然后再发送
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
@@ -127,8 +128,21 @@ public interface WxService {
* @throws WxErrorException
* @return
*/
- public WxMassSendResult sendMassMessage(WxMassMessage message) throws WxErrorException;
+ public WxMassSendResult sendMassMessageByGroup(WxMassGroupMessage message) throws WxErrorException;
+ /**
+ *
+ * 按openId列表群发消息
+ * 如果发送图文消息,必须先使用 {@link #uploadMassNews(WxMassNews)} 获得media_id,然后再发送
+ * 如果发送视频消息,必须先使用 {@link #uploadMassVideo(WxMassVideo)} 获得media_id,然后再发送
+ * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
+ *
+ * @param message
+ * @return
+ * @throws WxErrorException
+ */
+ public WxMassSendResult sendMassMessageByOpenIds(WxMassOpenIdsMessage message) throws WxErrorException;
+
/**
*
* 自定义菜单创建接口
diff --git a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
index 826bef932..2a0ad0eb1 100644
--- a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
+++ b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
@@ -18,13 +18,14 @@ import org.apache.http.impl.client.HttpClients;
import chanjarster.weixin.bean.WxAccessToken;
import chanjarster.weixin.bean.WxCustomMessage;
-import chanjarster.weixin.bean.WxMassMessage;
+import chanjarster.weixin.bean.WxMassGroupMessage;
import chanjarster.weixin.bean.WxMassNews;
+import chanjarster.weixin.bean.WxMassOpenIdsMessage;
import chanjarster.weixin.bean.WxMassVideo;
import chanjarster.weixin.bean.WxMenu;
import chanjarster.weixin.bean.result.WxError;
-import chanjarster.weixin.bean.result.WxMassMaterialUploadResult;
import chanjarster.weixin.bean.result.WxMassSendResult;
+import chanjarster.weixin.bean.result.WxMassUploadResult;
import chanjarster.weixin.bean.result.WxMediaUploadResult;
import chanjarster.weixin.exception.WxErrorException;
import chanjarster.weixin.util.fs.FileUtil;
@@ -47,6 +48,8 @@ public class WxServiceImpl implements WxService {
protected WxConfigStorage wxConfigStorage;
+ protected final ThreadLocal retryTimes = new ThreadLocal();
+
public boolean checkSignature(String timestamp, String nonce, String signature) {
try {
String token = wxConfigStorage.getToken();
@@ -156,24 +159,30 @@ public class WxServiceImpl implements WxService {
return execute(new MediaDownloadRequestExecutor(), url, "media_id=" + media_id);
}
- public WxMassMaterialUploadResult uploadMassNews(WxMassNews news) throws WxErrorException {
+ public WxMassUploadResult uploadMassNews(WxMassNews news) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/media/uploadnews";
String responseContent = execute(new SimplePostRequestExecutor(), url, news.toJson());
- return WxMassMaterialUploadResult.fromJson(responseContent);
+ return WxMassUploadResult.fromJson(responseContent);
}
- public WxMassMaterialUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException {
- String url = " https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo";
+ public WxMassUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException {
+ String url = "http://file.api.weixin.qq.com/cgi-bin/media/uploadvideo";
String responseContent = execute(new SimplePostRequestExecutor(), url, video.toJson());
- return WxMassMaterialUploadResult.fromJson(responseContent);
+ return WxMassUploadResult.fromJson(responseContent);
}
- public WxMassSendResult sendMassMessage(WxMassMessage message) throws WxErrorException {
+ public WxMassSendResult sendMassMessageByGroup(WxMassGroupMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall";
String responseContent = execute(new SimplePostRequestExecutor(), url, message.toJson());
return WxMassSendResult.fromJson(responseContent);
}
+ public WxMassSendResult sendMassMessageByOpenIds(WxMassOpenIdsMessage message) throws WxErrorException {
+ String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send";
+ String responseContent = execute(new SimplePostRequestExecutor(), url, message.toJson());
+ return WxMassSendResult.fromJson(responseContent);
+ }
+
/**
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
* @param executor
@@ -205,12 +214,21 @@ public class WxServiceImpl implements WxService {
return execute(executor, uri, data);
}
/**
- * -1 系统繁忙, 500ms后重试
+ * -1 系统繁忙, 1000ms后重试
*/
if (error.getErrcode() == -1) {
+ if(retryTimes.get() == null) {
+ retryTimes.set(0);
+ }
+ if (retryTimes.get() > 5) {
+ retryTimes.set(0);
+ throw new RuntimeException("微信服务端异常,超出重试次数");
+ }
+ int sleepMillis = 1000 * (1 >> (retryTimes.get() - 1));
try {
- System.out.println("微信系统繁忙,500ms后重试");
- Thread.sleep(500);
+ System.out.println("微信系统繁忙," + sleepMillis + "ms后重试");
+ Thread.sleep(sleepMillis);
+ retryTimes.set(retryTimes.get() + 1);
return execute(executor, uri, data);
} catch (InterruptedException e1) {
throw new RuntimeException(e1);
diff --git a/src/main/java/chanjarster/weixin/bean/WxMassGroupMessage.java b/src/main/java/chanjarster/weixin/bean/WxMassGroupMessage.java
new file mode 100644
index 000000000..a0b692d0c
--- /dev/null
+++ b/src/main/java/chanjarster/weixin/bean/WxMassGroupMessage.java
@@ -0,0 +1,69 @@
+package chanjarster.weixin.bean;
+
+import chanjarster.weixin.api.WxConsts;
+import chanjarster.weixin.util.json.WxGsonBuilder;
+
+/**
+ * 分组群发的消息
+ *
+ * @author chanjarster
+ */
+public class WxMassGroupMessage {
+
+ protected String group_id;
+ protected String msgtype;
+ protected String content;
+ protected String media_id;
+
+ public WxMassGroupMessage() {
+ super();
+ }
+
+ public String getMsgtype() {
+ return msgtype;
+ }
+
+ /**
+ *
+ * 请使用
+ * {@link WxConsts#MASS_MSG_IMAGE}
+ * {@link WxConsts#MASS_MSG_NEWS}
+ * {@link WxConsts#MASS_MSG_TEXT}
+ * {@link WxConsts#MASS_MSG_VIDEO}
+ * {@link WxConsts#MASS_MSG_VOICE}
+ *
+ * @param msgtype
+ */
+ public void setMsgtype(String msgtype) {
+ this.msgtype = msgtype;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getMedia_id() {
+ return media_id;
+ }
+
+ public void setMedia_id(String media_id) {
+ this.media_id = media_id;
+ }
+
+ public String toJson() {
+ return WxGsonBuilder.INSTANCE.create().toJson(this);
+ }
+
+ public String getGroup_id() {
+ return group_id;
+ }
+
+ public void setGroup_id(String group_id) {
+ this.group_id = group_id;
+ }
+
+}
diff --git a/src/main/java/chanjarster/weixin/bean/WxMassNews.java b/src/main/java/chanjarster/weixin/bean/WxMassNews.java
index 8207d80bc..42d4a774e 100644
--- a/src/main/java/chanjarster/weixin/bean/WxMassNews.java
+++ b/src/main/java/chanjarster/weixin/bean/WxMassNews.java
@@ -17,14 +17,29 @@ public class WxMassNews {
public List getArticles() {
return articles;
}
- public void setArticles(List articles) {
- this.articles = articles;
+
+ public void addArticle(WxMassNewsArticle article) {
+ this.articles.add(article);
}
public String toJson() {
return WxGsonBuilder.INSTANCE.create().toJson(this);
}
+ /**
+ *
+ * 群发图文消息article
+ * 1. thumb_media_id (必填) 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得
+ * 2. author 图文消息的作者
+ * 3. title (必填) 图文消息的标题
+ * 4. content_source_url 在图文消息页面点击“阅读原文”后的页面链接
+ * 5. content (必填) 图文消息页面的内容,支持HTML标签
+ * 6. digest 图文消息的描述
+ * 7, show_cover_pic 是否显示封面,true为显示,false为不显示
+ *
+ * @author chanjarster
+ *
+ */
public static class WxMassNewsArticle {
/**
* (必填) 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得
@@ -39,7 +54,7 @@ public class WxMassNews {
*/
protected String title;
/**
- * 在图文消息页面点击“阅读原文”后的页面
+ * 在图文消息页面点击“阅读原文”后的页面链接
*/
protected String content_source_url;
/**
@@ -51,7 +66,7 @@ public class WxMassNews {
*/
protected String digest;
/**
- * 是否显示封面,1为显示,0为不显示
+ * 是否显示封面,true为显示,false为不显示
*/
protected boolean show_cover_pic;
diff --git a/src/main/java/chanjarster/weixin/bean/WxMassMessage.java b/src/main/java/chanjarster/weixin/bean/WxMassOpenIdsMessage.java
similarity index 63%
rename from src/main/java/chanjarster/weixin/bean/WxMassMessage.java
rename to src/main/java/chanjarster/weixin/bean/WxMassOpenIdsMessage.java
index 706ed0e94..d790f8bab 100644
--- a/src/main/java/chanjarster/weixin/bean/WxMassMessage.java
+++ b/src/main/java/chanjarster/weixin/bean/WxMassOpenIdsMessage.java
@@ -4,40 +4,24 @@ import java.util.ArrayList;
import java.util.List;
import chanjarster.weixin.api.WxConsts;
-import chanjarster.weixin.bean.result.WxMassMaterialUploadResult;
import chanjarster.weixin.util.json.WxGsonBuilder;
/**
- * 群发消息
+ * OpenId列表群发的消息
*
* @author chanjarster
*/
-public class WxMassMessage {
+public class WxMassOpenIdsMessage {
protected List touser = new ArrayList();
- protected String group_id;
protected String msgtype;
protected String content;
protected String media_id;
- public WxMassMessage() {
+ public WxMassOpenIdsMessage() {
super();
}
- /**
- * 利用上传群发所用的素材的结果,构造群发消息
- * @param r
- * @return
- */
- public WxMassMessage(WxMassMaterialUploadResult r) {
- setMedia_id(r.getMedia_id());
- if("video".equals(r.getType())) {
- setMsgtype(WxConsts.MASS_MSG_VIDEO);
- } else {
- setMsgtype(r.getType());
- }
- }
-
public String getMsgtype() {
return msgtype;
}
@@ -77,20 +61,19 @@ public class WxMassMessage {
return WxGsonBuilder.INSTANCE.create().toJson(this);
}
+ /**
+ * OpenId列表,最多支持10,000个
+ * @return
+ */
public List getTouser() {
return touser;
}
- public void setTouser(List touser) {
- this.touser = touser;
+ /**
+ * 添加OpenId,最多支持10,000个
+ * @param openId
+ */
+ public void addUser(String openId) {
+ this.touser.add(openId);
}
-
- public String getGroup_id() {
- return group_id;
- }
-
- public void setGroup_id(String group_id) {
- this.group_id = group_id;
- }
-
}
diff --git a/src/main/java/chanjarster/weixin/bean/WxMassVideo.java b/src/main/java/chanjarster/weixin/bean/WxMassVideo.java
index 1084ad831..bd455e972 100644
--- a/src/main/java/chanjarster/weixin/bean/WxMassVideo.java
+++ b/src/main/java/chanjarster/weixin/bean/WxMassVideo.java
@@ -4,30 +4,40 @@ import chanjarster.weixin.util.json.WxGsonBuilder;
/**
* 群发时用到的视频素材
+ *
* @author chanjarster
- *
*/
public class WxMassVideo {
protected String media_id;
protected String title;
protected String description;
-
+
public String getTitle() {
return title;
}
+
public void setTitle(String title) {
this.title = title;
}
+
public String getDescription() {
return description;
}
+
public void setDescription(String description) {
this.description = description;
}
-
+
+ public String getMedia_id() {
+ return media_id;
+ }
+
+ public void setMedia_id(String media_id) {
+ this.media_id = media_id;
+ }
+
public String toJson() {
return WxGsonBuilder.INSTANCE.create().toJson(this);
}
-
}
diff --git a/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java b/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java
index 92a535233..c40c710e4 100644
--- a/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java
+++ b/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java
@@ -46,4 +46,10 @@ public class WxMassSendResult {
public static WxMassSendResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMassSendResult.class);
}
+
+ @Override
+ public String toString() {
+ return "WxMassSendResult [errcode=" + errcode + ", errmsg=" + errmsg + ", msg_id=" + msg_id + "]";
+ }
+
}
diff --git a/src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java b/src/main/java/chanjarster/weixin/bean/result/WxMassUploadResult.java
similarity index 73%
rename from src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java
rename to src/main/java/chanjarster/weixin/bean/result/WxMassUploadResult.java
index 5adbd1187..503061f7e 100644
--- a/src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java
+++ b/src/main/java/chanjarster/weixin/bean/result/WxMassUploadResult.java
@@ -3,11 +3,14 @@ package chanjarster.weixin.bean.result;
import chanjarster.weixin.util.json.WxGsonBuilder;
/**
- * 上传群发所用的素材的结果
+ *
+ * 上传群发用的素材的结果
+ * 视频和图文消息需要在群发前上传素材
+ *
* @author chanjarster
*
*/
-public class WxMassMaterialUploadResult {
+public class WxMassUploadResult {
protected String type;
protected String media_id;
@@ -37,8 +40,8 @@ public class WxMassMaterialUploadResult {
this.created_at = created_at;
}
- public static WxMassMaterialUploadResult fromJson(String json) {
- return WxGsonBuilder.create().fromJson(json, WxMassMaterialUploadResult.class);
+ public static WxMassUploadResult fromJson(String json) {
+ return WxGsonBuilder.create().fromJson(json, WxMassUploadResult.class);
}
@Override
diff --git a/src/main/java/chanjarster/weixin/util/json/WxGsonBuilder.java b/src/main/java/chanjarster/weixin/util/json/WxGsonBuilder.java
index 76e979415..ddad36b71 100644
--- a/src/main/java/chanjarster/weixin/util/json/WxGsonBuilder.java
+++ b/src/main/java/chanjarster/weixin/util/json/WxGsonBuilder.java
@@ -1,8 +1,9 @@
package chanjarster.weixin.util.json;
import chanjarster.weixin.bean.WxCustomMessage;
-import chanjarster.weixin.bean.WxMassMessage;
+import chanjarster.weixin.bean.WxMassGroupMessage;
import chanjarster.weixin.bean.WxMassNews;
+import chanjarster.weixin.bean.WxMassOpenIdsMessage;
import chanjarster.weixin.bean.WxMenu;
import com.google.gson.Gson;
@@ -17,7 +18,8 @@ public class WxGsonBuilder {
INSTANCE.registerTypeAdapter(WxCustomMessage.class, new WxCustomMessageGsonAdapter());
INSTANCE.registerTypeAdapter(WxMenu.class, new WxMenuGsonAdapter());
INSTANCE.registerTypeAdapter(WxMassNews.class, new WxMassNewsGsonAdapter());
- INSTANCE.registerTypeAdapter(WxMassMessage.class, new WxMassMessageGsonAdapter());
+ INSTANCE.registerTypeAdapter(WxMassGroupMessage.class, new WxMassMessageGsonAdapter());
+ INSTANCE.registerTypeAdapter(WxMassOpenIdsMessage.class, new WxMassOpenIdsMessageGsonAdapter());
}
public static Gson create() {
diff --git a/src/main/java/chanjarster/weixin/util/json/WxMassMessageGsonAdapter.java b/src/main/java/chanjarster/weixin/util/json/WxMassMessageGsonAdapter.java
index db1efae88..dd8632bbd 100644
--- a/src/main/java/chanjarster/weixin/util/json/WxMassMessageGsonAdapter.java
+++ b/src/main/java/chanjarster/weixin/util/json/WxMassMessageGsonAdapter.java
@@ -11,12 +11,10 @@ package chanjarster.weixin.util.json;
import java.lang.reflect.Type;
import chanjarster.weixin.api.WxConsts;
-import chanjarster.weixin.bean.WxMassMessage;
+import chanjarster.weixin.bean.WxMassGroupMessage;
-import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
@@ -25,47 +23,39 @@ import com.google.gson.JsonSerializer;
* @author qianjia
*
*/
-public class WxMassMessageGsonAdapter implements JsonSerializer {
+public class WxMassMessageGsonAdapter implements JsonSerializer {
- public JsonElement serialize(WxMassMessage message, Type typeOfSrc, JsonSerializationContext context) {
+ public JsonElement serialize(WxMassGroupMessage message, Type typeOfSrc, JsonSerializationContext context) {
JsonObject messageJson = new JsonObject();
- if (message.getTouser().size() > 0) {
- JsonArray sub = new JsonArray();
- for(String openId : message.getTouser()) {
- sub.add(new JsonPrimitive(openId));
- }
- messageJson.add("touser", sub);
- } else {
- JsonObject sub = new JsonObject();
- sub.addProperty("group_id", message.getGroup_id());
- messageJson.add("filter", sub);
- }
+ JsonObject filter = new JsonObject();
+ filter.addProperty("group_id", message.getGroup_id());
+ messageJson.add("filter", filter);
if (WxConsts.MASS_MSG_NEWS.equals(message.getMsgtype())) {
JsonObject sub = new JsonObject();
sub.addProperty("media_id", message.getMedia_id());
- messageJson.add("mpnews", sub);
+ messageJson.add(WxConsts.MASS_MSG_NEWS, sub);
}
if (WxConsts.MASS_MSG_TEXT.equals(message.getMsgtype())) {
JsonObject sub = new JsonObject();
sub.addProperty("content", message.getContent());
- messageJson.add("text", sub);
+ messageJson.add(WxConsts.MASS_MSG_TEXT, sub);
}
if (WxConsts.MASS_MSG_VOICE.equals(message.getMsgtype())) {
JsonObject sub = new JsonObject();
sub.addProperty("media_id", message.getMedia_id());
- messageJson.add("voice", sub);
+ messageJson.add(WxConsts.MASS_MSG_VOICE, sub);
}
if (WxConsts.MASS_MSG_IMAGE.equals(message.getMsgtype())) {
JsonObject sub = new JsonObject();
sub.addProperty("media_id", message.getMedia_id());
- messageJson.add("image", sub);
+ messageJson.add(WxConsts.MASS_MSG_IMAGE, sub);
}
if (WxConsts.MASS_MSG_VIDEO.equals(message.getMsgtype())) {
JsonObject sub = new JsonObject();
sub.addProperty("media_id", message.getMedia_id());
- messageJson.add("mpvideo", sub);
+ messageJson.add(WxConsts.MASS_MSG_VIDEO, sub);
}
messageJson.addProperty("msgtype", message.getMsgtype());
return messageJson;
diff --git a/src/main/java/chanjarster/weixin/util/json/WxMassOpenIdsMessageGsonAdapter.java b/src/main/java/chanjarster/weixin/util/json/WxMassOpenIdsMessageGsonAdapter.java
new file mode 100644
index 000000000..a4311d587
--- /dev/null
+++ b/src/main/java/chanjarster/weixin/util/json/WxMassOpenIdsMessageGsonAdapter.java
@@ -0,0 +1,68 @@
+/*
+ * KINGSTAR MEDIA SOLUTIONS Co.,LTD. Copyright c 2005-2013. All rights reserved.
+ *
+ * This source code is the property of KINGSTAR MEDIA SOLUTIONS LTD. It is intended
+ * only for the use of KINGSTAR MEDIA application development. Reengineering, reproduction
+ * arose from modification of the original source, or other redistribution of this source
+ * is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
+ */
+package chanjarster.weixin.util.json;
+
+import java.lang.reflect.Type;
+
+import chanjarster.weixin.api.WxConsts;
+import chanjarster.weixin.bean.WxMassOpenIdsMessage;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+/**
+ *
+ * @author qianjia
+ *
+ */
+public class WxMassOpenIdsMessageGsonAdapter implements JsonSerializer {
+
+ public JsonElement serialize(WxMassOpenIdsMessage message, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject messageJson = new JsonObject();
+
+ JsonArray touser = new JsonArray();
+ for (String openId : message.getTouser()) {
+ touser.add(new JsonPrimitive(openId));
+ }
+ messageJson.add("touser", touser);
+
+ if (WxConsts.MASS_MSG_NEWS.equals(message.getMsgtype())) {
+ JsonObject sub = new JsonObject();
+ sub.addProperty("media_id", message.getMedia_id());
+ messageJson.add(WxConsts.MASS_MSG_NEWS, sub);
+ }
+ if (WxConsts.MASS_MSG_TEXT.equals(message.getMsgtype())) {
+ JsonObject sub = new JsonObject();
+ sub.addProperty("content", message.getContent());
+ messageJson.add(WxConsts.MASS_MSG_TEXT, sub);
+ }
+ if (WxConsts.MASS_MSG_VOICE.equals(message.getMsgtype())) {
+ JsonObject sub = new JsonObject();
+ sub.addProperty("media_id", message.getMedia_id());
+ messageJson.add(WxConsts.MASS_MSG_VOICE, sub);
+ }
+ if (WxConsts.MASS_MSG_IMAGE.equals(message.getMsgtype())) {
+ JsonObject sub = new JsonObject();
+ sub.addProperty("media_id", message.getMedia_id());
+ messageJson.add(WxConsts.MASS_MSG_IMAGE, sub);
+ }
+ if (WxConsts.MASS_MSG_VIDEO.equals(message.getMsgtype())) {
+ JsonObject sub = new JsonObject();
+ sub.addProperty("media_id", message.getMedia_id());
+ messageJson.add(WxConsts.MASS_MSG_VIDEO, sub);
+ }
+ messageJson.addProperty("msgtype", message.getMsgtype());
+ return messageJson;
+ }
+
+}
diff --git a/src/test/java/chanjarster/weixin/api/ApiTestModule.java b/src/test/java/chanjarster/weixin/api/ApiTestModule.java
index 19f255a3b..ef95f1930 100644
--- a/src/test/java/chanjarster/weixin/api/ApiTestModule.java
+++ b/src/test/java/chanjarster/weixin/api/ApiTestModule.java
@@ -3,8 +3,10 @@ package chanjarster.weixin.api;
import java.io.InputStream;
import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
-import chanjarster.weixin.api.WxBaseAPITest.WxXmlConfigStorage;
import chanjarster.weixin.util.xml.XmlTransformer;
import com.google.inject.Binder;
@@ -26,4 +28,24 @@ public class ApiTestModule implements Module {
}
}
+ @XmlRootElement(name = "xml")
+ @XmlAccessorType(XmlAccessType.FIELD)
+ public static class WxXmlConfigStorage extends WxInMemoryConfigStorage {
+
+ protected String openId;
+
+ public String getOpenId() {
+ return openId;
+ }
+ public void setOpenId(String openId) {
+ this.openId = openId;
+ }
+ @Override
+ public String toString() {
+ return "SimpleWxConfigProvider [appId=" + appId + ", secret=" + secret + ", accessToken=" + accessToken
+ + ", expiresIn=" + expiresIn + ", token=" + token + ", openId=" + openId + "]";
+ }
+
+ }
+
}
diff --git a/src/test/java/chanjarster/weixin/api/WxBaseAPITest.java b/src/test/java/chanjarster/weixin/api/WxBaseAPITest.java
index 6fcb1f7a4..3002f2dd4 100644
--- a/src/test/java/chanjarster/weixin/api/WxBaseAPITest.java
+++ b/src/test/java/chanjarster/weixin/api/WxBaseAPITest.java
@@ -1,113 +1,42 @@
package chanjarster.weixin.api;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlRootElement;
-
import org.apache.commons.lang3.StringUtils;
import org.testng.Assert;
-import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
-import chanjarster.weixin.bean.result.WxMediaUploadResult;
import chanjarster.weixin.exception.WxErrorException;
import com.google.inject.Inject;
-@Test(groups="baseAPI")
+/**
+ * 基础API测试
+ * @author chanjarster
+ *
+ */
+@Test(groups = "baseAPI")
@Guice(modules = ApiTestModule.class)
public class WxBaseAPITest {
@Inject
protected WxServiceImpl wxService;
- private List media_ids = new ArrayList();
-
- @Test
public void testRefreshAccessToken() throws WxErrorException {
WxConfigStorage configStorage = wxService.wxConfigStorage;
String before = configStorage.getAccessToken();
wxService.refreshAccessToken();
-
+
String after = configStorage.getAccessToken();
-
+
Assert.assertNotEquals(before, after);
Assert.assertTrue(StringUtils.isNotBlank(after));
}
-
- @Test(dependsOnMethods = { "testRefreshAccessToken" }, dataProvider="uploadMedia", enabled = true)
- public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
- InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
- WxMediaUploadResult res = wxService.uploadMedia(mediaType, fileType, inputStream);
- Assert.assertNotNull(res.getType());
- Assert.assertNotNull(res.getCreated_at());
- Assert.assertTrue(res.getMedia_id() != null || res.getThumb_media_id() != null);
-
- if (res.getMedia_id() != null) {
- media_ids.add(res.getMedia_id());
- }
- if (res.getThumb_media_id() != null) {
- media_ids.add(res.getThumb_media_id());
- }
- }
-
- @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 {
- wxService.downloadMedia(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;
- }
-
- @Test(enabled = true)
+
public void testCheckSignature() throws WxErrorException {
String timestamp = "23234235423246";
String nonce = "y7didfkcmvnbd90sdofjkiefhsd";
String signature = "77b6651628dfb9a64bfb0d3432ee053ac566a459";
Assert.assertTrue(wxService.checkSignature(timestamp, nonce, signature));
}
-
- @XmlRootElement(name = "xml")
- @XmlAccessorType(XmlAccessType.FIELD)
- public static class WxXmlConfigStorage extends WxInMemoryConfigStorage {
-
- protected String openId;
-
- public String getOpenId() {
- return openId;
- }
- public void setOpenId(String openId) {
- this.openId = openId;
- }
- @Override
- public String toString() {
- return "SimpleWxConfigProvider [appId=" + appId + ", secret=" + secret + ", accessToken=" + accessToken
- + ", expiresIn=" + expiresIn + ", token=" + token + ", openId=" + openId + "]";
- }
-
- }
-
-
+
}
diff --git a/src/test/java/chanjarster/weixin/api/WxCustomMessageAPITest.java b/src/test/java/chanjarster/weixin/api/WxCustomMessageAPITest.java
index b2a99d522..ce99bdd6a 100644
--- a/src/test/java/chanjarster/weixin/api/WxCustomMessageAPITest.java
+++ b/src/test/java/chanjarster/weixin/api/WxCustomMessageAPITest.java
@@ -3,20 +3,24 @@ package chanjarster.weixin.api;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
-import com.google.inject.Inject;
-
-import chanjarster.weixin.api.WxBaseAPITest.WxXmlConfigStorage;
+import chanjarster.weixin.api.ApiTestModule.WxXmlConfigStorage;
import chanjarster.weixin.bean.WxCustomMessage;
import chanjarster.weixin.exception.WxErrorException;
-@Test(dependsOnGroups="baseAPI")
+import com.google.inject.Inject;
+
+/***
+ * 测试发送客服消息
+ * @author chanjarster
+ *
+ */
+@Test(groups="customMessageAPI", dependsOnGroups = "baseAPI")
@Guice(modules = ApiTestModule.class)
public class WxCustomMessageAPITest {
@Inject
protected WxServiceImpl wxService;
-
- @Test(enabled = true)
+
public void testSendCustomMessage() throws WxErrorException {
WxXmlConfigStorage configProvider = (WxXmlConfigStorage) wxService.wxConfigStorage;
WxCustomMessage message = new WxCustomMessage();
@@ -26,5 +30,5 @@ public class WxCustomMessageAPITest {
wxService.sendCustomMessage(message);
}
-
+
}
diff --git a/src/test/java/chanjarster/weixin/api/WxMassMessageAPITest.java b/src/test/java/chanjarster/weixin/api/WxMassMessageAPITest.java
new file mode 100644
index 000000000..7ffbdbf70
--- /dev/null
+++ b/src/test/java/chanjarster/weixin/api/WxMassMessageAPITest.java
@@ -0,0 +1,142 @@
+package chanjarster.weixin.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import chanjarster.weixin.api.ApiTestModule.WxXmlConfigStorage;
+import chanjarster.weixin.bean.WxMassNews;
+import chanjarster.weixin.bean.WxMassNews.WxMassNewsArticle;
+import chanjarster.weixin.bean.WxMassOpenIdsMessage;
+import chanjarster.weixin.bean.WxMassVideo;
+import chanjarster.weixin.bean.result.WxMassSendResult;
+import chanjarster.weixin.bean.result.WxMassUploadResult;
+import chanjarster.weixin.bean.result.WxMediaUploadResult;
+import chanjarster.weixin.exception.WxErrorException;
+
+import com.google.inject.Inject;
+
+/**
+ * 测试群发消息
+ * @author chanjarster
+ *
+ */
+@Test(groups = "massAPI", dependsOnGroups = { "baseAPI", "mediaAPI"})
+@Guice(modules = ApiTestModule.class)
+public class WxMassMessageAPITest {
+
+ @Inject
+ protected WxServiceImpl wxService;
+
+ @Test(enabled = false)
+ public void testSendMassTextByOpenIds() throws WxErrorException {
+ // 发送群发消息
+ WxXmlConfigStorage configProvider = (WxXmlConfigStorage) wxService.wxConfigStorage;
+ WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage();
+ massMessage.setMsgtype(WxConsts.MASS_MSG_TEXT);
+ massMessage.setContent("测试群发消息\n欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World");
+ massMessage.getTouser().add(configProvider.getOpenId());
+
+ WxMassSendResult massResult = wxService.sendMassMessageByOpenIds(massMessage);
+ Assert.assertNotNull(massResult);
+ Assert.assertNotNull(massResult.getMsg_id());
+ }
+
+ @Test(enabled = true, dataProvider="massMessages")
+ public void testSendMassByOpenIds(String massMsgType, String mediaId) throws WxErrorException, IOException {
+ // 发送群发消息
+ WxXmlConfigStorage configProvider = (WxXmlConfigStorage) wxService.wxConfigStorage;
+ WxMassOpenIdsMessage massMessage = new WxMassOpenIdsMessage();
+ massMessage.setMsgtype(massMsgType);
+ massMessage.setMedia_id(mediaId);
+ massMessage.getTouser().add(configProvider.getOpenId());
+
+ WxMassSendResult massResult = wxService.sendMassMessageByOpenIds(massMessage);
+ Assert.assertNotNull(massResult);
+ Assert.assertNotNull(massResult.getMsg_id());
+ }
+
+ @DataProvider
+ public Object[][] massMessages() throws WxErrorException, IOException {
+ Object[][] messages = new Object[4][];
+ /*
+ * 视频素材
+ */
+ {
+ // 上传视频到媒体库
+ InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.mp4");
+ WxMediaUploadResult uploadMediaRes = wxService.uploadMedia(WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, inputStream);
+ Assert.assertNotNull(uploadMediaRes);
+ Assert.assertNotNull(uploadMediaRes.getMedia_id());
+
+ // 把视频变成可被群发的媒体
+ WxMassVideo video = new WxMassVideo();
+ video.setTitle("测试标题");
+ video.setDescription("测试描述");
+ video.setMedia_id(uploadMediaRes.getMedia_id());
+ WxMassUploadResult uploadResult = wxService.uploadMassVideo(video);
+ Assert.assertNotNull(uploadResult);
+ Assert.assertNotNull(uploadResult.getMedia_id());
+ messages[0] = new Object[] { WxConsts.MASS_MSG_VIDEO, uploadResult.getMedia_id() };
+ }
+ /**
+ * 图片素材
+ */
+ {
+ InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg");
+ WxMediaUploadResult uploadMediaRes = wxService.uploadMedia(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
+ Assert.assertNotNull(uploadMediaRes);
+ Assert.assertNotNull(uploadMediaRes.getMedia_id());
+ messages[1] = new Object[] { WxConsts.MASS_MSG_IMAGE, uploadMediaRes.getMedia_id() };
+ }
+ /**
+ * 语音素材
+ */
+ {
+ InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.mp3");
+ WxMediaUploadResult uploadMediaRes = wxService.uploadMedia(WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, inputStream);
+ Assert.assertNotNull(uploadMediaRes);
+ Assert.assertNotNull(uploadMediaRes.getMedia_id());
+ messages[2] = new Object[] { WxConsts.MASS_MSG_VOICE, uploadMediaRes.getMedia_id() };
+ }
+ /**
+ * 图文素材
+ */
+ {
+ // 上传照片到媒体库
+ InputStream inputStream = ClassLoader.getSystemResourceAsStream("mm.jpeg");
+ WxMediaUploadResult uploadMediaRes = wxService.uploadMedia(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, inputStream);
+ Assert.assertNotNull(uploadMediaRes);
+ Assert.assertNotNull(uploadMediaRes.getMedia_id());
+
+ // 上传图文消息
+ WxMassNews news = new WxMassNews();
+ WxMassNewsArticle article1 = new WxMassNewsArticle();
+ article1.setTitle("标题1");
+ article1.setContent("内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1内容1");
+ article1.setThumb_media_id(uploadMediaRes.getMedia_id());
+ news.addArticle(article1);
+
+ WxMassNewsArticle article2 = new WxMassNewsArticle();
+ article2.setTitle("标题2");
+ article2.setContent("内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2内容2");
+ article2.setThumb_media_id(uploadMediaRes.getMedia_id());
+ article2.setShow_cover_pic(true);
+ article2.setAuthor("作者2");
+ article2.setContent_source_url("www.baidu.com");
+ article2.setDigest("摘要2");
+ news.addArticle(article2);
+
+ WxMassUploadResult massUploadResult = wxService.uploadMassNews(news);
+ Assert.assertNotNull(massUploadResult);
+ Assert.assertNotNull(uploadMediaRes.getMedia_id());
+ messages[3] = new Object[] { WxConsts.MASS_MSG_VIDEO, massUploadResult.getMedia_id() };
+ }
+ return messages;
+ }
+
+}
diff --git a/src/test/java/chanjarster/weixin/api/WxMediaAPITest.java b/src/test/java/chanjarster/weixin/api/WxMediaAPITest.java
new file mode 100644
index 000000000..009ffbfff
--- /dev/null
+++ b/src/test/java/chanjarster/weixin/api/WxMediaAPITest.java
@@ -0,0 +1,72 @@
+package chanjarster.weixin.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import chanjarster.weixin.bean.result.WxMediaUploadResult;
+import chanjarster.weixin.exception.WxErrorException;
+
+import com.google.inject.Inject;
+
+/**
+ * 测试多媒体文件上传下载
+ * @author chanjarster
+ *
+ */
+@Test(groups="mediaAPI", dependsOnGroups="baseAPI")
+@Guice(modules = ApiTestModule.class)
+public class WxMediaAPITest {
+
+ @Inject
+ protected WxServiceImpl wxService;
+
+ private List media_ids = new ArrayList();
+
+ @Test(dataProvider="uploadMedia", enabled = true)
+ public void testUploadMedia(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
+ InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
+ WxMediaUploadResult res = wxService.uploadMedia(mediaType, fileType, inputStream);
+ Assert.assertNotNull(res.getType());
+ Assert.assertNotNull(res.getCreated_at());
+ Assert.assertTrue(res.getMedia_id() != null || res.getThumb_media_id() != null);
+
+ if (res.getMedia_id() != null) {
+ media_ids.add(res.getMedia_id());
+ }
+ if (res.getThumb_media_id() != null) {
+ media_ids.add(res.getThumb_media_id());
+ }
+ }
+
+ @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 {
+ wxService.downloadMedia(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/src/test/java/chanjarster/weixin/api/WxMenuAPITest.java b/src/test/java/chanjarster/weixin/api/WxMenuAPITest.java
index 66f060a79..9ca7acef1 100644
--- a/src/test/java/chanjarster/weixin/api/WxMenuAPITest.java
+++ b/src/test/java/chanjarster/weixin/api/WxMenuAPITest.java
@@ -13,6 +13,11 @@ import chanjarster.weixin.bean.WxMenu;
import chanjarster.weixin.bean.WxMenu.WxMenuButton;
import chanjarster.weixin.exception.WxErrorException;
+/**
+ * 测试菜单
+ * @author chanjarster
+ *
+ */
@Test(dependsOnGroups="baseAPI")
@Guice(modules = ApiTestModule.class)
public class WxMenuAPITest {
diff --git a/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java b/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java
index 39d654980..944486db9 100644
--- a/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java
+++ b/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java
@@ -9,6 +9,11 @@ import org.testng.annotations.Test;
import chanjarster.weixin.bean.WxXmlMessage;
+/**
+ * 测试消息路由器
+ * @author chanjarster
+ *
+ */
@Test
public class WxMessageRouterTest {
diff --git a/src/test/resources/testng.xml b/src/test/resources/testng.xml
index 6691adb1c..e74f1ad10 100644
--- a/src/test/resources/testng.xml
+++ b/src/test/resources/testng.xml
@@ -7,10 +7,13 @@
+
+
+
-
+