新增素材管理、多客服会话管理、群发消息给所有人接口

This commit is contained in:
jinyu 2015-03-22 19:55:03 +08:00
parent 7cb8e21579
commit 264900ccbd
27 changed files with 1428 additions and 119 deletions

View File

@ -184,4 +184,15 @@
* 2015-03-17
+ **weixin4j-qy**: 新增企业应用设置接口
+ **weixin4j-qy**: 新增企业应用设置接口
* 2015-03-21
+ 替换<br/></br>
+ **weixin-mp**: 新增群发消息给所有人接口
+ **weixin-mp**: 新增素材管理多个接口
+ **weixin-mp**: 新增多客服会话管理多个接口

View File

@ -13,7 +13,7 @@ import com.foxinmy.weixin4j.response.ResponseMessage;
* @since JDK 1.7
* @see
*/
public abstract class DebugAction<M extends BaseMsg> extends AbstractAction<M> {
public class DebugAction<M extends BaseMsg> extends AbstractAction<M> {
@Override
public ResponseMessage execute(M message) {

View File

@ -579,6 +579,10 @@
<text>Api禁用</text>
</error>
<!-- 多客服API错误 -->
<error>
<code>61450</code>
<text>系统错误(system error)</text>
</error>
<error>
<code>61451</code>
<text>参数错误(invalid parameter)</text>
@ -607,6 +611,22 @@
<code>61457</code>
<text>无效头像文件类型(invalid file type)</text>
</error>
<error>
<code>61458</code>
<text>客户正在被其他客服接待(customer accepted by xxx@xxxx)</text>
</error>
<error>
<code>61459</code>
<text>客服不在线(kf offline)</text>
</error>
<error>
<code>61500</code>
<text>日期格式错误</text>
</error>
<error>
<code>61501</code>
<text>日期范围错误</text>
</error>
<error>
<code>50001</code>
<desc>api/redirect_uri unauthorized</desc>

View File

@ -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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
*/
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() + "]";
}
}

View File

@ -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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
*/
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() + "]";
}
}

View File

@ -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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81.E9.80.9A.E7.9F.A5.E4.BA.8B.E4.BB.B6">会话状态通知事件</a>
*/
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 + "]";
}
}

View File

