新增MessageConverter
This commit is contained in:
@@ -18,8 +18,8 @@ import java.util.Map;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.mch.APPPayRequest;
|
||||
@@ -746,7 +746,7 @@ public class PayApi extends MchApi {
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
getRequestUri("interface_report_uri"), param);
|
||||
return response.getAsXmlResult();
|
||||
return response.getAsXml();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-16
@@ -22,24 +22,20 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
||||
private final String SEPARATOR = File.separator;
|
||||
|
||||
public FileCacheStorager(String path) {
|
||||
this.tmpdir = new File(String.format("%s%sweixin4j_token_temp",
|
||||
path, SEPARATOR));
|
||||
this.tmpdir = new File(String.format("%s%s%s", path, SEPARATOR, ALLKEY));
|
||||
this.tmpdir.mkdirs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T lookup(String key) {
|
||||
File cacheFile = new File(String.format("%s%s%s",
|
||||
tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||
File cacheFile = new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||
try {
|
||||
if (cacheFile.exists()) {
|
||||
T cache = SerializationUtils.deserialize(new FileInputStream(
|
||||
cacheFile));
|
||||
T cache = SerializationUtils.deserialize(new FileInputStream(cacheFile));
|
||||
if (cache.getCreateTime() < 0) {
|
||||
return cache;
|
||||
}
|
||||
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System
|
||||
.currentTimeMillis()) {
|
||||
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System.currentTimeMillis()) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
@@ -52,10 +48,8 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
||||
@Override
|
||||
public void caching(String key, T cache) {
|
||||
try {
|
||||
SerializationUtils.serialize(
|
||||
cache,
|
||||
new FileOutputStream(new File(String.format("%s%s%s",
|
||||
tmpdir.getAbsolutePath(), SEPARATOR, key))));
|
||||
SerializationUtils.serialize(cache,
|
||||
new FileOutputStream(new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key))));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -64,12 +58,10 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
||||
@Override
|
||||
public T evict(String key) {
|
||||
T cache = null;
|
||||
File cacheFile = new File(String.format("%s%s%s",
|
||||
tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||
File cacheFile = new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||
try {
|
||||
if (cacheFile.exists()) {
|
||||
cache = SerializationUtils.deserialize(new FileInputStream(
|
||||
cacheFile));
|
||||
cache = SerializationUtils.deserialize(new FileInputStream(cacheFile));
|
||||
cacheFile.delete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
+9
-6
@@ -18,8 +18,7 @@ import com.whalin.MemCached.SockIOPool;
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class MemcacheCacheStorager<T extends Cacheable> implements
|
||||
CacheStorager<T> {
|
||||
public class MemcacheCacheStorager<T extends Cacheable> implements CacheStorager<T> {
|
||||
|
||||
private final MemCachedClient mc;
|
||||
|
||||
@@ -30,7 +29,13 @@ public class MemcacheCacheStorager<T extends Cacheable> implements
|
||||
public MemcacheCacheStorager(MemcachePoolConfig poolConfig) {
|
||||
mc = new MemCachedClient();
|
||||
poolConfig.initSocketIO();
|
||||
mc.set(ALLKEY, new HashSet<String>());
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (!mc.keyExists(ALLKEY)) {
|
||||
mc.set(ALLKEY, new HashSet<String>());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -43,9 +48,7 @@ public class MemcacheCacheStorager<T extends Cacheable> implements
|
||||
@Override
|
||||
public void caching(String key, T cache) {
|
||||
if (cache.getCreateTime() > 0l) {
|
||||
mc.set(key,
|
||||
cache,
|
||||
new Date(cache.getCreateTime() + cache.getExpires() - CUTMS));
|
||||
mc.set(key, cache, new Date(cache.getCreateTime() + cache.getExpires() - CUTMS));
|
||||
} else {
|
||||
mc.set(key, cache);
|
||||
}
|
||||
|
||||
@@ -10,17 +10,15 @@ import com.foxinmy.weixin4j.logging.InternalLoggerFactory;
|
||||
|
||||
public abstract class AbstractHttpClient implements HttpClient {
|
||||
|
||||
protected final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
|
||||
protected final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
@Override
|
||||
public HttpResponse get(String url) throws HttpClientException {
|
||||
return execute(HttpMethod.GET, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse get(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
public HttpResponse get(String url, URLParameter... parameters) throws HttpClientException {
|
||||
return execute(HttpMethod.GET, url, parameters);
|
||||
}
|
||||
|
||||
@@ -30,8 +28,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders head(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
public HttpHeaders head(String url, URLParameter... parameters) throws HttpClientException {
|
||||
return execute(HttpMethod.HEAD, url, parameters).getHeaders();
|
||||
}
|
||||
|
||||
@@ -41,8 +38,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse post(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
public HttpResponse post(String url, URLParameter... parameters) throws HttpClientException {
|
||||
HttpEntity entity = null;
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
entity = new FormUrlEntity(Arrays.asList(parameters));
|
||||
@@ -51,8 +47,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse post(String url, HttpEntity entity)
|
||||
throws HttpClientException {
|
||||
public HttpResponse post(String url, HttpEntity entity) throws HttpClientException {
|
||||
HttpRequest request = new HttpRequest(HttpMethod.POST, url);
|
||||
request.setEntity(entity);
|
||||
return execute(request);
|
||||
@@ -64,8 +59,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
public void put(String url, URLParameter... parameters) throws HttpClientException {
|
||||
execute(HttpMethod.PUT, url, parameters);
|
||||
}
|
||||
|
||||
@@ -75,8 +69,7 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
public void delete(String url, URLParameter... parameters) throws HttpClientException {
|
||||
execute(HttpMethod.DELETE, url, parameters);
|
||||
}
|
||||
|
||||
@@ -86,20 +79,17 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<HttpMethod> options(String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
HttpHeaders headers = execute(HttpMethod.OPTIONS, url, parameters)
|
||||
.getHeaders();
|
||||
public Set<HttpMethod> options(String url, URLParameter... parameters) throws HttpClientException {
|
||||
HttpHeaders headers = execute(HttpMethod.OPTIONS, url, parameters).getHeaders();
|
||||
return headers.getAllow();
|
||||
}
|
||||
|
||||
protected HttpResponse execute(HttpMethod method, String url)
|
||||
throws HttpClientException {
|
||||
protected HttpResponse execute(HttpMethod method, String url) throws HttpClientException {
|
||||
return execute(new HttpRequest(method, url));
|
||||
}
|
||||
|
||||
protected HttpResponse execute(HttpMethod method, String url,
|
||||
URLParameter... parameters) throws HttpClientException {
|
||||
protected HttpResponse execute(HttpMethod method, String url, URLParameter... parameters)
|
||||
throws HttpClientException {
|
||||
StringBuilder buf = new StringBuilder(url);
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
if (url.indexOf("?") < 0) {
|
||||
@@ -113,27 +103,20 @@ public abstract class AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
|
||||
protected boolean hasError(HttpStatus status) {
|
||||
return (status.series() == HttpStatus.Series.CLIENT_ERROR || status
|
||||
.series() == HttpStatus.Series.SERVER_ERROR);
|
||||
return (status.series() == HttpStatus.Series.CLIENT_ERROR || status.series() == HttpStatus.Series.SERVER_ERROR);
|
||||
}
|
||||
|
||||
protected void handleResponse(HttpResponse response)
|
||||
throws HttpClientException {
|
||||
protected void handleResponse(HttpResponse response) throws HttpClientException {
|
||||
HttpStatus status = response.getStatus();
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
String contentType = headers.getFirst(HttpHeaders.CONTENT_TYPE);
|
||||
boolean jsonResult = contentType != null
|
||||
&& contentType.contains(ContentType.APPLICATION_JSON
|
||||
.getMimeType());
|
||||
if (!jsonResult && hasError(status)) {
|
||||
MimeType resultType = MimeType.valueOf(headers.getFirst(HttpHeaders.CONTENT_TYPE));
|
||||
if (!MimeType.APPLICATION_JSON.includes(resultType) && hasError(status)) {
|
||||
switch (status.series()) {
|
||||
case CLIENT_ERROR:
|
||||
case SERVER_ERROR:
|
||||
throw new HttpClientException(String.format("%d %s",
|
||||
status.getStatusCode(), status.getStatusText()));
|
||||
throw new HttpClientException(String.format("%d %s", status.getStatusCode(), status.getStatusText()));
|
||||
default:
|
||||
throw new HttpClientException("Unknown status code [" + status
|
||||
+ "]");
|
||||
throw new HttpClientException("Unknown status code [" + status + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@@ -21,48 +20,32 @@ public final class ContentType implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1544245878894784980L;
|
||||
|
||||
public static final ContentType APPLICATION_ATOM_XML = create(
|
||||
"application/atom+xml", Consts.UTF_8);
|
||||
public static final ContentType APPLICATION_FORM_URLENCODED = create(
|
||||
"application/x-www-form-urlencoded", Consts.UTF_8);
|
||||
public static final ContentType APPLICATION_JSON = create(
|
||||
"application/json", Consts.UTF_8);
|
||||
public static final ContentType APPLICATION_OCTET_STREAM = create(
|
||||
"application/octet-stream", (Charset) null);
|
||||
public static final ContentType APPLICATION_SVG_XML = create(
|
||||
"application/svg+xml", Consts.UTF_8);
|
||||
public static final ContentType APPLICATION_XHTML_XML = create(
|
||||
"application/xhtml+xml", Consts.UTF_8);
|
||||
public static final ContentType APPLICATION_XML = create("application/xml",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType MULTIPART_FORM_DATA = create(
|
||||
"multipart/form-data", Consts.UTF_8);
|
||||
public static final ContentType TEXT_HTML = create("text/html",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType TEXT_PLAIN = create("text/plain",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType IMAGE_JPG = create("image/jpg",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType AUDIO_MP3 = create("audio/mp3",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType VIDEO_MPEG4 = create("video/mpeg4",
|
||||
Consts.UTF_8);
|
||||
public static final ContentType TEXT_XML = create("text/xml", Consts.UTF_8);
|
||||
public static final ContentType WILDCARD = create("*/*", (Charset) null);
|
||||
|
||||
// defaults
|
||||
public static final ContentType DEFAULT_TEXT = TEXT_PLAIN;
|
||||
public static final ContentType DEFAULT_BINARY = APPLICATION_OCTET_STREAM;
|
||||
|
||||
private final String mimeType;
|
||||
private final MimeType mimeType;
|
||||
private final Charset charset;
|
||||
private static final Charset DEFAULT_CHARSET = Consts.UTF_8;
|
||||
|
||||
ContentType(final String mimeType, final Charset charset) {
|
||||
public static final ContentType APPLICATION_FORM_URLENCODED;
|
||||
public static final ContentType MULTIPART_FORM_DATA;
|
||||
public static final ContentType DEFAULT_BINARY;
|
||||
public static final ContentType DEFAULT_TEXT;
|
||||
|
||||
static {
|
||||
APPLICATION_FORM_URLENCODED = new ContentType(MimeType.APPLICATION_FORM_URLENCODED);
|
||||
MULTIPART_FORM_DATA = new ContentType(MimeType.MULTIPART_FORM_DATA);
|
||||
DEFAULT_BINARY = new ContentType(MimeType.APPLICATION_OCTET_STREAM);
|
||||
DEFAULT_TEXT = new ContentType(MimeType.TEXT_PLAIN);
|
||||
}
|
||||
|
||||
ContentType(final MimeType mimeType) {
|
||||
this(mimeType, DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
ContentType(final MimeType mimeType, final Charset charset) {
|
||||
this.mimeType = mimeType;
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
public MimeType getMimeType() {
|
||||
return this.mimeType;
|
||||
}
|
||||
|
||||
@@ -73,7 +56,7 @@ public final class ContentType implements Serializable {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(this.mimeType);
|
||||
buf.append(this.mimeType.toString());
|
||||
if (this.charset != null) {
|
||||
buf.append("; charset=");
|
||||
buf.append(this.charset.name());
|
||||
@@ -102,8 +85,18 @@ public final class ContentType implements Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ContentType create(final String mimeType,
|
||||
final Charset charset) {
|
||||
public static ContentType create(final MimeType mimeType, final Charset charset) {
|
||||
if (mimeType == null) {
|
||||
throw new IllegalArgumentException("MIME type may not be null");
|
||||
}
|
||||
return new ContentType(mimeType, charset);
|
||||
}
|
||||
|
||||
public static ContentType create(final String mimeType) {
|
||||
return create(MimeType.valueOf(mimeType), (Charset) null);
|
||||
}
|
||||
|
||||
public static ContentType create(final String mimeType, final Charset charset) {
|
||||
if (mimeType == null) {
|
||||
throw new IllegalArgumentException("MIME type may not be null");
|
||||
}
|
||||
@@ -112,21 +105,8 @@ public final class ContentType implements Serializable {
|
||||
throw new IllegalArgumentException("MIME type may not be empty");
|
||||
}
|
||||
if (!valid(type)) {
|
||||
throw new IllegalArgumentException(
|
||||
"MIME type may not contain reserved characters");
|
||||
throw new IllegalArgumentException("MIME type may not contain reserved characters");
|
||||
}
|
||||
return new ContentType(type, charset);
|
||||
}
|
||||
|
||||
public static ContentType create(final String mimeType) {
|
||||
return new ContentType(mimeType, (Charset) null);
|
||||
}
|
||||
|
||||
public static ContentType create(final String mimeType, final String charset)
|
||||
throws UnsupportedCharsetException {
|
||||
return create(
|
||||
mimeType,
|
||||
(charset != null && charset.length() > 0) ? Charset
|
||||
.forName(charset) : null);
|
||||
return new ContentType(MimeType.valueOf(type), charset);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ public interface HttpResponse extends HttpMessage {
|
||||
* @return
|
||||
*/
|
||||
HttpStatus getStatus();
|
||||
|
||||
/**
|
||||
* 响应内容
|
||||
*
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
|
||||
/**
|
||||
* MIME type
|
||||
*
|
||||
* @className MimeType
|
||||
* @author jinyu
|
||||
* @date Jul 20, 2016
|
||||
* @since JDK 1.8
|
||||
*/
|
||||
public class MimeType implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4430596628682058362L;
|
||||
|
||||
private static final String WILDCARD_TYPE = "*";
|
||||
|
||||
private final String type;
|
||||
private final String subType;
|
||||
|
||||
public static final MimeType APPLICATION_FORM_URLENCODED;
|
||||
public static final MimeType APPLICATION_JSON;
|
||||
public static final MimeType APPLICATION_OCTET_STREAM;
|
||||
public static final MimeType APPLICATION_XML;
|
||||
public static final MimeType MULTIPART_FORM_DATA;
|
||||
public static final MimeType TEXT_HTML;
|
||||
public static final MimeType TEXT_PLAIN;
|
||||
public static final MimeType IMAGE_JPG;
|
||||
public static final MimeType AUDIO_MP3;
|
||||
public static final MimeType VIDEO_MPEG4;
|
||||
public static final MimeType TEXT_XML;
|
||||
|
||||
static {
|
||||
APPLICATION_FORM_URLENCODED = valueOf("application/x-www-form-urlencoded");
|
||||
APPLICATION_JSON = valueOf("application/json");
|
||||
APPLICATION_OCTET_STREAM = valueOf("application/octet-stream");
|
||||
APPLICATION_XML = valueOf("application/xml");
|
||||
MULTIPART_FORM_DATA = MimeType.valueOf("multipart/form-data");
|
||||
TEXT_HTML = valueOf("text/html");
|
||||
TEXT_PLAIN = valueOf("text/plain");
|
||||
IMAGE_JPG = valueOf("image/jpg");
|
||||
AUDIO_MP3 = valueOf("audio/mp3");
|
||||
VIDEO_MPEG4 = valueOf("video/mpeg4");
|
||||
TEXT_XML = valueOf("text/xml");
|
||||
}
|
||||
|
||||
public MimeType(String type) {
|
||||
this(type, WILDCARD_TYPE);
|
||||
}
|
||||
|
||||
public MimeType(String type, String subType) {
|
||||
this.type = type.toLowerCase(Locale.ENGLISH);
|
||||
this.subType = subType.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getSubType() {
|
||||
return subType;
|
||||
}
|
||||
|
||||
public boolean isWildcardType() {
|
||||
return WILDCARD_TYPE.equals(getType());
|
||||
}
|
||||
|
||||
public boolean isWildcardSubtype() {
|
||||
return WILDCARD_TYPE.equals(getSubType()) || getSubType().startsWith("*+");
|
||||
}
|
||||
|
||||
public static MimeType valueOf(String value) {
|
||||
if (StringUtil.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
String mimeType = StringUtil.tokenizeToStringArray(value, ";")[0].trim().toLowerCase(Locale.ENGLISH);
|
||||
if (WILDCARD_TYPE.equals(mimeType)) {
|
||||
mimeType = "*/*";
|
||||
}
|
||||
int subIndex = mimeType.indexOf('/');
|
||||
if (subIndex == -1) {
|
||||
throw new IllegalArgumentException(mimeType + ":does not contain '/'");
|
||||
}
|
||||
if (subIndex == mimeType.length() - 1) {
|
||||
throw new IllegalArgumentException(mimeType + ":does not contain subtype after '/'");
|
||||
}
|
||||
String type = mimeType.substring(0, subIndex);
|
||||
String subType = mimeType.substring(subIndex + 1, mimeType.length());
|
||||
if (WILDCARD_TYPE.equals(type) && !WILDCARD_TYPE.equals(subType)) {
|
||||
throw new IllegalArgumentException(mimeType + ":wildcard type is legal only in '*/*' (all mime types)");
|
||||
}
|
||||
return new MimeType(type, subType);
|
||||
}
|
||||
|
||||
/**
|
||||
* reference of apache Spring Web
|
||||
*/
|
||||
public boolean includes(MimeType other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.isWildcardType()) {
|
||||
// */* includes anything
|
||||
return true;
|
||||
} else if (getType().equals(other.getType())) {
|
||||
if (getSubType().equals(other.getSubType())) {
|
||||
return true;
|
||||
}
|
||||
if (this.isWildcardSubtype()) {
|
||||
// wildcard with suffix, e.g. application/*+xml
|
||||
int thisPlusIdx = getSubType().indexOf('+');
|
||||
if (thisPlusIdx == -1) {
|
||||
return true;
|
||||
} else {
|
||||
// application/*+xml includes application/soap+xml
|
||||
int otherPlusIdx = other.getSubType().indexOf('+');
|
||||
if (otherPlusIdx != -1) {
|
||||
String thisSubtypeNoSuffix = getSubType().substring(0, thisPlusIdx);
|
||||
String thisSubtypeSuffix = getSubType().substring(thisPlusIdx + 1);
|
||||
String otherSubtypeSuffix = other.getSubType().substring(otherPlusIdx + 1);
|
||||
if (thisSubtypeSuffix.equals(otherSubtypeSuffix) && WILDCARD_TYPE.equals(thisSubtypeNoSuffix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s/%s", this.type, this.subType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof MimeType)) {
|
||||
return false;
|
||||
}
|
||||
MimeType otherType = (MimeType) other;
|
||||
return this.type.equalsIgnoreCase(otherType.type) && this.subType.equalsIgnoreCase(otherType.subType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((subType == null) ? 0 : subType.hashCode());
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public class SimpleHttpClient extends AbstractHttpClient implements HttpClient {
|
||||
}
|
||||
if (httpEntity.getContentType() != null) {
|
||||
connection.setRequestProperty(HttpHeaders.CONTENT_TYPE,
|
||||
httpEntity.getContentType().getMimeType());
|
||||
httpEntity.getContentType().toString());
|
||||
}
|
||||
logger.debug("entity >> " + httpEntity.getContentType() + "("
|
||||
+ httpEntity.getContentLength() + "byte)");
|
||||
|
||||
@@ -137,6 +137,7 @@ public class MultipartEntity implements HttpEntity {
|
||||
return !isRepeatable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentLength() {
|
||||
if (this.dirty) {
|
||||
this.length = this.multipart.getTotalLength();
|
||||
@@ -145,6 +146,7 @@ public class MultipartEntity implements HttpEntity {
|
||||
return this.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType getContentType() {
|
||||
return ContentType.MULTIPART_FORM_DATA;
|
||||
}
|
||||
@@ -157,12 +159,14 @@ public class MultipartEntity implements HttpEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getContent() throws IOException,
|
||||
UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException(
|
||||
"Multipart form entity does not implement #getContent()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(final OutputStream outstream) throws IOException {
|
||||
this.multipart.writeTo(outstream);
|
||||
outstream.flush();
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
public abstract class AbstractMessageConverter implements MessageConverter {
|
||||
|
||||
protected Charset charset = Consts.UTF_8;
|
||||
|
||||
private List<MimeType> supportedMimeTypes;
|
||||
|
||||
protected AbstractMessageConverter() {
|
||||
this.supportedMimeTypes = Collections.emptyList();
|
||||
}
|
||||
|
||||
protected AbstractMessageConverter(MimeType supportedMimeType) {
|
||||
setSupportedMediaTypes(Collections.singletonList(supportedMimeType));
|
||||
}
|
||||
|
||||
protected AbstractMessageConverter(MimeType... supportedMimeTypes) {
|
||||
setSupportedMediaTypes(Arrays.asList(supportedMimeTypes));
|
||||
}
|
||||
|
||||
public void setSupportedMediaTypes(List<MimeType> supportedMimeTypes) {
|
||||
this.supportedMimeTypes = new ArrayList<MimeType>(supportedMimeTypes);
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
public void setCharset(Charset charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimeType> supportedMimeTypes() {
|
||||
return Collections.unmodifiableList(this.supportedMimeTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> clazz, HttpResponse response) {
|
||||
MimeType mimeType = MimeType.valueOf(response.getHeaders().getContentType());
|
||||
byte[] content = response.getContent();
|
||||
return supports(clazz, mimeType) || supports(clazz, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 满足其中一个supports
|
||||
*
|
||||
* @param clazz
|
||||
* 转换类型
|
||||
* @param mimeType
|
||||
* 媒体类型
|
||||
* @return 支持标识
|
||||
*/
|
||||
protected boolean supports(Class<?> clazz, MimeType mimeType) {
|
||||
if (mimeType == null) {
|
||||
return true;
|
||||
}
|
||||
for (MimeType supportedMediaType : supportedMimeTypes()) {
|
||||
if (supportedMediaType.includes(mimeType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 满足其中一个supports
|
||||
*
|
||||
* @param clazz
|
||||
* 转换类型
|
||||
* @param content
|
||||
* 内容数据
|
||||
* @return 支持标识
|
||||
*/
|
||||
protected abstract boolean supports(Class<?> clazz, byte[] content);
|
||||
|
||||
@Override
|
||||
public <T> T convert(Class<? extends T> clazz, HttpResponse response) throws IOException {
|
||||
return convertInternal(clazz, response.getBody());
|
||||
}
|
||||
|
||||
protected abstract <T> T convertInternal(Class<? extends T> clazz, InputStream body) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 调用接口的返回
|
||||
*
|
||||
* @className ApiResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年9月24日
|
||||
* @since JDK 1.6
|
||||
* @see <a href=
|
||||
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234&token=&lang=zh_CN">公众平台全局返回码说明</a>
|
||||
* @see <a href=
|
||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E">企业号全局返回码说明</a>
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class ApiResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
/**
|
||||
* 调用接口返回码,通信标识
|
||||
*/
|
||||
@XmlElement(name = "return_code")
|
||||
@JSONField(name = "errcode")
|
||||
private String returnCode;
|
||||
|
||||
/**
|
||||
* 调用接口返回消息,如非 空,为错误原因 可能为空
|
||||
*/
|
||||
@XmlElement(name = "return_msg")
|
||||
@JSONField(name = "errmsg")
|
||||
private String returnMsg;
|
||||
|
||||
public ApiResult() {
|
||||
this.returnCode = "0";
|
||||
this.returnMsg = "OK";
|
||||
}
|
||||
|
||||
public ApiResult(String returnCode, String returnMsg) {
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "returnCode=" + returnCode + ", returnMsg=" + returnMsg;
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.http.HttpHeaders;
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
import com.foxinmy.weixin4j.util.FileUtil;
|
||||
import com.foxinmy.weixin4j.util.IOUtil;
|
||||
import com.foxinmy.weixin4j.util.RegexUtil;
|
||||
|
||||
/**
|
||||
* JSON 转换
|
||||
*
|
||||
* @className JsonMessageConverter
|
||||
* @author jinyu
|
||||
* @date Jul 20, 2016
|
||||
* @since JDK 1.8
|
||||
*/
|
||||
public class JsonMessageConverter extends AbstractMessageConverter {
|
||||
|
||||
public static final JsonMessageConverter GLOBAL = new JsonMessageConverter();
|
||||
|
||||
private static final String JSO = "json";
|
||||
private static final int BRACE = 1 << '{';
|
||||
private static final int BRACKET = 1 << '[';
|
||||
private static final int MASK = BRACE | BRACKET;
|
||||
|
||||
public JsonMessageConverter() {
|
||||
super(MimeType.APPLICATION_JSON, new MimeType("application", "*+json"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> clazz, HttpResponse response) {
|
||||
if (!super.canConvert(clazz, response)) {
|
||||
String disposition = response.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION);
|
||||
String fileName = RegexUtil.regexFileNameFromContentDispositionHeader(disposition);
|
||||
return (fileName != null && FileUtil.getFileExtension(fileName).equalsIgnoreCase(JSO));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz, byte[] content) {
|
||||
return (MASK & (1 << content[0])) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T convertInternal(Class<? extends T> clazz, InputStream body) throws IOException {
|
||||
byte[] bytes = IOUtil.toByteArray(body);
|
||||
return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
|
||||
/**
|
||||
* 消息转换接口
|
||||
*
|
||||
* @className MessageConverter
|
||||
* @author jinyu
|
||||
* @date Jul 20, 2016
|
||||
* @since JDK 1.8
|
||||
* @see
|
||||
*/
|
||||
public interface MessageConverter {
|
||||
/**
|
||||
* 获取可以转换的媒体类型
|
||||
*
|
||||
* @return 媒体列表
|
||||
*/
|
||||
public List<MimeType> supportedMimeTypes();
|
||||
|
||||
/**
|
||||
* 是否可以转换
|
||||
*
|
||||
* @param clazz
|
||||
* 转换类型
|
||||
* @param response
|
||||
* 响应对象
|
||||
* @return 是否标识
|
||||
*/
|
||||
public boolean canConvert(Class<?> clazz, HttpResponse response);
|
||||
|
||||
/**
|
||||
* 转换消息
|
||||
*
|
||||
* @param clazz
|
||||
* 转换类型
|
||||
* @param response
|
||||
* 响应对象
|
||||
* @throws IOException
|
||||
* @return 消息对象
|
||||
*/
|
||||
public <T> T convert(Class<? extends T> clazz, HttpResponse response) throws IOException;
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.foxinmy.weixin4j.http.HttpHeaders;
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
import com.foxinmy.weixin4j.util.FileUtil;
|
||||
import com.foxinmy.weixin4j.util.RegexUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* XML 转换
|
||||
*
|
||||
* @className XmlMessageConverter
|
||||
* @author jinyu
|
||||
* @date Jul 20, 2016
|
||||
* @since JDK 1.8
|
||||
*/
|
||||
public class XmlMessageConverter extends AbstractMessageConverter {
|
||||
|
||||
public static final XmlMessageConverter GLOBAL = new XmlMessageConverter();
|
||||
|
||||
private static final String XML = "xml";
|
||||
private static final int BRACKET = '<';
|
||||
|
||||
public XmlMessageConverter() {
|
||||
super(MimeType.APPLICATION_XML, MimeType.TEXT_XML, new MimeType("application", "*+xml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> clazz, HttpResponse response) {
|
||||
if (!super.canConvert(clazz, response)) {
|
||||
String disposition = response.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION);
|
||||
String fileName = RegexUtil.regexFileNameFromContentDispositionHeader(disposition);
|
||||
return (fileName != null && FileUtil.getFileExtension(fileName).equalsIgnoreCase(XML));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz, byte[] content) {
|
||||
return BRACKET == content[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T convertInternal(Class<? extends T> clazz, InputStream body) throws IOException {
|
||||
return XmlStream.fromXML(body, clazz);
|
||||
}
|
||||
}
|
||||
+6
-39
@@ -1,6 +1,4 @@
|
||||
package com.foxinmy.weixin4j.http.weixin;
|
||||
|
||||
import java.io.Serializable;
|
||||
package com.foxinmy.weixin4j.http.message;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
@@ -20,22 +18,10 @@ import com.alibaba.fastjson.annotation.JSONField;
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class XmlResult implements Serializable {
|
||||
public class XmlResult extends ApiResult {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
/**
|
||||
* 此字段是通信标识,非交易 标识,交易是否成功需要查 看 result_code 来判断非空
|
||||
*/
|
||||
@XmlElement(name = "return_code")
|
||||
@JSONField(name = "return_code")
|
||||
private String returnCode;
|
||||
/**
|
||||
* 返回信息,如非 空,为错误原因 可能为空
|
||||
*/
|
||||
@XmlElement(name = "return_msg")
|
||||
@JSONField(name = "return_msg")
|
||||
private String returnMsg;
|
||||
|
||||
/**
|
||||
* 业务结果SUCCESS/FAIL 非空
|
||||
*/
|
||||
@@ -55,20 +41,11 @@ public class XmlResult implements Serializable {
|
||||
@JSONField(name = "err_code_des")
|
||||
private String errCodeDes;
|
||||
|
||||
public XmlResult() {
|
||||
protected XmlResult() {
|
||||
}
|
||||
|
||||
public XmlResult(String returnCode, String returnMsg) {
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return returnMsg;
|
||||
super(returnCode, returnMsg);
|
||||
}
|
||||
|
||||
public String getResultCode() {
|
||||
@@ -83,14 +60,6 @@ public class XmlResult implements Serializable {
|
||||
return errCodeDes;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public void setResultCode(String resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
@@ -105,8 +74,6 @@ public class XmlResult implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "returnCode=" + returnCode + ", returnMsg=" + returnMsg
|
||||
+ ", resultCode=" + resultCode + ", errCode=" + errCode
|
||||
+ ", errCodeDes=" + errCodeDes;
|
||||
return super.toString() + ", resultCode=" + resultCode + ", errCode=" + errCode + ", errCodeDes=" + errCodeDes;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.foxinmy.weixin4j.http.weixin;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 调用接口返回JSON格式
|
||||
*
|
||||
* @className JsonResult
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年9月24日
|
||||
* @since JDK 1.6
|
||||
* @see <a
|
||||
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433747234&token=&lang=zh_CN">公众平台全局返回码说明</a>
|
||||
* @see <a
|
||||
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E">企业号全局返回码说明</a>
|
||||
*/
|
||||
public class JsonResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
@JSONField(name = "errcode")
|
||||
private int code;
|
||||
@JSONField(name = "errmsg")
|
||||
private String desc;
|
||||
private String text;
|
||||
|
||||
public JsonResult() {
|
||||
this.desc = "";
|
||||
this.text = "";
|
||||
}
|
||||
|
||||
public JsonResult(int code, String desc, String text) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonResult [code=" + code + ", desc=" + desc + ", text=" + text
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
+28
-80
@@ -1,13 +1,11 @@
|
||||
package com.foxinmy.weixin4j.http.weixin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSONException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.ContentType;
|
||||
import com.foxinmy.weixin4j.http.HttpClient;
|
||||
import com.foxinmy.weixin4j.http.HttpClientException;
|
||||
import com.foxinmy.weixin4j.http.HttpHeaders;
|
||||
import com.foxinmy.weixin4j.http.HttpMethod;
|
||||
import com.foxinmy.weixin4j.http.HttpParams;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
@@ -19,10 +17,12 @@ import com.foxinmy.weixin4j.http.entity.FormUrlEntity;
|
||||
import com.foxinmy.weixin4j.http.entity.HttpEntity;
|
||||
import com.foxinmy.weixin4j.http.entity.StringEntity;
|
||||
import com.foxinmy.weixin4j.http.factory.HttpClientFactory;
|
||||
import com.foxinmy.weixin4j.http.message.ApiResult;
|
||||
import com.foxinmy.weixin4j.http.message.XmlMessageConverter;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.logging.InternalLogger;
|
||||
import com.foxinmy.weixin4j.logging.InternalLoggerFactory;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* 负责微信请求的执行
|
||||
@@ -35,8 +35,9 @@ import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
*/
|
||||
public class WeixinRequestExecutor {
|
||||
|
||||
protected final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
protected final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
private static final String SUCCESS_CODE = ",0,success,";
|
||||
|
||||
protected final HttpClient httpClient;
|
||||
protected final HttpParams httpParams;
|
||||
@@ -55,8 +56,7 @@ public class WeixinRequestExecutor {
|
||||
return doRequest(request);
|
||||
}
|
||||
|
||||
public WeixinResponse get(String url, Map<String, String> parameters)
|
||||
throws WeixinException {
|
||||
public WeixinResponse get(String url, Map<String, String> parameters) throws WeixinException {
|
||||
StringBuilder buf = new StringBuilder(url);
|
||||
if (parameters != null && !parameters.isEmpty()) {
|
||||
if (url.indexOf("?") < 0) {
|
||||
@@ -81,10 +81,8 @@ public class WeixinRequestExecutor {
|
||||
return doRequest(request);
|
||||
}
|
||||
|
||||
public WeixinResponse post(String url, FormBodyPart... bodyParts)
|
||||
throws WeixinException {
|
||||
MultipartEntity entity = new MultipartEntity(
|
||||
HttpMultipartMode.BROWSER_COMPATIBLE, null, Consts.UTF_8);
|
||||
public WeixinResponse post(String url, FormBodyPart... bodyParts) throws WeixinException {
|
||||
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Consts.UTF_8);
|
||||
for (FormBodyPart bodyPart : bodyParts) {
|
||||
entity.addPart(bodyPart);
|
||||
}
|
||||
@@ -93,85 +91,35 @@ public class WeixinRequestExecutor {
|
||||
return doRequest(request);
|
||||
}
|
||||
|
||||
protected WeixinResponse doRequest(HttpRequest request)
|
||||
throws WeixinException {
|
||||
protected WeixinResponse doRequest(HttpRequest request) throws WeixinException {
|
||||
request.setParams(httpParams);
|
||||
try {
|
||||
logger.info("weixin request >> " + request.getMethod() + " "
|
||||
+ request.getURI().toString());
|
||||
logger.info("weixin request >> " + request.getMethod() + " " + request.getURI().toString());
|
||||
HttpResponse httpResponse = httpClient.execute(request);
|
||||
HttpHeaders headers = httpResponse.getHeaders();
|
||||
WeixinResponse response = new WeixinResponse(httpResponse);
|
||||
logger.info("weixin response << " + httpResponse.getProtocol()
|
||||
+ httpResponse.getStatus() + ":" + response.getAsString());
|
||||
String contentType = headers.getFirst(HttpHeaders.CONTENT_TYPE);
|
||||
String disposition = headers
|
||||
.getFirst(HttpHeaders.CONTENT_DISPOSITION);
|
||||
// json
|
||||
if (contentType
|
||||
.contains(ContentType.APPLICATION_JSON.getMimeType())
|
||||
|| (disposition != null && disposition.indexOf(".json") > 0)) {
|
||||
checkJson(response);
|
||||
} else if (contentType.contains(ContentType.TEXT_XML.getMimeType())) {
|
||||
checkXml(response);
|
||||
} else if (contentType.contains(ContentType.TEXT_PLAIN
|
||||
.getMimeType())
|
||||
|| contentType
|
||||
.contains(ContentType.TEXT_HTML.getMimeType())) {
|
||||
try {
|
||||
checkJson(response);
|
||||
return response;
|
||||
} catch (JSONException e) {
|
||||
;
|
||||
}
|
||||
try {
|
||||
checkXml(response);
|
||||
return response;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
;
|
||||
}
|
||||
throw new WeixinException(response.getAsString());
|
||||
}
|
||||
logger.info("weixin response << " + httpResponse.getProtocol() + httpResponse.getStatus() + ":"
|
||||
+ response.getAsString());
|
||||
handlResponse(response);
|
||||
return response;
|
||||
} catch (HttpClientException e) {
|
||||
throw new WeixinException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkJson(WeixinResponse response) throws WeixinException {
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
response.setJsonResult(true);
|
||||
if (jsonResult.getCode() != 0) {
|
||||
throw new WeixinException(Integer.toString(jsonResult.getCode()),
|
||||
jsonResult.getDesc());
|
||||
protected void handlResponse(WeixinResponse response) throws WeixinException {
|
||||
ApiResult result = response.getAsResult();
|
||||
if (!SUCCESS_CODE.contains(String.format(",%s,", result.getReturnCode().toLowerCase()))) {
|
||||
throw new WeixinException(result.getReturnCode(), result.getReturnMsg());
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkXml(WeixinResponse response) throws WeixinException {
|
||||
String xmlContent = response.getAsString();
|
||||
if (xmlContent.length() != xmlContent.replaceFirst("<retcode>",
|
||||
"<return_code>").length()) {
|
||||
// <?xml><root><data..../data></root>
|
||||
xmlContent = xmlContent.replaceFirst("<root>", "<xml>")
|
||||
.replaceFirst("<retcode>", "<return_code>")
|
||||
.replaceFirst("</retcode>", "</return_code>")
|
||||
.replaceFirst("<retmsg>", "<return_msg>")
|
||||
.replaceFirst("</retmsg>", "</return_msg>")
|
||||
.replaceFirst("</root>", "</xml>");
|
||||
}
|
||||
XmlResult xmlResult = XmlStream.fromXML(xmlContent, XmlResult.class);
|
||||
response.setText(xmlContent);
|
||||
response.setXmlResult(true);
|
||||
if ("0".equals(xmlResult.getReturnCode())) {
|
||||
return;
|
||||
}
|
||||
if (!Consts.SUCCESS.equalsIgnoreCase(xmlResult.getReturnCode())) {
|
||||
throw new WeixinException(xmlResult.getReturnCode(),
|
||||
xmlResult.getReturnMsg());
|
||||
}
|
||||
if (!Consts.SUCCESS.equalsIgnoreCase(xmlResult.getResultCode())) {
|
||||
throw new WeixinException(xmlResult.getErrCode(),
|
||||
xmlResult.getErrCodeDes());
|
||||
if (XmlMessageConverter.GLOBAL.canConvert(XmlResult.class, response)) {
|
||||
try {
|
||||
XmlResult xmlResult = XmlMessageConverter.GLOBAL.convert(XmlResult.class, response);
|
||||
if (!SUCCESS_CODE.contains(xmlResult.getResultCode())) {
|
||||
throw new WeixinException(xmlResult.getErrCode(), xmlResult.getErrCodeDes());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.foxinmy.weixin4j.http.weixin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@@ -8,73 +11,102 @@ import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.http.HttpHeaders;
|
||||
import com.foxinmy.weixin4j.http.HttpResponse;
|
||||
import com.foxinmy.weixin4j.http.HttpStatus;
|
||||
import com.foxinmy.weixin4j.http.HttpVersion;
|
||||
import com.foxinmy.weixin4j.http.message.ApiResult;
|
||||
import com.foxinmy.weixin4j.http.message.JsonMessageConverter;
|
||||
import com.foxinmy.weixin4j.http.message.MessageConverter;
|
||||
import com.foxinmy.weixin4j.http.message.XmlMessageConverter;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
public class WeixinResponse {
|
||||
/**
|
||||
* 调用微信接口响应
|
||||
*
|
||||
* @className WeixinResponse
|
||||
* @author jinyu
|
||||
* @date Jul 21, 2016
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
public class WeixinResponse implements HttpResponse {
|
||||
|
||||
private boolean isJsonResult;
|
||||
private boolean isXmlResult;
|
||||
private volatile String text;
|
||||
|
||||
private final HttpResponse response;
|
||||
private static List<MessageConverter> messageConverters = new ArrayList<MessageConverter>();
|
||||
private final TypeReference<ApiResult> APIRESULT_CLAZZ = new TypeReference<ApiResult>() {
|
||||
};
|
||||
private final TypeReference<XmlResult> XMLRESULT_CLAZZ = new TypeReference<XmlResult>() {
|
||||
};
|
||||
|
||||
static {
|
||||
messageConverters.add(new JsonMessageConverter());
|
||||
messageConverters.add(new XmlMessageConverter());
|
||||
}
|
||||
|
||||
public WeixinResponse(HttpResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public void setJsonResult(boolean isJsonResult) {
|
||||
this.isJsonResult = isJsonResult;
|
||||
}
|
||||
|
||||
public void setXmlResult(boolean isXmlResult) {
|
||||
this.isXmlResult = isXmlResult;
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
if (text == null) {
|
||||
text = StringUtil.newStringUtf8(response.getContent());
|
||||
text = StringUtil.newStringUtf8(getContent());
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public JsonResult getAsJsonResult() {
|
||||
return JSON.parseObject(getAsString(), JsonResult.class);
|
||||
public ApiResult getAsResult() {
|
||||
return getAsObject(APIRESULT_CLAZZ);
|
||||
}
|
||||
|
||||
public JSONObject getAsJson() {
|
||||
return JSON.parseObject(getAsString());
|
||||
}
|
||||
|
||||
public XmlResult getAsXml() {
|
||||
return getAsObject(XMLRESULT_CLAZZ);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAsObject(TypeReference<T> typeReference) {
|
||||
if (isJsonResult) {
|
||||
return JSON.parseObject(getAsString(), typeReference);
|
||||
Class<T> clazz = (Class<T>) typeReference.getType();
|
||||
for (MessageConverter messageConverter : messageConverters) {
|
||||
if (messageConverter.canConvert(clazz, response)) {
|
||||
try {
|
||||
return messageConverter.convert(clazz, response);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("IO error on convert to " + typeReference, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isXmlResult) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> clazz = (Class<T>) typeReference.getType();
|
||||
return XmlStream.fromXML(getAsString(), clazz);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public XmlResult getAsXmlResult() {
|
||||
return XmlStream.fromXML(getAsString(), XmlResult.class);
|
||||
throw new RuntimeException("cannot convert to " + typeReference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return response.getHeaders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatus() {
|
||||
return response.getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getContent() {
|
||||
return response.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() {
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpVersion getProtocol() {
|
||||
return response.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.foxinmy.weixin4j.api.CouponApi;
|
||||
import com.foxinmy.weixin4j.api.CustomsApi;
|
||||
import com.foxinmy.weixin4j.api.PayApi;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Pageable;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
|
||||
|
||||
@@ -6,7 +6,7 @@ import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.type.RedpacketSendType;
|
||||
import com.foxinmy.weixin4j.type.RedpacketStatus;
|
||||
import com.foxinmy.weixin4j.type.RedpacketType;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
package com.foxinmy.weixin4j.type;
|
||||
|
||||
import com.foxinmy.weixin4j.http.ContentType;
|
||||
import com.foxinmy.weixin4j.http.MimeType;
|
||||
|
||||
/**
|
||||
* 上传的媒体类型</br>
|
||||
* <p>
|
||||
* 公众平台上传限制:</br> 图片(image): 2MB,支持bmp/png/jpeg/jpg/gif格式</br>
|
||||
* 公众平台上传限制:</br>
|
||||
* 图片(image): 2MB,支持bmp/png/jpeg/jpg/gif格式</br>
|
||||
* 语音(voice):2MB,播放长度不超过60s,支持mp3/wma/wav/amr格式</br>
|
||||
* 视频(video):10MB,支持rm/rmvb/wmv/avi/mpg/mpeg/mp4格式</br>
|
||||
* 缩略图(thumb):64KB,支持JPG格式</br>
|
||||
* </p>
|
||||
* <p>
|
||||
* 企业号上传限制:</br> 图片(image):1MB,支持bmp/png/jpeg/jpg/gif格式</br>
|
||||
* 企业号上传限制:</br>
|
||||
* 图片(image):1MB,支持bmp/png/jpeg/jpg/gif格式</br>
|
||||
* 语音(voice):2MB,播放长度不超过60s,支持mp3/wma/wav/amr格式</br>
|
||||
* 视频(video):10MB,支持rm/rmvb/wmv/avi/mpg/mpeg/mp4格式</br> 普通文件(file):20MB</br>
|
||||
* 视频(video):10MB,支持rm/rmvb/wmv/avi/mpg/mpeg/mp4格式</br>
|
||||
* 普通文件(file):20MB</br>
|
||||
* </p>
|
||||
* <p>
|
||||
* <font color='red'>临时媒体文件在后台保存时间为3天,即3天后media_id失效</font>
|
||||
@@ -24,18 +27,16 @@ import com.foxinmy.weixin4j.http.ContentType;
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
public enum MediaType {
|
||||
image(ContentType.IMAGE_JPG), voice(ContentType.AUDIO_MP3), video(
|
||||
ContentType.VIDEO_MPEG4), thumb(ContentType.IMAGE_JPG), file(
|
||||
ContentType.MULTIPART_FORM_DATA), news(
|
||||
ContentType.MULTIPART_FORM_DATA);
|
||||
image(MimeType.IMAGE_JPG), voice(MimeType.AUDIO_MP3), video(MimeType.VIDEO_MPEG4), thumb(MimeType.IMAGE_JPG), file(
|
||||
MimeType.MULTIPART_FORM_DATA), news(MimeType.MULTIPART_FORM_DATA);
|
||||
|
||||
MediaType(ContentType contentType) {
|
||||
this.contentType = contentType;
|
||||
MediaType(MimeType mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
private ContentType contentType;
|
||||
private MimeType mimeType;
|
||||
|
||||
public ContentType getContentType() {
|
||||
return contentType;
|
||||
public MimeType getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
@@ -62,9 +65,7 @@ public final class StringUtil {
|
||||
return str;
|
||||
}
|
||||
|
||||
return new StringBuilder(strLen)
|
||||
.append(Character.toLowerCase(firstChar))
|
||||
.append(str.substring(1)).toString();
|
||||
return new StringBuilder(strLen).append(Character.toLowerCase(firstChar)).append(str.substring(1)).toString();
|
||||
}
|
||||
|
||||
public static String capitalize(final String str) {
|
||||
@@ -78,13 +79,10 @@ public final class StringUtil {
|
||||
// already capitalized
|
||||
return str;
|
||||
}
|
||||
return new StringBuilder(strLen)
|
||||
.append(Character.toTitleCase(firstChar))
|
||||
.append(str.substring(1)).toString();
|
||||
return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString();
|
||||
}
|
||||
|
||||
public static String substringBefore(final String str,
|
||||
final String separator) {
|
||||
public static String substringBefore(final String str, final String separator) {
|
||||
if (isEmpty(str) || separator == null) {
|
||||
return str;
|
||||
}
|
||||
@@ -119,8 +117,7 @@ public final class StringUtil {
|
||||
return join(array, separator, 0, array.length);
|
||||
}
|
||||
|
||||
public static String join(final Object[] array, final char separator,
|
||||
final int startIndex, final int endIndex) {
|
||||
public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -187,8 +184,7 @@ public final class StringUtil {
|
||||
return join(array, separator, 0, array.length);
|
||||
}
|
||||
|
||||
public static String join(final int[] array, final char separator,
|
||||
final int startIndex, final int endIndex) {
|
||||
public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -234,4 +230,28 @@ public final class StringUtil {
|
||||
return clazz.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] tokenizeToStringArray(String str, String delimiters) {
|
||||
return tokenizeToStringArray(str, delimiters, true, true);
|
||||
}
|
||||
|
||||
public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens,
|
||||
boolean ignoreEmptyTokens) {
|
||||
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer st = new StringTokenizer(str, delimiters);
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken();
|
||||
if (trimTokens) {
|
||||
token = token.trim();
|
||||
}
|
||||
if (!ignoreEmptyTokens || token.length() > 0) {
|
||||
tokens.add(token);
|
||||
}
|
||||
}
|
||||
return tokens.toArray(new String[tokens.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public final class XmlStream {
|
||||
unmarshaller = jaxbContext.createUnmarshaller();
|
||||
messageUnmarshaller.put(clazz, unmarshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -83,7 +83,7 @@ public final class XmlStream {
|
||||
return (T) unmarshaller.unmarshal(source);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (content != null) {
|
||||
try {
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.http.message.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.WeixinPayProxy;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
|
||||
@@ -45,7 +45,7 @@ public class PayTest {
|
||||
static {
|
||||
ACCOUNT = new WeixinPayAccount("appid", "paysignkey", "mchid");
|
||||
SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey());
|
||||
PAY = new WeixinPayProxy(new Weixin4jSettings(ACCOUNT));
|
||||
PAY = new WeixinPayProxy(new Weixin4jSettings<WeixinPayAccount>(ACCOUNT));
|
||||
}
|
||||
/**
|
||||
* 商户证书文件
|
||||
|
||||
Reference in New Issue
Block a user