50001
api/redirect_uri unauthorized
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCloseEventMessage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCloseEventMessage.java
new file mode 100644
index 00000000..f1d473f2
--- /dev/null
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCloseEventMessage.java
@@ -0,0 +1,40 @@
+package com.foxinmy.weixin4j.msg.event;
+
+import com.foxinmy.weixin4j.type.EventType;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 客服关闭会话事件
+ *
+ * @className KfCloseEventMessage
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see 会话状态通知事件
+ */
+public class KfCloseEventMessage extends EventMessage {
+
+ private static final long serialVersionUID = 3644449346935205541L;
+
+ public KfCloseEventMessage() {
+ super(EventType.kf_close_session);
+ }
+
+ @XStreamAlias("KfAccount")
+ private String kfAccount; // 客服账号
+
+ public String getKfAccount() {
+ return kfAccount;
+ }
+
+ public void setKfAccount(String kfAccount) {
+ this.kfAccount = kfAccount;
+ }
+
+ @Override
+ public String toString() {
+ return "KfCloseEventMessage [kfAccount=" + kfAccount + ", ="
+ + super.toString() + "]";
+ }
+}
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCreateEventMessage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCreateEventMessage.java
new file mode 100644
index 00000000..4fdabc79
--- /dev/null
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfCreateEventMessage.java
@@ -0,0 +1,40 @@
+package com.foxinmy.weixin4j.msg.event;
+
+import com.foxinmy.weixin4j.type.EventType;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 客服接入会话事件
+ *
+ * @className KfCreateEventMessage
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see 会话状态通知事件
+ */
+public class KfCreateEventMessage extends EventMessage {
+
+ private static final long serialVersionUID = -8968189700999202108L;
+
+ public KfCreateEventMessage() {
+ super(EventType.kf_create_session);
+ }
+
+ @XStreamAlias("KfAccount")
+ private String kfAccount; // 客服账号
+
+ public String getKfAccount() {
+ return kfAccount;
+ }
+
+ public void setKfAccount(String kfAccount) {
+ this.kfAccount = kfAccount;
+ }
+
+ @Override
+ public String toString() {
+ return "KfCreateEventMessage [kfAccount=" + kfAccount + ", ="
+ + super.toString() + "]";
+ }
+}
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfSwitchEventMessage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfSwitchEventMessage.java
new file mode 100644
index 00000000..5099b299
--- /dev/null
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/KfSwitchEventMessage.java
@@ -0,0 +1,51 @@
+package com.foxinmy.weixin4j.msg.event;
+
+import com.foxinmy.weixin4j.type.EventType;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+/**
+ * 客服转接会话事件
+ *
+ * @className KfSwitchEventMessage
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see 会话状态通知事件
+ */
+public class KfSwitchEventMessage extends EventMessage {
+
+ private static final long serialVersionUID = 4319501074109623413L;
+
+ public KfSwitchEventMessage() {
+ super(EventType.kf_switch_session);
+ }
+
+ @XStreamAlias("FromKfAccount")
+ private String fromKfAccount; // 来自的客服账号
+
+ @XStreamAlias("ToKfAccount")
+ private String toKfAccount; // 转移给客服账号
+
+ public String getFromKfAccount() {
+ return fromKfAccount;
+ }
+
+ public void setFromKfAccount(String fromKfAccount) {
+ this.fromKfAccount = fromKfAccount;
+ }
+
+ public String getToKfAccount() {
+ return toKfAccount;
+ }
+
+ public void setToKfAccount(String toKfAccount) {
+ this.toKfAccount = toKfAccount;
+ }
+
+ @Override
+ public String toString() {
+ return "KfSwitchEventMessage [fromKfAccount=" + fromKfAccount
+ + ", toKfAccount=" + toKfAccount + "]";
+ }
+}
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java
index 0499e745..c4960dba 100644
--- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/event/MassEventMessage.java
@@ -63,9 +63,9 @@ public class MassEventMessage extends EventMessage {
}
/**
- * 发送状态描述
- * err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)
- * err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)
+ * 发送状态描述
+ * err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)
+ * err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)
* err(20013,涉嫌版权) err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
*
* @param status
@@ -76,9 +76,9 @@ public class MassEventMessage extends EventMessage {
}
/**
- * 发送状态描述
- * err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)
- * err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)
+ * 发送状态描述
+ * err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)
+ * err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)
* err(20013,涉嫌版权) err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
*
* @param status
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/model/Base.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/model/Base.java
index 5185504d..3f5c3b1c 100644
--- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/model/Base.java
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/msg/model/Base.java
@@ -6,6 +6,15 @@ import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.type.MediaType;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
+/**
+ * 消息对象基类
+ *
+ * @className Base
+ * @author jy
+ * @date 2015年3月21日
+ * @since JDK 1.7
+ * @see
+ */
public class Base implements Serializable {
private static final long serialVersionUID = 8487251213352068227L;
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/EventType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/EventType.java
index bb1bb3e8..45499e76 100644
--- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/EventType.java
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/EventType.java
@@ -2,6 +2,9 @@ package com.foxinmy.weixin4j.type;
import com.foxinmy.weixin4j.msg.event.EnterAgentEventMessage;
import com.foxinmy.weixin4j.msg.event.EventMessage;
+import com.foxinmy.weixin4j.msg.event.KfCloseEventMessage;
+import com.foxinmy.weixin4j.msg.event.KfCreateEventMessage;
+import com.foxinmy.weixin4j.msg.event.KfSwitchEventMessage;
import com.foxinmy.weixin4j.msg.event.LocationEventMessage;
import com.foxinmy.weixin4j.msg.event.MassEventMessage;
import com.foxinmy.weixin4j.msg.event.ScanEventMessage;
@@ -30,9 +33,13 @@ public enum EventType {
MenuPhotoEventMessage.class), pic_weixin(
MenuPhotoEventMessage.class), location_select(
MenuLocationEventMessage.class), click(MenuEventMessage.class), location(
- LocationEventMessage.class),masssendjobfinish(
+ LocationEventMessage.class), masssendjobfinish(
MassEventMessage.class), templatesendjobfinish(
- TemplatesendjobfinishMessage.class),enter_agent(EnterAgentEventMessage.class);
+ TemplatesendjobfinishMessage.class), enter_agent(
+ EnterAgentEventMessage.class), kf_create_session(
+ KfCreateEventMessage.class), kf_close_session(
+ KfCloseEventMessage.class), kf_switch_session(
+ KfSwitchEventMessage.class);
private Class extends EventMessage> eventClass;
diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/MediaType.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/MediaType.java
index 0a158da7..36338a1d 100644
--- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/MediaType.java
+++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/type/MediaType.java
@@ -3,13 +3,18 @@ package com.foxinmy.weixin4j.type;
/**
* 上传的媒体类型
*
- * 公众平台上传限制: 图片(image): 128K,支持JPG格式
- * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式 视频(video):1MB,支持MP4格式
+ * 公众平台上传限制:
+ * 图片(image): 128K,支持JPG格式
+ * 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式
+ * 视频(video):1MB,支持MP4格式
* 缩略图(thumb):64KB,支持JPG格式
*
*
- * 企业号上传限制:图片(image):1MB,支持JPG格式 语音(voice):2MB,播放长度不超过60s,支持AMR格式
- * 视频(video):10MB,支持MP4格式 普通文件(file):10MB
+ * 企业号上传限制:
+ * 图片(image):1MB,支持JPG格式
+ * 语音(voice):2MB,播放长度不超过60s,支持AMR格式
+ * 视频(video):10MB,支持MP4格式
+ * 普通文件(file):10MB
*
*
* 媒体文件在后台保存时间为3天,即3天后media_id失效
diff --git a/weixin4j-mp/README.md b/weixin4j-mp/README.md
index 92944097..6fa033b6 100644
--- a/weixin4j-mp/README.md
+++ b/weixin4j-mp/README.md
@@ -180,4 +180,12 @@ weixin4j-mp
* 2015-03-06
- + **weixin4j-mp-api**: 新增oauth授权接口
\ No newline at end of file
+ + **weixin4j-mp-api**: 新增oauth授权接口
+
+* 2015-03-21
+
+ + **weixin-mp-api**: 新增群发消息给所有人接口
+
+ + **weixin-mp-api**: 新增素材管理多个接口
+
+ + **weixin-mp-api**: 新增多客服会话管理多个接口
\ No newline at end of file
diff --git a/weixin4j-mp/weixin4j-mp-api/README.md b/weixin4j-mp/weixin4j-mp-api/README.md
index 9263dc9a..2548a858 100644
--- a/weixin4j-mp/weixin4j-mp-api/README.md
+++ b/weixin4j-mp/weixin4j-mp-api/README.md
@@ -159,4 +159,12 @@ weixin.properties说明
* 2015-03-06
- + 新增oauth授权接口
\ No newline at end of file
+ + 新增oauth授权接口
+
+* 2015-03-21
+
+ + 新增群发消息给所有人接口
+
+ + 新增素材管理多个接口
+
+ + 新增多客服会话管理多个接口
\ No newline at end of file
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java
index 0026d4d8..82ca8f2a 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java
@@ -25,6 +25,9 @@ import com.foxinmy.weixin4j.mp.model.CustomRecord;
import com.foxinmy.weixin4j.mp.model.Following;
import com.foxinmy.weixin4j.mp.model.Group;
import com.foxinmy.weixin4j.mp.model.KfAccount;
+import com.foxinmy.weixin4j.mp.model.KfSession;
+import com.foxinmy.weixin4j.mp.model.MediaCounter;
+import com.foxinmy.weixin4j.mp.model.MediaRecord;
import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.model.SemQuery;
import com.foxinmy.weixin4j.mp.model.SemResult;
@@ -105,13 +108,16 @@ public class WeixinProxy {
*
* @param file
* 媒体对象
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
- public String uploadMedia(File file) throws WeixinException, IOException {
- return mediaApi.uploadMedia(file);
+ public String uploadMedia(File file, boolean isMaterial)
+ throws WeixinException, IOException {
+ return mediaApi.uploadMedia(file, isMaterial);
}
/**
@@ -121,15 +127,17 @@ public class WeixinProxy {
* 文件对象
* @param mediaType
* 媒体类型
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @throws IOException
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#uploadMedia(String, byte[],String)}
*/
- public String uploadMedia(File file, MediaType mediaType)
+ public String uploadMedia(File file, MediaType mediaType, boolean isMaterial)
throws WeixinException, IOException {
- return mediaApi.uploadMedia(file, mediaType);
+ return mediaApi.uploadMedia(file, mediaType, isMaterial);
}
/**
@@ -145,15 +153,17 @@ public class WeixinProxy {
* 媒体数据包
* @param mediaType
* 媒体类型
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @see 上传下载说明
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @throws WeixinException
*/
- public String uploadMedia(String fileName, byte[] data, String mediaType)
- throws WeixinException {
- return mediaApi.uploadMedia(fileName, data, mediaType);
+ public String uploadMedia(String fileName, byte[] data, String mediaType,
+ boolean isMaterial) throws WeixinException {
+ return mediaApi.uploadMedia(fileName, data, mediaType, isMaterial);
}
/**
@@ -166,6 +176,8 @@ public class WeixinProxy {
* 存储在微信服务器上的媒体标识
* @param mediaType
* 媒体类型
+ * @param isMaterial
+ * 是否永久素材
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see 上传下载说明
*/
- public byte[] downloadMedia(String mediaId) throws WeixinException {
- return mediaApi.downloadMedia(mediaId);
+ public byte[] downloadMedia(String mediaId, boolean isMaterial)
+ throws WeixinException {
+ return mediaApi.downloadMedia(mediaId, isMaterial);
+ }
+
+ /**
+ * 上传永久图文素材
+ *
+ * 、新增的永久素材也可以在公众平台官网素材管理模块中看到,永久素材的数量是有上限的,请谨慎新增。图文消息素材和图片素材的上限为5000,
+ * 其他类型为1000
+ *
+ *
+ * @param articles
+ * 图文列表
+ * @return 上传到微信服务器返回的媒体标识
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ * @see 上传永久媒体素材
+ */
+ public String uploadMaterialArticle(List articles)
+ throws WeixinException {
+ return mediaApi.uploadMaterialArticle(articles);
+ }
+
+ /**
+ * 下载永久图文素材
+ *
+ * @param mediaId
+ * 媒体ID
+ * @return 图文列表
+ * @throws WeixinException
+ * @see 下载永久媒体素材
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ */
+ public List downloadArticle(String mediaId)
+ throws WeixinException {
+ return mediaApi.downloadArticle(mediaId);
+ }
+
+ /**
+ * 更新永久图文素材
+ *
+ * @param mediaId
+ * 要修改的图文消息的id
+ * @param index
+ * 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
+ * @param articles
+ * 图文列表
+ * @return 处理结果
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ * @see 更新永久图文素材
+ */
+ public JsonResult updateMaterialArticle(String mediaId, int index,
+ List articles) throws WeixinException {
+ return mediaApi.updateMaterialArticle(mediaId, index, articles);
+ }
+
+ /**
+ * 删除永久媒体素材
+ *
+ * @param mediaId
+ * 媒体素材的media_id
+ * @return 处理结果
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ * @see 删除永久媒体素材
+ */
+ public JsonResult deleteMaterialMedia(String mediaId)
+ throws WeixinException {
+ return mediaApi.deleteMaterialMedia(mediaId);
+ }
+
+ /**
+ * 上传永久视频素材
+ *
+ * @param file
+ * 大小不超过1M且格式为MP4的视频文件
+ * @param title
+ * 视频标题
+ * @param introduction
+ * 视频描述
+ * @return 上传到微信服务器返回的媒体标识
+ * @see 上传永久媒体素材
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ * @throws WeixinException
+ * @throws IOException
+ */
+ public String uploadMaterialVideo(File file, String title,
+ String introduction) throws WeixinException, IOException {
+ return mediaApi.uploadMaterialVideo(file, title, introduction);
+ }
+
+ /**
+ * 获取永久媒体素材的总数 .图片和图文消息素材(包括单图文和多图文)的总数上限为5000,其他素材的总数上限为1000
+ *
+ * @return 总数对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.MediaCounter
+ * @see 获取素材总数
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ */
+ public MediaCounter countMaterialMedia() throws WeixinException {
+ return mediaApi.countMaterialMedia();
+ }
+
+ /**
+ * 获取媒体素材记录列表
+ *
+ * @param mediaType
+ * 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
+ * @param offset
+ * 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回
+ * @param count
+ * 返回素材的数量,取值在1到20之间
+ * @return 媒体素材的记录对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.MediaApi
+ * @see com.foxinmy.weixin4j.mp.model.MediaRecord
+ * @see com.foxinmy.weixin4j.type.MediaType
+ * @see com.foxinmy.weixin4j.mp.model.MediaItem
+ * @see 获取素材列表
+ */
+ public MediaRecord listMaterialMedia(MediaType mediaType, int offset,
+ int count) throws WeixinException {
+ return mediaApi.listMaterialMedia(mediaType, offset, count);
}
/**
@@ -346,6 +494,98 @@ public class WeixinProxy {
return customApi.deleteAccount(id);
}
+ /**
+ * 创建会话
+ *
+ * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。
+ * 只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
+ *
+ *
+ * @param userOpenId
+ * 用户的userOpenId
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号
+ * @param text
+ * 附加信息,文本会展示在客服人员的多客服客户端
+ * @return 处理结果
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.CustomApi
+ * @see 创建会话
+ */
+ public JsonResult createSession(String userOpenId, String kfAccount,
+ String text) throws WeixinException {
+ return customApi.createSession(userOpenId, kfAccount, text);
+ }
+
+ /**
+ * 关闭会话
+ *
+ * @param userOpenId
+ * 用户的userOpenId
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号
+ * @param text
+ * 附加信息,文本会展示在客服人员的多客服客户端
+ * @return 处理结果
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.CustomApi
+ * @see 创建会话
+ */
+ public JsonResult closeSession(String userOpenId, String kfAccount,
+ String text) throws WeixinException {
+ return customApi.closeSession(userOpenId, kfAccount, text);
+ }
+
+ /**
+ * 获取客户的会话状态:获取客户当前的会话状态。
+ *
+ * @param userOpenId
+ * 用户的openid
+ * @return 会话对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.CustomApi
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取会话状态
+ */
+ public KfSession getSession(String userOpenId) throws WeixinException {
+ return customApi.getSession(userOpenId);
+ }
+
+ /**
+ * 获取客服的会话列表:获取某个客服正在接待的会话列表。
+ *
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。
+ * @return 会话列表
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.CustomApi
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取客服的会话列表
+ */
+ public List getSessionList(String kfAccount)
+ throws WeixinException {
+ return customApi.getSessionList(kfAccount);
+ }
+
+ /**
+ * 获取未接入会话列表:获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。 缺陷:没有count字段
+ *
+ * @return 会话列表
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.api.CustomApi
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取客服的会话列表
+ */
+ public List getSessionWaitList() throws WeixinException {
+ return customApi.getSessionWaitList();
+ }
+
/**
* 上传图文消息,一个图文消息支持1到10条图文
*
@@ -386,26 +626,47 @@ public class WeixinProxy {
* 分组群发
*
* @param box
- * 消息项
+ * 消息对象
+ * @param groupId
+ * 分组ID
+ * @return 群发后的消息ID
+ * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massMessage(Base,boolean,int)}
+ * @throws WeixinException
+ */
+ public String massByGroupId(Base box, int groupId) throws WeixinException {
+ return massApi.massByGroupId(box, groupId);
+ }
+
+ /**
+ * 群发消息
+ *
+ * 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
+ * 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
+ *
+ *
+ * @param box
+ * 消息对象
+ * @param isToAll
+ * 用于设定是否向全部用户发送,值为true或false,选择true该消息群发给所有用户,
+ * 选择false可根据group_id发送给指定群组的用户
* @param groupId
* 分组ID
* @return 群发后的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.Group
- * @see com.foxinmy.weixin4j.mp.api.MassApi
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
+ * @see com.foxinmy.weixin4j.mp.api.MassApi
+ * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
* @see 根据分组群发
- * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
- * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroupByOpenId(String)}
- * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
*/
- public String massByGroupId(Base box, int groupId) throws WeixinException {
- return massApi.massByGroupId(box, groupId);
+ public String massMessage(Base box, boolean isToAll, int groupId)
+ throws WeixinException {
+ return massApi.massMessage(box, isToAll, groupId);
}
/**
@@ -419,6 +680,7 @@ public class WeixinProxy {
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Base,int)}
* @see 根据分组群发
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByGroupId(List articles, int groupId)
@@ -429,19 +691,24 @@ public class WeixinProxy {
/**
* openId群发
*
+ *
+ * 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
+ * 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
+ *
+ *
* @param box
- * 消息项
+ * 消息对象
* @param openIds
* openId列表
* @return 群发后的消息ID
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.User
- * @see com.foxinmy.weixin4j.mp.api.MassApi
* @see com.foxinmy.weixin4j.msg.model.Text
* @see com.foxinmy.weixin4j.msg.model.Image
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
+ * @see com.foxinmy.weixin4j.mp.api.MassApi
* @see 根据openid群发
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
@@ -463,6 +730,7 @@ public class WeixinProxy {
* @see 根据openid群发
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Base,String...)}
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByOpenIds(List articles,
@@ -490,8 +758,7 @@ public class WeixinProxy {
}
/**
- * 预览群发消息
- * 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版
+ * 预览群发消息 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版
*
* @param openId
* 接收用户的ID
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java
index 55dcb491..64c0e2c5 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/CustomApi.java
@@ -11,6 +11,7 @@ import org.apache.http.entity.mime.content.ByteArrayBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.PartParameter;
@@ -18,6 +19,7 @@ import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.CustomRecord;
import com.foxinmy.weixin4j.mp.model.KfAccount;
+import com.foxinmy.weixin4j.mp.model.KfSession;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.util.IOUtil;
@@ -223,4 +225,133 @@ public class CustomApi extends MpApi {
return response.getAsJsonResult();
}
+
+ /**
+ * 创建会话
+ *
+ * 开发者可以使用本接口,为多客服的客服工号创建会话,将某个客户直接指定给客服工号接待,需要注意此接口不会受客服自动接入数以及自动接入开关限制。
+ * 只能为在线的客服(PC客户端在线,或者已绑定多客服助手)创建会话。
+ *
+ *
+ * @param userOpenId
+ * 用户的userOpenId
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号
+ * @param text
+ * 附加信息,文本会展示在客服人员的多客服客户端
+ * @return 处理结果
+ * @throws WeixinException
+ * @see 创建会话
+ */
+ public JsonResult createSession(String userOpenId, String kfAccount,
+ String text) throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String kfsession_create_uri = getRequestUri("kfsession_create_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("openid", userOpenId);
+ obj.put("kf_account", kfAccount);
+ obj.put("text", text);
+ Response response = request.post(
+ String.format(kfsession_create_uri, token.getAccessToken()),
+ obj.toJSONString());
+
+ return response.getAsJsonResult();
+ }
+
+ /**
+ * 关闭会话
+ *
+ * @param userOpenId
+ * 用户的userOpenId
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号
+ * @param text
+ * 附加信息,文本会展示在客服人员的多客服客户端
+ * @return 处理结果
+ * @throws WeixinException
+ * @see 创建会话
+ */
+ public JsonResult closeSession(String userOpenId, String kfAccount,
+ String text) throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String kfsession_close_uri = getRequestUri("kfsession_close_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("openid", userOpenId);
+ obj.put("kf_account", kfAccount);
+ obj.put("text", text);
+ Response response = request.post(
+ String.format(kfsession_close_uri, token.getAccessToken()),
+ obj.toJSONString());
+
+ return response.getAsJsonResult();
+ }
+
+ /**
+ * 获取客户的会话状态:获取客户当前的会话状态。
+ *
+ * @param userOpenId
+ * 用户的openid
+ * @return 会话对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取会话状态
+ */
+ public KfSession getSession(String userOpenId) throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String kfsession_get_uri = getRequestUri("kfsession_get_uri");
+ Response response = request.get(String.format(kfsession_get_uri,
+ token.getAccessToken(), userOpenId));
+
+ KfSession session = response
+ .getAsObject(new TypeReference() {
+ });
+ session.setUserOpenId(userOpenId);
+ return session;
+ }
+
+ /**
+ * 获取客服的会话列表:获取某个客服正在接待的会话列表。
+ *
+ * @param kfAccount
+ * 完整客服账号,格式为:账号前缀@公众号微信号,账号前缀最多10个字符,必须是英文或者数字字符。
+ * @return 会话列表
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取客服的会话列表
+ */
+ public List getSessionList(String kfAccount)
+ throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String kfsession_list_uri = getRequestUri("kfsession_list_uri");
+ Response response = request.get(String.format(kfsession_list_uri,
+ token.getAccessToken(), kfAccount));
+
+ List sessionList = JSON.parseArray(response.getAsJson()
+ .getString("sessionlist"), KfSession.class);
+ return sessionList;
+ }
+
+ /**
+ * 获取未接入会话列表:获取当前正在等待队列中的会话列表,此接口最多返回最早进入队列的100个未接入会话。
+ * 缺陷:没有count字段
+ * @return 会话列表
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.KfSession
+ * @see 获取客服的会话列表
+ */
+ public List getSessionWaitList() throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String kfsession_wait_uri = getRequestUri("kfsession_wait_uri");
+ Response response = request.get(String.format(kfsession_wait_uri,
+ token.getAccessToken()));
+
+ List sessionList = JSON.parseArray(response.getAsJson()
+ .getString("waitcaselist"), KfSession.class);
+ return sessionList;
+ }
}
\ No newline at end of file
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java
index a61174d5..de0894b5 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java
@@ -16,8 +16,8 @@ import com.foxinmy.weixin4j.util.DateUtil;
/**
* 数据分析API
*
- * 1、接口侧的公众号数据的数据库中仅存储了2014年12月1日之后的数据,将查询不到在此之前的日期,即使有查到,也是不可信的脏数据;
- * 2、请开发者在调用接口获取数据后,将数据保存在自身数据库中,即加快下次用户的访问速度,也降低了微信侧接口调用的不必要损耗。
+ * 1、接口侧的公众号数据的数据库中仅存储了2014年12月1日之后的数据,将查询不到在此之前的日期,即使有查到,也是不可信的脏数据;
+ * 2、请开发者在调用接口获取数据后,将数据保存在自身数据库中,即加快下次用户的访问速度,也降低了微信侧接口调用的不必要损耗。
*
*
* @className DataApi
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java
index 287937e1..8c343352 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java
@@ -86,13 +86,31 @@ public class MassApi extends MpApi {
/**
* 分组群发
+ *
+ * @param box
+ * 消息对象
+ * @param groupId
+ * 分组ID
+ * @return 群发后的消息ID
+ * @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massMessage(Base,boolean,int)}
+ * @throws WeixinException
+ */
+ public String massByGroupId(Base box, int groupId) throws WeixinException {
+ return massMessage(box, false, groupId);
+ }
+
+ /**
+ * 群发消息
*
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
* 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
*
*
* @param box
- * 消息项
+ * 消息对象
+ * @param isToAll
+ * 用于设定是否向全部用户发送,值为true或false,选择true该消息群发给所有用户,
+ * 选择false可根据group_id发送给指定群组的用户
* @param groupId
* 分组ID
* @return 群发后的消息ID
@@ -103,19 +121,21 @@ public class MassApi extends MpApi {
* @see com.foxinmy.weixin4j.msg.model.Voice
* @see com.foxinmy.weixin4j.msg.model.MpVideo
* @see com.foxinmy.weixin4j.msg.model.MpNews
+ * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
* @see 根据分组群发
- * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
- * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()}
*/
- public String massByGroupId(Base box, int groupId) throws WeixinException {
+ public String massMessage(Base box, boolean isToAll, int groupId)
+ throws WeixinException {
if (box instanceof MpNews) {
MpNews _news = (MpNews) box;
List _articles = _news.getArticles();
- if (StringUtils.isBlank(_news.getMediaId()) && _articles != null
- && !_articles.isEmpty()) {
- return massArticleByGroupId(_articles, groupId);
+ if (StringUtils.isBlank(_news.getMediaId())
+ && (_articles == null || _articles.isEmpty())) {
+ throw new WeixinException(
+ "mass fail:mediaId or articles is required");
}
+ box = new MpNews(uploadArticle(_articles));
}
if (!(box instanceof Massable)) {
throw new WeixinException(String.format(
@@ -124,7 +144,10 @@ public class MassApi extends MpApi {
String msgtype = box.getMediaType().name();
JSONObject obj = new JSONObject();
JSONObject item = new JSONObject();
- item.put("group_id", groupId);
+ item.put("is_to_all", isToAll);
+ if (!isToAll) {
+ item.put("group_id", groupId);
+ }
obj.put("filter", item);
obj.put(msgtype, JSON.toJSON(box));
obj.put("msgtype", msgtype);
@@ -148,6 +171,7 @@ public class MassApi extends MpApi {
* @see 根据分组群发
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroupId(Base,int)}
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByGroupId(List articles, int groupId)
@@ -160,7 +184,7 @@ public class MassApi extends MpApi {
* openId群发
*
* @param box
- * 消息项
+ * 消息对象
* @param openIds
* openId列表
* @return 群发后的消息ID
@@ -173,7 +197,6 @@ public class MassApi extends MpApi {
* @see com.foxinmy.weixin4j.msg.model.MpNews
* @see 根据openid群发
- * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
* @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String)}
*/
public String massByOpenIds(Base box, String... openIds)
@@ -181,10 +204,12 @@ public class MassApi extends MpApi {
if (box instanceof MpNews) {
MpNews _news = (MpNews) box;
List _articles = _news.getArticles();
- if (StringUtils.isBlank(_news.getMediaId()) && _articles != null
- && !_articles.isEmpty()) {
- return massArticleByOpenIds(_articles, openIds);
+ if (StringUtils.isBlank(_news.getMediaId())
+ && (_articles == null || _articles.isEmpty())) {
+ throw new WeixinException(
+ "mass fail:mediaId or articles is required");
}
+ box = new MpNews(uploadArticle(_articles));
}
if (!(box instanceof Massable)) {
throw new WeixinException(String.format(
@@ -215,6 +240,7 @@ public class MassApi extends MpApi {
* @see 根据openid群发
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Base,String...)}
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByOpenIds(List articles,
@@ -250,8 +276,7 @@ public class MassApi extends MpApi {
}
/**
- * 预览群发消息
- * 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版
+ * 预览群发消息 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版
*
* @param openId
* 接收用户的ID
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java
index aa71f5fb..9d4d5cb5 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java
@@ -5,14 +5,27 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.mime.content.ByteArrayBody;
+import org.apache.http.entity.mime.content.StringBody;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.foxinmy.weixin4j.exception.WeixinException;
+import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.PartParameter;
import com.foxinmy.weixin4j.http.Response;
+import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
+import com.foxinmy.weixin4j.mp.model.MediaCounter;
+import com.foxinmy.weixin4j.mp.model.MediaItem;
+import com.foxinmy.weixin4j.mp.model.MediaRecord;
+import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.type.MediaType;
import com.foxinmy.weixin4j.util.ConfigUtil;
@@ -20,14 +33,12 @@ import com.foxinmy.weixin4j.util.FileUtil;
import com.foxinmy.weixin4j.util.IOUtil;
/**
- * 多媒体相关API
+ * 素材相关API
*
* @className MediaApi
* @author jy.hu
* @date 2014年9月25日
* @since JDK 1.7
- * @see 上传多媒体文件
* @see com.foxinmy.weixin4j.type.MediaType
*/
public class MediaApi extends MpApi {
@@ -42,41 +53,46 @@ public class MediaApi extends MpApi {
* 上传媒体文件
*
* @param file
- * 媒体对象
+ * 文件对象
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File, MediaType)}
* @throws WeixinException
* @throws IOException
*/
- public String uploadMedia(File file) throws WeixinException, IOException {
+ public String uploadMedia(File file, boolean isMaterial)
+ throws WeixinException, IOException {
String mediaTypeKey = IOUtil.getExtension(file.getName());
if (StringUtils.isBlank(mediaTypeKey)) {
mediaTypeKey = FileUtil.getFileType(file);
}
MediaType mediaType = MediaType.getMediaType(mediaTypeKey);
- return uploadMedia(file, mediaType);
+ return uploadMedia(file, mediaType, isMaterial);
}
/**
- * 上传媒体文件
+ * 上传媒体文件 此接口只包含图片、语音、缩略图三种媒体类型的上传
*
* @param file
* 文件对象
* @param mediaType
- * 媒体类型
+ * 媒体类型 (image)、语音(voice)和缩略图(thumb)
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see com.foxinmy.weixin4j.type.MediaType
- * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(String, byte[],String)}
+ * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(String, byte[],String,boolean)}
*/
- public String uploadMedia(File file, MediaType mediaType)
+ public String uploadMedia(File file, MediaType mediaType, boolean isMaterial)
throws WeixinException, IOException {
byte[] datas = IOUtil.toByteArray(new FileInputStream(file));
- return uploadMedia(file.getName(), datas, mediaType.name());
+ return uploadMedia(file.getName(), datas, mediaType.name(), isMaterial);
}
/**
- * 上传媒体文件
+ * 上传媒体文件 此接口只包含图片、语音、缩略图、视频(临时)四种媒体类型的上传
*
* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789},
* 否则抛出异常.
@@ -87,25 +103,51 @@ public class MediaApi extends MpApi {
* @param bytes
* 媒体数据包
* @param mediaType
- * 媒体类型
+ * 媒体文件类型:分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
+ * @param isMaterial
+ * 是否永久上传
* @return 上传到微信服务器返回的媒体标识
* @see 上传下载说明
+ * href="http://mp.weixin.qq.com/wiki/5/963fc70b80dc75483a271298a76a8d59.html">上传临时素材
+ * @see 上传永久素材
* @throws WeixinException
*/
- public String uploadMedia(String fileName, byte[] bytes, String mediaType)
- throws WeixinException {
+ public String uploadMedia(String fileName, byte[] bytes, String mediaType,
+ boolean isMaterial) throws WeixinException {
+ if (",image,voice,video,thumb,".indexOf(String
+ .format(",%s,", mediaType)) < 0) {
+ throw new WeixinException(String.format(
+ "unsupported media type:%s", mediaType));
+ }
+ if (mediaType.equals(MediaType.video.name()) && isMaterial) {
+ throw new WeixinException(
+ "please invoke uploadMaterialVideo method");
+ }
Token token = tokenHolder.getToken();
- String file_upload_uri = getRequestUri("file_upload_uri");
- Response response = request.post(String.format(file_upload_uri,
- token.getAccessToken(), mediaType), new PartParameter("media",
- new ByteArrayBody(bytes, fileName)));
-
+ Response response = null;
+ if (isMaterial) {
+ String material_media_upload_uri = getRequestUri("material_media_upload_uri");
+ try {
+ response = request.post(String.format(
+ material_media_upload_uri, token.getAccessToken()),
+ new PartParameter("media", new ByteArrayBody(bytes,
+ fileName)), new PartParameter("type",
+ new StringBody(mediaType, Consts.UTF_8)));
+ } catch (UnsupportedEncodingException e) {
+ ; // ignore
+ }
+ } else {
+ String file_upload_uri = getRequestUri("file_upload_uri");
+ response = request.post(String.format(file_upload_uri,
+ token.getAccessToken(), mediaType), new PartParameter(
+ "media", new ByteArrayBody(bytes, fileName)));
+ }
return response.getAsJson().getString("media_id");
}
/**
- * 下载媒体文件
+ * 下载媒体素材
*
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
*
@@ -113,32 +155,38 @@ public class MediaApi extends MpApi {
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param mediaType
- * 媒体类型
+ * 媒体文件类型:分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb)
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see 上传下载说明
+ * href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体文件
+ * @see 下载永久媒体素材
* @see com.foxinmy.weixin4j.type.MediaType
- * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#downloadMedia(String)}
+ * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#downloadMedia(String,boolean)}
*/
- public File downloadMedia(String mediaId, MediaType mediaType)
- throws WeixinException {
+ public File downloadMedia(String mediaId, MediaType mediaType,
+ boolean isMaterial) throws WeixinException {
+ if (",image,voice,video,thumb,".indexOf(String.format(",%s,",
+ mediaType.name())) < 0) {
+ throw new WeixinException(String.format(
+ "unsupported media type:%s", mediaType.name()));
+ }
String media_path = ConfigUtil.getValue("media_path");
File file = new File(media_path + File.separator + mediaId + "."
+ mediaType.getFormatName());
if (file.exists()) {
return file;
}
- byte[] datas = downloadMedia(mediaId);
+ byte[] datas = downloadMedia(mediaId, isMaterial);
OutputStream os = null;
try {
- boolean flag = file.createNewFile();
- if (flag) {
+ if (file.createNewFile()) {
os = new FileOutputStream(file);
os.write(datas);
} else {
- throw new WeixinException(String.format(
- "create file fail:%s", file.getAbsolutePath()));
+ throw new WeixinException(String.format("create file fail:%s",
+ file.getAbsolutePath()));
}
} catch (IOException e) {
throw new WeixinException(e.getMessage());
@@ -155,21 +203,245 @@ public class MediaApi extends MpApi {
}
/**
- * 下载媒体文件
+ * 下载媒体素材
*
* @param mediaId
* 媒体ID
+ * @param isMaterial
+ * 是否下载永久素材
* @return 二进制数据包
* @throws WeixinException
* @see 上传下载说明
+ * href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体素材
+ * @see 下载永久媒体素材
*/
- public byte[] downloadMedia(String mediaId) throws WeixinException {
+ public byte[] downloadMedia(String mediaId, boolean isMaterial)
+ throws WeixinException {
Token token = tokenHolder.getToken();
- String file_download_uri = getRequestUri("file_download_uri");
- Response response = request.get(String.format(file_download_uri,
- token.getAccessToken(), mediaId));
-
+ Response response = null;
+ if (isMaterial) {
+ JSONObject media = new JSONObject();
+ media.put("media_id", mediaId);
+ String material_media_download_uri = getRequestUri("material_media_download_uri");
+ response = request.post(
+ String.format(material_media_download_uri,
+ token.getAccessToken()), media.toJSONString());
+ } else {
+ String file_download_uri = getRequestUri("file_download_uri");
+ response = request.get(String.format(file_download_uri,
+ token.getAccessToken(), mediaId));
+ }
return response.getBody();
}
+
+ /**
+ * 上传永久图文素材
+ *
+ * 、新增的永久素材也可以在公众平台官网素材管理模块中看到,永久素材的数量是有上限的,请谨慎新增。图文消息素材和图片素材的上限为5000,
+ * 其他类型为1000
+ *
+ *
+ * @param articles
+ * 图文列表
+ * @return 上传到微信服务器返回的媒体标识
+ * @throws WeixinException
+ * @see 上传永久媒体素材
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ */
+ public String uploadMaterialArticle(List articles)
+ throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String material_article_upload_uri = getRequestUri("material_article_upload_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("articles", articles);
+ Response response = request.post(
+ String.format(material_article_upload_uri,
+ token.getAccessToken()), obj.toJSONString());
+
+ return response.getAsJson().getString("media_id");
+ }
+
+ /**
+ * 下载永久图文素材
+ *
+ * @param mediaId
+ * 媒体ID
+ * @return 图文列表
+ * @throws WeixinException
+ * @see 下载永久媒体素材
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ */
+ public List downloadArticle(String mediaId)
+ throws WeixinException {
+ byte[] bytes = downloadMedia(mediaId, true);
+ JSONObject obj = JSON.parseObject(bytes, 0, bytes.length,
+ Consts.UTF_8.newDecoder(), JSONObject.class);
+ return JSON.parseArray(obj.getString("news_item"), MpArticle.class);
+ }
+
+ /**
+ * 更新永久图文素材
+ *
+ * @param mediaId
+ * 要修改的图文消息的id
+ * @param index
+ * 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
+ * @param articles
+ * 图文列表
+ * @return 处理结果
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.msg.model.MpArticle
+ * @see 更新永久图文素材
+ */
+ public JsonResult updateMaterialArticle(String mediaId, int index,
+ List articles) throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String material_article_update_uri = getRequestUri("material_article_update_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("articles", articles);
+ obj.put("media_id", mediaId);
+ obj.put("index", index);
+ Response response = request.post(
+ String.format(material_article_update_uri,
+ token.getAccessToken()), obj.toJSONString());
+
+ return response.getAsJsonResult();
+ }
+
+ /**
+ * 删除永久媒体素材
+ *
+ * @param mediaId
+ * 媒体素材的media_id
+ * @return 处理结果
+ * @throws WeixinException
+ * @see 删除永久媒体素材
+ */
+ public JsonResult deleteMaterialMedia(String mediaId)
+ throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String material_media_del_uri = getRequestUri("material_media_del_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("media_id", mediaId);
+ Response response = request.post(
+ String.format(material_media_del_uri, token.getAccessToken()),
+ obj.toJSONString());
+
+ return response.getAsJsonResult();
+ }
+
+ /**
+ * 上传永久视频素材
+ *
+ * @param file
+ * 大小不超过1M且格式为MP4的视频文件
+ * @param title
+ * 视频标题
+ * @param introduction
+ * 视频描述
+ * @return 上传到微信服务器返回的媒体标识
+ * @see 上传永久媒体素材
+ * @throws WeixinException
+ * @throws IOException
+ */
+ public String uploadMaterialVideo(File file, String title,
+ String introduction) throws WeixinException, IOException {
+ String material_media_upload_uri = getRequestUri("material_media_upload_uri");
+ Token token = tokenHolder.getToken();
+ try {
+ JSONObject description = new JSONObject();
+ description.put("title", title);
+ description.put("introduction", introduction);
+ byte[] bytes = IOUtil.toByteArray(new FileInputStream(file));
+ Response response = request.post(
+ String.format(material_media_upload_uri,
+ token.getAccessToken()),
+ new PartParameter("media", new ByteArrayBody(bytes, file
+ .getName())),
+ new PartParameter("type", new StringBody(MediaType.video
+ .name(), Consts.UTF_8)),
+ new PartParameter("description", new StringBody(description
+ .toJSONString(), Consts.UTF_8)));
+ return response.getAsJson().getString("media_id");
+ } catch (UnsupportedEncodingException e) {
+ throw new WeixinException("unsupported encoding");
+ }
+ }
+
+ /**
+ * 获取永久媒体素材的总数 .图片和图文消息素材(包括单图文和多图文)的总数上限为5000,其他素材的总数上限为1000
+ *
+ * @return 总数对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.MediaCounter
+ * @see 获取素材总数
+ */
+ public MediaCounter countMaterialMedia() throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String material_media_count_uri = getRequestUri("material_media_count_uri");
+ Response response = request.get(String.format(material_media_count_uri,
+ token.getAccessToken()));
+
+ return response.getAsObject(new TypeReference() {
+ });
+ }
+
+ /**
+ * 获取媒体素材记录列表
+ *
+ * @param mediaType
+ * 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)
+ * @param offset
+ * 从全部素材的该偏移位置开始返回,0表示从第一个素材返回
+ * @param count
+ * 返回素材的数量,取值在1到20之间
+ * @return 媒体素材的记录对象
+ * @throws WeixinException
+ * @see com.foxinmy.weixin4j.mp.model.MediaRecord
+ * @see com.foxinmy.weixin4j.type.MediaType
+ * @see com.foxinmy.weixin4j.mp.model.MediaItem
+ * @see 获取素材列表
+ */
+ public MediaRecord listMaterialMedia(MediaType mediaType, int offset,
+ int count) throws WeixinException {
+ Token token = tokenHolder.getToken();
+ String material_media_list_uri = getRequestUri("material_media_list_uri");
+ JSONObject obj = new JSONObject();
+ obj.put("type", mediaType.name());
+ obj.put("offset", offset);
+ obj.put("count", count);
+ Response response = request.post(
+ String.format(material_media_list_uri, token.getAccessToken()),
+ obj.toJSONString());
+ MediaRecord mediaRecord = null;
+ if (mediaType == MediaType.news) {
+ mediaRecord = JSON.parseObject(response.getAsString(), MediaRecord.class,
+ new ExtraProcessor() {
+ @Override
+ public void processExtra(Object object, String key,
+ Object value) {
+ if (key.equals("content")) {
+ ((MediaItem) object).setArticles(JSON
+ .parseArray(((JSONObject) value)
+ .getString("news_item"),
+ MpArticle.class));
+ }
+ }
+ });
+ } else {
+ mediaRecord = response
+ .getAsObject(new TypeReference() {
+ });
+ }
+ mediaRecord.setMediaType(mediaType);
+ return mediaRecord;
+ }
}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties
index 5ad4b236..046b7191 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties
@@ -81,6 +81,16 @@ custom_uploadheadimg_uri={api_base_url}/customservice/kfacount/uploadheadimg?acc
custom_delete_uri={api_base_url}/customservice/kfaccount/del?access_token=%s&kf_account=%s
# \u5728\u7ebf\u5ba2\u670d\u57fa\u672c\u4fe1\u606f
getonlinekflist_uri={api_cgi_url}/customservice/getonlinekflist?access_token=%s
+# \u521b\u5efa\u5ba2\u670d\u4f1a\u8bdd
+kfsession_create_uri={api_base_url}/customservice/kfsession/create?access_token=%s
+# \u5173\u95ed\u5ba2\u670d\u4f1a\u8bdd
+kfsession_close_uri={api_base_url}/customservice/kfsession/close?access_token=%s
+# \u83b7\u53d6\u5ba2\u670d\u4f1a\u8bdd\u72b6\u6001
+kfsession_get_uri={api_base_url}/customservice/kfsession/getsession?access_token=%s&openid=%s
+# \u83b7\u53d6\u5ba2\u670d\u7684\u4f1a\u8bdd\u5217\u8868
+kfsession_list_uri={api_base_url}/customservice/kfsession/getsessionlist?access_token=%s&kf_account=%s
+# \u83b7\u53d6\u672a\u63a5\u5165\u4f1a\u8bdd\u5217\u8868
+kfsession_wait_uri={api_base_url}/customservice/kfsession/getwaitcase?access_token=%s
# \u957f\u94fe\u63a5\u8f6c\u77ed\u94fe\u63a5
shorturl_uri={api_cgi_url}/shorturl?access_token=%s
p_shorturl_uri={mch_base_url}/tools/shorturl
@@ -134,4 +144,19 @@ nativepay_v2_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tam
nativepay_v3_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s
# \u6570\u636e\u7edf\u8ba1
-datacube_uri={api_base_url}/datacube/%s?access_token=%s
\ No newline at end of file
+datacube_uri={api_base_url}/datacube/%s?access_token=%s
+
+# \u4e0a\u4f20\u6c38\u4e45\u56fe\u6587\u7d20\u6750
+material_article_upload_uri={api_cgi_url}/material/add_news?access_token=%s
+# \u4e0a\u4f20\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
+material_media_upload_uri={file_base_url}/material/add_material?access_token=%s
+# \u4e0b\u8f7d\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
+material_media_download_uri={api_cgi_url}/material/get_material?access_token=%s
+# \u66f4\u65b0\u6c38\u4e45\u56fe\u6587\u7d20\u6750
+material_article_update_uri={api_cgi_url}/material/update_news?access_token=%s
+# \u5220\u9664\u6c38\u4e45\u5a92\u4f53\u7d20\u6750
+material_media_del_uri={api_cgi_url}/material/del_material?access_token=%s
+# \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u603b\u6570
+material_media_count_uri={api_cgi_url}/material/get_materialcount?access_token=%s
+# \u83b7\u53d6\u5a92\u4f53\u7d20\u6750\u5217\u8868
+material_media_list_uri={api_cgi_url}/material/batchget_material?access_token=%s
\ No newline at end of file
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfSession.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfSession.java
new file mode 100644
index 00000000..5b38ef88
--- /dev/null
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/KfSession.java
@@ -0,0 +1,57 @@
+package com.foxinmy.weixin4j.mp.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.alibaba.fastjson.annotation.JSONField;
+
+/**
+ * 客服会话信息
+ *
+ * @className KfSession
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see
+ */
+public class KfSession implements Serializable {
+
+ private static final long serialVersionUID = 7236468333492555458L;
+
+ @JSONField(name = "kf_account")
+ private String kfAccount; // 客服账号
+ @JSONField(name = "openid")
+ private String userOpenId; // 用户ID
+ @JSONField(name = "createtime")
+ private Date createTime; // 创建时间
+
+ public String getKfAccount() {
+ return kfAccount;
+ }
+
+ public void setKfAccount(String kfAccount) {
+ this.kfAccount = kfAccount;
+ }
+
+ public String getUserOpenId() {
+ return userOpenId;
+ }
+
+ public void setUserOpenId(String userOpenId) {
+ this.userOpenId = userOpenId;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ @Override
+ public String toString() {
+ return "KfSession [kfAccount=" + kfAccount + ", userOpenId="
+ + userOpenId + ", createTime=" + createTime + "]";
+ }
+}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaCounter.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaCounter.java
new file mode 100644
index 00000000..5f42d96c
--- /dev/null
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaCounter.java
@@ -0,0 +1,67 @@
+package com.foxinmy.weixin4j.mp.model;
+
+import java.io.Serializable;
+
+import com.alibaba.fastjson.annotation.JSONField;
+
+/**
+ * 媒体素材总数
+ *
+ * @className MediaCounter
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see
+ */
+public class MediaCounter implements Serializable {
+
+ private static final long serialVersionUID = -1752502821323552783L;
+
+ @JSONField(name = "voice_count")
+ private long voiceCount;// 语音总数量
+ @JSONField(name = "video_count")
+ private long videoCount;// 视频总数量
+ @JSONField(name = "image_count")
+ private long imageCount; // 图片总数量
+ @JSONField(name = "news_count")
+ private long newsCount; // 图文总数量
+
+ public long getVoiceCount() {
+ return voiceCount;
+ }
+
+ public void setVoiceCount(long voiceCount) {
+ this.voiceCount = voiceCount;
+ }
+
+ public long getVideoCount() {
+ return videoCount;
+ }
+
+ public void setVideoCount(long videoCount) {
+ this.videoCount = videoCount;
+ }
+
+ public long getImageCount() {
+ return imageCount;
+ }
+
+ public void setImageCount(long imageCount) {
+ this.imageCount = imageCount;
+ }
+
+ public long getNewsCount() {
+ return newsCount;
+ }
+
+ public void setNewsCount(long newsCount) {
+ this.newsCount = newsCount;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaCounter [voiceCount=" + voiceCount + ", videoCount="
+ + videoCount + ", imageCount=" + imageCount + ", newsCount="
+ + newsCount + "]";
+ }
+}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaItem.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaItem.java
new file mode 100644
index 00000000..8d977cde
--- /dev/null
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaItem.java
@@ -0,0 +1,68 @@
+package com.foxinmy.weixin4j.mp.model;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.foxinmy.weixin4j.msg.model.MpArticle;
+
+/**
+ * 媒体素材信息
+ *
+ * @className MediaItem
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see
+ */
+public class MediaItem implements Serializable {
+
+ private static final long serialVersionUID = -2923028664954250134L;
+
+ @JSONField(name = "media_id")
+ private String mediaId; // 媒体素材ID
+ private String name; // 媒体素材名称
+ @JSONField(name = "update_time")
+ private Date updateTime; // 媒体素材最后更新时间
+ @JSONField(name = "news_item")
+ private List articles; // 图文素材列表
+
+ public String getMediaId() {
+ return mediaId;
+ }
+
+ public void setMediaId(String mediaId) {
+ this.mediaId = mediaId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ public List getArticles() {
+ return articles;
+ }
+
+ public void setArticles(List articles) {
+ this.articles = articles;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaItem [mediaId=" + mediaId + ", name=" + name
+ + ", updateTime=" + updateTime + ", articles=" + articles + "]";
+ }
+}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaRecord.java b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaRecord.java
new file mode 100644
index 00000000..fee3c347
--- /dev/null
+++ b/weixin4j-mp/weixin4j-mp-api/src/main/java/com/foxinmy/weixin4j/mp/model/MediaRecord.java
@@ -0,0 +1,69 @@
+package com.foxinmy.weixin4j.mp.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.foxinmy.weixin4j.type.MediaType;
+
+/**
+ * 媒体素材记录
+ *
+ * @className MediaRecord
+ * @author jy
+ * @date 2015年3月22日
+ * @since JDK 1.7
+ * @see
+ */
+public class MediaRecord implements Serializable {
+
+ private static final long serialVersionUID = 7017503153256241457L;
+
+ @JSONField(name = "total_count")
+ private int totalCount;// 该类型的素材的总数
+ @JSONField(name = "item_count")
+ private int itemCount;// 本次调用获取的素材的数量
+ @JSONField(serialize = false)
+ private MediaType mediaType; // 媒体类型
+ @JSONField(name = "item")
+ private List items; // 媒体信息
+
+ public int getTotalCount() {
+ return totalCount;
+ }
+
+ public void setTotalCount(int totalCount) {
+ this.totalCount = totalCount;
+ }
+
+ public int getItemCount() {
+ return itemCount;
+ }
+
+ public void setItemCount(int itemCount) {
+ this.itemCount = itemCount;
+ }
+
+ public MediaType getMediaType() {
+ return mediaType;
+ }
+
+ public void setMediaType(MediaType mediaType) {
+ this.mediaType = mediaType;
+ }
+
+ public List getItems() {
+ return items;
+ }
+
+ public void setItems(List items) {
+ this.items = items;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaRecord [totalCount=" + totalCount + ", itemCount="
+ + itemCount + ", mediaType=" + mediaType + ", items=" + items
+ + "]";
+ }
+}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java
index 755a5b71..a732e217 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java
@@ -2,13 +2,19 @@ package com.foxinmy.weixin4j.mp.test;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
+import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.mp.api.MediaApi;
+import com.foxinmy.weixin4j.mp.model.MediaCounter;
+import com.foxinmy.weixin4j.mp.model.MediaRecord;
+import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.type.MediaType;
/**
@@ -30,19 +36,106 @@ public class MediaTest extends TokenTest {
}
@Test
- public void upload() throws IOException, WeixinException {
- File file = new File("/tmp/test.jpg");
- String mediaId = mediaApi.uploadMedia(file, MediaType.image);
- // vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay
+ public void upload1() throws IOException, WeixinException {
+ File file = new File("/Users/jy/Downloads/test.jpg");
+ String mediaId = mediaApi.uploadMedia(file, MediaType.image, false);
+ // Sy1KOLsi4ri3kB3TYUuculVelcW2I7W6BrfGwkGvSW8beTCAarxuGQLjuNJChJr8
Assert.assertNotNull(mediaId);
+ System.err.println(mediaId);
}
@Test
- public void download() throws WeixinException, IOException {
+ public void download1() throws WeixinException, IOException {
File file = mediaApi
.downloadMedia(
- "vvU_AUtovWyfAxQ8J1DsCoNMtK6U_bUmTpe6lpINUOVRLvt_7rtO4zxzBpPgkmay",
- MediaType.image);
+ "Sy1KOLsi4ri3kB3TYUuculVelcW2I7W6BrfGwkGvSW8beTCAarxuGQLjuNJChJr8",
+ MediaType.image, false);
Assert.assertTrue(file.exists());
}
+
+ @Test
+ public void upload2() throws IOException, WeixinException {
+ File file = new File("/Users/jy/Downloads/test.jpg");
+ String mediaId = mediaApi.uploadMedia(file, MediaType.image, true);
+ // 8790403529
+ Assert.assertNotNull(mediaId);
+ System.err.println(mediaId);
+ }
+
+ @Test
+ public void uploadMaterialVideo() throws IOException, WeixinException {
+ File file = new File("/Users/jy/Downloads/test.jpg");
+ String mediaId = mediaApi.uploadMaterialVideo(file, "title",
+ "introduction");
+ // Sy1KOLsi4ri3kB3TYUuculVelcW2I7W6BrfGwkGvSW8beTCAarxuGQLjuNJChJr8
+ Assert.assertNotNull(mediaId);
+ System.err.println(mediaId);
+ }
+
+ @Test
+ public void uploadMaterialArticle() throws WeixinException {
+ List articles = new ArrayList();
+ articles.add(new MpArticle(
+ "8790403529",
+ "title", "content"));
+ String mediaId = mediaApi.uploadMaterialArticle(articles);
+ // 17385064953
+ Assert.assertNotNull(mediaId);
+ System.err.println(mediaId);
+ }
+
+ @Test
+ public void download2() throws WeixinException, IOException {
+ File file = mediaApi
+ .downloadMedia(
+ "8790403529",
+ MediaType.image, true);
+ Assert.assertTrue(file.exists());
+ }
+
+ @Test
+ public void downloadArticle() throws WeixinException {
+ List articles = mediaApi
+ .downloadArticle("17385064953");
+ Assert.assertTrue(articles != null && !articles.isEmpty());
+ System.err.println(articles);
+ }
+
+ @Test
+ public void deleteMaterialMedia() throws WeixinException {
+ JsonResult result = mediaApi
+ .deleteMaterialMedia("17385064953");
+ System.err.println(result);
+ }
+
+ @Test
+ public void updateMaterialArticle() throws WeixinException {
+ MpArticle mpArticle = new MpArticle(
+ "8790403529",
+ "title", "content");
+ mpArticle.setAuthor("author_update");
+ mpArticle.setDigest("digest_update");
+ mpArticle.setShowCoverPic(false);
+ mpArticle.setUrl("http://www.baidu.com");
+ List articles = new ArrayList();
+ articles.add(mpArticle);
+ JsonResult result = mediaApi
+ .updateMaterialArticle(
+ "17385064953",
+ 0, articles);
+ System.err.println(result);
+ // 17385065153
+ }
+
+ @Test
+ public void countMaterialMedia() throws WeixinException {
+ MediaCounter counter = mediaApi.countMaterialMedia();
+ System.err.println(counter);
+ }
+
+ @Test
+ public void listMaterialMedia() throws WeixinException {
+ MediaRecord mediaRecord = mediaApi.listMaterialMedia(MediaType.news, 0, 20);
+ System.err.println(mediaRecord);
+ }
}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java
index e79880f6..09c46693 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/CustomTest.java
@@ -15,6 +15,7 @@ import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.mp.api.CustomApi;
import com.foxinmy.weixin4j.mp.model.CustomRecord;
import com.foxinmy.weixin4j.mp.model.KfAccount;
+import com.foxinmy.weixin4j.mp.model.KfSession;
import com.foxinmy.weixin4j.mp.test.TokenTest;
/**
@@ -61,27 +62,60 @@ public class CustomTest extends TokenTest {
@Test
public void addAccount() throws WeixinException {
- JsonResult result = customApi.addAccount("temp1@canyidianzhang", "temp",
- "123456");
+ JsonResult result = customApi.addAccount("test@test", "test", "123456");
Assert.assertEquals(0, result.getCode());
}
-
+
@Test
public void updateAccount() throws WeixinException {
- JsonResult result = customApi.updateAccount("temp1@canyidianzhang", "temp",
- "123456");
+ JsonResult result = customApi.updateAccount("temp1@canyidianzhang",
+ "temp", "123456");
Assert.assertEquals(0, result.getCode());
}
-
+
@Test
public void uploadAccountHeadimg() throws WeixinException, IOException {
- JsonResult result = customApi.uploadAccountHeadimg("temp1@canyidianzhang", new File("/Users/jy/Music/简谱/风动草.jpg"));
+ JsonResult result = customApi.uploadAccountHeadimg(
+ "temp1@canyidianzhang", new File("/Users/jy/Music/简谱/风动草.jpg"));
Assert.assertEquals(0, result.getCode());
}
-
+
@Test
public void deleteAccount() throws WeixinException, IOException {
JsonResult result = customApi.deleteAccount("temp@canyidianzhang");
Assert.assertEquals(0, result.getCode());
}
+
+ @Test
+ public void createSession() throws WeixinException {
+ JsonResult result = customApi.createSession(
+ "opKwyt6IhrqPmTTZshyqH5W9gIVo", "kfAccount", "text");
+ Assert.assertEquals(0, result.getCode());
+ }
+
+ @Test
+ public void closeSession() throws WeixinException {
+ JsonResult result = customApi.closeSession(
+ "opKwyt6IhrqPmTTZshyqH5W9gIVo", "kfAccount", "text");
+ Assert.assertEquals(0, result.getCode());
+ }
+
+ @Test
+ public void getSession() throws WeixinException {
+ KfSession session = customApi
+ .getSession("oz5axuNnJim8yTYs_jzE1bWFj9eA");
+ System.err.println(session);
+ }
+
+ @Test
+ public void getSessionList() throws WeixinException {
+ List sessionList = customApi.getSessionList("kfAccount");
+ System.err.println(sessionList);
+ }
+
+ @Test
+ public void getSessionWaitList() throws WeixinException {
+ List sessionList = customApi.getSessionWaitList();
+ System.err.println(sessionList);
+ }
}
diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MassMsgTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MassMsgTest.java
index 8a388e25..0d61b0ab 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MassMsgTest.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/MassMsgTest.java
@@ -44,7 +44,7 @@ public class MassMsgTest extends TokenTest {
public void uploadArticle() throws IOException, WeixinException {
List articles = new ArrayList();
String thumbMediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
- MediaType.image);
+ MediaType.image, false);
articles.add(new MpArticle(thumbMediaId, "title", "content"));
massApi.uploadArticle(articles);
}
@@ -64,7 +64,8 @@ public class MassMsgTest extends TokenTest {
@Test
public void massByOpenIds() throws WeixinException {
- String msgId = massApi.massByOpenIds(new Text("HI"), "oyFLst1bqtuTcxK-ojF8hOGtLQao");
+ String msgId = massApi.massByOpenIds(new Text("HI"),
+ "oyFLst1bqtuTcxK-ojF8hOGtLQao");
Assert.assertTrue(msgId != null);
}
@@ -72,7 +73,7 @@ public class MassMsgTest extends TokenTest {
public void massArticleByGroup() throws IOException, WeixinException {
List articles = new ArrayList();
String thumbMediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
- MediaType.image);
+ MediaType.image, false);
articles.add(new MpArticle(thumbMediaId, "title", "content"));
String massId = massApi.massArticleByGroupId(articles, 0);
Assert.assertTrue(massId != null);
@@ -82,7 +83,7 @@ public class MassMsgTest extends TokenTest {
public void massArticleByOpenIds() throws IOException, WeixinException {
List articles = new ArrayList();
String thumbMediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
- MediaType.image);
+ MediaType.image, false);
articles.add(new MpArticle(thumbMediaId, "title", "content"));
String massId = massApi.massArticleByOpenIds(articles,
"owGBft_vbBbOaQOmpEUE4xDLeRSU");
@@ -97,10 +98,11 @@ public class MassMsgTest extends TokenTest {
@Test
public void previewMass() throws WeixinException {
- JsonResult result = massApi.previewMassNews("oyFLst1bqtuTcxK-ojF8hOGtLQao", new Text("test"));
+ JsonResult result = massApi.previewMassNews(
+ "oyFLst1bqtuTcxK-ojF8hOGtLQao", new Text("test"));
Assert.assertEquals("0", result.getCode());
}
-
+
@Test
public void getMassNews() throws WeixinException {
String status = massApi.getMassNews("82358");
diff --git a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java
index bab2a231..10e83ea8 100644
--- a/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java
+++ b/weixin4j-mp/weixin4j-mp-api/src/test/java/com/foxinmy/weixin4j/mp/test/msg/NotifyMsgTest.java
@@ -92,7 +92,7 @@ public class NotifyMsgTest extends TokenTest {
@Test
public void send2() throws WeixinException, IOException {
String mediaId = mediaApi.uploadMedia(new File("/tmp/test.jpg"),
- MediaType.image);
+ MediaType.image, false);
NotifyMessage imageNotify = new NotifyMessage(
"owGBft_vbBbOaQOmpEUE4xDLeRSU", new Image(mediaId));
JsonResult result = notifyApi.sendNotify(imageNotify);
diff --git a/weixin4j-qy/pom.xml b/weixin4j-qy/pom.xml
index 4053cae5..e23a899a 100644
--- a/weixin4j-qy/pom.xml
+++ b/weixin4j-qy/pom.xml
@@ -15,4 +15,4 @@
weixin4j-qy-api
weixin4j-qy-server
-
\ No newline at end of file
+