@ -63,9 +63,9 @@ public class MassEventMessage extends EventMessage {
}
/**
* 发送状态描述<br/>
* err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)<br/>
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)<br/>
* 发送状态描述</br>
* err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)</br>
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)</br>
* err(20013,涉嫌版权) err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
*
* @param status
@ -76,9 +76,9 @@ public class MassEventMessage extends EventMessage {
}
/**
* 发送状态描述<br/>
* err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)<br/>
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)<br/>
* 发送状态描述</br>
* err(10001,涉嫌广告) err(20001,涉嫌政治) err(20004,涉嫌社会)</br>
* err(20002,涉嫌色情) err(20006,涉嫌违法犯罪) err(20008,涉嫌欺诈)</br>
* err(20013,涉嫌版权) err(22000,涉嫌互推(互相宣传) err(21000,涉嫌其他)
*
* @param status

View File

@ -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;

View File

@ -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;

View File

@ -3,13 +3,18 @@ package com.foxinmy.weixin4j.type;
/**
* 上传的媒体类型</br>
* <p>
* 公众平台上传限制:</br> 图片(image): 128K,支持JPG格式</br>
* 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式</br> 视频(video):1MB,支持MP4格式</br>
* 公众平台上传限制:</br>
* 图片(image): 128K,支持JPG格式</br>
* 语音(voice):256K,播放长度不超过60s,支持AMR\MP3格式</br>
* 视频(video):1MB,支持MP4格式</br>
* 缩略图(thumb):64KB,支持JPG格式</br>
* </p>
* <p>
* 企业号上传限制:</br>图片image:1MB支持JPG格式</br> 语音voice2MB播放长度不超过60s支持AMR格式</br>
* 视频video10MB支持MP4格式</br> 普通文件file10MB</br>
* 企业号上传限制:</br>
* 图片image:1MB支持JPG格式</br>
* 语音voice2MB播放长度不超过60s支持AMR格式</br>
* 视频video10MB支持MP4格式</br>
* 普通文件file10MB</br>
* </p>
* <p>
* <font color='red'>媒体文件在后台保存时间为3天,即3天后media_id失效</font>

View File

@ -180,4 +180,12 @@ weixin4j-mp
* 2015-03-06
+ **weixin4j-mp-api**: 新增oauth授权接口
+ **weixin4j-mp-api**: 新增oauth授权接口
* 2015-03-21
+ **weixin-mp-api**: 新增群发消息给所有人接口
+ **weixin-mp-api**: 新增素材管理多个接口
+ **weixin-mp-api**: 新增多客服会话管理多个接口

View File

@ -159,4 +159,12 @@ weixin.properties说明
* 2015-03-06
+ 新增oauth授权接口
+ 新增oauth授权接口
* 2015-03-21
+ 新增群发消息给所有人接口
+ 新增素材管理多个接口
+ 新增多客服会话管理多个接口

View File

@ -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 <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传下载说明</a>
* @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 <a
@ -174,9 +186,9 @@ public class WeixinProxy {
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String)}
*/
public File downloadMedia(String mediaId, MediaType mediaType)
throws WeixinException {
return mediaApi.downloadMedia(mediaId, mediaType);
public File downloadMedia(String mediaId, MediaType mediaType,
boolean isMaterial) throws WeixinException {
return mediaApi.downloadMedia(mediaId, mediaType, isMaterial);
}
/**
@ -184,14 +196,150 @@ public class WeixinProxy {
*
* @param mediaId
* 媒体ID
* @param isMaterial
* 是否永久素材
* @return 二进制数据包
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传下载说明</a>
*/
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);
}
/**
* 上传永久图文素材
* <p>
* 新增的永久素材也可以在公众平台官网素材管理模块中看到,永久素材的数量是有上限的请谨慎新增图文消息素材和图片素材的上限为5000
* 其他类型为1000
* </P>
*
* @param articles
* 图文列表
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @see <a
* href="http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html">上传永久媒体素材</a>
*/
public String uploadMaterialArticle(List<MpArticle> articles)
throws WeixinException {
return mediaApi.uploadMaterialArticle(articles);
}
/**
* 下载永久图文素材
*
* @param mediaId
* 媒体ID
* @return 图文列表
* @throws WeixinException
* @see <a href=
* "http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html">下载永久媒体素材</a>
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @see com.foxinmy.weixin4j.mp.api.MediaApi
*/
public List<MpArticle> 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 <a
* href="http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html">更新永久图文素材</a>
*/
public JsonResult updateMaterialArticle(String mediaId, int index,
List<MpArticle> articles) throws WeixinException {
return mediaApi.updateMaterialArticle(mediaId, index, articles);
}
/**
* 删除永久媒体素材
*
* @param mediaId
* 媒体素材的media_id
* @return 处理结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.MediaApi
* @see <a
* href="http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html">删除永久媒体素材</a>
*/
public JsonResult deleteMaterialMedia(String mediaId)
throws WeixinException {
return mediaApi.deleteMaterialMedia(mediaId);
}
/**
* 上传永久视频素材
*
* @param file
* 大小不超过1M且格式为MP4的视频文件
* @param title
* 视频标题
* @param introduction
* 视频描述
* @return 上传到微信服务器返回的媒体标识
* @see <a
* href="http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html">上传永久媒体素材</a>
* @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);
}
/**
* 获取永久媒体素材的总数</br> .图片和图文消息素材包括单图文和多图文的总数上限为5000其他素材的总数上限为1000
*
* @return 总数对象
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MediaCounter
* @see <a
* href="http://mp.weixin.qq.com/wiki/16/8cc64f8c189674b421bee3ed403993b8.html">获取素材总数</a>
* @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 <a
* href="http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html">获取素材列表</a>
*/
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);
}
/**
* 创建会话
* <p>
* 开发者可以使用本接口为多客服的客服工号创建会话将某个客户直接指定给客服工号接待需要注意此接口不会受客服自动接入数以及自动接入开关限制
* 只能为在线的客服PC客户端在线或者已绑定多客服助手创建会话
* </p>
*
* @param userOpenId
* 用户的userOpenId
* @param kfAccount
* 完整客服账号格式为账号前缀@公众号微信号
* @param text
* 附加信息文本会展示在客服人员的多客服客户端
* @return 处理结果
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.CustomApi
* @see <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E5.88.9B.E5.BB.BA.E4.BC.9A.E8.AF.9D">创建会话</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E5.85.B3.E9.97.AD.E4.BC.9A.E8.AF.9D">创建会话</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E5.AE.A2.E6.88.B7.E7.9A.84.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81">获取会话状态</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E5.AE.A2.E6.9C.8D.E7.9A.84.E4.BC.9A.E8.AF.9D.E5.88.97.E8.A1.A8">获取客服的会话列表</a>
*/
public List<KfSession> getSessionList(String kfAccount)
throws WeixinException {
return customApi.getSessionList(kfAccount);
}
/**
* 获取未接入会话列表:获取当前正在等待队列中的会话列表此接口最多返回最早进入队列的100个未接入会话</br> <font
* color="red">缺陷没有count字段</font>
*
* @return 会话列表
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.api.CustomApi
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E6.9C.AA.E6.8E.A5.E5.85.A5.E4.BC.9A.E8.AF.9D.E5.88.97.E8.A1.A8">获取客服的会话列表</a>
*/
public List<KfSession> 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);
}
/**
* 群发消息
* <p>
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
* 如消息有时会进行审核服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
* </p>
*
* @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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
* @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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByGroupId(List<MpArticle> articles, int groupId)
@ -429,19 +691,24 @@ public class WeixinProxy {
/**
* openId群发
*
* <p>
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
* 如消息有时会进行审核服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
* </p>
*
* @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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8D.E5.8F.AF.E7.94.A8.EF.BC.8C.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.8F.AF.E7.94.A8.E3.80.91">根据openid群发</a>
* @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)}
@ -463,6 +730,7 @@ public class WeixinProxy {
* @see <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8D.E5.8F.AF.E7.94.A8.EF.BC.8C.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.8F.AF.E7.94.A8.E3.80.91">根据openid群发</a>
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Base,String...)}
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByOpenIds(List<MpArticle> articles,
@ -490,8 +758,7 @@ public class WeixinProxy {
}
/**
* 预览群发消息<br/>
* 开发者可通过该接口发送消息给指定用户在手机端查看消息的样式和排版
* 预览群发消息</br> 开发者可通过该接口发送消息给指定用户在手机端查看消息的样式和排版
*
* @param openId
* 接收用户的ID

View File

@ -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();
}
/**
* 创建会话
* <p>
* 开发者可以使用本接口为多客服的客服工号创建会话将某个客户直接指定给客服工号接待需要注意此接口不会受客服自动接入数以及自动接入开关限制
* 只能为在线的客服PC客户端在线或者已绑定多客服助手创建会话
* </p>
*
* @param userOpenId
* 用户的userOpenId
* @param kfAccount
* 完整客服账号格式为账号前缀@公众号微信号
* @param text
* 附加信息文本会展示在客服人员的多客服客户端
* @return 处理结果
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E5.88.9B.E5.BB.BA.E4.BC.9A.E8.AF.9D">创建会话</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E5.85.B3.E9.97.AD.E4.BC.9A.E8.AF.9D">创建会话</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E5.AE.A2.E6.88.B7.E7.9A.84.E4.BC.9A.E8.AF.9D.E7.8A.B6.E6.80.81">获取会话状态</a>
*/
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<KfSession>() {
});
session.setUserOpenId(userOpenId);
return session;
}
/**
* 获取客服的会话列表:获取某个客服正在接待的会话列表
*
* @param kfAccount
* 完整客服账号格式为账号前缀@公众号微信号账号前缀最多10个字符必须是英文或者数字字符
* @return 会话列表
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E5.AE.A2.E6.9C.8D.E7.9A.84.E4.BC.9A.E8.AF.9D.E5.88.97.E8.A1.A8">获取客服的会话列表</a>
*/
public List<KfSession> 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<KfSession> sessionList = JSON.parseArray(response.getAsJson()
.getString("sessionlist"), KfSession.class);
return sessionList;
}
/**
* 获取未接入会话列表:获取当前正在等待队列中的会话列表此接口最多返回最早进入队列的100个未接入会话</br>
* <font color="red">缺陷没有count字段</font>
* @return 会话列表
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.KfSession
* @see <a
* href="http://mp.weixin.qq.com/wiki/2/6c20f3e323bdf5986cfcb33cbd3b829a.html#.E8.8E.B7.E5.8F.96.E6.9C.AA.E6.8E.A5.E5.85.A5.E4.BC.9A.E8.AF.9D.E5.88.97.E8.A1.A8">获取客服的会话列表</a>
*/
public List<KfSession> 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<KfSession> sessionList = JSON.parseArray(response.getAsJson()
.getString("waitcaselist"), KfSession.class);
return sessionList;
}
}

