From f326d7e72e2db128ce8c8b5f0bd5cacd26426be8 Mon Sep 17 00:00:00 2001 From: Daniel Qian Date: Mon, 25 Aug 2014 11:01:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BE=A4=E5=8F=91=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chanjarster/weixin/api/WxConsts.java | 98 +++++++++++++---- .../chanjarster/weixin/api/WxService.java | 45 +++++++- .../chanjarster/weixin/api/WxServiceImpl.java | 29 ++++- .../weixin/bean/WxCustomMessage.java | 14 +++ .../weixin/bean/WxMassMessage.java | 96 +++++++++++++++++ .../chanjarster/weixin/bean/WxMassNews.java | 102 ++++++++++++++++++ .../chanjarster/weixin/bean/WxMassVideo.java | 33 ++++++ .../chanjarster/weixin/bean/WxXmlMessage.java | 27 +++++ .../result/WxMassMaterialUploadResult.java | 49 +++++++++ .../weixin/bean/result/WxMassSendResult.java | 49 +++++++++ ...adResult.java => WxMediaUploadResult.java} | 6 +- .../util/http/MediaUploadRequestExecutor.java | 8 +- .../util/json/WxCustomMessageGsonAdapter.java | 12 +-- .../weixin/util/json/WxGsonBuilder.java | 4 + .../util/json/WxMassMessageGsonAdapter.java | 74 +++++++++++++ .../util/json/WxMassNewsGsonAdapter.java | 56 ++++++++++ .../weixin/api/WxMessageRouterTest.java | 18 ++-- .../chanjarster/weixin/api/WxServiceTest.java | 6 +- .../weixin/bean/WxCustomMessageTest.java | 12 +-- .../weixin/bean/WxXmlMessageTest.java | 4 +- 20 files changed, 682 insertions(+), 60 deletions(-) create mode 100644 src/main/java/chanjarster/weixin/bean/WxMassMessage.java create mode 100644 src/main/java/chanjarster/weixin/bean/WxMassNews.java create mode 100644 src/main/java/chanjarster/weixin/bean/WxMassVideo.java create mode 100644 src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java create mode 100644 src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java rename src/main/java/chanjarster/weixin/bean/result/{WxUploadResult.java => WxMediaUploadResult.java} (85%) create mode 100644 src/main/java/chanjarster/weixin/util/json/WxMassMessageGsonAdapter.java create mode 100644 src/main/java/chanjarster/weixin/util/json/WxMassNewsGsonAdapter.java diff --git a/src/main/java/chanjarster/weixin/api/WxConsts.java b/src/main/java/chanjarster/weixin/api/WxConsts.java index d2ae9050b..4dc9b6c94 100644 --- a/src/main/java/chanjarster/weixin/api/WxConsts.java +++ b/src/main/java/chanjarster/weixin/api/WxConsts.java @@ -1,17 +1,78 @@ package chanjarster.weixin.api; +import java.util.HashMap; +import java.util.Map; + public class WxConsts { - public static final String MSG_TEXT = "text"; - public static final String MSG_IMAGE = "image"; - public static final String MSG_VOICE = "voice"; - public static final String MSG_MUSIC = "music"; - public static final String MSG_VIDEO = "video"; - public static final String MSG_NEWS = "news"; - public static final String MSG_LOCATION = "location"; - public static final String MSG_LINK = "link"; - public static final String MSG_EVENT = "event"; - + /////////////////////// + // 微信推送过来的消息的类型,和发送给微信xml格式消息的消息类型 + /////////////////////// + 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_VIDEO = "video"; + public static final String XML_MSG_NEWS = "news"; + public static final String XML_MSG_MUSIC = "news"; + public static final String XML_MSG_LOCATION = "location"; + public static final String XML_MSG_LINK = "link"; + public static final String XML_MSG_EVENT = "event"; + + /////////////////////// + // 客服消息的消息类型 + /////////////////////// + public static final String CUSTOM_MSG_TEXT = "text"; + public static final String CUSTOM_MSG_IMAGE = "image"; + public static final String CUSTOM_MSG_VOICE = "voice"; + public static final String CUSTOM_MSG_VIDEO = "video"; + public static final String CUSTOM_MSG_MUSIC = "music"; + public static final String CUSTOM_MSG_NEWS = "news"; + + /////////////////////// + // 群发消息的消息类型 + /////////////////////// + public static final String MASS_MSG_NEWS = "mpnews"; + public static final String MASS_MSG_TEXT = "text"; + public static final String MASS_MSG_VOICE = "voice"; + public static final String MASS_MSG_IMAGE = "image"; + public static final String MASS_MSG_VIDEO = "mpvideo"; + + /////////////////////// + // 群发消息后微信端推送给服务器的反馈消息 + /////////////////////// + public static final String MASS_ST_SUCCESS = "send success"; + public static final String MASS_ST_FAIL = "send fail"; + public static final String MASS_ST_涉嫌广告 = "err(10001)"; + public static final String MASS_ST_涉嫌政治 = "err(20001)"; + public static final String MASS_ST_涉嫌社会 = "err(20004)"; + public static final String MASS_ST_涉嫌色情 = "err(20002)"; + public static final String MASS_ST_涉嫌违法犯罪 = "err(20006)"; + public static final String MASS_ST_涉嫌欺诈 = "err(20008)"; + public static final String MASS_ST_涉嫌版权 = "err(20013)"; + public static final String MASS_ST_涉嫌互推_互相宣传 = "err(22000)"; + public static final String MASS_ST_涉嫌其他 = "err(21000)"; + + /** + * 群发反馈消息代码所对应的文字描述 + */ + public static final Map MASS_ST_2_DESC = new HashMap(); + static { + MASS_ST_2_DESC.put(MASS_ST_SUCCESS, "发送成功"); + MASS_ST_2_DESC.put(MASS_ST_FAIL, "发送失败"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌广告, "涉嫌广告"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌政治, "涉嫌政治"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌社会, "涉嫌社会"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌色情, "涉嫌色情"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌违法犯罪, "涉嫌违法犯罪"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌欺诈, "涉嫌欺诈"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌版权, "涉嫌版权"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌互推_互相宣传, "涉嫌互推_互相宣传"); + MASS_ST_2_DESC.put(MASS_ST_涉嫌其他, "涉嫌其他"); + } + + /////////////////////// + // 微信端推送过来的事件类型 + /////////////////////// public static final String EVT_SUBSCRIBE = "subscribe"; public static final String EVT_UNSUBSCRIBE = "unsubscribe"; public static final String EVT_SCAN = "SCAN"; @@ -20,25 +81,20 @@ public class WxConsts { public static final String EVT_VIEW = "VIEW"; public static final String EVT_MASS_SEND_JOB_FINISH = "MASSSENDJOBFINISH"; + /////////////////////// + // 上传多媒体文件的类型 + /////////////////////// public static final String MEDIA_IMAGE = "image"; public static final String MEDIA_VOICE = "voice"; public static final String MEDIA_VIDEO = "video"; public static final String MEDIA_THUMB = "thumb"; + /////////////////////// + // 文件类型 + /////////////////////// public static final String FILE_JPG = "jpeg"; public static final String FILE_MP3 = "mp3"; public static final String FILE_ARM = "arm"; public static final String FILE_MP4 = "mp4"; - public static final String ST_SEND_SUCCESS = "send success"; - public static final String ST_SEND_FAIL = "send fail"; - public static final String ST_涉嫌广告 = "err(10001)"; - public static final String ST_涉嫌政治 = "err(20001)"; - public static final String ST_涉嫌社会 = "err(20004)"; - public static final String ST_涉嫌色情 = "err(20002)"; - public static final String ST_涉嫌违法犯罪 = "err(20006)"; - public static final String ST_涉嫌欺诈 = "err(20008)"; - public static final String ST_涉嫌版权 = "err(20013)"; - public static final String ST_涉嫌互推_互相宣传 = "err(22000)"; - public static final String ST_涉嫌其他 = "err(21000)"; } diff --git a/src/main/java/chanjarster/weixin/api/WxService.java b/src/main/java/chanjarster/weixin/api/WxService.java index fe37ed15b..1de320039 100644 --- a/src/main/java/chanjarster/weixin/api/WxService.java +++ b/src/main/java/chanjarster/weixin/api/WxService.java @@ -5,8 +5,13 @@ import java.io.IOException; import java.io.InputStream; import chanjarster.weixin.bean.WxCustomMessage; +import chanjarster.weixin.bean.WxMassMessage; +import chanjarster.weixin.bean.WxMassNews; +import chanjarster.weixin.bean.WxMassVideo; import chanjarster.weixin.bean.WxMenu; -import chanjarster.weixin.bean.result.WxUploadResult; +import chanjarster.weixin.bean.result.WxMassMaterialUploadResult; +import chanjarster.weixin.bean.result.WxMassSendResult; +import chanjarster.weixin.bean.result.WxMediaUploadResult; import chanjarster.weixin.exception.WxErrorException; /** @@ -58,7 +63,7 @@ public interface WxService { * @param inputStream 输入流 * @throws WxErrorException */ - public WxUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; + public WxMediaUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException; /** * @see #uploadMedia(String, String, InputStream) @@ -66,7 +71,7 @@ public interface WxService { * @param file * @throws WxErrorException */ - public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException; + public WxMediaUploadResult uploadMedia(String mediaType, File file) throws WxErrorException; /** *
@@ -90,6 +95,40 @@ public interface WxService {
    */
   public void sendCustomMessage(WxCustomMessage message) throws WxErrorException;
   
+  /**
+   * 
+   * 上传群发用的图文消息,上传后才能群发图文消息 {@link #sendMassMessage(WxMassMessage)}
+   * 
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
+   * 
+ * @param news + * @throws WxErrorException + */ + public WxMassMaterialUploadResult uploadMassNews(WxMassNews news) throws WxErrorException; + + /** + *
+   * 上传群发用的视频,上传后才能群发视频消息 {@link #sendMassMessage(WxMassMessage)}
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
+   * 
+ * @return + * @throws WxErrorException + */ + public WxMassMaterialUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException; + + /** + *
+   * 群发消息
+   * 如果发送图文消息,必须先使用 {@link #uploadMassNews(WxMassNews)} 获得media_id,然后再发送
+   * 如果发送视频消息,必须先使用 {@link #uploadMassVideo(WxMassVideo)} 获得media_id,然后再发送
+   * 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口
+   * 
+ * @param message + * @throws WxErrorException + * @return + */ + public WxMassSendResult sendMassMessage(WxMassMessage message) throws WxErrorException; + /** *
    * 自定义菜单创建接口
diff --git a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
index f6e4b19fe..826bef932 100644
--- a/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
+++ b/src/main/java/chanjarster/weixin/api/WxServiceImpl.java
@@ -18,9 +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.WxMassNews;
+import chanjarster.weixin.bean.WxMassVideo;
 import chanjarster.weixin.bean.WxMenu;
 import chanjarster.weixin.bean.result.WxError;
-import chanjarster.weixin.bean.result.WxUploadResult;
+import chanjarster.weixin.bean.result.WxMassMaterialUploadResult;
+import chanjarster.weixin.bean.result.WxMassSendResult;
+import chanjarster.weixin.bean.result.WxMediaUploadResult;
 import chanjarster.weixin.exception.WxErrorException;
 import chanjarster.weixin.util.fs.FileUtil;
 import chanjarster.weixin.util.http.MediaDownloadRequestExecutor;
@@ -137,11 +142,11 @@ public class WxServiceImpl implements WxService {
     }
   }
 
-  public WxUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
+  public WxMediaUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
     return uploadMedia(mediaType,FileUtil.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
   }
   
-  public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException {
+  public WxMediaUploadResult uploadMedia(String mediaType, File file) throws WxErrorException {
     String url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
     return execute(new MediaUploadRequestExecutor(), url, file);
   }
@@ -151,6 +156,24 @@ public class WxServiceImpl implements WxService {
     return execute(new MediaDownloadRequestExecutor(), url, "media_id=" + media_id);
   }
 
+  public WxMassMaterialUploadResult 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);
+  }
+  
+  public WxMassMaterialUploadResult uploadMassVideo(WxMassVideo video) throws WxErrorException {
+    String url = " https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo";
+    String responseContent = execute(new SimplePostRequestExecutor(), url, video.toJson());
+    return WxMassMaterialUploadResult.fromJson(responseContent);
+  }
+  
+  public WxMassSendResult sendMassMessage(WxMassMessage 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);
+  }
+
   /**
    * 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
    * @param executor
diff --git a/src/main/java/chanjarster/weixin/bean/WxCustomMessage.java b/src/main/java/chanjarster/weixin/bean/WxCustomMessage.java
index 2ca24e678..92084a59f 100644
--- a/src/main/java/chanjarster/weixin/bean/WxCustomMessage.java
+++ b/src/main/java/chanjarster/weixin/bean/WxCustomMessage.java
@@ -3,6 +3,7 @@ package chanjarster.weixin.bean;
 import java.util.ArrayList;
 import java.util.List;
 
+import chanjarster.weixin.api.WxConsts;
 import chanjarster.weixin.util.json.WxGsonBuilder;
 
 /**
@@ -32,6 +33,19 @@ public class WxCustomMessage {
   public String getMsgtype() {
     return msgtype;
   }
+  
+  /**
+   * 
+   * 请使用
+   * {@link WxConsts#CUSTOM_MSG_TEXT}
+   * {@link WxConsts#CUSTOM_MSG_IMAGE}
+   * {@link WxConsts#CUSTOM_MSG_VOICE}
+   * {@link WxConsts#CUSTOM_MSG_MUSIC}
+   * {@link WxConsts#CUSTOM_MSG_VIDEO}
+   * {@link WxConsts#CUSTOM_MSG_NEWS}
+   * 
+ * @param msgtype + */ public void setMsgtype(String msgtype) { this.msgtype = msgtype; } diff --git a/src/main/java/chanjarster/weixin/bean/WxMassMessage.java b/src/main/java/chanjarster/weixin/bean/WxMassMessage.java new file mode 100644 index 000000000..706ed0e94 --- /dev/null +++ b/src/main/java/chanjarster/weixin/bean/WxMassMessage.java @@ -0,0 +1,96 @@ +package chanjarster.weixin.bean; + +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; + +/** + * 群发消息 + * + * @author chanjarster + */ +public class WxMassMessage { + + protected List touser = new ArrayList(); + protected String group_id; + protected String msgtype; + protected String content; + protected String media_id; + + public WxMassMessage() { + 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; + } + + /** + *
+   * 请使用
+   * {@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 List getTouser() { + return touser; + } + + public void setTouser(List touser) { + this.touser = touser; + } + + 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 new file mode 100644 index 000000000..8207d80bc --- /dev/null +++ b/src/main/java/chanjarster/weixin/bean/WxMassNews.java @@ -0,0 +1,102 @@ +package chanjarster.weixin.bean; + +import java.util.ArrayList; +import java.util.List; + +import chanjarster.weixin.util.json.WxGsonBuilder; + +/** + * 群发时用到的图文消息素材 + * @author chanjarster + * + */ +public class WxMassNews { + + protected List articles = new ArrayList(); + + public List getArticles() { + return articles; + } + public void setArticles(List articles) { + this.articles = articles; + } + + public String toJson() { + return WxGsonBuilder.INSTANCE.create().toJson(this); + } + + public static class WxMassNewsArticle { + /** + * (必填) 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得 + */ + protected String thumb_media_id; + /** + * 图文消息的作者 + */ + protected String author; + /** + * (必填) 图文消息的标题 + */ + protected String title; + /** + * 在图文消息页面点击“阅读原文”后的页面 + */ + protected String content_source_url; + /** + * (必填) 图文消息页面的内容,支持HTML标签 + */ + protected String content; + /** + * 图文消息的描述 + */ + protected String digest; + /** + * 是否显示封面,1为显示,0为不显示 + */ + protected boolean show_cover_pic; + + public String getThumb_media_id() { + return thumb_media_id; + } + public void setThumb_media_id(String thumb_media_id) { + this.thumb_media_id = thumb_media_id; + } + public String getAuthor() { + return author; + } + public void setAuthor(String author) { + this.author = author; + } + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getContent_source_url() { + return content_source_url; + } + public void setContent_source_url(String content_source_url) { + this.content_source_url = content_source_url; + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public String getDigest() { + return digest; + } + public void setDigest(String digest) { + this.digest = digest; + } + public boolean isShow_cover_pic() { + return show_cover_pic; + } + public void setShow_cover_pic(boolean show_cover_pic) { + this.show_cover_pic = show_cover_pic; + } + + } +} diff --git a/src/main/java/chanjarster/weixin/bean/WxMassVideo.java b/src/main/java/chanjarster/weixin/bean/WxMassVideo.java new file mode 100644 index 000000000..1084ad831 --- /dev/null +++ b/src/main/java/chanjarster/weixin/bean/WxMassVideo.java @@ -0,0 +1,33 @@ +package chanjarster.weixin.bean; + +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 toJson() { + return WxGsonBuilder.INSTANCE.create().toJson(this); + } + +} diff --git a/src/main/java/chanjarster/weixin/bean/WxXmlMessage.java b/src/main/java/chanjarster/weixin/bean/WxXmlMessage.java index 716505673..e862c69b0 100644 --- a/src/main/java/chanjarster/weixin/bean/WxXmlMessage.java +++ b/src/main/java/chanjarster/weixin/bean/WxXmlMessage.java @@ -9,6 +9,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import chanjarster.weixin.api.WxConsts; import chanjarster.weixin.util.xml.AdapterCDATA; import chanjarster.weixin.util.xml.XmlTransformer; @@ -159,9 +160,35 @@ public class WxXmlMessage { CreateTime = createTime; } + /** + *
+   * 当接受用户消息时,可能会获得以下值:
+   * {@link WxConsts#XML_MSG_TEXT}
+   * {@link WxConsts#XML_MSG_IMAGE}
+   * {@link WxConsts#XML_MSG_VOICE}
+   * {@link WxConsts#XML_MSG_VIDEO}
+   * {@link WxConsts#XML_MSG_LOCATION}
+   * {@link WxConsts#XML_MSG_LINK}
+   * {@link WxConsts#XML_MSG_EVENT}
+   * 
+ * @return + */ public String getMsgType() { return MsgType; } + + /** + *
+   * 当发送消息的时候使用:
+   * {@link WxConsts#XML_MSG_TEXT}
+   * {@link WxConsts#XML_MSG_IMAGE}
+   * {@link WxConsts#XML_MSG_VOICE}
+   * {@link WxConsts#XML_MSG_VIDEO}
+   * {@link WxConsts#XML_MSG_NEWS}
+   * {@link WxConsts#XML_MSG_MUSIC}
+   * 
+ * @param msgType + */ public void setMsgType(String msgType) { MsgType = msgType; } diff --git a/src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java b/src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java new file mode 100644 index 000000000..5adbd1187 --- /dev/null +++ b/src/main/java/chanjarster/weixin/bean/result/WxMassMaterialUploadResult.java @@ -0,0 +1,49 @@ +package chanjarster.weixin.bean.result; + +import chanjarster.weixin.util.json.WxGsonBuilder; + +/** + * 上传群发所用的素材的结果 + * @author chanjarster + * + */ +public class WxMassMaterialUploadResult { + + protected String type; + protected String media_id; + protected long created_at; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMedia_id() { + return media_id; + } + + public void setMedia_id(String media_id) { + this.media_id = media_id; + } + + public long getCreated_at() { + return created_at; + } + + public void setCreated_at(long created_at) { + this.created_at = created_at; + } + + public static WxMassMaterialUploadResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, WxMassMaterialUploadResult.class); + } + + @Override + public String toString() { + return "WxUploadResult [type=" + type + ", media_id=" + media_id + ", created_at=" + created_at + "]"; + } + +} diff --git a/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java b/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java new file mode 100644 index 000000000..92a535233 --- /dev/null +++ b/src/main/java/chanjarster/weixin/bean/result/WxMassSendResult.java @@ -0,0 +1,49 @@ +package chanjarster.weixin.bean.result; + +import chanjarster.weixin.util.json.WxGsonBuilder; + +/** + *
+ * 群发消息一发送就返回的结果
+ * 
+ * 真正的群发消息是否发送成功要看
+ * http://mp.weixin.qq.com/wiki/index.php?title=高级群发接口#.E4.BA.8B.E4.BB.B6.E6.8E.A8.E9.80.81.E7.BE.A4.E5.8F.91.E7.BB.93.E6.9E.9C
+ * 
+ * 
+ * @author chanjarster + * + */ +public class WxMassSendResult { + + protected String errcode; + protected String errmsg; + protected String msg_id; + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + public String getMsg_id() { + return msg_id; + } + + public void setMsg_id(String msg_id) { + this.msg_id = msg_id; + } + + public static WxMassSendResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, WxMassSendResult.class); + } +} diff --git a/src/main/java/chanjarster/weixin/bean/result/WxUploadResult.java b/src/main/java/chanjarster/weixin/bean/result/WxMediaUploadResult.java similarity index 85% rename from src/main/java/chanjarster/weixin/bean/result/WxUploadResult.java rename to src/main/java/chanjarster/weixin/bean/result/WxMediaUploadResult.java index 98bee3e30..64e175048 100644 --- a/src/main/java/chanjarster/weixin/bean/result/WxUploadResult.java +++ b/src/main/java/chanjarster/weixin/bean/result/WxMediaUploadResult.java @@ -2,7 +2,7 @@ package chanjarster.weixin.bean.result; import chanjarster.weixin.util.json.WxGsonBuilder; -public class WxUploadResult { +public class WxMediaUploadResult { protected String type; protected String media_id; @@ -33,8 +33,8 @@ public class WxUploadResult { this.created_at = created_at; } - public static WxUploadResult fromJson(String json) { - return WxGsonBuilder.create().fromJson(json, WxUploadResult.class); + public static WxMediaUploadResult fromJson(String json) { + return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class); } public String getThumb_media_id() { diff --git a/src/main/java/chanjarster/weixin/util/http/MediaUploadRequestExecutor.java b/src/main/java/chanjarster/weixin/util/http/MediaUploadRequestExecutor.java index 46287ab1e..f0844c069 100644 --- a/src/main/java/chanjarster/weixin/util/http/MediaUploadRequestExecutor.java +++ b/src/main/java/chanjarster/weixin/util/http/MediaUploadRequestExecutor.java @@ -11,7 +11,7 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import chanjarster.weixin.bean.result.WxError; -import chanjarster.weixin.bean.result.WxUploadResult; +import chanjarster.weixin.bean.result.WxMediaUploadResult; import chanjarster.weixin.exception.WxErrorException; /** @@ -19,10 +19,10 @@ import chanjarster.weixin.exception.WxErrorException; * @author chanjarster * */ -public class MediaUploadRequestExecutor implements RequestExecutor { +public class MediaUploadRequestExecutor implements RequestExecutor { @Override - public WxUploadResult execute(String uri, File file) throws WxErrorException, ClientProtocolException, IOException { + public WxMediaUploadResult execute(String uri, File file) throws WxErrorException, ClientProtocolException, IOException { HttpPost httpPost = new HttpPost(uri); if (file != null) { HttpEntity entity = MultipartEntityBuilder @@ -38,7 +38,7 @@ public class MediaUploadRequestExecutor implements RequestExecutor { + + public JsonElement serialize(WxMassMessage 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); + } + + if (WxConsts.MASS_MSG_NEWS.equals(message.getMsgtype())) { + JsonObject sub = new JsonObject(); + sub.addProperty("media_id", message.getMedia_id()); + messageJson.add("mpnews", sub); + } + if (WxConsts.MASS_MSG_TEXT.equals(message.getMsgtype())) { + JsonObject sub = new JsonObject(); + sub.addProperty("content", message.getContent()); + messageJson.add("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); + } + if (WxConsts.MASS_MSG_IMAGE.equals(message.getMsgtype())) { + JsonObject sub = new JsonObject(); + sub.addProperty("media_id", message.getMedia_id()); + messageJson.add("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.addProperty("msgtype", message.getMsgtype()); + return messageJson; + } + +} diff --git a/src/main/java/chanjarster/weixin/util/json/WxMassNewsGsonAdapter.java b/src/main/java/chanjarster/weixin/util/json/WxMassNewsGsonAdapter.java new file mode 100644 index 000000000..125379db8 --- /dev/null +++ b/src/main/java/chanjarster/weixin/util/json/WxMassNewsGsonAdapter.java @@ -0,0 +1,56 @@ +/* + * 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.bean.WxMassNews; +import chanjarster.weixin.bean.WxMassNews.WxMassNewsArticle; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * + * @author qianjia + * + */ +public class WxMassNewsGsonAdapter implements JsonSerializer { + + public JsonElement serialize(WxMassNews message, Type typeOfSrc, JsonSerializationContext context) { + JsonObject newsJson = new JsonObject(); + + JsonArray articleJsonArray = new JsonArray(); + for (WxMassNewsArticle article : message.getArticles()) { + JsonObject articleJson = new JsonObject(); + articleJson.addProperty("thumb_media_id", article.getThumb_media_id()); + articleJson.addProperty("title", article.getTitle()); + articleJson.addProperty("content", article.getContent()); + + if (null != article.getAuthor()) { + articleJson.addProperty("author", article.getAuthor()); + } + if (null != article.getContent_source_url()) { + articleJson.addProperty("content_source_url", article.getContent_source_url()); + } + if (null != article.getDigest()) { + articleJson.addProperty("digest", article.getDigest()); + } + articleJson.addProperty("show_cover_pic", article.isShow_cover_pic() ? "1" : "0"); + articleJsonArray.add(articleJson); + } + newsJson.add("articles", articleJsonArray); + + return newsJson; + } + +} diff --git a/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java b/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java index 44518686d..65e3f4f23 100644 --- a/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java +++ b/src/test/java/chanjarster/weixin/api/WxMessageRouterTest.java @@ -21,18 +21,18 @@ public class WxMessageRouterTest { this.router = new WxMessageRouter(); router .rule() - .msgType(WxConsts.MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1").content("CONTENT_1") + .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1").content("CONTENT_1") .handler(new WxEchoMessageHandler(sb, "COMBINE_4")) .end() .rule() - .msgType(WxConsts.MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1") + .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK).eventKey("KEY_1") .handler(new WxEchoMessageHandler(sb, "COMBINE_3")) .end() .rule() - .msgType(WxConsts.MSG_TEXT).event(WxConsts.EVT_CLICK) + .msgType(WxConsts.XML_MSG_TEXT).event(WxConsts.EVT_CLICK) .handler(new WxEchoMessageHandler(sb, "COMBINE_2")) .end() - .rule().msgType(WxConsts.MSG_TEXT).handler(new WxEchoMessageHandler(sb, WxConsts.MSG_TEXT)).end() + .rule().msgType(WxConsts.XML_MSG_TEXT).handler(new WxEchoMessageHandler(sb, WxConsts.XML_MSG_TEXT)).end() .rule().event(WxConsts.EVT_CLICK).handler(new WxEchoMessageHandler(sb, WxConsts.EVT_CLICK)).end() .rule().eventKey("KEY_1").handler(new WxEchoMessageHandler(sb, "KEY_1")).end() .rule().content("CONTENT_1").handler(new WxEchoMessageHandler(sb, "CONTENT_1")).end() @@ -54,7 +54,7 @@ public class WxMessageRouterTest { @DataProvider(name="messages-1") public Object[][] messages2() { WxXmlMessage message1 = new WxXmlMessage(); - message1.setMsgType(WxConsts.MSG_TEXT); + message1.setMsgType(WxConsts.XML_MSG_TEXT); WxXmlMessage message2 = new WxXmlMessage(); message2.setEvent(WxConsts.EVT_CLICK); @@ -69,22 +69,22 @@ public class WxMessageRouterTest { message5.setContent("BLA"); WxXmlMessage c2 = new WxXmlMessage(); - c2.setMsgType(WxConsts.MSG_TEXT); + c2.setMsgType(WxConsts.XML_MSG_TEXT); c2.setEvent(WxConsts.EVT_CLICK); WxXmlMessage c3 = new WxXmlMessage(); - c3.setMsgType(WxConsts.MSG_TEXT); + c3.setMsgType(WxConsts.XML_MSG_TEXT); c3.setEvent(WxConsts.EVT_CLICK); c3.setEventKey("KEY_1"); WxXmlMessage c4 = new WxXmlMessage(); - c4.setMsgType(WxConsts.MSG_TEXT); + c4.setMsgType(WxConsts.XML_MSG_TEXT); c4.setEvent(WxConsts.EVT_CLICK); c4.setEventKey("KEY_1"); c4.setContent("CONTENT_1"); return new Object[][] { - new Object[] { message1, WxConsts.MSG_TEXT + "," }, + new Object[] { message1, WxConsts.XML_MSG_TEXT + "," }, new Object[] { message2, WxConsts.EVT_CLICK + "," }, new Object[] { message3, "KEY_1," }, new Object[] { message4, "CONTENT_1," }, diff --git a/src/test/java/chanjarster/weixin/api/WxServiceTest.java b/src/test/java/chanjarster/weixin/api/WxServiceTest.java index 4649a1616..181e2e6cd 100644 --- a/src/test/java/chanjarster/weixin/api/WxServiceTest.java +++ b/src/test/java/chanjarster/weixin/api/WxServiceTest.java @@ -19,7 +19,7 @@ import org.testng.annotations.Test; import chanjarster.weixin.bean.WxCustomMessage; import chanjarster.weixin.bean.WxMenu; import chanjarster.weixin.bean.WxMenu.WxMenuButton; -import chanjarster.weixin.bean.result.WxUploadResult; +import chanjarster.weixin.bean.result.WxMediaUploadResult; import chanjarster.weixin.exception.WxErrorException; import chanjarster.weixin.util.xml.XmlTransformer; @@ -54,7 +54,7 @@ public class WxServiceTest { public void sendCustomMessage() throws WxErrorException { WxXmlConfigStorage configProvider = (WxXmlConfigStorage) wxService.wxConfigStorage; WxCustomMessage message = new WxCustomMessage(); - message.setMsgtype(WxConsts.MSG_TEXT); + message.setMsgtype(WxConsts.CUSTOM_MSG_TEXT); message.setTouser(configProvider.getOpenId()); message.setContent("欢迎欢迎,热烈欢迎\n换行测试\n超链接:Hello World"); @@ -79,7 +79,7 @@ public class WxServiceTest { @Test(dependsOnMethods = { "testRefreshAccessToken" }, dataProvider="uploadMedia", enabled = true) public void testUploadMedia1(String mediaType, String fileType, String fileName) throws WxErrorException, IOException { InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName); - WxUploadResult res = wxService.uploadMedia(mediaType, fileType, inputStream); + 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); diff --git a/src/test/java/chanjarster/weixin/bean/WxCustomMessageTest.java b/src/test/java/chanjarster/weixin/bean/WxCustomMessageTest.java index 420730963..bf1cb7b62 100644 --- a/src/test/java/chanjarster/weixin/bean/WxCustomMessageTest.java +++ b/src/test/java/chanjarster/weixin/bean/WxCustomMessageTest.java @@ -12,7 +12,7 @@ public class WxCustomMessageTest { public void testTextReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_TEXT); + reply.setMsgtype(WxConsts.CUSTOM_MSG_TEXT); reply.setContent("sfsfdsdf"); Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"text\",\"text\":{\"content\":\"sfsfdsdf\"}}"); } @@ -20,7 +20,7 @@ public class WxCustomMessageTest { public void testImageReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_IMAGE); + reply.setMsgtype(WxConsts.CUSTOM_MSG_IMAGE); reply.setMedia_id("MEDIA_ID"); Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"image\",\"image\":{\"media_id\":\"MEDIA_ID\"}}"); } @@ -28,7 +28,7 @@ public class WxCustomMessageTest { public void testVoiceReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_VOICE); + reply.setMsgtype(WxConsts.CUSTOM_MSG_VOICE); reply.setMedia_id("MEDIA_ID"); Assert.assertEquals(reply.toJson(), "{\"touser\":\"OPENID\",\"msgtype\":\"voice\",\"voice\":{\"media_id\":\"MEDIA_ID\"}}"); } @@ -36,7 +36,7 @@ public class WxCustomMessageTest { public void testVideoReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_VIDEO); + reply.setMsgtype(WxConsts.CUSTOM_MSG_VIDEO); reply.setMedia_id("MEDIA_ID"); reply.setThumb_media_id("MEDIA_ID"); reply.setTitle("TITLE"); @@ -47,7 +47,7 @@ public class WxCustomMessageTest { public void testMusicReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_MUSIC); + reply.setMsgtype(WxConsts.CUSTOM_MSG_MUSIC); reply.setThumb_media_id("MEDIA_ID"); reply.setDescription("DESCRIPTION"); reply.setTitle("TITLE"); @@ -59,7 +59,7 @@ public class WxCustomMessageTest { public void testNewsReply() { WxCustomMessage reply = new WxCustomMessage(); reply.setTouser("OPENID"); - reply.setMsgtype(WxConsts.MSG_NEWS); + reply.setMsgtype(WxConsts.CUSTOM_MSG_NEWS); WxArticle article1 = new WxArticle(); article1.setUrl("URL"); diff --git a/src/test/java/chanjarster/weixin/bean/WxXmlMessageTest.java b/src/test/java/chanjarster/weixin/bean/WxXmlMessageTest.java index b390269c4..23243d30a 100644 --- a/src/test/java/chanjarster/weixin/bean/WxXmlMessageTest.java +++ b/src/test/java/chanjarster/weixin/bean/WxXmlMessageTest.java @@ -39,7 +39,7 @@ public class WxXmlMessageTest { Assert.assertEquals(wxMessage.getToUserName(), "toUser"); Assert.assertEquals(wxMessage.getFromUserName(), "fromUser"); Assert.assertEquals(wxMessage.getCreateTime(), new Long(1348831860l)); - Assert.assertEquals(wxMessage.getMsgType(), WxConsts.MSG_TEXT); + Assert.assertEquals(wxMessage.getMsgType(), WxConsts.XML_MSG_TEXT); Assert.assertEquals(wxMessage.getContent(), "this is a test"); Assert.assertEquals(wxMessage.getMsgId(), new Long(1234567890123456l)); Assert.assertEquals(wxMessage.getPicUrl(), "this is a url"); @@ -66,7 +66,7 @@ public class WxXmlMessageTest { wxMessage.setToUserName("toUser"); wxMessage.setFromUserName("fromUser"); wxMessage.setCreateTime(new Long(1348831860l)); - wxMessage.setMsgType(WxConsts.MSG_TEXT); + wxMessage.setMsgType(WxConsts.XML_MSG_TEXT); wxMessage.setContent("this is a test"); wxMessage.setMsgId(new Long(1234567890123456l)); wxMessage.setPicUrl("this is a url");