weixin-mp & pay

This commit is contained in:
jy.hu
2014-11-03 15:44:12 +08:00
parent c908581178
commit 45ce10141a
172 changed files with 5591 additions and 742 deletions
+12 -3
View File
@@ -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`等类
+4 -1
View File
@@ -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);
}
}