View File

@ -16,8 +16,8 @@ import com.foxinmy.weixin4j.util.DateUtil;
/**
* 数据分析API
* <p>
* 1接口侧的公众号数据的数据库中仅存储了2014年12月1日之后的数据将查询不到在此之前的日期即使有查到也是不可信的脏数据<br/>
* 2请开发者在调用接口获取数据后将数据保存在自身数据库中即加快下次用户的访问速度也降低了微信侧接口调用的不必要损耗<br/>
* 1接口侧的公众号数据的数据库中仅存储了2014年12月1日之后的数据将查询不到在此之前的日期即使有查到也是不可信的脏数据</br>
* 2请开发者在调用接口获取数据后将数据保存在自身数据库中即加快下次用户的访问速度也降低了微信侧接口调用的不必要损耗</br>
* </p>
*
* @className DataApi

View File

@ -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);
}
/**
* 群发消息
* <p>
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
* 如消息有时会进行审核服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
* </p>
*
* @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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
* @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<MpArticle> _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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroupId(Base,int)}
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByGroupId(List<MpArticle> 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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8D.E5.8F.AF.E7.94.A8.EF.BC.8C.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.8F.AF.E7.94.A8.E3.80.91">根据openid群发</a>
* @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<MpArticle> _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 <a
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AEOpenID.E5.88.97.E8.A1.A8.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8D.E5.8F.AF.E7.94.A8.EF.BC.8C.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.8F.AF.E7.94.A8.E3.80.91">根据openid群发</a>
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Base,String...)}
* @see com.foxinmy.weixin4j.msg.model.MpArticle
* @throws WeixinException
*/
public String massArticleByOpenIds(List<MpArticle> articles,
@ -250,8 +276,7 @@ public class MassApi extends MpApi {
}
/**
* 预览群发消息<br/>
* 开发者可通过该接口发送消息给指定用户在手机端查看消息的样式和排版
* 预览群发消息</br> 开发者可通过该接口发送消息给指定用户在手机端查看消息的样式和排版
*
* @param openId
* 接收用户的ID

View File

@ -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 <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传多媒体文件</a>
* @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);
}
/**
* 上传媒体文件
* 上传媒体文件</br> <font color="red">此接口只包含图片语音缩略图三种媒体类型的上传</font>
*
* @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);
}
/**
* 上传媒体文件
* 上传媒体文件 </br> <font color="red">此接口只包含图片语音缩略图视频(临时)四种媒体类型的上传</font>
* <p>
* 正常情况下返回{"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 <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传下载说明</a>
* href="http://mp.weixin.qq.com/wiki/5/963fc70b80dc75483a271298a76a8d59.html">上传临时素材</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html">上传永久素材</a>
* @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");
}
/**
* 下载媒体文件
* 下载媒体素材
* <p>
* 正常情况下返回表头如Content-Type: image/jpeg,否则抛出异常.
* </p>
@ -113,32 +155,38 @@ public class MediaApi extends MpApi {
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param mediaType
* 媒体类型
* 媒体文件类型分别有图片image语音voice视频video和缩略图thumb
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传下载说明</a>
* href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体文件</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html">下载永久媒体素材</a>
* @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 <a
* href="http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html">上传下载说明</a>
* href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体素材</a>
* @see <a
* href="http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html">下载永久媒体素材</a>
*/
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();
}
/**
* 上传永久图文素材
* <p>
* 新增的永久素材也可以在公众平台官网素材管理模块中看到,永久素材的数量是有上限的请谨慎新增图文消息素材和图片素材的上限为5000
* 其他类型为1000
* </P>
*
* @param articles
* 图文列表
* @return 上传到微信服务器返回的媒体标识
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html">上传永久媒体素材</a>
* @see com.foxinmy.weixin4j.msg.model.MpArticle
*/
public String uploadMaterialArticle(List<MpArticle> 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 <a href=
* "http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html">下载永久媒体素材</a>
* @see com.foxinmy.weixin4j.msg.model.MpArticle
*/
public List<MpArticle> 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 <a
* href="http://mp.weixin.qq.com/wiki/4/19a59cba020d506e767360ca1be29450.html">更新永久图文素材</a>
*/
public JsonResult updateMaterialArticle(String mediaId, int index,
List<MpArticle> 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 <a
* href="http://mp.weixin.qq.com/wiki/5/e66f61c303db51a6c0f90f46b15af5f5.html">删除永久媒体素材</a>
*/
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 <a
* href="http://mp.weixin.qq.com/wiki/14/7e6c03263063f4813141c3e17dd4350a.html">上传永久媒体素材</a>
* @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");
}
}
/**
* 获取永久媒体素材的总数</br> .图片和图文消息素材包括单图文和多图文的总数上限为5000其他素材的总数上限为1000
*
* @return 总数对象
* @throws WeixinException
* @see com.foxinmy.weixin4j.mp.model.MediaCounter
* @see <a
* href="http://mp.weixin.qq.com/wiki/16/8cc64f8c189674b421bee3ed403993b8.html">获取素材总数</a>
*/
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<MediaCounter>() {
});
}
/**
* 获取媒体素材记录列表
*
* @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 <a
* href="http://mp.weixin.qq.com/wiki/12/2108cd7aafff7f388f41f37efa710204.html">获取素材列表</a>
*/
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>() {
});
}
mediaRecord.setMediaType(mediaType);
return mediaRecord;
}
}

