weixin-mp & pay
This commit is contained in:
+12
-3
@@ -1,12 +1,21 @@
|
||||
weixin4j-base
|
||||
=============
|
||||
|
||||
tencent weixin base java sdk 微信开发基础工程
|
||||
@(weixin4j)[base]
|
||||
|
||||
微信开发基础工程
|
||||
--------------
|
||||
|
||||
功能列表
|
||||
-------
|
||||
`Token的实现`
|
||||
|
||||
`通用消息实体`
|
||||
|
||||
更新LOG
|
||||
-------
|
||||
* 2014-10-31
|
||||
|
||||
1).TokenApi重命名为TokenHolder
|
||||
+ `TokenApi`重命名为`TokenHolder`
|
||||
|
||||
2).新增WeixinConfig等类
|
||||
+ 新增`WeixinConfig`等类
|
||||
@@ -10,7 +10,10 @@
|
||||
</parent>
|
||||
<artifactId>weixin4j-base</artifactId>
|
||||
<name>weixin4j-base</name>
|
||||
<url>https://github.com/foxinmy</url>
|
||||
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-base</url>
|
||||
<build>
|
||||
<finalName>weixin4j-base</finalName>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 调用接口响应值
|
||||
*
|
||||
* @className BaseResult
|
||||
* @author jy.hu
|
||||
* @date 2014年9月24日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.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>
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class BaseResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
private String errcode = "0";
|
||||
@XStreamAlias("return_msg")
|
||||
private String errmsg = "";
|
||||
private String msgid;
|
||||
private String text;
|
||||
|
||||
public BaseResult() {
|
||||
|
||||
}
|
||||
|
||||
public BaseResult(String errcode, String errmsg, String text) {
|
||||
this(errcode, errmsg, null, text);
|
||||
}
|
||||
|
||||
public BaseResult(String errcode, String errmsg, String msgid, String text) {
|
||||
this.errcode = errcode;
|
||||
this.errmsg = errmsg;
|
||||
this.msgid = msgid;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getErrcode() {
|
||||
return errcode;
|
||||
}
|
||||
|
||||
public void setErrcode(String errcode) {
|
||||
this.errcode = errcode;
|
||||
}
|
||||
|
||||
public String getErrmsg() {
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
public void setErrmsg(String errmsg) {
|
||||
this.errmsg = errmsg;
|
||||
}
|
||||
|
||||
public String getMsgid() {
|
||||
return msgid;
|
||||
}
|
||||
|
||||
public void setMsgid(String msgid) {
|
||||
this.msgid = msgid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseResult [errcode=" + errcode + ", errmsg=" + errmsg
|
||||
+ ", msgid=" + msgid + ", text=" + text + "]";
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
* @see
|
||||
*/
|
||||
public class HttpRequest {
|
||||
private final String SUCCESS = "success";
|
||||
private AbstractHttpClient client;
|
||||
|
||||
public HttpRequest() {
|
||||
@@ -149,6 +150,7 @@ public class HttpRequest {
|
||||
|
||||
protected Response doRequest(HttpRequestBase request)
|
||||
throws WeixinException {
|
||||
Response response = null;
|
||||
try {
|
||||
HttpResponse httpResponse = client.execute(request);
|
||||
StatusLine statusLine = httpResponse.getStatusLine();
|
||||
@@ -166,38 +168,47 @@ public class HttpRequest {
|
||||
httpResponse.getFirstHeader("location")));
|
||||
}
|
||||
byte[] data = EntityUtils.toByteArray(httpEntity);
|
||||
Response response = new Response();
|
||||
response = new Response();
|
||||
response.setBody(data);
|
||||
response.setStatusCode(status);
|
||||
response.setStatusText(statusLine.getReasonPhrase());
|
||||
response.setStream(new ByteArrayInputStream(data));
|
||||
response.setText(new String(data, StandardCharsets.UTF_8));
|
||||
|
||||
EntityUtils.consume(httpEntity);
|
||||
Header contentType = httpResponse
|
||||
.getFirstHeader(HttpHeaders.CONTENT_TYPE);
|
||||
if (contentType.getValue().contains(
|
||||
ContentType.APPLICATION_JSON.getMimeType())
|
||||
|| contentType.getValue().contains(
|
||||
ContentType.TEXT_PLAIN.getMimeType())) {
|
||||
BaseResult result = null;
|
||||
response.setText(new String(data, StandardCharsets.UTF_8));
|
||||
try {
|
||||
result = response.getAsResult();
|
||||
} catch (JSONException e) {
|
||||
result = response.getAsXml(BaseResult.class);
|
||||
}
|
||||
if (result.getErrcode().equals("0")
|
||||
|| result.getErrcode().equalsIgnoreCase("success")) {
|
||||
EntityUtils.consume(httpEntity);
|
||||
JsonResult jsonResult = response.getAsJsonResult();
|
||||
response.setJsonResult(true);
|
||||
if (jsonResult.getCode() != 0) {
|
||||
throw new WeixinException(jsonResult.getCode() + "",
|
||||
jsonResult.getDesc());
|
||||
}
|
||||
return response;
|
||||
} catch (JSONException e) {
|
||||
;
|
||||
}
|
||||
XmlResult xmlResult = response.getAsXmlResult();
|
||||
response.setXmlResult(true);
|
||||
if (!xmlResult.getReturnCode().equalsIgnoreCase(SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getReturnCode(),
|
||||
xmlResult.getReturnMsg());
|
||||
}
|
||||
if (!xmlResult.getResultCode().equalsIgnoreCase(SUCCESS)) {
|
||||
throw new WeixinException(xmlResult.getErrCode(),
|
||||
xmlResult.getErrCodeDes());
|
||||
}
|
||||
throw new WeixinException(result.getErrcode(),
|
||||
result.getErrmsg());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
} finally {
|
||||
request.releaseConnection();
|
||||
}
|
||||
throw new WeixinException("-1", "request fail");
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 调用接口返回JSON格式
|
||||
*
|
||||
* @className JsonResult
|
||||
* @author jy.hu
|
||||
* @date 2014年9月24日
|
||||
* @since JDK 1.7
|
||||
* @see <a
|
||||
* href="http://mp.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
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import org.dom4j.io.SAXReader;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
public class Response {
|
||||
@@ -18,6 +19,8 @@ public class Response {
|
||||
private String statusText;
|
||||
private byte[] body;
|
||||
private InputStream stream;
|
||||
private boolean isJsonResult;
|
||||
private boolean isXmlResult;
|
||||
|
||||
public Response() {
|
||||
}
|
||||
@@ -26,26 +29,40 @@ public class Response {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void setJsonResult(boolean isJsonResult) {
|
||||
this.isJsonResult = isJsonResult;
|
||||
}
|
||||
|
||||
public void setXmlResult(boolean isXmlResult) {
|
||||
this.isXmlResult = isXmlResult;
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public BaseResult getAsResult() {
|
||||
return JSON.parseObject(text, BaseResult.class);
|
||||
public JsonResult getAsJsonResult() {
|
||||
return JSON.parseObject(text, JsonResult.class);
|
||||
}
|
||||
|
||||
public JSONObject getAsJson() {
|
||||
return JSON.parseObject(text);
|
||||
}
|
||||
|
||||
public <T> T getAsObject(Class<T> clazz) {
|
||||
return (T) JSON.parseObject(text, clazz);
|
||||
public <T> T getAsObject(TypeReference<T> typeReference) {
|
||||
if (isJsonResult) {
|
||||
return JSON.parseObject(text, typeReference);
|
||||
}
|
||||
if (isXmlResult) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> clazz = (Class<T>) typeReference.getType();
|
||||
return XStream.get(text, clazz);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getAsXml(Class<T> clazz) {
|
||||
XStream xStream = XStream.get();
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(text, clazz);
|
||||
public XmlResult getAsXmlResult() {
|
||||
return XStream.get(text, XmlResult.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,24 +73,22 @@ public class Response {
|
||||
* @return
|
||||
* @throws DocumentException
|
||||
*/
|
||||
public BaseResult getBaseError() throws DocumentException {
|
||||
BaseResult result = getAsResult();
|
||||
if (!result.getErrcode().equals("0")) {
|
||||
public JsonResult getTextError() throws DocumentException {
|
||||
JsonResult result = getAsJsonResult();
|
||||
if (result.getCode() != 0) {
|
||||
SAXReader reader = new SAXReader();
|
||||
Document doc = reader.read(Response.class.getResourceAsStream("error.xml"));
|
||||
Document doc = reader.read(Response.class
|
||||
.getResourceAsStream("error.xml"));
|
||||
Node node = doc.getRootElement().selectSingleNode(
|
||||
String.format("error[@code='%s']", result.getErrcode()));
|
||||
String.format("error/code[text()='%d']", result.getCode()));
|
||||
if (node != null) {
|
||||
result.setText(node.getStringValue());
|
||||
result.setText(node.getParent().selectSingleNode("text")
|
||||
.getStringValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.foxinmy.weixin4j.http;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 调用接口返回xml格式
|
||||
*
|
||||
* @className XmlResult
|
||||
* @author jy
|
||||
* @date 2014年11月1日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class XmlResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
public static final String SUCCESS = "SUCCESS";
|
||||
public static final String FAIL = "FAIL";
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
private String returnCode;// 此字段是通信标识,非交易 标识,交易是否成功需要查 看 result_code 来判断 非空
|
||||
@XStreamAlias("return_msg")
|
||||
private String returnMsg;// 返回信息,如非 空,为错误原因 可能为空
|
||||
@XStreamAlias("result_code")
|
||||
private String resultCode;// 业务结果SUCCESS/FAIL 非空
|
||||
@XStreamAlias("err_code")
|
||||
private String errCode;// 错误代码 可为空
|
||||
@XStreamAlias("err_code_des")
|
||||
private String errCodeDes;// 结果信息描述 可为空
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public String getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void setResultCode(String resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public String getErrCode() {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
public void setErrCode(String errCode) {
|
||||
this.errCode = errCode;
|
||||
}
|
||||
|
||||
public String getErrCodeDes() {
|
||||
return errCodeDes;
|
||||
}
|
||||
|
||||
public void setErrCodeDes(String errCodeDes) {
|
||||
this.errCodeDes = errCodeDes;
|
||||
}
|
||||
|
||||
public XmlResult() {
|
||||
this("success", "");
|
||||
}
|
||||
|
||||
public XmlResult(String returnCode, String returnMsg) {
|
||||
this.returnCode = returnCode;
|
||||
this.returnMsg = returnMsg;
|
||||
if (returnCode.equalsIgnoreCase(SUCCESS)) {
|
||||
this.resultCode = SUCCESS.toLowerCase();
|
||||
this.errCode = SUCCESS.toLowerCase();
|
||||
this.errCodeDes = "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XmlResult [returnCode=" + returnCode + ", returnMsg="
|
||||
+ returnMsg + ", resultCode=" + resultCode + ", errCode="
|
||||
+ errCode + ", errCodeDes=" + errCodeDes + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,97 +1,427 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- http://mp.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 -->
|
||||
<errors>
|
||||
<error code="-1">系统繁忙</error>
|
||||
<error code="40001">获取access_token时AppSecret错误,或者access_token无效</error>
|
||||
<error code="40002">不合法的凭证类型</error>
|
||||
<error code="40003">不合法的OpenID</error>
|
||||
<error code="40004">不合法的媒体文件类型</error>
|
||||
<error code="40005">不合法的文件类型</error>
|
||||
<error code="40006">不合法的文件大小</error>
|
||||
<error code="40007">不合法的媒体文件id</error>
|
||||
<error code="40008">不合法的消息类型</error>
|
||||
<error code="40009">不合法的图片文件大小</error>
|
||||
<error code="40010">不合法的语音文件大小</error>
|
||||
<error code="40011">不合法的视频文件大小</error>
|
||||
<error code="40012">不合法的缩略图文件大小</error>
|
||||
<error code="40013">不合法的APPID</error>
|
||||
<error code="40014">不合法的access_token</error>
|
||||
<error code="40015">不合法的菜单类型</error>
|
||||
<error code="40016">不合法的按钮个数</error>
|
||||
<error code="40017">不合法的按钮个数</error>
|
||||
<error code="40018">不合法的按钮名字长度</error>
|
||||
<error code="40019">不合法的按钮KEY长度</error>
|
||||
<error code="40020">不合法的按钮URL长度</error>
|
||||
<error code="40021">不合法的菜单版本号</error>
|
||||
<error code="40022">不合法的子菜单级数</error>
|
||||
<error code="40023">不合法的子菜单按钮个数</error>
|
||||
<error code="40024">不合法的子菜单按钮类型</error>
|
||||
<error code="40025">不合法的子菜单按钮名字长度</error>
|
||||
<error code="40026">不合法的子菜单按钮KEY长度</error>
|
||||
<error code="40027">不合法的子菜单按钮URL长度</error>
|
||||
<error code="40028">不合法的自定义菜单使用用户</error>
|
||||
<error code="40029">不合法的oauth_code</error>
|
||||
<error code="40030">不合法的refresh_token</error>
|
||||
<error code="40031">不合法的openid列表</error>
|
||||
<error code="40032">不合法的openid列表长度</error>
|
||||
<error code="40033">不合法的请求字符,不能包含\uxxxx格式的字符</error>
|
||||
<error code="40035">不合法的参数</error>
|
||||
<error code="40038">不合法的请求格式</error>
|
||||
<error code="40039">不合法的URL长度</error>
|
||||
<error code="40050">不合法的分组id</error>
|
||||
<error code="40051">分组名字不合法</error>
|
||||
<error code="41001">缺少access_token参数</error>
|
||||
<error code="41002">缺少appid参数</error>
|
||||
<error code="41003">缺少refresh_token参数</error>
|
||||
<error code="41004">缺少secret参数</error>
|
||||
<error code="41005">缺少多媒体文件数据</error>
|
||||
<error code="41006">缺少media_id参数</error>
|
||||
<error code="41007">缺少子菜单数据</error>
|
||||
<error code="41008">缺少oauth code</error>
|
||||
<error code="41009">缺少openid</error>
|
||||
<error code="42001">access_token超时</error>
|
||||
<error code="42002">refresh_token超时</error>
|
||||
<error code="42003">oauth_code超时</error>
|
||||
<error code="43001">需要GET请求</error>
|
||||
<error code="43002">需要POST请求</error>
|
||||
<error code="43003">需要HTTPS请求</error>
|
||||
<error code="43004">需要接收者关注</error>
|
||||
<error code="43005">需要好友关系</error>
|
||||
<error code="44001">多媒体文件为空</error>
|
||||
<error code="44002">POST的数据包为空</error>
|
||||
<error code="44003">图文消息内容为空</error>
|
||||
<error code="44004">文本消息内容为空</error>
|
||||
<error code="45001">多媒体文件大小超过限制</error>
|
||||
<error code="45002">消息内容超过限制</error>
|
||||
<error code="45003">标题字段超过限制</error>
|
||||
<error code="45004">描述字段超过限制</error>
|
||||
<error code="45005">链接字段超过限制</error>
|
||||
<error code="45006">图片链接字段超过限制</error>
|
||||
<error code="45007">语音播放时间超过限制</error>
|
||||
<error code="45008">图文消息超过限制</error>
|
||||
<error code="45009">接口调用超过限制</error>
|
||||
<error code="45010">创建菜单个数超过限制</error>
|
||||
<error code="45015">回复时间超过限制</error>
|
||||
<error code="45016">系统分组,不允许修改</error>
|
||||
<error code="45017">分组名字过长</error>
|
||||
<error code="45018">分组数量超过上限</error>
|
||||
<error code="46001">不存在媒体数据</error>
|
||||
<error code="46002">不存在的菜单版本</error>
|
||||
<error code="46003">不存在的菜单数据</error>
|
||||
<error code="46004">不存在的用户</error>
|
||||
<error code="47001">解析JSON/XML内容错误</error>
|
||||
<error code="48001">api功能未授权</error>
|
||||
<error code="50001">用户未授权该api</error>
|
||||
<error code="SYSTEMERROR">接口后台错误</error>
|
||||
<error code="INVALID_TRANSACTIONID">无效 transaction_id</error>
|
||||
<error code="PARAM_ERROR">提交参数错误</error>
|
||||
<error code="ORDERPAID">订单已支付</error>
|
||||
<error code="OUT_TRADE_NO_USED">商户订单号重复</error>
|
||||
<error code="NOAUTH">商户无权限</error>
|
||||
<error code="NOTENOUGH">余额不足</error>
|
||||
<error code="NOTSUPORTCARD">不支持卡类型</error>
|
||||
<error code="ORDERCLOSED">订单已关闭</error>
|
||||
<error code="BANKERROR">银行系统异常</error>
|
||||
<error code="REFUND_FEE_INVALID">退款金额大于支付金额</error>
|
||||
<error code="ORDERNOTEXIST">订单不存在</error>
|
||||
<error>
|
||||
<code>0</code>
|
||||
<desc>OK</desc>
|
||||
<text>请求成功</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>-1</code>
|
||||
<desc>system error</desc>
|
||||
<text>系统繁忙</text>
|
||||
</error>
|
||||
<!-- 公众平台API错误 -->
|
||||
<error>
|
||||
<code>40001</code>
|
||||
<desc>invalid credential</desc>
|
||||
<text>不合法的调用凭证</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40002</code>
|
||||
<desc>invalid grant_type</desc>
|
||||
<text>不合法的grant_type</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40003</code>
|
||||
<desc>invalid openid</desc>
|
||||
<text>不合法的OpenID</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40004</code>
|
||||
<desc>invalid media type</desc>
|
||||
<text>不合法的媒体文件类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40007</code>
|
||||
<desc>invalid media_id</desc>
|
||||
<text>不合法的media_id</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40008</code>
|
||||
<desc>invalid message type</desc>
|
||||
<text>不合法的message_type</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40009</code>
|
||||
<desc>invalid image size</desc>
|
||||
<text>不合法的图片大小</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40010</code>
|
||||
<desc>invalid voice size</desc>
|
||||
<text>不合法的语音大小</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40011</code>
|
||||
<desc>invalid video size</desc>
|
||||
<text>不合法的视频大小</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40012</code>
|
||||
<desc>invalid thumb size</desc>
|
||||
<text>不合法的缩略图大小</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40013</code>
|
||||
<desc>invalid appid</desc>
|
||||
<text>不合法的AppID</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40014</code>
|
||||
<desc>invalid access_token</desc>
|
||||
<text>不合法的access_token</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40015</code>
|
||||
<desc>invalid menu type</desc>
|
||||
<text>不合法的菜单类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40016</code>
|
||||
<desc>invalid button size</desc>
|
||||
<text>不合法的菜单按钮个数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40017</code>
|
||||
<desc>invalid button type</desc>
|
||||
<text>不合法的按钮类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40018</code>
|
||||
<desc>invalid button name size</desc>
|
||||
<text>不合法的按钮名称长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40019</code>
|
||||
<desc>invalid button key size</desc>
|
||||
<text>不合法的按钮KEY长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40020</code>
|
||||
<desc>invalid button url size</desc>
|
||||
<text>不合法的url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40023</code>
|
||||
<desc>invalid sub button size</desc>
|
||||
<text>不合法的子菜单按钮个数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40024</code>
|
||||
<desc>invalid sub button type</desc>
|
||||
<text>不合法的子菜单类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40025</code>
|
||||
<desc>invalid sub button name size</desc>
|
||||
<text>不合法的子菜单按钮名称长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40026</code>
|
||||
<desc>invalid sub button key size</desc>
|
||||
<text>不合法的子菜单按钮KEY长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40027</code>
|
||||
<desc>invalid sub button url size</desc>
|
||||
<text>不合法的子菜单按钮url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40029</code>
|
||||
<desc>invalid code</desc>
|
||||
<text>不合法或已过期的code</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40030</code>
|
||||
<desc>invalid refresh_token</desc>
|
||||
<text>不合法的refresh_token</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40036</code>
|
||||
<desc>invalid template_id size</desc>
|
||||
<text>不合法的template_id长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40037</code>
|
||||
<desc>invalid template_id</desc>
|
||||
<text>不合法的template_id</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40039</code>
|
||||
<desc>invalid url size</desc>
|
||||
<text>不合法的url长度</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40048</code>
|
||||
<desc>invalid url domain</desc>
|
||||
<text>不合法的url域名</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40054</code>
|
||||
<desc>invalid sub button url domain</desc>
|
||||
<text>不合法的子菜单按钮url域名</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40055</code>
|
||||
<desc>invalid button url domain</desc>
|
||||
<text>不合法的菜单按钮url域名</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>40066</code>
|
||||
<desc>invalid url</desc>
|
||||
<text>不合法的url</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41001</code>
|
||||
<desc>access_token missing</desc>
|
||||
<text>缺失access_token参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41002</code>
|
||||
<desc>appid missing</desc>
|
||||
<text>缺失appid参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41003</code>
|
||||
<desc>refresh_token missing</desc>
|
||||
<text>缺失refresh_token参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41004</code>
|
||||
<desc>appsecret missing</desc>
|
||||
<text>缺失secret参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41005</code>
|
||||
<desc>media data missing</desc>
|
||||
<text>缺失二进制媒体文件</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41006</code>
|
||||
<desc>media_id missing</desc>
|
||||
<text>缺失media_id参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41007</code>
|
||||
<desc>sub_menu data missing</desc>
|
||||
<text>缺失子菜单数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41008</code>
|
||||
<desc>missing code</desc>
|
||||
<text>缺失code参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41009</code>
|
||||
<desc>missing openid</desc>
|
||||
<text>缺失openid参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>41010</code>
|
||||
<desc>missing url</desc>
|
||||
<text>缺失url参数</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>42001</code>
|
||||
<desc>access_token expired</desc>
|
||||
<text>access_token超时</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>42002</code>
|
||||
<desc>refresh_token expired</desc>
|
||||
<text>refresh_token超时</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>42003</code>
|
||||
<desc>code expired</desc>
|
||||
<text>code超时</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43001</code>
|
||||
<desc>require GET method</desc>
|
||||
<text>需要使用GET方法请求</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43002</code>
|
||||
<desc>require POST method</desc>
|
||||
<text>需要使用POST方法请求</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43003</code>
|
||||
<desc>require https</desc>
|
||||
<text>需要使用HTTPS</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>43004</code>
|
||||
<desc>require subscribe</desc>
|
||||
<text>需要订阅关系</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44001</code>
|
||||
<desc>empty media data</desc>
|
||||
<text>空白的二进制数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44002</code>
|
||||
<desc>empty post data</desc>
|
||||
<text>空白的POST数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44003</code>
|
||||
<desc>empty news data</desc>
|
||||
<text>空白的news数据</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44004</code>
|
||||
<desc>empty content</desc>
|
||||
<text>空白的内容</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>44005</code>
|
||||
<desc>empty list size</desc>
|
||||
<text>空白的列表</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45001</code>
|
||||
<desc>media size out of limit</desc>
|
||||
<text>二进制文件超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45002</code>
|
||||
<desc>content size out of limit</desc>
|
||||
<text>content参数超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45003</code>
|
||||
<desc>title size out of limit</desc>
|
||||
<text>title参数超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45004</code>
|
||||
<desc>description size out of limit</desc>
|
||||
<text>description参数超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45005</code>
|
||||
<desc>url size out of limit</desc>
|
||||
<text>url参数长度超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45006</code>
|
||||
<desc>picurl size out of limit</desc>
|
||||
<text>picurl参数超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45007</code>
|
||||
<desc>playtime out of limit</desc>
|
||||
<text>播放时间超过限制(语音为60s最大)</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45008</code>
|
||||
<desc>article size out of limit</desc>
|
||||
<text>article参数超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45009</code>
|
||||
<desc>api freq out of limit</desc>
|
||||
<text>接口调动频率超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45010</code>
|
||||
<desc>create menu limit</desc>
|
||||
<text>建立菜单被限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45011</code>
|
||||
<desc>api limit</desc>
|
||||
<text>频率限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45012</code>
|
||||
<desc>template size out of limit</desc>
|
||||
<text>模板大小超过限制</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45016</code>
|
||||
<desc>can't modify sys group</desc>
|
||||
<text>不能修改默认组</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45017</code>
|
||||
<desc>can't set group name too long sys group</desc>
|
||||
<text>修改组名过长</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>45018</code>
|
||||
<desc>too many group now, no need to add new</desc>
|
||||
<text>组数量过多</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>50001</code>
|
||||
<desc>api unauthorized</desc>
|
||||
<text>接口未授权</text>
|
||||
</error>
|
||||
<!-- 微信支付API错误 -->
|
||||
<error>
|
||||
<code>SYSTEMERROR</code>
|
||||
<desc>SYSTEMERROR</desc>
|
||||
<text>接口后台错误</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>INVALID_TRANSACTIONID</code>
|
||||
<desc>INVALID_TRANSACTIONID</desc>
|
||||
<text>无效 transaction_id</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>PARAM_ERROR</code>
|
||||
<desc>PARAM_ERROR</desc>
|
||||
<text>提交参数错误</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>ORDERPAID</code>
|
||||
<desc>ORDERPAID</desc>
|
||||
<text>订单已支付</text>
|
||||
</error>
|
||||
|
||||
<error>
|
||||
<code>OUT_TRADE_NO_USED</code>
|
||||
<desc>OUT_TRADE_NO_USED</desc>
|
||||
<text>商户订单号重复</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>NOAUTH</code>
|
||||
<desc>NOAUTH</desc>
|
||||
<text>商户无权限</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>NOTENOUGH</code>
|
||||
<desc>NOTENOUGH</desc>
|
||||
<text>余额不足</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>NOTSUPORTCARD</code>
|
||||
<desc>NOTSUPORTCARD</desc>
|
||||
<text>不支持卡类型</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>ORDERCLOSED</code>
|
||||
<desc>ORDERCLOSED</desc>
|
||||
<text>订单已关闭</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>BANKERROR</code>
|
||||
<desc>BANKERROR</desc>
|
||||
<text>银行系统异常</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>REFUND_FEE_INVALID</code>
|
||||
<desc>REFUND_FEE_INVALID</desc>
|
||||
<text>退款金额大于支付金额</text>
|
||||
</error>
|
||||
<error>
|
||||
<code>ORDERNOTEXIST</code>
|
||||
<desc>ORDERNOTEXIST</desc>
|
||||
<text>订单不存在</text>
|
||||
</error>
|
||||
</errors>
|
||||
@@ -3,22 +3,72 @@ package com.foxinmy.weixin4j.model;
|
||||
/**
|
||||
* 微信账户信息
|
||||
*
|
||||
* @className WeixinAccountV2
|
||||
* @className WeixinAccount
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccount extends WeixinAccountV2 {
|
||||
public class WeixinAccount extends WeixinConfig {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 财付通商户身份的标识
|
||||
private String partnerId;
|
||||
// 财付通商户权限密钥Key
|
||||
private String partnerKey;
|
||||
// 微信支付商户号V3.x版本
|
||||
private String mchId;
|
||||
// 微信支付分配的设备号
|
||||
private String deviceInfo;
|
||||
|
||||
// 是否已经认证
|
||||
private boolean isAlive;
|
||||
// 是否是服务号
|
||||
private boolean isService;
|
||||
// 是否是订阅号
|
||||
private boolean isSubscribe = true;
|
||||
// 微信支付商户号
|
||||
private String mchId;
|
||||
private boolean isSubscribe;
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
|
||||
public String getPartnerKey() {
|
||||
return partnerKey;
|
||||
}
|
||||
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public String getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public void setDeviceInfo(String deviceInfo) {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public boolean getIsAlive() {
|
||||
return isAlive;
|
||||
@@ -39,46 +89,28 @@ public class WeixinAccount extends WeixinAccountV2 {
|
||||
public boolean getIsSubscribe() {
|
||||
return isSubscribe;
|
||||
}
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public void setIsSubscribe(Boolean isSubscribe) {
|
||||
this.isSubscribe = isSubscribe;
|
||||
}
|
||||
|
||||
public WeixinAccount() {
|
||||
|
||||
}
|
||||
|
||||
public WeixinAccount(boolean isAlive, boolean isService,
|
||||
boolean isSubscribe, String token, String openId) {
|
||||
super.setToken(token);
|
||||
super.setOpenId(openId);
|
||||
this.isAlive = isAlive;
|
||||
this.isService = isService;
|
||||
this.isSubscribe = isSubscribe;
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String mchId) {
|
||||
super(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
public WeixinAccount(boolean isAlive, boolean isService,
|
||||
boolean isSubscribe, String token, String openId, String appId,
|
||||
String appSecret) {
|
||||
super.setToken(token);
|
||||
super.setOpenId(openId);
|
||||
super.setAppId(appId);
|
||||
super.setAppSecret(appSecret);
|
||||
this.isAlive = isAlive;
|
||||
this.isService = isService;
|
||||
this.isSubscribe = isSubscribe;
|
||||
public WeixinAccount(String appId, String appSecret, String paySignKey,
|
||||
String partnerId, String partnerKey) {
|
||||
super(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccount [isAlive=" + isAlive + ", isService=" + isService
|
||||
+ ", isSubscribe=" + isSubscribe + ", mchId=" + mchId
|
||||
+ ", getIsAlive()=" + getIsAlive() + ", getIsService()="
|
||||
+ getIsService() + ", getIsSubscribe()=" + getIsSubscribe()
|
||||
+ ", getMchId()=" + getMchId() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信支付V2.7
|
||||
*
|
||||
* @className WeixinAccountV2
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccountV2 extends WeixinConfig {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 财付通商户身份的标识
|
||||
private String partnerId;
|
||||
// 财付通商户权限密钥Key
|
||||
private String partnerKey;
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
public String getPartnerId() {
|
||||
return partnerId;
|
||||
}
|
||||
public void setPartnerId(String partnerId) {
|
||||
this.partnerId = partnerId;
|
||||
}
|
||||
public String getPartnerKey() {
|
||||
return partnerKey;
|
||||
}
|
||||
public void setPartnerKey(String partnerKey) {
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
|
||||
public WeixinAccountV2() {
|
||||
}
|
||||
public WeixinAccountV2(String openId, String appId, String appSecret,
|
||||
String paySignKey, String partnerId, String partnerKey) {
|
||||
super(null, openId, appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccountV2 [paySignKey=" + paySignKey + ", partnerId="
|
||||
+ partnerId + ", partnerKey=" + partnerKey
|
||||
+ ", getPaySignKey()=" + getPaySignKey() + ", getPartnerId()="
|
||||
+ getPartnerId() + ", getPartnerKey()=" + getPartnerKey() + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.foxinmy.weixin4j.model;
|
||||
|
||||
/**
|
||||
* 微信支付V3.3.6
|
||||
*
|
||||
* @className WeixinConfig
|
||||
* @author jy
|
||||
* @date 2014年8月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccountV3 extends WeixinConfig {
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
// 公众号支付请求中用于加密的密钥 Key,可验证商户唯一身份,PaySignKey 对应于支付场景中的 appKey 值
|
||||
private String paySignKey;
|
||||
// 微信支付商户号
|
||||
private String mchId;
|
||||
|
||||
public String getPaySignKey() {
|
||||
return paySignKey;
|
||||
}
|
||||
public void setPaySignKey(String paySignKey) {
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
}
|
||||
public void setMchId(String mchId) {
|
||||
this.mchId = mchId;
|
||||
}
|
||||
public WeixinAccountV3() {
|
||||
}
|
||||
|
||||
public WeixinAccountV3(String appId, String appSecret, String paySignKey,
|
||||
String mchId, String openId) {
|
||||
super(null, openId, appId, appSecret);
|
||||
this.mchId = mchId;
|
||||
this.paySignKey = paySignKey;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinAccountV3 [paySignKey=" + paySignKey + ", mchId=" + mchId
|
||||
+ ", getPaySignKey()=" + getPaySignKey() + ", getMchId()="
|
||||
+ getMchId() + "]";
|
||||
}
|
||||
}
|
||||
@@ -13,40 +13,48 @@ public class WeixinConfig implements Serializable {
|
||||
private String appId;
|
||||
// 除了支付请求需要用到 paySignKey,公众平台接口 API 的权限获取所需密 钥 Key
|
||||
private String appSecret;
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getOpenId() {
|
||||
return openId;
|
||||
}
|
||||
|
||||
public void setOpenId(String openId) {
|
||||
this.openId = openId;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getAppSecret() {
|
||||
return appSecret;
|
||||
}
|
||||
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
public WeixinConfig() {
|
||||
|
||||
}
|
||||
public WeixinConfig(String token, String openId, String appId,
|
||||
String appSecret) {
|
||||
this.token = token;
|
||||
this.openId = openId;
|
||||
|
||||
public WeixinConfig(String appId, String appSecret) {
|
||||
this.appId = appId;
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinConfig [token=" + token + ", openId=" + openId
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 获取config.properties中的appid&appsecret信息
|
||||
* 获取weixin.properties中的appid&appsecret信息
|
||||
*
|
||||
* @className AbstractTokenApi
|
||||
* @className AbstractTokenHolder
|
||||
* @author jy
|
||||
* @date 2014年10月6日
|
||||
* @since JDK 1.7
|
||||
@@ -17,18 +16,25 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
public abstract class AbstractTokenHolder implements TokenHolder {
|
||||
protected final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||
protected final HttpRequest request = new HttpRequest();
|
||||
private final WeixinConfig weixinConfig;
|
||||
private final String appid;
|
||||
private final String appsecret;
|
||||
|
||||
public AbstractTokenHolder() {
|
||||
weixinConfig = JSON.parseObject(ConfigUtil.getValue("account"),
|
||||
WeixinConfig.class);
|
||||
WeixinConfig weixinConfig = ConfigUtil.getWeixinConfig();
|
||||
this.appid = weixinConfig.getAppId();
|
||||
this.appsecret = weixinConfig.getAppSecret();
|
||||
}
|
||||
|
||||
public AbstractTokenHolder(String appid, String appsecret) {
|
||||
this.appid = appid;
|
||||
this.appsecret = appsecret;
|
||||
}
|
||||
|
||||
protected String getAppid() {
|
||||
return weixinConfig.getAppId();
|
||||
return this.appid;
|
||||
}
|
||||
|
||||
protected String getAppsecret() {
|
||||
return weixinConfig.getAppSecret();
|
||||
return this.appsecret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.foxinmy.weixin4j.token;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
@@ -26,17 +28,12 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
*/
|
||||
public class FileTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
private final String appid;
|
||||
private final String appsecret;
|
||||
|
||||
public FileTokenHolder() {
|
||||
this.appid = getAppid();
|
||||
this.appsecret = getAppsecret();
|
||||
super();
|
||||
}
|
||||
|
||||
public FileTokenHolder(String appid, String appsecret) {
|
||||
this.appid = appid;
|
||||
this.appsecret = appsecret;
|
||||
super(appid, appsecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,12 +50,12 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
*/
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getAppid();
|
||||
String appsecret = getAppsecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
}
|
||||
XStream xstream = XStream.get();
|
||||
xstream.processAnnotations(Token.class);
|
||||
File token_file = new File(String.format("%s/token_%s.xml",
|
||||
ConfigUtil.getValue("token_path"), appid));
|
||||
Token token = null;
|
||||
@@ -66,7 +63,8 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
long now_time = ca.getTimeInMillis();
|
||||
try {
|
||||
if (token_file.exists()) {
|
||||
token = (Token) xstream.fromXML(token_file);
|
||||
token = XStream.get(new FileInputStream(token_file),
|
||||
Token.class);
|
||||
|
||||
long expise_time = token.getTime()
|
||||
+ (token.getExpiresIn() * 1000) - 3;
|
||||
@@ -74,23 +72,18 @@ public class FileTokenHolder extends AbstractTokenHolder {
|
||||
return token;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
token_file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
token_file.getParentFile().mkdirs();
|
||||
}
|
||||
token_file.createNewFile();
|
||||
}
|
||||
String api_token_uri = String.format(
|
||||
tokenUrl, appid, appsecret);
|
||||
String api_token_uri = String.format(tokenUrl, appid, appsecret);
|
||||
Response response = request.get(api_token_uri);
|
||||
token = response.getAsObject(Token.class);
|
||||
token = response.getAsObject(new TypeReference<Token>() {
|
||||
});
|
||||
token.setTime(now_time);
|
||||
token.setOpenid(appid);
|
||||
xstream.toXML(token, new FileOutputStream(token_file));
|
||||
return token;
|
||||
XStream.to(token, new FileOutputStream(token_file));
|
||||
} catch (IOException e) {
|
||||
;
|
||||
throw new WeixinException("-1", "IO ERROR");
|
||||
}
|
||||
throw new WeixinException("-1", "request fail");
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
|
||||
@@ -22,13 +23,10 @@ import com.foxinmy.weixin4j.model.Token;
|
||||
*/
|
||||
public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
private final String appid;
|
||||
private final String appsecret;
|
||||
private JedisPool jedisPool;
|
||||
|
||||
public RedisTokenHolder() {
|
||||
this.appid = getAppid();
|
||||
this.appsecret = getAppsecret();
|
||||
super();
|
||||
}
|
||||
|
||||
public RedisTokenHolder(String appid, String appsecret) {
|
||||
@@ -37,8 +35,7 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
public RedisTokenHolder(String appid, String appsecret, String host,
|
||||
int port) {
|
||||
this.appid = appid;
|
||||
this.appsecret = appsecret;
|
||||
super(appid, appsecret);
|
||||
JedisPoolConfig poolConfig = new JedisPoolConfig();
|
||||
poolConfig.setMaxTotal(50);
|
||||
poolConfig.setMaxIdle(5);
|
||||
@@ -50,6 +47,8 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
|
||||
@Override
|
||||
public Token getToken() throws WeixinException {
|
||||
String appid = getAppid();
|
||||
String appsecret = getAppsecret();
|
||||
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appsecret)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appid or appsecret not be null!");
|
||||
@@ -63,7 +62,9 @@ public class RedisTokenHolder extends AbstractTokenHolder {
|
||||
if (StringUtils.isBlank(accessToken)) {
|
||||
String api_token_uri = String
|
||||
.format(tokenUrl, appid, appsecret);
|
||||
token = request.get(api_token_uri).getAsObject(Token.class);
|
||||
token = request.get(api_token_uri).getAsObject(
|
||||
new TypeReference<Token>() {
|
||||
});
|
||||
jedis.setex(key, token.getExpiresIn() - 3,
|
||||
token.getAccessToken());
|
||||
} else {
|
||||
|
||||
@@ -6,6 +6,14 @@ import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 对class的获取
|
||||
* @className ClassUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class ClassUtil {
|
||||
|
||||
public static Set<Class<?>> getClasses(Package _package) {
|
||||
|
||||
@@ -1,27 +1,46 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.io.File;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.model.WeixinConfig;
|
||||
|
||||
/**
|
||||
* 商户配置工具类
|
||||
*
|
||||
* @className ConfigUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class ConfigUtil {
|
||||
private static Properties props = new Properties();
|
||||
private static ResourceBundle weixin;
|
||||
static {
|
||||
try {
|
||||
props.load(Thread.currentThread().getContextClassLoader()
|
||||
.getResourceAsStream("weixin.properties"));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
weixin = ResourceBundle.getBundle("weixin");
|
||||
Set<String> keySet = weixin.keySet();
|
||||
for (String key : keySet) {
|
||||
if (!key.endsWith("_path")) {
|
||||
continue;
|
||||
}
|
||||
new File(getValue(key)).mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getValue(String key) {
|
||||
return props.getProperty(key);
|
||||
return weixin.getString(key);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getValue("api_token_uri"));
|
||||
public static WeixinAccount getWeixinAccount() {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinAccount.class);
|
||||
}
|
||||
|
||||
public static WeixinConfig getWeixinConfig() {
|
||||
String text = getValue("account");
|
||||
return JSON.parseObject(text, WeixinConfig.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日期工具类
|
||||
*
|
||||
* @className DateUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class DateUtil {
|
||||
private static final String YYYYMMDD = "yyyyMMdd";
|
||||
|
||||
public static String fortmatYYYYMMDD(Date date) {
|
||||
return new SimpleDateFormat(YYYYMMDD).format(date);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
|
||||
/**
|
||||
* 签名工具类
|
||||
* @className MapUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MapUtil {
|
||||
private final static Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
public static String toJoinString(Object object, boolean encoder,
|
||||
boolean lowerCase, JSONObject extra) {
|
||||
String text = JSON.toJSONString(object);
|
||||
Map<String, String> map = new TreeMap<String, String>(
|
||||
new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
map.putAll(JSON.parseObject(text,
|
||||
new TypeReference<Map<String, String>>() {
|
||||
}));
|
||||
if (extra != null && !extra.isEmpty()) {
|
||||
for (String key : extra.keySet()) {
|
||||
map.put(key, extra.getString(key));
|
||||
}
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<Map.Entry<String, String>> set = map.entrySet();
|
||||
try {
|
||||
if (encoder && lowerCase) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey().toLowerCase())
|
||||
.append("=")
|
||||
.append(URLEncoder.encode(entry.getValue(),
|
||||
charset.name())).append("&");
|
||||
}
|
||||
} else if (encoder) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey())
|
||||
.append("=")
|
||||
.append(URLEncoder.encode(entry.getValue(),
|
||||
charset.name())).append("&");
|
||||
}
|
||||
} else if (lowerCase) {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey().toLowerCase()).append("=")
|
||||
.append(entry.getValue()).append("&");
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<String, String> entry : set) {
|
||||
sb.append(entry.getKey()).append("=")
|
||||
.append(entry.getValue()).append("&");
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
;
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,14 @@ import com.foxinmy.weixin4j.type.EventType;
|
||||
import com.foxinmy.weixin4j.type.MessageType;
|
||||
import com.foxinmy.weixin4j.xml.XStream;
|
||||
|
||||
/**
|
||||
* 消息工具类
|
||||
* @className MessageUtil
|
||||
* @author jy
|
||||
* @date 2014年10月31日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class MessageUtil {
|
||||
|
||||
private final static Logger log = LoggerFactory
|
||||
@@ -111,10 +119,7 @@ public class MessageUtil {
|
||||
messageClass = EventType.valueOf(type.toLowerCase())
|
||||
.getEventClass();
|
||||
}
|
||||
XStream xstream = XStream.get();
|
||||
xstream.processAnnotations(messageClass);
|
||||
xstream.alias("xml", messageClass);
|
||||
return xstream.fromXML(xmlMsg, messageClass);
|
||||
return XStream.get(xmlMsg, messageClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* @title 反射工具类
|
||||
* @description 提供对类,字段的反射调用
|
||||
* @author jy.hu , 2012-10-26
|
||||
*/
|
||||
public class ReflectionUtil {
|
||||
|
||||
// 获取包包名
|
||||
public static String getPackageName(Object obj) {
|
||||
return obj.getClass().getPackage().getName();
|
||||
}
|
||||
|
||||
// 获取字段的泛型参数类型
|
||||
public static Class<?> getFieldGenericType(Object obj, String fieldName) {
|
||||
Field field = getAccessibleField(obj, fieldName);
|
||||
Type type = field.getGenericType();
|
||||
if (type instanceof ParameterizedType) {
|
||||
return (Class<?>) ((ParameterizedType) type)
|
||||
.getActualTypeArguments()[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用方法
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param propertyName
|
||||
* 属性名称
|
||||
*/
|
||||
public static Object invokeMethod(Object object, String propertyName) {
|
||||
try {
|
||||
Method getterMethod = object.getClass().getMethod(propertyName);
|
||||
return getterMethod.invoke(object);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invokeMethod(Object object, String propertyName,
|
||||
Object... args) {
|
||||
try {
|
||||
Method getterMethod = object.getClass().getMethod(propertyName);
|
||||
return getterMethod.invoke(object, args);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用Getter方法
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param propertyName
|
||||
* 属性名称
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static Object invokeGetterMethod(Object object, String propertyName)
|
||||
throws Exception {
|
||||
String getterMethodName = null;
|
||||
Method getterMethod = null;
|
||||
String propertyNa = null;
|
||||
if (propertyName.contains(".")) {
|
||||
propertyNa = StringUtils.substringBefore(propertyName, ".");
|
||||
getterMethodName = "get" + StringUtils.capitalize(propertyNa);
|
||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||
return invokeGetterMethod(getterMethod.invoke(object),
|
||||
StringUtils.substringAfter(propertyName, "."));
|
||||
} else {
|
||||
getterMethodName = "get" + StringUtils.capitalize(propertyName);
|
||||
getterMethod = object.getClass().getMethod(getterMethodName);
|
||||
return getterMethod.invoke(object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用Setter方法
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param propertyName
|
||||
* 属性名称
|
||||
*
|
||||
* @param propertyValue
|
||||
* 属性值
|
||||
*/
|
||||
public static void invokeSetterMethod(Object object, String propertyName,
|
||||
Object propertyValue) {
|
||||
Class<?> setterMethodClass = propertyValue.getClass();
|
||||
invokeSetterMethod(object, propertyName, propertyValue,
|
||||
setterMethodClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用Setter方法
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param propertyName
|
||||
* 属性名称
|
||||
*
|
||||
* @param propertyValue
|
||||
* 属性值
|
||||
*
|
||||
* @param setterMethodClass
|
||||
* 参数类型
|
||||
*/
|
||||
public static void invokeSetterMethod(Object object, String propertyName,
|
||||
Object propertyValue, Class<?> setterMethodClass) {
|
||||
String setterMethodName = "set" + StringUtils.capitalize(propertyName);
|
||||
try {
|
||||
Method setterMethod = object.getClass().getMethod(setterMethodName,
|
||||
setterMethodClass);
|
||||
setterMethod.invoke(object, propertyValue);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象属性值,无视private/protected/getter
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param fieldName
|
||||
* 属性名称
|
||||
*/
|
||||
public static Object getFieldValue(Object object, String fieldName) {
|
||||
Field field = getAccessibleField(object, fieldName);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Could not find field "
|
||||
+ fieldName);
|
||||
}
|
||||
Object result = null;
|
||||
try {
|
||||
result = field.get(object);
|
||||
} catch (IllegalAccessException e) {
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对象属性值,无视private/protected/setter
|
||||
*
|
||||
* @param object
|
||||
* 对象
|
||||
*
|
||||
* @param fieldName
|
||||
* 属性名称
|
||||
*/
|
||||
public static void setFieldValue(Object object, String fieldName,
|
||||
Object value) {
|
||||
Field field = getAccessibleField(object, fieldName);
|
||||
if (field == null) {
|
||||
throw new IllegalArgumentException("Could not find field "
|
||||
+ fieldName);
|
||||
}
|
||||
try {
|
||||
field.set(object, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 获取字段的类型
|
||||
public static String getFieldType(Object object, String fieldName) {
|
||||
Field field = getAccessibleField(object, fieldName);
|
||||
return field.getType().getSimpleName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static Field getAccessibleField(final Object object,
|
||||
final String fieldName) {
|
||||
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
|
||||
.getSuperclass()) {
|
||||
try {
|
||||
Field field = superClass.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
||||
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
|
||||
@@ -15,13 +20,26 @@ public class Map2ObjectConverter extends MapConverter {
|
||||
super(mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(HierarchicalStreamReader reader,
|
||||
UnmarshallingContext context) {
|
||||
Map<String,String> map = new HashMap<String, String>();
|
||||
while(reader.hasMoreChildren()){
|
||||
reader.moveDown();
|
||||
map.put(reader.getNodeName(), reader.getValue());
|
||||
reader.moveUp();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object source, HierarchicalStreamWriter writer,
|
||||
MarshallingContext context) {
|
||||
Map<?, ?> map = (Map<?, ?>) source;
|
||||
for (Iterator<?> iterator = map.entrySet().iterator(); iterator
|
||||
.hasNext();) {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) iterator.next();
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
if (StringUtils.isBlank((String) entry.getValue())) {
|
||||
continue;
|
||||
}
|
||||
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
||||
.getKey().toString(), entry.getClass());
|
||||
writer.setValue(entry.getValue().toString());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.thoughtworks.xstream.core.util.QuickWriter;
|
||||
@@ -50,4 +51,34 @@ public class XStream extends com.thoughtworks.xstream.XStream {
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream;
|
||||
}
|
||||
|
||||
public static <T> T get(InputStream inputStream, Class<T> clazz) {
|
||||
XStream xStream = get();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(inputStream, clazz);
|
||||
}
|
||||
|
||||
public static <T> T get(String xml, Class<T> clazz) {
|
||||
XStream xStream = get();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(xml, clazz);
|
||||
}
|
||||
|
||||
public static String to(Object obj) {
|
||||
XStream xStream = get();
|
||||
Class<?> clazz = obj.getClass();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.toXML(obj);
|
||||
}
|
||||
|
||||
public static void to(Object obj, OutputStream out) {
|
||||
XStream xStream = get();
|
||||
Class<?> clazz = obj.getClass();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
xStream.toXML(obj, out);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user