mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-06-28 13:16:19 +08:00
添加多媒体文件下载支持
This commit is contained in:
parent
7a2f7a8a4b
commit
71215bbe79
@ -26,7 +26,6 @@ public class WxConsts {
|
|||||||
public static final String MEDIA_THUMB = "thumb";
|
public static final String MEDIA_THUMB = "thumb";
|
||||||
|
|
||||||
public static final String FILE_JPG = "jpeg";
|
public static final String FILE_JPG = "jpeg";
|
||||||
public static final String FILE_PNG = "png";
|
|
||||||
public static final String FILE_MP3 = "mp3";
|
public static final String FILE_MP3 = "mp3";
|
||||||
public static final String FILE_ARM = "arm";
|
public static final String FILE_ARM = "arm";
|
||||||
public static final String FILE_MP4 = "mp4";
|
public static final String FILE_MP4 = "mp4";
|
||||||
|
@ -44,6 +44,7 @@ public interface WxService {
|
|||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 上传多媒体文件
|
* 上传多媒体文件
|
||||||
|
*
|
||||||
* 上传的多媒体文件有格式和大小限制,如下:
|
* 上传的多媒体文件有格式和大小限制,如下:
|
||||||
* 图片(image): 1M,支持JPG格式
|
* 图片(image): 1M,支持JPG格式
|
||||||
* 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
|
* 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
|
||||||
@ -67,6 +68,18 @@ public interface WxService {
|
|||||||
*/
|
*/
|
||||||
public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException;
|
public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 下载多媒体文件
|
||||||
|
*
|
||||||
|
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=上传下载多媒体文件
|
||||||
|
* </pre>
|
||||||
|
* @params media_id
|
||||||
|
* @return 保存到本地的临时文件
|
||||||
|
* @throws WxErrorException
|
||||||
|
*/
|
||||||
|
public File downloadMedia(String media_id) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
* 发送客服消息
|
* 发送客服消息
|
||||||
@ -75,7 +88,7 @@ public interface WxService {
|
|||||||
* @param message
|
* @param message
|
||||||
* @throws WxErrorException
|
* @throws WxErrorException
|
||||||
*/
|
*/
|
||||||
public String sendCustomMessage(WxCustomMessage message) throws WxErrorException;
|
public void sendCustomMessage(WxCustomMessage message) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -85,7 +98,7 @@ public interface WxService {
|
|||||||
* @param menu
|
* @param menu
|
||||||
* @throws WxErrorException
|
* @throws WxErrorException
|
||||||
*/
|
*/
|
||||||
public String createMenu(WxMenu menu) throws WxErrorException;
|
public void createMenu(WxMenu menu) throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
@ -94,7 +107,7 @@ public interface WxService {
|
|||||||
* </pre>
|
* </pre>
|
||||||
* @throws WxErrorException
|
* @throws WxErrorException
|
||||||
*/
|
*/
|
||||||
public String deleteMenu() throws WxErrorException;
|
public void deleteMenu() throws WxErrorException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package chanjarster.weixin.api;
|
package chanjarster.weixin.api;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@ -10,15 +9,9 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.Consts;
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.entity.ContentType;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
|
||||||
import org.apache.http.impl.client.BasicResponseHandler;
|
import org.apache.http.impl.client.BasicResponseHandler;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
@ -29,7 +22,12 @@ import chanjarster.weixin.bean.WxMenu;
|
|||||||
import chanjarster.weixin.bean.result.WxError;
|
import chanjarster.weixin.bean.result.WxError;
|
||||||
import chanjarster.weixin.bean.result.WxUploadResult;
|
import chanjarster.weixin.bean.result.WxUploadResult;
|
||||||
import chanjarster.weixin.exception.WxErrorException;
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
import chanjarster.weixin.util.Utf8ResponseHandler;
|
import chanjarster.weixin.util.fs.FileUtil;
|
||||||
|
import chanjarster.weixin.util.http.MediaDownloadRequestExecutor;
|
||||||
|
import chanjarster.weixin.util.http.MediaUploadRequestExecutor;
|
||||||
|
import chanjarster.weixin.util.http.RequestExecutor;
|
||||||
|
import chanjarster.weixin.util.http.SimpleGetRequestExecutor;
|
||||||
|
import chanjarster.weixin.util.http.SimplePostRequestExecutor;
|
||||||
|
|
||||||
public class WxServiceImpl implements WxService {
|
public class WxServiceImpl implements WxService {
|
||||||
|
|
||||||
@ -62,7 +60,7 @@ public class WxServiceImpl implements WxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String bytesToHex(byte[] b) {
|
protected String bytesToHex(byte[] b) {
|
||||||
char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
@ -110,25 +108,25 @@ public class WxServiceImpl implements WxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sendCustomMessage(WxCustomMessage message) throws WxErrorException {
|
public void sendCustomMessage(WxCustomMessage message) throws WxErrorException {
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
|
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
|
||||||
return post(url, message.toJson());
|
execute(new SimplePostRequestExecutor(), url, message.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createMenu(WxMenu menu) throws WxErrorException {
|
public void createMenu(WxMenu menu) throws WxErrorException {
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
|
String url = "https://api.weixin.qq.com/cgi-bin/menu/create";
|
||||||
return post(url, menu.toJson());
|
execute(new SimplePostRequestExecutor(), url, menu.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String deleteMenu() throws WxErrorException {
|
public void deleteMenu() throws WxErrorException {
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
|
String url = "https://api.weixin.qq.com/cgi-bin/menu/delete";
|
||||||
return get(url, null);
|
execute(new SimpleGetRequestExecutor(), url, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WxMenu getMenu() throws WxErrorException {
|
public WxMenu getMenu() throws WxErrorException {
|
||||||
String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
|
String url = "https://api.weixin.qq.com/cgi-bin/menu/get";
|
||||||
try {
|
try {
|
||||||
String resultContent = get(url, null);
|
String resultContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||||
return WxMenu.fromJson(resultContent);
|
return WxMenu.fromJson(resultContent);
|
||||||
} catch (WxErrorException e) {
|
} catch (WxErrorException e) {
|
||||||
// 46003 不存在的菜单数据
|
// 46003 不存在的菜单数据
|
||||||
@ -140,30 +138,28 @@ public class WxServiceImpl implements WxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public WxUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
|
public WxUploadResult uploadMedia(String mediaType, String fileType, InputStream inputStream) throws WxErrorException, IOException {
|
||||||
return uploadMedia(mediaType, createTmpFile(inputStream, fileType));
|
return uploadMedia(mediaType,FileUtil.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException {
|
public WxUploadResult uploadMedia(String mediaType, File file) throws WxErrorException {
|
||||||
String url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
|
String url = "http://file.api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType;
|
||||||
String json = post(url, file);
|
return execute(new MediaUploadRequestExecutor(), url, file);
|
||||||
return WxUploadResult.fromJson(json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String post(String uri, Object data) throws WxErrorException {
|
public File downloadMedia(String media_id) throws WxErrorException {
|
||||||
return execute("POST", uri, data);
|
String url = "http://file.api.weixin.qq.com/cgi-bin/media/get";
|
||||||
}
|
return execute(new MediaDownloadRequestExecutor(), url, "media_id=" + media_id);
|
||||||
|
|
||||||
protected String get(String uri, Object data) throws WxErrorException {
|
|
||||||
return execute("GET", uri, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
|
* 向微信端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
|
||||||
* @param request
|
* @param executor
|
||||||
* @return 微信服务端返回的结果
|
* @param uri
|
||||||
* @throws WxErrorException
|
* @param data
|
||||||
|
* @return
|
||||||
|
* @throws WxErrorException
|
||||||
*/
|
*/
|
||||||
protected String execute(String method, String uri, Object data) throws WxErrorException {
|
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
|
||||||
if (StringUtils.isBlank(wxConfigStorage.getAccessToken())) {
|
if (StringUtils.isBlank(wxConfigStorage.getAccessToken())) {
|
||||||
refreshAccessToken();
|
refreshAccessToken();
|
||||||
}
|
}
|
||||||
@ -173,38 +169,9 @@ public class WxServiceImpl implements WxService {
|
|||||||
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
|
uriWithAccessToken += uri.indexOf('?') == -1 ? "?access_token=" + accessToken : "&access_token=" + accessToken;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String resultContent = null;
|
return executor.execute(uriWithAccessToken, data);
|
||||||
if ("POST".equals(method)) {
|
} catch (WxErrorException e) {
|
||||||
HttpPost httpPost = new HttpPost(uriWithAccessToken);
|
WxError error = e.getError();
|
||||||
if (data != null) {
|
|
||||||
if (data instanceof String) {
|
|
||||||
StringEntity entity = new StringEntity((String)data, Consts.UTF_8);
|
|
||||||
httpPost.setEntity(entity);
|
|
||||||
}
|
|
||||||
if (data instanceof File) {
|
|
||||||
File file = (File) data;
|
|
||||||
HttpEntity entity = MultipartEntityBuilder
|
|
||||||
.create()
|
|
||||||
.addBinaryBody("media", file)
|
|
||||||
.build();
|
|
||||||
httpPost.setEntity(entity);
|
|
||||||
httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseableHttpResponse response = httpclient.execute(httpPost);
|
|
||||||
resultContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
|
||||||
} else if ("GET".equals(method)) {
|
|
||||||
if (data != null) {
|
|
||||||
if (data instanceof String) {
|
|
||||||
uriWithAccessToken += uriWithAccessToken.endsWith("&") ? data : '&' + (String)data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HttpGet httpGet = new HttpGet(uriWithAccessToken);
|
|
||||||
CloseableHttpResponse response = httpclient.execute(httpGet);
|
|
||||||
resultContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
WxError error = WxError.fromJson(resultContent);
|
|
||||||
/*
|
/*
|
||||||
* 发生以下情况时尝试刷新access_token
|
* 发生以下情况时尝试刷新access_token
|
||||||
* 40001 获取access_token时AppSecret错误,或者access_token无效
|
* 40001 获取access_token时AppSecret错误,或者access_token无效
|
||||||
@ -212,12 +179,24 @@ public class WxServiceImpl implements WxService {
|
|||||||
*/
|
*/
|
||||||
if (error.getErrcode() == 42001 || error.getErrcode() == 40001) {
|
if (error.getErrcode() == 42001 || error.getErrcode() == 40001) {
|
||||||
refreshAccessToken();
|
refreshAccessToken();
|
||||||
return execute(method, uri, data);
|
return execute(executor, uri, data);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* -1 系统繁忙, 500ms后重试
|
||||||
|
*/
|
||||||
|
if (error.getErrcode() == -1) {
|
||||||
|
try {
|
||||||
|
System.out.println("微信系统繁忙,500ms后重试");
|
||||||
|
Thread.sleep(500);
|
||||||
|
return execute(executor, uri, data);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
throw new RuntimeException(e1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (error.getErrcode() != 0) {
|
if (error.getErrcode() != 0) {
|
||||||
throw new WxErrorException(error);
|
throw new WxErrorException(error);
|
||||||
}
|
}
|
||||||
return resultContent;
|
return null;
|
||||||
} catch (ClientProtocolException e) {
|
} catch (ClientProtocolException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -225,38 +204,8 @@ public class WxServiceImpl implements WxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File createTmpFile(InputStream inputStream, String fileType) throws IOException {
|
|
||||||
FileOutputStream fos = null;
|
|
||||||
try {
|
|
||||||
File tmpFile = File.createTempFile(UUID.randomUUID().toString(), '.' + fileType);
|
|
||||||
tmpFile.deleteOnExit();
|
|
||||||
fos = new FileOutputStream(tmpFile);
|
|
||||||
int read = 0;
|
|
||||||
byte[] bytes = new byte[1024 * 100];
|
|
||||||
while ((read = inputStream.read(bytes)) != -1) {
|
|
||||||
fos.write(bytes, 0, read);
|
|
||||||
}
|
|
||||||
fos.flush();
|
|
||||||
return tmpFile;
|
|
||||||
} finally {
|
|
||||||
if (inputStream != null) {
|
|
||||||
try {
|
|
||||||
inputStream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fos != null) {
|
|
||||||
try {
|
|
||||||
fos.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWxConfigStorage(WxConfigStorage wxConfigProvider) {
|
public void setWxConfigStorage(WxConfigStorage wxConfigProvider) {
|
||||||
this.wxConfigStorage = wxConfigProvider;
|
this.wxConfigStorage = wxConfigProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package chanjarster.weixin.bean;
|
package chanjarster.weixin.bean;
|
||||||
|
|
||||||
import chanjarster.weixin.util.WxGsonBuilder;
|
import chanjarster.weixin.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
public class WxAccessToken {
|
public class WxAccessToken {
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package chanjarster.weixin.bean;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import chanjarster.weixin.util.WxGsonBuilder;
|
import chanjarster.weixin.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客服消息
|
* 客服消息
|
||||||
|
@ -5,7 +5,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import chanjarster.weixin.util.WxGsonBuilder;
|
import chanjarster.weixin.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公众号菜单
|
* 公众号菜单
|
||||||
|
@ -9,8 +9,8 @@ import javax.xml.bind.annotation.XmlElement;
|
|||||||
import javax.xml.bind.annotation.XmlRootElement;
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||||
|
|
||||||
import chanjarster.weixin.util.AdapterCDATA;
|
import chanjarster.weixin.util.xml.AdapterCDATA;
|
||||||
import chanjarster.weixin.util.XmlTransformer;
|
import chanjarster.weixin.util.xml.XmlTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <pre>
|
* <pre>
|
||||||
|
@ -3,7 +3,7 @@ package chanjarster.weixin.bean.result;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import chanjarster.weixin.util.WxGsonBuilder;
|
import chanjarster.weixin.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信错误码说明
|
* 微信错误码说明
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package chanjarster.weixin.bean.result;
|
package chanjarster.weixin.bean.result;
|
||||||
|
|
||||||
import chanjarster.weixin.util.WxGsonBuilder;
|
import chanjarster.weixin.util.json.WxGsonBuilder;
|
||||||
|
|
||||||
public class WxUploadResult {
|
public class WxUploadResult {
|
||||||
|
|
||||||
|
47
src/main/java/chanjarster/weixin/util/fs/FileUtil.java
Normal file
47
src/main/java/chanjarster/weixin/util/fs/FileUtil.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package chanjarster.weixin.util.fs;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class FileUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建临时文件
|
||||||
|
* @param inputStream
|
||||||
|
* @param name 文件名
|
||||||
|
* @param ext 扩展名
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
File tmpFile = File.createTempFile(name, '.' + ext);
|
||||||
|
tmpFile.deleteOnExit();
|
||||||
|
fos = new FileOutputStream(tmpFile);
|
||||||
|
int read = 0;
|
||||||
|
byte[] bytes = new byte[1024 * 100];
|
||||||
|
while ((read = inputStream.read(bytes)) != -1) {
|
||||||
|
fos.write(bytes, 0, read);
|
||||||
|
}
|
||||||
|
fos.flush();
|
||||||
|
return tmpFile;
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.StatusLine;
|
||||||
|
import org.apache.http.client.HttpResponseException;
|
||||||
|
import org.apache.http.client.ResponseHandler;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
public class InputStreamResponseHandler implements ResponseHandler<InputStream> {
|
||||||
|
|
||||||
|
public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler();
|
||||||
|
|
||||||
|
public InputStream handleResponse(final HttpResponse response) throws HttpResponseException, IOException {
|
||||||
|
final StatusLine statusLine = response.getStatusLine();
|
||||||
|
final HttpEntity entity = response.getEntity();
|
||||||
|
if (statusLine.getStatusCode() >= 300) {
|
||||||
|
EntityUtils.consume(entity);
|
||||||
|
throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
|
||||||
|
}
|
||||||
|
return entity == null ? null : entity.getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
|
||||||
|
import chanjarster.weixin.bean.result.WxError;
|
||||||
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
|
import chanjarster.weixin.util.fs.FileUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载媒体文件请求执行器,请求的参数是String, 返回的结果是String
|
||||||
|
* @author chanjarster
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File execute(String uri, String queryParam) throws WxErrorException, ClientProtocolException, IOException {
|
||||||
|
if (queryParam != null) {
|
||||||
|
if (uri.indexOf('?') == -1) {
|
||||||
|
uri += '?';
|
||||||
|
}
|
||||||
|
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpGet httpGet = new HttpGet(uri);
|
||||||
|
CloseableHttpResponse response = httpclient.execute(httpGet);
|
||||||
|
|
||||||
|
Header[] contentTypeHeader = response.getHeaders("Content-Type");
|
||||||
|
if (contentTypeHeader != null && contentTypeHeader.length > 0) {
|
||||||
|
// 下载媒体文件出错
|
||||||
|
if (ContentType.TEXT_PLAIN.getMimeType().equals(contentTypeHeader[0].getValue())) {
|
||||||
|
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
throw new WxErrorException(WxError.fromJson(responseContent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
|
||||||
|
// 视频文件不支持下载
|
||||||
|
String fileName = getFileName(response);
|
||||||
|
if (StringUtils.isBlank(fileName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String[] name_ext = fileName.split("\\.");
|
||||||
|
File localFile = FileUtil.createTmpFile(inputStream, name_ext[0], name_ext[1]);
|
||||||
|
return localFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getFileName(CloseableHttpResponse response) {
|
||||||
|
Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
|
||||||
|
Pattern p = Pattern.compile(".*filename=\"(.*)\"");
|
||||||
|
Matcher m = p.matcher(contentDispositionHeader[0].getValue());
|
||||||
|
m.matches();
|
||||||
|
String fileName = m.group(1);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||||
|
|
||||||
|
import chanjarster.weixin.bean.result.WxError;
|
||||||
|
import chanjarster.weixin.bean.result.WxUploadResult;
|
||||||
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传媒体文件请求执行器,请求的参数是File, 返回的结果是String
|
||||||
|
* @author chanjarster
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MediaUploadRequestExecutor implements RequestExecutor<WxUploadResult, File> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxUploadResult execute(String uri, File file) throws WxErrorException, ClientProtocolException, IOException {
|
||||||
|
HttpPost httpPost = new HttpPost(uri);
|
||||||
|
if (file != null) {
|
||||||
|
HttpEntity entity = MultipartEntityBuilder
|
||||||
|
.create()
|
||||||
|
.addBinaryBody("media", file)
|
||||||
|
.build();
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
|
||||||
|
}
|
||||||
|
CloseableHttpResponse response = httpclient.execute(httpPost);
|
||||||
|
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
WxError error = WxError.fromJson(responseContent);
|
||||||
|
if (error.getErrcode() != 0) {
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
return WxUploadResult.fromJson(responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
|
||||||
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http请求执行器
|
||||||
|
* @author chanjarster
|
||||||
|
*
|
||||||
|
* @param <T> 返回值类型
|
||||||
|
* @param <E> 请求参数类型
|
||||||
|
*/
|
||||||
|
public interface RequestExecutor<T, E> {
|
||||||
|
|
||||||
|
public static final CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||||
|
|
||||||
|
public T execute(String uri, E data) throws WxErrorException, ClientProtocolException, IOException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
|
||||||
|
import chanjarster.weixin.bean.result.WxError;
|
||||||
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单的GET请求执行器,请求的参数是String, 返回的结果也是String
|
||||||
|
* @author chanjarster
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SimpleGetRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(String uri, String queryParam) throws WxErrorException, ClientProtocolException, IOException {
|
||||||
|
if (queryParam != null) {
|
||||||
|
if (uri.indexOf('?') == -1) {
|
||||||
|
uri += '?';
|
||||||
|
}
|
||||||
|
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
||||||
|
}
|
||||||
|
HttpGet httpGet = new HttpGet(uri);
|
||||||
|
CloseableHttpResponse response = httpclient.execute(httpGet);
|
||||||
|
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
WxError error = WxError.fromJson(responseContent);
|
||||||
|
if (error.getErrcode() != 0) {
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
return responseContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.http.Consts;
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
|
||||||
|
import chanjarster.weixin.bean.result.WxError;
|
||||||
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单的POST请求执行器,请求的参数是String, 返回的结果也是String
|
||||||
|
* @author chanjarster
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SimplePostRequestExecutor implements RequestExecutor<String, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(String uri, String postEntity) throws WxErrorException, ClientProtocolException, IOException {
|
||||||
|
HttpPost httpPost = new HttpPost(uri);
|
||||||
|
if (postEntity != null) {
|
||||||
|
StringEntity entity = new StringEntity(postEntity, Consts.UTF_8);
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
}
|
||||||
|
CloseableHttpResponse response = httpclient.execute(httpPost);
|
||||||
|
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||||
|
WxError error = WxError.fromJson(responseContent);
|
||||||
|
if (error.getErrcode() != 0) {
|
||||||
|
throw new WxErrorException(error);
|
||||||
|
}
|
||||||
|
return responseContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.http;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
* arose from modification of the original source, or other redistribution of this source
|
* arose from modification of the original source, or other redistribution of this source
|
||||||
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
||||||
*/
|
*/
|
||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.json;
|
||||||
|
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
@ -6,7 +6,7 @@
|
|||||||
* arose from modification of the original source, or other redistribution of this source
|
* arose from modification of the original source, or other redistribution of this source
|
||||||
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
||||||
*/
|
*/
|
||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.json;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.json;
|
||||||
|
|
||||||
import chanjarster.weixin.bean.WxCustomMessage;
|
import chanjarster.weixin.bean.WxCustomMessage;
|
||||||
import chanjarster.weixin.bean.WxMenu;
|
import chanjarster.weixin.bean.WxMenu;
|
@ -6,7 +6,7 @@
|
|||||||
* arose from modification of the original source, or other redistribution of this source
|
* arose from modification of the original source, or other redistribution of this source
|
||||||
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
* is not permitted without written permission of the KINGSTAR MEDIA SOLUTIONS LTD.
|
||||||
*/
|
*/
|
||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.json;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.xml;
|
||||||
|
|
||||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package chanjarster.weixin.util;
|
package chanjarster.weixin.util.xml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
@ -2,6 +2,8 @@ package chanjarster.weixin.api;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
@ -19,14 +21,17 @@ import chanjarster.weixin.bean.WxMenu;
|
|||||||
import chanjarster.weixin.bean.WxMenu.WxMenuButton;
|
import chanjarster.weixin.bean.WxMenu.WxMenuButton;
|
||||||
import chanjarster.weixin.bean.result.WxUploadResult;
|
import chanjarster.weixin.bean.result.WxUploadResult;
|
||||||
import chanjarster.weixin.exception.WxErrorException;
|
import chanjarster.weixin.exception.WxErrorException;
|
||||||
import chanjarster.weixin.util.XmlTransformer;
|
import chanjarster.weixin.util.xml.XmlTransformer;
|
||||||
|
|
||||||
public class WxServiceTest {
|
public class WxServiceTest {
|
||||||
|
|
||||||
private WxServiceImpl wxService;
|
private WxServiceImpl wxService;
|
||||||
|
|
||||||
|
private List<String> media_ids = new ArrayList<String>();
|
||||||
|
|
||||||
@BeforeTest
|
@BeforeTest
|
||||||
public void prepare() throws JAXBException {
|
public void prepare() throws JAXBException {
|
||||||
|
this.wxService = null;
|
||||||
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
||||||
WxXmlConfigStorage config = XmlTransformer.fromXml(WxXmlConfigStorage.class, is1);
|
WxXmlConfigStorage config = XmlTransformer.fromXml(WxXmlConfigStorage.class, is1);
|
||||||
this.wxService = new WxServiceImpl();
|
this.wxService = new WxServiceImpl();
|
||||||
@ -66,32 +71,51 @@ public class WxServiceTest {
|
|||||||
Assert.assertNotNull(wxService.getMenu());
|
Assert.assertNotNull(wxService.getMenu());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = { "testRefreshAccessToken", "testGetMenu" }, enabled = true)
|
@Test(dependsOnMethods = { "testRefreshAccessToken", "testGetMenu"}, enabled = true)
|
||||||
public void testDeleteMenu() throws WxErrorException {
|
public void testDeleteMenu() throws WxErrorException {
|
||||||
wxService.deleteMenu();
|
wxService.deleteMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = { "testRefreshAccessToken" }, dataProvider="uploadFiles", enabled = true)
|
@Test(dependsOnMethods = { "testRefreshAccessToken" }, dataProvider="uploadMedia", enabled = true)
|
||||||
public void testUploadMedia1(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
|
public void testUploadMedia1(String mediaType, String fileType, String fileName) throws WxErrorException, IOException {
|
||||||
InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
|
InputStream inputStream = ClassLoader.getSystemResourceAsStream(fileName);
|
||||||
WxUploadResult res = wxService.uploadMedia(mediaType, fileType, inputStream);
|
WxUploadResult res = wxService.uploadMedia(mediaType, fileType, inputStream);
|
||||||
Assert.assertNotNull(res.getType());
|
Assert.assertNotNull(res.getType());
|
||||||
Assert.assertNotNull(res.getCreated_at());
|
Assert.assertNotNull(res.getCreated_at());
|
||||||
Assert.assertTrue(res.getMedia_id() != null || res.getThumb_media_id() != null);
|
Assert.assertTrue(res.getMedia_id() != null || res.getThumb_media_id() != null);
|
||||||
|
|
||||||
|
if (res.getMedia_id() != null) {
|
||||||
|
media_ids.add(res.getMedia_id());
|
||||||
|
}
|
||||||
|
if (res.getThumb_media_id() != null) {
|
||||||
|
media_ids.add(res.getThumb_media_id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DataProvider
|
@DataProvider
|
||||||
public Object[][] uploadFiles() {
|
public Object[][] uploadMedia() {
|
||||||
return new Object[][] {
|
return new Object[][] {
|
||||||
new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_PNG, "mm.png" },
|
|
||||||
new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg" },
|
new Object[] { WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, "mm.jpeg" },
|
||||||
new Object[] { WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3" },
|
new Object[] { WxConsts.MEDIA_VOICE, WxConsts.FILE_MP3, "mm.mp3" },
|
||||||
new Object[] { WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4" },
|
new Object[] { WxConsts.MEDIA_VIDEO, WxConsts.FILE_MP4, "mm.mp4" },
|
||||||
new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_PNG, "mm.png" },
|
|
||||||
new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg" }
|
new Object[] { WxConsts.MEDIA_THUMB, WxConsts.FILE_JPG, "mm.jpeg" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = { "testUploadMedia1" }, dataProvider="downloadMedia")
|
||||||
|
public void testDownloadMedia(String media_id) throws WxErrorException {
|
||||||
|
wxService.downloadMedia(media_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DataProvider
|
||||||
|
public Object[][] downloadMedia() {
|
||||||
|
Object[][] params = new Object[this.media_ids.size()][];
|
||||||
|
for (int i = 0; i < this.media_ids.size(); i++) {
|
||||||
|
params[i] = new Object[] { this.media_ids.get(i) };
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
@Test(enabled = true)
|
@Test(enabled = true)
|
||||||
public void testCheckSignature() throws WxErrorException {
|
public void testCheckSignature() throws WxErrorException {
|
||||||
String timestamp = "23234235423246";
|
String timestamp = "23234235423246";
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
Loading…
Reference in New Issue
Block a user