View File

@ -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&timestam
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
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

View File

@ -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 + "]";
}
}

View File

@ -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 + "]";
}
}

View File

@ -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<MpArticle> 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<MpArticle> getArticles() {
return articles;
}
public void setArticles(List<MpArticle> articles) {
this.articles = articles;
}
@Override
public String toString() {
return "MediaItem [mediaId=" + mediaId + ", name=" + name
+ ", updateTime=" + updateTime + ", articles=" + articles + "]";
}
}

View File

@ -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<MediaItem> 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<MediaItem> getItems() {
return items;
}
public void setItems(List<MediaItem> items) {
this.items = items;
}
@Override
public String toString() {
return "MediaRecord [totalCount=" + totalCount + ", itemCount="
+ itemCount + ", mediaType=" + mediaType + ", items=" + items
+ "]";
}
}

View File

@ -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<MpArticle> articles = new ArrayList<MpArticle>();
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<MpArticle> 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<MpArticle> articles = new ArrayList<MpArticle>();
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);
}
}

View File

@ -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<KfSession> sessionList = customApi.getSessionList("kfAccount");
System.err.println(sessionList);
}
@Test
public void getSessionWaitList() throws WeixinException {
List<KfSession> sessionList = customApi.getSessionWaitList();
System.err.println(sessionList);
}
}

View File

@ -44,7 +44,7 @@ public class MassMsgTest extends TokenTest {
public void uploadArticle() throws IOException, WeixinException {
List<MpArticle> articles = new ArrayList<MpArticle>();
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<MpArticle> articles = new ArrayList<MpArticle>();
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<MpArticle> articles = new ArrayList<MpArticle>();
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");

View File

@ -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);

View File

@ -15,4 +15,4 @@
<module>weixin4j-qy-api</module>
<module>weixin4j-qy-server</module>
</modules>
</project>
</project>