diff --git a/CHANGE.md b/CHANGE.md index f5b042d8..a70bda70 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -375,4 +375,10 @@ * 2015-07-23 - + 微信支付新增授权码查询OPENID接口 \ No newline at end of file + + 微信支付新增授权码查询OPENID接口 + +* 2015-07-25 + + + 精简函数上的@link注释 + + + 新增媒体文件上传、下载结果类([MediaUploadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java),[MediaDownloadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java)) \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java index 21ce6a23..4865f2ab 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/api/Pay3Api.java @@ -178,7 +178,7 @@ public class Pay3Api { * 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY * @param opUserId * 操作员帐号, 默认为商户号 - * @see {@link com.foxinmy.weixin4j.api.Pay3Api#refundApply(InputStream, IdQuery, String, double, double, String, Map)} + * @see {@link #refundApply(InputStream, IdQuery, String, double, double, String, Map)} */ public RefundResult refundApply(InputStream ca, IdQuery idQuery, String outRefundNo, double totalFee, double refundFee, diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java new file mode 100644 index 00000000..c27a56d7 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java @@ -0,0 +1,58 @@ +package com.foxinmy.weixin4j.model; + +import java.io.Serializable; +import java.util.Arrays; + +import com.foxinmy.weixin4j.http.ContentType; + +/** + * 媒体文件下载结果 + * + * @className MediaDownloadResult + * @author jy + * @date 2015年7月25日 + * @since JDK 1.7 + * @see + */ +public class MediaDownloadResult implements Serializable { + + private static final long serialVersionUID = -7090523911701729058L; + /** + * 内容 + */ + private byte[] content; + /** + * 类型 + */ + private ContentType contentType; + /** + * 文件名 + */ + private String fileName; + + public byte[] getContent() { + return content; + } + + public ContentType getContentType() { + return contentType; + } + + public String getFileName() { + return fileName; + } + + public MediaDownloadResult(byte[] content, ContentType contentType, + String fileName) { + this.content = content; + this.contentType = contentType; + this.fileName = fileName; + } + + @Override + public String toString() { + return "MediaDownloadResult [content=" + Arrays.toString(content) + + ", contentType=" + contentType + ", fileName=" + fileName + + "]"; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java new file mode 100644 index 00000000..855cbf82 --- /dev/null +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java @@ -0,0 +1,52 @@ +package com.foxinmy.weixin4j.model; + +import java.io.Serializable; +import java.util.Date; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.type.MediaType; + +/** + * 媒体文件上传结果 + * + * @className MediaUploadResult + * @author jy + * @date 2015年7月25日 + * @since JDK 1.7 + * @see + */ +public class MediaUploadResult implements Serializable { + + private static final long serialVersionUID = -620630472640999536L; + private String mediaId; + private MediaType mediaType; + private Date createdAt; + + @JSONCreator + public MediaUploadResult(@JSONField(name = "media_id") String mediaId, + @JSONField(name = "type") MediaType mediaType, + @JSONField(name = "created_at") Date createdAt) { + this.mediaId = mediaId; + this.mediaType = mediaType; + this.createdAt = createdAt; + } + + public String getMediaId() { + return mediaId; + } + + public MediaType getMediaType() { + return mediaType; + } + + public Date getCreatedAt() { + return createdAt; + } + + @Override + public String toString() { + return "MediaUploadResult [mediaId=" + mediaId + ", mediaType=" + mediaType + + ", createdAt=" + createdAt + "]"; + } +} diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java index a7f2b15d..df7dd43c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java @@ -267,7 +267,7 @@ public class PayUtil { * @param weixinAccount * 商户信息 * @return 支付的订单信息 - * @see {@link com.foxinmy.weixin4j.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinPayAccount)} + * @see {@link #createMicroPay(MicroPayPackage, WeixinPayAccount)} * @throws WeixinException */ public static Order createMicroPay(String authCode, String body, diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java index 37ed0e74..cff65784 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/WeixinPayProxy.java @@ -146,7 +146,7 @@ public class WeixinPayProxy { * * @throws IOException * - * @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#refund(InputStream, IdQuery, String, double, double,CurrencyType, String)} + * @see {@link #refundApply(InputStream, IdQuery, String, double, double,CurrencyType, String)} */ public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply( IdQuery idQuery, String outRefundNo, double totalFee, @@ -233,7 +233,7 @@ public class WeixinPayProxy { * @param idQuery * transaction_id、out_trade_no 二选一 * @return 撤销结果 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#reverse(InputStream, IdQuery)} + * @see {@link #reverseOrder(InputStream, IdQuery)} * @throws WeixinException * @throws IOException */ diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/FileUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/FileUtil.java index 85bf591e..4ff2327c 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/FileUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/FileUtil.java @@ -124,4 +124,22 @@ public class FileUtil { } return fileType; } + + /** + * 获取文件后缀 + * + * @param fileName + * @return + */ + public static String getFileExtension(String fileName) { + int extensionPos = fileName.lastIndexOf("."); + if (extensionPos < 0) { + return ""; + } + int lastUnixPos = fileName.lastIndexOf("/"); + int lastWindowsPos = fileName.lastIndexOf("\\"); + int lastSeparator = Math.max(lastUnixPos, lastWindowsPos); + return lastSeparator > extensionPos ? "" : fileName + .substring(extensionPos + 1); + } } \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java index fc3bf95f..314c41a2 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/util/IOUtil.java @@ -68,16 +68,4 @@ public class IOUtil { } return count; } - - public static String getExtension(String filename) { - int extensionPos = filename.lastIndexOf("."); - if (extensionPos < 0) { - return ""; - } - int lastUnixPos = filename.lastIndexOf("/"); - int lastWindowsPos = filename.lastIndexOf("\\"); - int lastSeparator = Math.max(lastUnixPos, lastWindowsPos); - return lastSeparator > extensionPos ? "" : filename - .substring(extensionPos + 1); - } } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java index 18b6bb22..88d6d97c 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java @@ -10,8 +10,10 @@ import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.JsonResult; import com.foxinmy.weixin4j.model.Button; import com.foxinmy.weixin4j.model.MediaCounter; +import com.foxinmy.weixin4j.model.MediaDownloadResult; import com.foxinmy.weixin4j.model.MediaItem; import com.foxinmy.weixin4j.model.MediaRecord; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.mp.api.CustomApi; import com.foxinmy.weixin4j.mp.api.DataApi; import com.foxinmy.weixin4j.mp.api.GroupApi; @@ -143,13 +145,14 @@ public class WeixinProxy { * href="http://mp.weixin.qq.com/wiki/5/963fc70b80dc75483a271298a76a8d59.html">上传临时素材 * @see 上传永久素材 + * @see com.foxinmy.weixin4j.model.MediaUploadResult * @see com.foxinmy.weixin4j.type.MediaType * @see com.com.foxinmy.weixin4j.mp.api.MediaApi * @throws WeixinException */ - public String uploadMedia(InputStream is, String fileName, - boolean isMaterial) throws WeixinException { - return mediaApi.uploadMedia(is, fileName, isMaterial); + public MediaUploadResult uploadMedia(boolean isMaterial, InputStream is, + String fileName) throws WeixinException { + return mediaApi.uploadMedia(isMaterial, is, fileName); } /** @@ -169,7 +172,7 @@ public class WeixinProxy { * @see 上传下载说明 * @see com.com.foxinmy.weixin4j.mp.api.MediaApi - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#downloadMedia(String)} + * @see {@link #downloadMedia(String)} */ public File downloadMediaFile(String mediaId, boolean isMaterial) throws WeixinException { @@ -183,13 +186,14 @@ public class WeixinProxy { * 媒体ID * @param isMaterial * 是否永久素材 - * @return 二进制数据包 + * @return 媒体文件下载结果 * @throws WeixinException * @see com.com.foxinmy.weixin4j.mp.api.MediaApi + * @see com.foxinmy.weixin4j.model.MediaDownloadResult * @see 上传下载说明 */ - public byte[] downloadMedia(String mediaId, boolean isMaterial) + public MediaDownloadResult downloadMedia(String mediaId, boolean isMaterial) throws WeixinException { return mediaApi.downloadMedia(mediaId, isMaterial); } @@ -222,8 +226,7 @@ public class WeixinProxy { * 媒体ID * @return 图文列表 * @throws WeixinException - * @see 下载永久媒体素材 + * @see {@link #downloadMedia(String, boolean)} * @see com.foxinmy.weixin4j.tuple.MpArticle * @see com.com.foxinmy.weixin4j.mp.api.MediaApi */ @@ -333,7 +336,7 @@ public class WeixinProxy { * 媒体类型 * @return 素材列表 * @see com.com.foxinmy.weixin4j.mp.api.MediaApi - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#listMaterialMedia(MediaType, int, int)} + * @see {@link #listMaterialMedia(MediaType, int, int)} * @throws WeixinException */ public List listAllMaterialMedia(MediaType mediaType) @@ -347,7 +350,7 @@ public class WeixinProxy { * @param notify * 客服消息对象 * @return 处理结果 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#sendNotify(NotifyMessage,String) } + * @see {@link #sendNotify(NotifyMessage,String) } * @throws WeixinException */ public JsonResult sendNotify(NotifyMessage notify) throws WeixinException { @@ -646,7 +649,7 @@ public class WeixinProxy { * @param groupId * 分组ID * @return 群发后的消息ID - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massMessage(MassTuple,boolean,int)} + * @see {@link #massMessage(MassTuple,boolean,int)} * @throws WeixinException */ public String massByGroupId(MassTuple tuple, int groupId) @@ -695,7 +698,7 @@ public class WeixinProxy { * @param groupId * 分组ID * @return 群发后的消息ID - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Tuple,int)} + * @see {@link #massByGroupId(Tuple,int)} * @see 根据分组群发 * @see com.foxinmy.weixin4j.tuple.MpArticle @@ -748,7 +751,7 @@ public class WeixinProxy { * @return 群发后的消息ID * @see 根据openid群发 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Tuple,String...)} + * @see {@link #massByOpenIds(Tuple,String...)} * @see com.foxinmy.weixin4j.tuple.MpArticle * @throws WeixinException */ @@ -769,8 +772,8 @@ public class WeixinProxy { * @see 删除群发 * @see com.foxinmy.weixin4j.mp.api.MassApi - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByGroupId(Tuple, int)} - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#massByOpenIds(Tuple, String...) + * @see {@link #massByGroupId(Tuple, int)} + * @see {@link #massByOpenIds(Tuple, String...) */ public JsonResult deleteMassNews(String msgid) throws WeixinException { return massApi.deleteMassNews(msgid); @@ -824,7 +827,7 @@ public class WeixinProxy { * href="http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html">获取用户信息 * @see com.foxinmy.weixin4j.mp.model.User * @see com.foxinmy.weixin4j.mp.api.UserApi - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getUser(String,Lang)} + * @see {@link #getUser(String,Lang)} */ public User getUser(String openId) throws WeixinException { return userApi.getUser(openId); @@ -882,7 +885,7 @@ public class WeixinProxy { * href="http://mp.weixin.qq.com/wiki/3/17e6919a39c1c53555185907acf70093.html">获取关注者列表 * @see com.foxinmy.weixin4j.mp.model.Following * @see com.foxinmy.weixin4j.mp.api.UserApi - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getFollowing(String)} + * @see {@link #getFollowing(String)} */ public List getAllFollowing() throws WeixinException { return userApi.getAllFollowing(); @@ -1085,7 +1088,7 @@ public class WeixinProxy { * * @return 二维码图片解析后的地址 开发者可根据该地址自行生成需要的二维码图片 * @throws WeixinException - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getQRData(QRParameter)} + * @see {@link #getQRData(QRParameter)} */ public String getQRUrl(QRParameter parameter) throws WeixinException { return qrApi.getQRUrl(parameter); @@ -1096,7 +1099,7 @@ public class WeixinProxy { * * @return 硬盘存储的文件对象 * @throws WeixinException - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getQRData(QRParameter)} + * @see {@link #getQRData(QRParameter)} */ public File getQRFile(QRParameter parameter) throws WeixinException { return qrApi.getQRFile(parameter); @@ -1202,7 +1205,7 @@ public class WeixinProxy { * 而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。 * * @return 菜单集合 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#getMenu()} + * @see {@link #getMenu()} * @see 获取自定义菜单配置 * @see com.foxinmy.weixin4j.model.Button @@ -1271,7 +1274,7 @@ public class WeixinProxy { * 开始日期 * @param offset * 增量 表示向前几天 比如 offset=1 则查询 beginDate的后一天之间的数据 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @see com.foxinmy.weixin4j.mp.api.DataApi * @throws WeixinException */ @@ -1289,7 +1292,7 @@ public class WeixinProxy { * 增量 表示向后几天 比如 offset=1 则查询 beginDate的前一天之间的数据 * @param endDate * 截至日期 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @see com.foxinmy.weixin4j.mp.api.DataApi * @throws WeixinException */ @@ -1305,7 +1308,7 @@ public class WeixinProxy { * 统计类型 * @param date * 统计日期 - * @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @see com.foxinmy.weixin4j.mp.api.DataApi * @throws WeixinException */ diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java index 9b31e013..8587a1bc 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/DataApi.java @@ -42,7 +42,7 @@ public class DataApi extends MpApi { * 开始日期 * @param offset * 增量 表示向前几天 比如 offset=1 则查询 beginDate的后一天之间的数据 - * @see {@link com.foxinmy.weixin4j.mp.api.DataApi#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @throws WeixinException */ public List datacube(DatacubeType datacubeType, Date beginDate, @@ -62,7 +62,7 @@ public class DataApi extends MpApi { * 增量 表示向后几天 比如 offset=1 则查询 beginDate的前一天之间的数据 * @param endDate * 截至日期 - * @see {@link com.foxinmy.weixin4j.mp.api.DataApi#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @throws WeixinException */ public List datacube(DatacubeType datacubeType, int offset, Date endDate) @@ -80,7 +80,7 @@ public class DataApi extends MpApi { * 统计类型 * @param date * 统计日期 - * @see {@link com.foxinmy.weixin4j.mp.api.DataApi#datacube(DatacubeType, Date,Date)} + * @see {@link #datacube(DatacubeType, Date,Date)} * @throws WeixinException */ public List datacube(DatacubeType datacubeType, Date date) diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java index b7dea7ff..6181b4f9 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/HelperApi.java @@ -104,7 +104,7 @@ public class HelperApi extends MpApi { * 而如果公众号是在公众平台官网通过网站功能发布菜单,则本接口返回运营者设置的菜单配置。 * * @return 菜单集合 - * @see {@link com.foxinmy.weixin4j.mp.api.MenuApi#getMenu()} + * @see {@link MenuApi#getMenu()} * @see 获取自定义菜单配置 * @see com.foxinmy.weixin4j.model.Button diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java index da1665e3..afa5518d 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MassApi.java @@ -1,6 +1,5 @@ package com.foxinmy.weixin4j.mp.api; -import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -73,7 +72,6 @@ public class MassApi extends MpApi { * href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html">高级群发 * @see com.foxinmy.weixin4j.tuple.Video * @see com.foxinmy.weixin4j.tuple.MpVideo - * @see {@link com.com.foxinmy.weixin4j.mp.api.MediaApi#uploadMedia(File)} */ public String uploadVideo(Video video) throws WeixinException { String video_upload_uri = getRequestUri("video_upload_uri"); @@ -124,7 +122,7 @@ public class MassApi extends MpApi { * @see com.foxinmy.weixin4j.tuple.MpVideo * @see com.foxinmy.weixin4j.tuple.MpNews * @see com.foxinmy.weixin4j.tuple.MassTuple - * @see {@link com.foxinmy.weixin4j.mp.api.GroupApi#getGroups()} + * @see {@link GroupApi#getGroups()} * @see 根据分组群发 */ @@ -170,7 +168,7 @@ public class MassApi extends MpApi { * @return 群发后的消息ID * @see 根据分组群发 - * @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroupId(Tuple,int)} + * @see {@link #massByGroupId(Tuple,int)} * @see com.foxinmy.weixin4j.tuple.MpArticle * @throws WeixinException */ @@ -198,7 +196,7 @@ public class MassApi extends MpApi { * @see com.foxinmy.weixin4j.tuple.MassTuple * @see 根据openid群发 - * @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String)} + * @see {@link UserApi#getUser(String)} */ public String massByOpenIds(MassTuple tuple, String... openIds) throws WeixinException { @@ -236,7 +234,7 @@ public class MassApi extends MpApi { * @return 群发后的消息ID * @see 根据openid群发 - * @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Tuple,String...)} + * @see {@link #massByOpenIds(Tuple,String...)} * @see com.foxinmy.weixin4j.tuple.MpArticle * @throws WeixinException */ @@ -257,8 +255,8 @@ public class MassApi extends MpApi { * @throws WeixinException * @see 删除群发 - * @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByGroupId(Tuple, int)} - * @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massByOpenIds(Tuple, String...) + * @see {@link #massByGroupId(Tuple, int)} + * @see {@link #massByOpenIds(Tuple, String...) */ public JsonResult deleteMassNews(String msgid) throws WeixinException { JSONObject obj = new JSONObject(); @@ -311,7 +309,6 @@ public class MassApi extends MpApi { * 消息ID * @return 消息发送状态,如sendsuccess:发送成功、sendfail:发送失败 * @throws WeixinException - * @see {@link com.foxinmy.weixin4j.mp.event.MassEventMessage#getStatusDesc(String)} * @see 查询群发状态 */ diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java index a9ae952d..fe36a8c4 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/MediaApi.java @@ -3,11 +3,13 @@ package com.foxinmy.weixin4j.mp.api; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; +import java.util.Date; import java.util.List; import com.alibaba.fastjson.JSON; @@ -15,9 +17,13 @@ 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.ContentType; +import com.foxinmy.weixin4j.http.Header; import com.foxinmy.weixin4j.http.HttpGet; import com.foxinmy.weixin4j.http.HttpPost; +import com.foxinmy.weixin4j.http.HttpResponse; import com.foxinmy.weixin4j.http.apache.FormBodyPart; +import com.foxinmy.weixin4j.http.apache.HttpHeaders; import com.foxinmy.weixin4j.http.apache.InputStreamBody; import com.foxinmy.weixin4j.http.apache.StringBody; import com.foxinmy.weixin4j.http.entity.StringEntity; @@ -25,13 +31,16 @@ import com.foxinmy.weixin4j.http.weixin.JsonResult; import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.MediaCounter; +import com.foxinmy.weixin4j.model.MediaDownloadResult; import com.foxinmy.weixin4j.model.MediaItem; import com.foxinmy.weixin4j.model.MediaRecord; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.token.TokenHolder; import com.foxinmy.weixin4j.tuple.MpArticle; import com.foxinmy.weixin4j.type.MediaType; import com.foxinmy.weixin4j.util.ConfigUtil; +import com.foxinmy.weixin4j.util.ErrorUtil; import com.foxinmy.weixin4j.util.FileUtil; import com.foxinmy.weixin4j.util.IOUtil; import com.foxinmy.weixin4j.util.ObjectId; @@ -63,22 +72,23 @@ public class MediaApi extends MpApi { * 否则抛出异常. *

* + * @param isMaterial + * 是否永久上传 * @param is * 媒体数据流 * @param fileName * 文件名 - * @param isMaterial - * 是否永久上传 * @return 上传到微信服务器返回的媒体标识 * @see 上传临时素材 * @see 上传永久素材 + * @see com.foxinmy.weixin4j.model.MediaUploadResult * @see com.foxinmy.weixin4j.type.MediaType * @throws WeixinException */ - public String uploadMedia(InputStream is, String fileName, - boolean isMaterial) throws WeixinException { + public MediaUploadResult uploadMedia(boolean isMaterial, InputStream is, + String fileName) throws WeixinException { byte[] content; try { content = IOUtil.toByteArray(is); @@ -88,18 +98,21 @@ public class MediaApi extends MpApi { if (StringUtil.isBlank(fileName)) { fileName = ObjectId.get().toHexString(); } - String suffixName = IOUtil.getExtension(fileName); + String suffixName = FileUtil.getFileExtension(fileName); if (StringUtil.isBlank(suffixName)) { suffixName = FileUtil .getFileType(new ByteArrayInputStream(content)); fileName = String.format("%s.%s", fileName, suffixName); } - MediaType mediaType = null; - if ("bmp/png/jpeg/jpg/gif".contains(suffixName)) { + MediaType mediaType; + if (",bmp,png,jpeg,jpg,gif," + .contains(String.format(",%s,", suffixName))) { mediaType = MediaType.image; - } else if ("mp3/wma/wav/amr".contains(suffixName)) { + } else if (",mp3,wma,wav,amr,".contains(String.format(",%s,", + suffixName))) { mediaType = MediaType.voice; - } else if ("rm/rmvb/wmv/avi/mpg/mpeg/mp4".equals(suffixName)) { + } else if (",rm,rmvb,wmv,avi,mpg,mpeg,mp4,".contains(String.format( + ",%s,", suffixName))) { mediaType = MediaType.video; } else { throw new WeixinException("cannot handle mediaType:" + suffixName); @@ -120,6 +133,8 @@ public class MediaApi extends MpApi { .getContentType().getMimeType(), fileName)), new FormBodyPart("type", new StringBody(mediaType.name(), Consts.UTF_8))); + return new MediaUploadResult(response.getAsJson().getString( + "media_id"), mediaType, new Date()); } else { String media_upload_uri = getRequestUri("media_upload_uri"); response = weixinClient.post(String.format(media_upload_uri, @@ -127,6 +142,14 @@ public class MediaApi extends MpApi { new FormBodyPart("media", new InputStreamBody(is, mediaType.getContentType().getMimeType(), fileName))); + JSONObject obj = response.getAsJson(); + return new MediaUploadResult(obj.getString("media_id"), + obj.getObject("type", MediaType.class), new Date( + obj.getLong("created_at") * 1000l)); + /* + * return response.getAsObject(new TypeReference() + * { }); + */ } } catch (UnsupportedEncodingException e) { throw new WeixinException(e); @@ -137,7 +160,6 @@ public class MediaApi extends MpApi { ; } } - return response.getAsJson().getString("media_id"); } /** @@ -154,22 +176,29 @@ public class MediaApi extends MpApi { * href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体文件 * @see 下载永久媒体素材 - * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#downloadMedia(String,boolean)} + * @see {@link #downloadMedia(String,boolean)} */ public File downloadMediaFile(String mediaId, boolean isMaterial) throws WeixinException { String media_path = ConfigUtil.getValue("media_path", Weixin4jConst.DEFAULT_MEDIA_PATH); - File file = new File(media_path + File.separator + mediaId); - if (file.exists()) { - return file; + final String prefixName = String.format("%s.", mediaId); + File[] files = new File(media_path).listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(prefixName); + } + }); + if (files.length > 0) { + return files[0]; } - byte[] datas = downloadMedia(mediaId, isMaterial); + MediaDownloadResult result = downloadMedia(mediaId, isMaterial); + File file = new File(media_path + File.separator + result.getFileName()); OutputStream os = null; try { if (file.createNewFile()) { os = new FileOutputStream(file); - os.write(datas); + os.write(result.getContent()); } else { throw new WeixinException(String.format("create file fail:%s", file.getAbsolutePath())); @@ -195,30 +224,57 @@ public class MediaApi extends MpApi { * 媒体ID * @param isMaterial * 是否下载永久素材 - * @return 二进制数据包(需自行判断类型) + * @return 媒体下载结果 + * * @throws WeixinException + * @see com.foxinmy.weixin4j.model.MediaDownloadResult * @see 下载临时媒体素材 * @see 下载永久媒体素材 */ - public byte[] downloadMedia(String mediaId, boolean isMaterial) + public MediaDownloadResult downloadMedia(String mediaId, boolean isMaterial) throws WeixinException { Token token = tokenHolder.getToken(); try { + HttpResponse response = null; if (isMaterial) { String material_media_download_uri = getRequestUri("material_media_download_uri"); HttpPost method = new HttpPost(String.format( material_media_download_uri, token.getAccessToken())); method.setEntity(new StringEntity(String.format( "{\"media_id\":\"%s\"}", mediaId))); - return weixinClient.execute(method).getContent(); + response = weixinClient.execute(method); } else { String meida_download_uri = getRequestUri("meida_download_uri"); HttpGet method = new HttpGet(String.format(meida_download_uri, token.getAccessToken(), mediaId)); - return weixinClient.execute(method).getContent(); + response = weixinClient.execute(method); } + byte[] content = response.getContent(); + Header contentType = response + .getFirstHeader(HttpHeaders.CONTENT_TYPE); + Header disposition = response.getFirstHeader("Content-disposition"); + if (contentType.getValue().contains( + ContentType.APPLICATION_JSON.getMimeType()) + || (disposition != null && disposition.getValue().indexOf( + ".json") > 0)) { + JsonResult jsonResult = JSON.parseObject(content, 0, + content.length, Consts.UTF_8.newDecoder(), + JsonResult.class); + if (jsonResult.getCode() != 0) { + if (StringUtil.isBlank(jsonResult.getDesc())) { + jsonResult.setDesc(ErrorUtil.getText(Integer + .toString(jsonResult.getCode()))); + } + throw new WeixinException(Integer.toString(jsonResult + .getCode()), jsonResult.getDesc()); + } + } + String fileName = String.format("%s.%s", mediaId, contentType + .getValue().split("/")[1]); + return new MediaDownloadResult(content, + ContentType.create(contentType.getValue()), fileName); } catch (IOException e) { throw new WeixinException(e); } @@ -259,14 +315,14 @@ public class MediaApi extends MpApi { * 媒体ID * @return 图文列表 * @throws WeixinException - * @see 下载永久媒体素材 + * @see {@link #downloadMedia(String, boolean)} * @see com.foxinmy.weixin4j.tuple.MpArticle */ public List downloadArticle(String mediaId) throws WeixinException { - byte[] bytes = downloadMedia(mediaId, true); - JSONObject obj = JSON.parseObject(bytes, 0, bytes.length, + MediaDownloadResult result = downloadMedia(mediaId, true); + byte[] content = result.getContent(); + JSONObject obj = JSON.parseObject(content, 0, content.length, Consts.UTF_8.newDecoder(), JSONObject.class); return JSON.parseArray(obj.getString("news_item"), MpArticle.class); } @@ -447,7 +503,7 @@ public class MediaApi extends MpApi { * @param mediaType * 媒体类型 * @return 素材列表 - * @see {@link com.foxinmy.weixin4j.mp.api.MediaApi#listMaterialMedia(MediaType, int, int)} + * @see {@link #listMaterialMedia(MediaType, int, int)} * @throws WeixinException */ public List listAllMaterialMedia(MediaType mediaType) diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java index c002a14b..6be16a98 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/NotifyApi.java @@ -35,7 +35,7 @@ public class NotifyApi extends MpApi { * @param notify * 客服消息对象 * @return 处理结果 - * @see {@link com.foxinmy.weixin4j.mp.api.NotifyApi#sendNotify(NotifyMessage, String)} + * @see {@link #sendNotify(NotifyMessage, String)} * @throws WeixinException */ public JsonResult sendNotify(NotifyMessage notify) throws WeixinException { diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java index 052bba93..f018893d 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java @@ -26,7 +26,7 @@ import com.foxinmy.weixin4j.util.StringUtil; public class OauthApi extends MpApi { /** - * @see {@link com.foxinmy.weixin4j.mp.api.OauthApi#getAuthorizeURL(String, String,String)} + * @see {@link #getAuthorizeURL(String, String,String)} * * @return 请求授权的URL */ @@ -61,7 +61,7 @@ public class OauthApi extends MpApi { } /** - * @see {@link com.foxinmy.weixin4j.mp.api.OauthApi#getOauthToken(String, String,String)} + * @see {@link #getOauthToken(String, String,String)} * * @return */ @@ -94,7 +94,7 @@ public class OauthApi extends MpApi { } /** - * @see {@link com.foxinmy.weixin4j.mp.api.OauthApi#getOauthToken(String, String,String)} + * @see {@link #getOauthToken(String, String,String)} * * @return */ @@ -154,8 +154,8 @@ public class OauthApi extends MpApi { * href="http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html">授权获取用户信息 * @see com.foxinmy.weixin4j.mp.model.User * @see com.foxinmy.weixin4j.mp.model.OauthToken - * @see {@link com.foxinmy.weixin4j.mp.api.OauthApi#getOauthToken(String)} - * @see {@link com.foxinmy.weixin4j.mp.api.OauthApi#getUser(String,Sring,Lang)} + * @see {@link #getOauthToken(String)} + * @see {@link #getUser(String,Sring,Lang)} */ public User getUser(OauthToken token) throws WeixinException { return getUser(token.getAccessToken(), token.getOpenid(), Lang.zh_CN); diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java index 685826fa..6ef0afc2 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java @@ -269,7 +269,7 @@ public class Pay2Api extends MpApi { * 操作员帐号, 默认为商户号 * @param opUserPasswd * 操作员密码,默认为商户后台登录密码 - * @see {@link com.foxinmy.weixin4j.mp.api.Pay2Api#refundApply(File, IdQuery, String, double, double, String, Map)} + * @see {@link #refundApply(File, IdQuery, String, double, double, String, Map)} */ public RefundResultV2 refundApply(File caFile, IdQuery idQuery, String outRefundNo, double totalFee, double refundFee, @@ -307,7 +307,7 @@ public class Pay2Api extends MpApi { * @param refundType * 为空或者填 1:商户号余额退款;2:现金帐号 退款;3:优先商户号退款,若商户号余额不足, 再做现金帐号退款。使用 2 或 * 3 时,需联系财 付通开通此功能 - * @see {@link com.foxinmy.weixin4j.mp.api.Pay2Api#refundApply(File, IdQuery, String, double, double, String, Map)} + * @see {@link #refundApply(File, IdQuery, String, double, double, String, Map)} * @return 退款结果 */ public RefundResultV2 refundApply(File caFile, IdQuery idQuery, diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/UserApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/UserApi.java index 9acf40ed..c6c40f74 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/UserApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/UserApi.java @@ -42,7 +42,7 @@ public class UserApi extends MpApi { * @see 获取用户信息 * @see com.foxinmy.weixin4j.mp.model.User - * @see {@link com.foxinmy.weixin4j.mp.api.UserApi#getUser(String,Lang)} + * @see {@link #getUser(String,Lang)} */ public User getUser(String openId) throws WeixinException { return getUser(openId, Lang.zh_CN); diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MassTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MassTest.java index ccb19bc8..bb56bbb0 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MassTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MassTest.java @@ -12,6 +12,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.JsonResult; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.mp.api.MassApi; import com.foxinmy.weixin4j.mp.api.MediaApi; import com.foxinmy.weixin4j.tuple.Image; @@ -42,9 +43,9 @@ public class MassTest extends TokenTest { public void uploadArticle() throws IOException, WeixinException { List articles = new ArrayList(); File file = new File("/tmp/test.jpg"); - String thumbMediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), false); - articles.add(new MpArticle(thumbMediaId, "title", "content")); + MediaUploadResult mediaResult = mediaApi.uploadMedia(false, + new FileInputStream(file), file.getName()); + articles.add(new MpArticle(mediaResult.getMediaId(), "title", "content")); massApi.uploadArticle(articles); } @@ -72,9 +73,9 @@ public class MassTest extends TokenTest { public void massArticleByGroup() throws IOException, WeixinException { List articles = new ArrayList(); File file = new File("/tmp/test.jpg"); - String thumbMediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), false); - articles.add(new MpArticle(thumbMediaId, "title", "content")); + MediaUploadResult mediaResult = mediaApi.uploadMedia(false, + new FileInputStream(file), file.getName()); + articles.add(new MpArticle(mediaResult.getMediaId(), "title", "content")); String massId = massApi.massArticleByGroupId(articles, 0); Assert.assertTrue(massId != null); } @@ -83,9 +84,9 @@ public class MassTest extends TokenTest { public void massArticleByOpenIds() throws IOException, WeixinException { List articles = new ArrayList(); File file = new File("/tmp/test.jpg"); - String thumbMediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), false); - articles.add(new MpArticle(thumbMediaId, "title", "content")); + MediaUploadResult mediaResult = mediaApi.uploadMedia(false, + new FileInputStream(file), file.getName()); + articles.add(new MpArticle(mediaResult.getMediaId(), "title", "content")); String massId = massApi.massArticleByOpenIds(articles, "owGBft_vbBbOaQOmpEUE4xDLeRSU"); Assert.assertTrue(massId != null); diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java index 20f9e632..e7ece222 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MediaTest.java @@ -13,8 +13,10 @@ import org.junit.Test; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.JsonResult; import com.foxinmy.weixin4j.model.MediaCounter; +import com.foxinmy.weixin4j.model.MediaDownloadResult; import com.foxinmy.weixin4j.model.MediaItem; import com.foxinmy.weixin4j.model.MediaRecord; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.mp.api.MediaApi; import com.foxinmy.weixin4j.tuple.MpArticle; import com.foxinmy.weixin4j.type.MediaType; @@ -40,8 +42,8 @@ public class MediaTest extends TokenTest { @Test public void upload1() throws IOException, WeixinException { File file = new File("/Users/jy/Downloads/weixin4j.png"); - String mediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), false); + MediaUploadResult mediaId = mediaApi.uploadMedia(false, new FileInputStream( + file), file.getName()); // 1Vgd1R5DdznSc3rPxd-sNZ3pLt54cejhJ5ItuNcCgrqoQArNANWy5oxso_r9KNlE Assert.assertNotNull(mediaId); System.err.println(mediaId); @@ -49,7 +51,7 @@ public class MediaTest extends TokenTest { @Test public void download1() throws WeixinException, IOException { - byte[] content = mediaApi.downloadMedia( + MediaDownloadResult content = mediaApi.downloadMedia( "jM5OWhnYb2DgrNm97HGj8aUdsZcweQc93tnwbH1mERo", true); Assert.assertTrue(content != null); } @@ -57,8 +59,8 @@ public class MediaTest extends TokenTest { @Test public void upload2() throws IOException, WeixinException { File file = new File("/Users/jy/Downloads/test.jpg"); - String mediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), true); + MediaUploadResult mediaId = mediaApi.uploadMedia(true, new FileInputStream( + file), file.getName()); // 8790403529 Assert.assertNotNull(mediaId); System.err.println(mediaId); diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java index 73dcfd9e..53a14683 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/NotifyTest.java @@ -10,6 +10,7 @@ import org.junit.Test; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.JsonResult; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.mp.api.MediaApi; import com.foxinmy.weixin4j.mp.api.NotifyApi; import com.foxinmy.weixin4j.mp.message.NotifyMessage; @@ -91,10 +92,11 @@ public class NotifyTest extends TokenTest { @Test public void send2() throws WeixinException, IOException { File file = new File("/tmp/test.jpg"); - String mediaId = mediaApi.uploadMedia(new FileInputStream(file), - file.getName(), false); + MediaUploadResult mediaResult = mediaApi.uploadMedia(false, + new FileInputStream(file), file.getName()); NotifyMessage imageNotify = new NotifyMessage( - "owGBft_vbBbOaQOmpEUE4xDLeRSU", new Image(mediaId)); + "owGBft_vbBbOaQOmpEUE4xDLeRSU", new Image( + mediaResult.getMediaId())); JsonResult result = notifyApi.sendNotify(imageNotify); Assert.assertEquals(0, result.getCode()); } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java index 8196ff09..39832ab1 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java @@ -9,8 +9,10 @@ import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.JsonResult; import com.foxinmy.weixin4j.model.Button; import com.foxinmy.weixin4j.model.MediaCounter; +import com.foxinmy.weixin4j.model.MediaDownloadResult; import com.foxinmy.weixin4j.model.MediaItem; import com.foxinmy.weixin4j.model.MediaRecord; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.qy.api.AgentApi; import com.foxinmy.weixin4j.qy.api.BatchApi; import com.foxinmy.weixin4j.qy.api.HelperApi; @@ -219,14 +221,15 @@ public class WeixinProxy { * 文件名 * @return 上传到微信服务器返回的媒体标识 * @see com.foxinmy.weixin4j.qy.api.MediaApi + * @see com.foxinmy.weixin4j.model.MediaUploadResult * @see 上传临时素材文件说明 * @see 上传永久素材文件说明 * @throws WeixinException */ - public String uploadMedia(int agentid, InputStream is, String fileName) - throws WeixinException { + public MediaUploadResult uploadMedia(int agentid, InputStream is, + String fileName) throws WeixinException { return mediaApi.uploadMedia(agentid, is, fileName); } @@ -241,7 +244,7 @@ public class WeixinProxy { * @throws WeixinException * @see com.foxinmy.weixin4j.qy.api.MediaApi * @see com.foxinmy.weixin4j.type.MediaType - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#downloadMedia(int,String)} + * @see {@link #downloadMedia(int,String)} */ public File downloadMediaFile(int agentid, String mediaId) throws WeixinException { @@ -255,7 +258,8 @@ public class WeixinProxy { * 企业应用Id(大于0时视为获取永久媒体文件) * @param mediaId * 媒体ID - * @return 二进制数据包(需自行判断类型) + * @return 媒体下载结果 + * @see com.foxinmy.weixin4j.model.MediaDownloadResult * @see com.foxinmy.weixin4j.qy.api.MediaApi * @see 获取临时媒体说明 @@ -263,7 +267,7 @@ public class WeixinProxy { * href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E6%B0%B8%E4%B9%85%E7%B4%A0%E6%9D%90">获取永久媒体说明 * @throws WeixinException */ - public byte[] downloadMedia(int agentid, String mediaId) + public MediaDownloadResult downloadMedia(int agentid, String mediaId) throws WeixinException { return mediaApi.downloadMedia(agentid, mediaId); } @@ -309,6 +313,24 @@ public class WeixinProxy { return mediaApi.deleteMaterialMedia(agentid, mediaId); } + /** + * 下载永久图文素材 + * + * @param agentid + * 企业应用ID + * @param mediaId + * 媒体素材的media_id + * @return 图文列表 + * @throws WeixinException + * @see {@link #downloadMedia(int, String)} + * @see com.foxinmy.weixin4j.qy.api.MediaApi + * @see com.foxinmy.weixin4j.tuple.MpArticle + */ + public List downloadArticle(int agentid, String mediaId) + throws WeixinException { + return mediaApi.downloadArticle(agentid, mediaId); + } + /** * 修改永久图文素材 * @@ -380,7 +402,7 @@ public class WeixinProxy { * 媒体类型 * @return 素材列表 * @see com.foxinmy.weixin4j.qy.api.MediaApi - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#listMaterialMedia(int,MediaType, int, int)} + * @see {@link #listMaterialMedia(int,MediaType, int, int)} * @throws WeixinException */ public List listAllMaterialMedia(int agentid, MediaType mediaType) @@ -458,7 +480,7 @@ public class WeixinProxy { * 部门列表 * @see com.foxinmy.weixin4j.qy.api.MediaApi * @see com.foxinmy.weixin4j.qy.api.BatchApi - * @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#replaceparty(String,Callback)} + * @see {@link #replaceparty(String,Callback)} * @see 批量任务 * @return 上传后的mediaId @@ -563,8 +585,8 @@ public class WeixinProxy { * @see com.foxinmy.weixin4j.qy.model.User * @see com.foxinmy.weixin4j.qy.api.UserApi * @return 成员对象 - * @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#getUser(String)} - * @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#getUserIdByCode(String,int)} + * @see {@link #getUser(String)} + * @see {@link #getUserIdByCode(String,int)} * @see 企业获取code * @see 批量任务 * @return 上传后的mediaId diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java index 41dd4089..32a52375 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/BatchApi.java @@ -75,7 +75,7 @@ public class BatchApi extends QyApi { * @param callback * 接收任务执行结果的回调地址等信息 * @return 异步任务id,最大长度为64字符 - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadUsers(java.util.List)} + * @see {@link MediaApi#batchUploadUsers(java.util.List)} * @see com.foxinmy.weixin4j.qy.model.Callback * @see 批量更新成员 @@ -113,7 +113,7 @@ public class BatchApi extends QyApi { * @param callback * 接收任务执行结果的回调地址等信息 * @return 异步任务id,最大长度为64字符 - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadUsers(java.util.List)} + * @see {@link MediaApi#batchUploadUsers(java.util.List)} * @see com.foxinmy.weixin4j.qy.model.Callback * @see 批量覆盖成员 @@ -138,7 +138,7 @@ public class BatchApi extends QyApi { * @param callback * 接收任务执行结果的回调地址等信息 * @return 异步任务id,最大长度为64字符 - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#batchUploadParties(java.util.List)} + * @see {@link MediaApi#batchUploadParties(java.util.List)} * @see com.foxinmy.weixin4j.qy.model.Callback * @see 批量覆盖部门 diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java index d846bd26..333027d4 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/MediaApi.java @@ -3,11 +3,13 @@ package com.foxinmy.weixin4j.qy.api; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -17,15 +19,21 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.PropertyFilter; import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.ContentType; +import com.foxinmy.weixin4j.http.Header; import com.foxinmy.weixin4j.http.HttpGet; +import com.foxinmy.weixin4j.http.HttpResponse; import com.foxinmy.weixin4j.http.apache.FormBodyPart; +import com.foxinmy.weixin4j.http.apache.HttpHeaders; import com.foxinmy.weixin4j.http.apache.InputStreamBody; import com.foxinmy.weixin4j.http.weixin.JsonResult; import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.model.Consts; import com.foxinmy.weixin4j.model.MediaCounter; +import com.foxinmy.weixin4j.model.MediaDownloadResult; import com.foxinmy.weixin4j.model.MediaItem; import com.foxinmy.weixin4j.model.MediaRecord; +import com.foxinmy.weixin4j.model.MediaUploadResult; import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.qy.model.Callback; import com.foxinmy.weixin4j.qy.model.Party; @@ -34,6 +42,7 @@ import com.foxinmy.weixin4j.token.TokenHolder; import com.foxinmy.weixin4j.tuple.MpArticle; import com.foxinmy.weixin4j.type.MediaType; import com.foxinmy.weixin4j.util.ConfigUtil; +import com.foxinmy.weixin4j.util.ErrorUtil; import com.foxinmy.weixin4j.util.FileUtil; import com.foxinmy.weixin4j.util.IOUtil; import com.foxinmy.weixin4j.util.ObjectId; @@ -60,7 +69,7 @@ public class MediaApi extends QyApi { } /** - * 上传媒体文件 + * 上传媒体文件:分别有图片(image)、语音(voice)、视频(video),普通文件(file) *

* 正常情况下返回{"type":"TYPE","media_id":"MEDIA_ID","created_at":123456789}, * 否则抛出异常. @@ -73,14 +82,15 @@ public class MediaApi extends QyApi { * @param fileName * 文件名 * @return 上传到微信服务器返回的媒体标识 + * @see com.foxinmy.weixin4j.model.MediaUploadResult * @see 上传临时素材文件说明 * @see 上传永久素材文件说明 * @throws WeixinException */ - public String uploadMedia(int agentid, InputStream is, String fileName) - throws WeixinException { + public MediaUploadResult uploadMedia(int agentid, InputStream is, + String fileName) throws WeixinException { byte[] content; try { content = IOUtil.toByteArray(is); @@ -90,21 +100,22 @@ public class MediaApi extends QyApi { if (StringUtil.isBlank(fileName)) { fileName = ObjectId.get().toHexString(); } - String suffixName = IOUtil.getExtension(fileName); + String suffixName = FileUtil.getFileExtension(fileName); if (StringUtil.isBlank(suffixName)) { suffixName = FileUtil .getFileType(new ByteArrayInputStream(content)); fileName = String.format("%s.%s", fileName, suffixName); } - MediaType mediaType = null; - if ("bmp/png/jpeg/jpg/gif".contains(suffixName)) { + MediaType mediaType = MediaType.file; + if (",bmp,png,jpeg,jpg,gif," + .contains(String.format(",%s,", suffixName))) { mediaType = MediaType.image; - } else if ("mp3/wma/wav/amr".contains(suffixName)) { + } else if (",mp3,wma,wav,amr,".contains(String.format(",%s,", + suffixName))) { mediaType = MediaType.voice; - } else if ("rm/rmvb/wmv/avi/mpg/mpeg/mp4".contains(suffixName)) { + } else if (",rm,rmvb,wmv,avi,mpg,mpeg,mp4,".contains(String.format( + ",%s,", suffixName))) { mediaType = MediaType.video; - } else { - mediaType = MediaType.file; } Token token = tokenHolder.getToken(); try { @@ -117,6 +128,8 @@ public class MediaApi extends QyApi { new InputStreamBody(new ByteArrayInputStream(content), mediaType.getContentType().getMimeType(), fileName))); + return new MediaUploadResult(response.getAsJson().getString( + "media_id"), mediaType, new Date()); } else { String file_upload_uri = getRequestUri("file_upload_uri"); response = weixinClient.post(String.format(file_upload_uri, @@ -125,8 +138,15 @@ public class MediaApi extends QyApi { new ByteArrayInputStream(content), mediaType .getContentType().getMimeType(), fileName))); + JSONObject obj = response.getAsJson(); + return new MediaUploadResult(obj.getString("media_id"), + obj.getObject("type", MediaType.class), new Date( + obj.getLong("created_at") * 1000l)); + /* + * return response.getAsObject(new TypeReference() + * { }); + */ } - return response.getAsJson().getString("media_id"); } finally { if (is != null) { try { @@ -148,22 +168,29 @@ public class MediaApi extends QyApi { * @return 写入硬盘后的文件对象,存储路径见weixin4j.properties配置 * @throws WeixinException * @see com.foxinmy.weixin4j.type.MediaType - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#downloadMedia(int,String)} + * @see {@link #downloadMedia(int,String)} */ public File downloadMediaFile(int agentid, String mediaId) throws WeixinException { String media_path = ConfigUtil.getValue("media_path", Weixin4jConst.DEFAULT_MEDIA_PATH); - File file = new File(media_path + File.separator + mediaId); - if (file.exists()) { - return file; + final String prefixName = String.format("%d_%s.", agentid, mediaId); + File[] files = new File(media_path).listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(prefixName); + } + }); + if (files.length > 0) { + return files[0]; } - byte[] datas = downloadMedia(agentid, mediaId); + MediaDownloadResult result = downloadMedia(agentid, mediaId); + File file = new File(media_path + File.separator + result.getFileName()); OutputStream os = null; try { if (file.createNewFile()) { os = new FileOutputStream(file); - os.write(datas); + os.write(result.getContent()); } else { throw new WeixinException(String.format("create file fail:%s", file.getAbsolutePath())); @@ -189,14 +216,15 @@ public class MediaApi extends QyApi { * 企业应用Id(大于0时视为获取永久媒体文件) * @param mediaId * 媒体ID - * @return 二进制数据包(需自行判断类型) + * @return 媒体下载结果 + * @see com.foxinmy.weixin4j.model.MediaDownloadResult * @see 获取临时媒体说明 * @see 获取永久媒体说明 * @throws WeixinException */ - public byte[] downloadMedia(int agentid, String mediaId) + public MediaDownloadResult downloadMedia(int agentid, String mediaId) throws WeixinException { Token token = tokenHolder.getToken(); try { @@ -210,7 +238,34 @@ public class MediaApi extends QyApi { method = new HttpGet(String.format(meida_download_uri, token.getAccessToken(), mediaId)); } - return weixinClient.execute(method).getContent(); + HttpResponse response = weixinClient.execute(method); + byte[] content = response.getContent(); + String fileName = ""; + Header contentType = response + .getFirstHeader(HttpHeaders.CONTENT_TYPE); + Header disposition = response.getFirstHeader("Content-disposition"); + if (contentType.getValue().contains( + ContentType.APPLICATION_JSON.getMimeType()) + || (disposition != null && disposition.getValue().indexOf( + ".json") > 0)) { + JsonResult jsonResult = JSON.parseObject(content, 0, + content.length, Consts.UTF_8.newDecoder(), + JsonResult.class); + if (jsonResult.getCode() != 0) { + if (StringUtil.isBlank(jsonResult.getDesc())) { + jsonResult.setDesc(ErrorUtil.getText(Integer + .toString(jsonResult.getCode()))); + } + throw new WeixinException(Integer.toString(jsonResult + .getCode()), jsonResult.getDesc()); + } + } + if (StringUtil.isBlank(fileName)) { + fileName = String.format("%s.%s", mediaId, contentType + .getValue().split("/")[1]); + } + return new MediaDownloadResult(content, + ContentType.create(contentType.getValue()), fileName); } catch (IOException e) { throw new WeixinException(e); } @@ -271,6 +326,28 @@ public class MediaApi extends QyApi { return response.getAsJsonResult(); } + /** + * 下载永久图文素材 + * + * @param agentid + * 企业应用ID + * @param mediaId + * 媒体素材的media_id + * @return 图文列表 + * @throws WeixinException + * @see {@link #downloadMedia(int, String)} + * @see com.foxinmy.weixin4j.tuple.MpArticle + */ + public List downloadArticle(int agentid, String mediaId) + throws WeixinException { + MediaDownloadResult result = downloadMedia(agentid, mediaId); + byte[] content = result.getContent(); + JSONObject obj = JSON.parseObject(content, 0, content.length, + Consts.UTF_8.newDecoder(), JSONObject.class); + return JSON.parseArray(obj.getJSONObject("mpnews") + .getString("articles"), MpArticle.class); + } + /** * 修改永久图文素材 * @@ -375,7 +452,7 @@ public class MediaApi extends QyApi { * @param mediaType * 媒体类型 * @return 素材列表 - * @see {@link com.foxinmy.weixin4j.qy.api.MediaApi#listMaterialMedia(int,MediaType, int, int)} + * @see {@link #listMaterialMedia(int,MediaType, int, int)} * @throws WeixinException */ public List listAllMaterialMedia(int agentid, MediaType mediaType) @@ -400,8 +477,8 @@ public class MediaApi extends QyApi { * * @param users * 成员列表 - * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#syncuser(String,Callback)} - * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceuser(String,Callback)} + * @see {@link BatchApi#syncuser(String,Callback)} + * @see {@link BatchApi#replaceuser(String,Callback)} * @see 批量任务 * @return 上传后的mediaId @@ -416,7 +493,7 @@ public class MediaApi extends QyApi { * * @param parties * 部门列表 - * @see {@link com.foxinmy.weixin4j.qy.api.BatchApi#replaceparty(String,Callback)} + * @see {@link BatchApi#replaceparty(String,Callback)} * @see 批量任务 * @return 上传后的mediaId @@ -454,8 +531,10 @@ public class MediaApi extends QyApi { writer.write(StringUtil.join(column.values(), ',')); writer.write("\r\n"); } - return uploadMedia(0, new ByteArrayInputStream(writer.getBuffer() - .toString().getBytes(Consts.UTF_8)), batchName); + return uploadMedia( + 0, + new ByteArrayInputStream(writer.getBuffer().toString() + .getBytes(Consts.UTF_8)), batchName).getMediaId(); } finally { try { writer.close(); diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java index 863e63c2..dfd5a971 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java @@ -29,7 +29,7 @@ public class OauthApi extends QyApi { /** * 企业号用户身份授权 * - * @see {@link com.foxinmy.weixin4j.qy.api.OauthApi#getUserAuthorizeURL(String, String,String)} + * @see {@link OauthApi#getUserAuthorizeURL(String, String,String)} * * @return 请求授权的URL */ @@ -67,7 +67,7 @@ public class OauthApi extends QyApi { /** * 企业号第三方提供商授权 * - * @see {@link com.foxinmy.weixin4j.qy.api.OauthApi#getThirdAuthorizeURL(String, String,String)} + * @see {@link #getThirdAuthorizeURL(String, String,String)} * * @return 请求授权的URL */ @@ -125,7 +125,7 @@ public class OauthApi extends QyApi { } /** - * @see {@link com.foxinmy.weixin4j.qy.api.OauthApi#getSuiteAuthorizeURL(String,String, String,String)} + * @see {@link #getSuiteAuthorizeURL(String,String, String,String)} * @param preAuthCode * 预授权码 * @return diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java index 3100a924..c5700a99 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/UserApi.java @@ -155,10 +155,9 @@ public class UserApi extends QyApi { * @param code * 通过员工授权获取到的code,每次员工授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期 * @see com.foxinmy.weixin4j.qy.model.User - * @see com.foxinmy.weixin4j.qy.api.UserApi * @return 成员对象 - * @see {@link com.foxinmy.weixin4j.qy.api.UserApi#getUser(String)} - * @see {@link com.foxinmy.weixin4j.qy.api.UserApi#getUserIdByCode(String,int)} + * @see {@link #getUser(String)} + * @see {@link #getUserIdByCode(String,int)} * @see 企业获取code * @see