diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index 9db06d7a..abde0215 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -1,73 +1,79 @@ - 4.0.0 - - com.github.binarywang - weixin-java-parent - 2.4.6.BETA - - weixin-java-mp - WeiXin Java Tools - MP - 微信公众号Java SDK + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"> + 4.0.0 + + com.github.binarywang + weixin-java-parent + 2.4.6.BETA + + weixin-java-mp + WeiXin Java Tools - MP + 微信公众号Java SDK - - - com.github.binarywang - weixin-java-common - ${project.version} - - - junit - junit - test - - - org.testng - testng - test - - - org.mockito - mockito-all - test - - - com.google.inject - guice - test - - - org.eclipse.jetty - jetty-server - test - - - org.eclipse.jetty - jetty-servlet - test - - - joda-time - joda-time - 2.9.4 - test - - + + + com.github.binarywang + weixin-java-common + ${project.version} + + + junit + junit + test + + + org.testng + testng + test + + + org.mockito + mockito-all + test + + + com.google.inject + guice + test + + + org.eclipse.jetty + jetty-server + test + + + org.eclipse.jetty + jetty-servlet + test + + + joda-time + joda-time + 2.9.4 + test + + + io.rest-assured + xml-path + 3.0.1 + - - - - org.apache.maven.plugins - maven-surefire-plugin - - - src/test/resources/testng.xml - - - - - + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/testng.xml + + + + + diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java index 5172a5d7..29fbed63 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java @@ -310,20 +310,25 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage { } @Override - public void setSslContextFilePath(String filePath) throws Exception { + public void setSslContextFilePath(String filePath) { if (null == partnerId) { - throw new Exception("请先将partnerId进行赋值"); + throw new IllegalArgumentException("请设置partnerId的值"); } File file = new File(filePath); if (!file.exists()) { - throw new RuntimeException(file.getPath() + ":文件不存在!在设置SSLContext的时候"); + throw new RuntimeException("证书文件:【" + file.getPath() + "】不存在!"); + } + + try { + FileInputStream inputStream = new FileInputStream(file); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + char[] partnerId2charArray = partnerId.toCharArray(); + keystore.load(inputStream, partnerId2charArray); + this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build(); + } catch (Exception e) { + throw new RuntimeException("证书文件有问题,请核实!", e); } - FileInputStream inputStream = new FileInputStream(file); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - char[] partnerId2charArray = partnerId.toCharArray(); - keystore.load(inputStream, partnerId2charArray); - this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build(); } @Override diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index 8ad6ed35..6ab639f1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -1,14 +1,11 @@ package me.chanjar.weixin.mp.api.impl; -import com.thoughtworks.xstream.XStream; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.BeanUtils; -import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpPayService; import me.chanjar.weixin.mp.api.WxMpService; -import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter; import me.chanjar.weixin.mp.bean.pay.request.*; import me.chanjar.weixin.mp.bean.pay.result.*; import org.apache.commons.codec.digest.DigestUtils; @@ -54,20 +51,16 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayRefundRequest.class); - xstream.processAnnotations(WxPayRefundResult.class); - - initRequest(request); + this.initRequest(request); if (StringUtils.isBlank(request.getOpUserId())) { - request.setOpUserId(getConfig().getPartnerId()); + request.setOpUserId(this.getConfig().getPartnerId()); } - checkParameters(request); + this.checkParameters(request); request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/secapi/pay/refund"; - String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); - WxPayRefundResult result = (WxPayRefundResult) xstream.fromXML(responseContent); + String responseContent = this.executeWithKey(url, request.toXML()); + WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class); this.checkResult(result); return result; } @@ -79,12 +72,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { throw new IllegalArgumentException("transaction_id , out_trade_no,out_refund_no, refund_id 必须四选一"); } - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayRefundQueryRequest.class); - xstream.processAnnotations(WxPayRefundQueryResult.class); - WxPayRefundQueryRequest request = new WxPayRefundQueryRequest(); - initRequest(request); + this.initRequest(request); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setTransactionId(StringUtils.trimToNull(transactionId)); request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); @@ -92,8 +81,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/refundquery"; - String responseContent = this.executeRequest(url, xstream.toXML(request)); - WxPayRefundQueryResult result = (WxPayRefundQueryResult) xstream.fromXML(responseContent); + String responseContent = this.executeRequest(url, request.toXML()); + WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class); result.composeRefundRecords(responseContent); this.checkResult(result); return result; @@ -102,8 +91,9 @@ public class WxMpPayServiceImpl implements WxMpPayService { private void checkResult(WxPayBaseResult result) throws WxErrorException { //校验返回结果签名 - if (!checkSign(result.toMap())) { - log.debug("校验结果签名失败,参数:{}", result.toMap()); + Map map = result.toMap(); + if (!this.checkSign(map)) { + log.debug("校验结果签名失败,参数:{}", map); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); } @@ -115,7 +105,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) .build(); - log.error("结果业务代码异常,参数:{},详细:{}", result.toMap(), error); + log.error("结果业务代码异常,参数:{},详细:{}", map, error); throw new WxErrorException(error); } } @@ -138,10 +128,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { try { log.trace("微信支付回调参数详细:{}", xmlData); - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayOrderNotifyResult.class); - xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider())); - WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData); + WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); log.debug("微信支付回调结果对象:{}", result); this.checkResult(result); return result; @@ -157,11 +144,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPaySendRedpackRequest.class); - xstream.processAnnotations(WxPaySendRedpackResult.class); - - initRequest(request); + this.initRequest(request); request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack"; @@ -169,18 +152,14 @@ public class WxMpPayServiceImpl implements WxMpPayService { //裂变红包 url = PAY_BASE_URL + "/mmpaymkttransfers/sendgroupredpack"; } - String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); - WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream.fromXML(responseContent); + String responseContent = this.executeWithKey(url, request.toXML()); + WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class); this.checkResult(result); return result; } @Override public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayRedpackQueryRequest.class); - xstream.processAnnotations(WxPayRedpackQueryResult.class); - WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); request.setMchBillNo(mchBillNo); request.setBillType("MCHT"); @@ -188,8 +167,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo"; - String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); - WxPayRedpackQueryResult result = (WxPayRedpackQueryResult) xstream.fromXML(responseContent); + String responseContent = this.executeWithKey(url, request.toXML()); + WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class); this.checkResult(result); return result; } @@ -201,10 +180,6 @@ public class WxMpPayServiceImpl implements WxMpPayService { throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一"); } - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayOrderQueryRequest.class); - xstream.processAnnotations(WxPayOrderQueryResult.class); - WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setTransactionId(StringUtils.trimToNull(transactionId)); @@ -212,8 +187,8 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/orderquery"; - String responseContent = this.executeRequest(url, xstream.toXML(request)); - WxPayOrderQueryResult result = (WxPayOrderQueryResult) xstream.fromXML(responseContent); + String responseContent = this.executeRequest(url, request.toXML()); + WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class); result.composeCoupons(responseContent); this.checkResult(result); return result; @@ -225,18 +200,14 @@ public class WxMpPayServiceImpl implements WxMpPayService { throw new IllegalArgumentException("out_trade_no 不能为空"); } - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayOrderCloseRequest.class); - xstream.processAnnotations(WxPayOrderCloseResult.class); - WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); initRequest(request); request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/closeorder"; - String responseContent = this.executeRequest(url, xstream.toXML(request)); - WxPayOrderCloseResult result = (WxPayOrderCloseResult) xstream.fromXML(responseContent); + String responseContent = this.executeRequest(url, request.toXML()); + WxPayOrderCloseResult result = WxPayOrderCloseResult.fromXML(responseContent, WxPayOrderCloseResult.class); this.checkResult(result); return result; @@ -246,11 +217,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxPayUnifiedOrderRequest.class); - xstream.processAnnotations(WxPayUnifiedOrderResult.class); - - initRequest(request); + this.initRequest(request); if (StringUtils.isBlank(request.getNotifyURL())) { request.setNotifyURL(getConfig().getNotifyURL()); } @@ -261,12 +228,12 @@ public class WxMpPayServiceImpl implements WxMpPayService { request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/pay/unifiedorder"; - String xmlParam = xstream.toXML(request); + String xmlParam = request.toXML(); log.debug("微信统一下单接口,URL:{},参数:{}", url, xmlParam); String responseContent = this.executeRequest(url, xmlParam); log.debug("微信统一下单接口,URL:{},结果:{}", url, responseContent); - WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream.fromXML(responseContent); + WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class); this.checkResult(result); return result; } @@ -324,35 +291,27 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxEntPayRequest.class); - xstream.processAnnotations(WxEntPayResult.class); - - initRequest(request); + this.initRequest(request); BeanUtils.checkRequiredFields(request); request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers"; - String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); - WxEntPayResult result = (WxEntPayResult) xstream.fromXML(responseContent); + String responseContent = this.executeWithKey(url, request.toXML()); + WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class); this.checkResult(result); return result; } @Override public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException { - XStream xstream = XStreamInitializer.getInstance(); - xstream.processAnnotations(WxEntPayQueryRequest.class); - xstream.processAnnotations(WxEntPayQueryResult.class); - WxEntPayQueryRequest request = new WxEntPayQueryRequest(); - initRequest(request); + this.initRequest(request); request.setSign(this.createSign(request)); String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo"; - String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); - WxEntPayQueryResult result = (WxEntPayQueryResult) xstream.fromXML(responseContent); + String responseContent = this.executeWithKey(url, request.toXML()); + WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class); this.checkResult(result); return result; } @@ -379,11 +338,11 @@ public class WxMpPayServiceImpl implements WxMpPayService { } } - private String executeRequestWithKeyFile(String url, String requestStr) throws WxErrorException { + private String executeWithKey(String url, String requestStr) throws WxErrorException { try { SSLContext sslContext = getConfig().getSslContext(); if (null == sslContext) { - throw new Exception("请将配置类(即WxMpConfigStorage的实现类)中的SSLContext初始化"); + throw new IllegalArgumentException("请先初始化配置类(即WxMpConfigStorage的实现类)中的SSLContext!"); } SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null, @@ -412,17 +371,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public String createSign(Object xmlBean) { - return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); + return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); } @Override public String createSign(Object xmlBean, String signKey) { - return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); + return this.createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); } @Override public String createSign(Map params) { - return createSign(params, getConfig().getPartnerKey()); + return this.createSign(params, this.getConfig().getPartnerKey()); } @Override @@ -443,17 +402,17 @@ public class WxMpPayServiceImpl implements WxMpPayService { @Override public boolean checkSign(Object xmlBean) { - return checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); + return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); } @Override public boolean checkSign(Object xmlBean, String signKey) { - return checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey); + return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey); } @Override public boolean checkSign(Map params) { - return checkSign(params, getConfig().getPartnerKey()); + return this.checkSign(params, getConfig().getPartnerKey()); } @Override diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java index 3bfe556f..c13f1b8f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayBaseRequest.java @@ -1,7 +1,9 @@ package me.chanjar.weixin.mp.bean.pay.request; +import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; import java.math.BigDecimal; @@ -17,6 +19,7 @@ import java.math.BigDecimal; *
  • 示例值 *
  • 描述 * + * * @author binarywang(Binary Wang) */ public abstract class WxPayBaseRequest { @@ -69,12 +72,22 @@ public abstract class WxPayBaseRequest { @XStreamAlias("sign") protected String sign; + /** + * 将单位为元转换为单位为分 + * + * @param yuan 将要转换的元的数值字符串 + */ + public static Integer yuanToFee(String yuan) { + return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue(); + } + public String getAppid() { return this.appid; } /** * 如果配置中已经设置,可以不设置值 + * * @param appid 微信公众号appid */ public void setAppid(String appid) { @@ -87,6 +100,7 @@ public abstract class WxPayBaseRequest { /** * 如果配置中已经设置,可以不设置值 + * * @param mchId 微信商户号 */ public void setMchId(String mchId) { @@ -99,6 +113,7 @@ public abstract class WxPayBaseRequest { /** * 默认采用时间戳为随机字符串,可以不设置 + * * @param nonceStr 随机字符串 */ public void setNonceStr(String nonceStr) { @@ -113,17 +128,14 @@ public abstract class WxPayBaseRequest { this.sign = sign; } - /** - * 将单位为元转换为单位为分 - * - * @param yuan 将要转换的元的数值字符串 - */ - public static Integer yuanToFee(String yuan) { - return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue(); - } - @Override public String toString() { return ToStringUtils.toSimpleString(this); } + + public String toXML() { + XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(this.getClass()); + return xstream.toXML(this); + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java index 66ba5d34..22bc6ae2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayRefundRequest.java @@ -1,7 +1,6 @@ package me.chanjar.weixin.mp.bean.pay.request; import com.thoughtworks.xstream.annotations.XStreamAlias; - import me.chanjar.weixin.common.annotation.Required; /** @@ -144,8 +143,6 @@ public class WxPayRefundRequest extends WxPayBaseRequest { @XStreamAlias("refund_account") private String refundAccount; - - public String getDeviceInfo() { return this.deviceInfo; } @@ -217,4 +214,5 @@ public class WxPayRefundRequest extends WxPayBaseRequest { public void setRefundAccount(String refundAccount) { this.refundAccount = refundAccount; } + } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java index cafd8a56..b06f3cca 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java @@ -1,10 +1,19 @@ package me.chanjar.weixin.mp.bean.pay.result; +import com.google.common.collect.Maps; +import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; -import me.chanjar.weixin.common.util.BeanUtils; +import io.restassured.internal.path.xml.NodeChildrenImpl; +import io.restassured.path.xml.XmlPath; +import io.restassured.path.xml.element.Node; +import io.restassured.path.xml.element.NodeChildren; import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.math.BigDecimal; +import java.util.Iterator; import java.util.Map; /** @@ -15,65 +24,90 @@ import java.util.Map; * */ public abstract class WxPayBaseResult { - @Override - public String toString() { - return ToStringUtils.toSimpleString(this); - } - /** * 返回状态码 */ @XStreamAlias("return_code") protected String returnCode; - /** * 返回信息 */ @XStreamAlias("return_msg") protected String returnMsg; - + private String xmlString; /** * 业务结果 */ @XStreamAlias("result_code") private String resultCode; - /** * 错误代码 */ @XStreamAlias("err_code") private String errCode; - /** * 错误代码描述 */ @XStreamAlias("err_code_des") private String errCodeDes; - /** * 公众账号ID */ @XStreamAlias("appid") private String appid; - /** * 商户号 */ @XStreamAlias("mch_id") private String mchId; - /** * 随机字符串 */ @XStreamAlias("nonce_str") private String nonceStr; - /** * 签名 */ @XStreamAlias("sign") private String sign; + /** + * 将单位分转换成单位圆 + * + * @param fee 将要被转换为元的分的数值 + */ + public static String feeToYuan(Integer fee) { + return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); + } + + /** + * 从xml字符串创建bean对象 + */ + public static T fromXML(String xmlString, Class clz) { + XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(clz); + T result = (T) xstream.fromXML(xmlString); + result.setXmlString(xmlString); + return result; + } + + public String getXmlString() { + return this.xmlString; + } + + public void setXmlString(String xmlString) { + this.xmlString = xmlString; + } + + protected Logger getLogger() { + return LoggerFactory.getLogger(this.getClass()); + } + + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + public String getReturnCode() { return this.returnCode; } @@ -147,14 +181,43 @@ public abstract class WxPayBaseResult { } /** - * 将单位分转换成单位圆 - * @param fee 将要被转换为元的分的数值 + * 将bean通过保存的xml字符串转换成map */ - public static String feeToYuan(Integer fee) { - return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); - } - - public Map toMap(){ - return BeanUtils.xmlBean2Map(this); + public Map toMap() { + Map result = Maps.newHashMap(); + XmlPath xmlPath = new XmlPath(this.xmlString); + NodeChildren nodeChildren = xmlPath.getNodeChildren("xml"); + Iterator iterator = nodeChildren.nodeIterator(); + while (iterator.hasNext()) { + Node node = iterator.next(); + result.put(node.name(), node.value()); + } + return result; + } + + private String getXmlValueIfExists(XmlPath xmlPath, String path) { + if (xmlPath.get(path) instanceof NodeChildrenImpl) { + if (((NodeChildrenImpl) xmlPath.get(path)).size() == 0) { + return null; + } + } + + return xmlPath.getString(path); + } + + protected T getXmlValueIfExists(XmlPath xmlPath, String path, Class clz) { + String value = this.getXmlValueIfExists(xmlPath, path); + if (value == null) { + return null; + } + + switch (clz.getSimpleName()) { + case "String": + return (T) value; + case "Integer": + return (T) Integer.valueOf(value); + } + + throw new UnsupportedOperationException("暂时不支持此种类型的数据"); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java index a5770873..1cf783a8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayOrderNotifyResult.java @@ -1,10 +1,12 @@ package me.chanjar.weixin.mp.bean.pay.result; +import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.util.BeanUtils; +import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; +import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter; import java.io.Serializable; import java.util.List; @@ -376,6 +378,15 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializ @Override public String toString() { - return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE); + return ToStringUtils.toSimpleString(this); } + + public static WxPayOrderNotifyResult fromXML(String xmlString) { + XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(WxPayOrderNotifyResult.class); + xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider())); + WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlString); + result.setXmlString(xmlString); + return result; + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java index 43028846..146c35df 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResult.java @@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.bean.pay.result; import com.google.common.collect.Lists; import com.thoughtworks.xstream.annotations.XStreamAlias; +import io.restassured.path.xml.XmlPath; import java.util.List; @@ -186,7 +187,38 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { public void composeRefundRecords(String xmlString) { if (this.refundCount != null && this.refundCount > 0) { this.refundRecords = Lists.newArrayList(); - //TODO 暂时待实现 + XmlPath xmlPath = new XmlPath(xmlString); + + for (int i = 0; i < this.refundCount; i++) { + RefundRecord refundRecord = new RefundRecord(); + this.refundRecords.add(refundRecord); + + refundRecord.setOutRefundNo(this.getXmlValueIfExists(xmlPath, "xml.out_refund_no_" + i, String.class)); + refundRecord.setRefundId(this.getXmlValueIfExists(xmlPath, "xml.refund_id_" + i, String.class)); + refundRecord.setRefundChannel(this.getXmlValueIfExists(xmlPath, "xml.refund_channel_" + i, String.class)); + refundRecord.setRefundFee(this.getXmlValueIfExists(xmlPath, "xml.refund_fee_" + i, Integer.class)); + refundRecord.setSettlementRefundFee(this.getXmlValueIfExists(xmlPath, "xml.settlement_refund_fee_" + i, Integer.class)); + refundRecord.setCouponType(this.getXmlValueIfExists(xmlPath, "xml.coupon_type_" + i, String.class)); + refundRecord.setCouponRefundFee(this.getXmlValueIfExists(xmlPath, "xml.coupon_refund_fee_" + i, Integer.class)); + refundRecord.setCouponRefundCount(this.getXmlValueIfExists(xmlPath, "xml.coupon_refund_count_" + i, Integer.class)); + refundRecord.setRefundStatus(this.getXmlValueIfExists(xmlPath, "xml.refund_status_" + i, String.class)); + refundRecord.setRefundRecvAccout(this.getXmlValueIfExists(xmlPath, "xml.refund_recv_accout_" + i, String.class)); + + if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) { + continue; + } + + List coupons = Lists.newArrayList(); + for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) { + coupons.add( + new RefundRecord.RefundCoupon( + this.getXmlValueIfExists(xmlPath, "xml.coupon_refund_id_" + i + "_" + j, String.class), + this.getXmlValueIfExists(xmlPath, "xml.coupon_refund_fee_" + i + "_" + j, Integer.class) + ) + ); + } + } + } } @@ -241,7 +273,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { * */ @XStreamAlias("refund_fee") - private String refundFee; + private Integer refundFee; /** *
    @@ -254,7 +286,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
          * 
    */ @XStreamAlias("settlement_refund_fee") - private String settlementRefundFee; + private Integer settlementRefundFee; /** *
    @@ -293,7 +325,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
          * 
    */ @XStreamAlias("coupon_refund_fee") - private String couponRefundFee; + private Integer couponRefundFee; /** *
    @@ -306,7 +338,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
          * 
    */ @XStreamAlias("coupon_refund_count") - private String couponRefundCount; + private Integer couponRefundCount; private List refundCoupons; @@ -364,19 +396,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { this.refundChannel = refundChannel; } - public String getRefundFee() { + public Integer getRefundFee() { return refundFee; } - public void setRefundFee(String refundFee) { + public void setRefundFee(Integer refundFee) { this.refundFee = refundFee; } - public String getSettlementRefundFee() { + public Integer getSettlementRefundFee() { return settlementRefundFee; } - public void setSettlementRefundFee(String settlementRefundFee) { + public void setSettlementRefundFee(Integer settlementRefundFee) { this.settlementRefundFee = settlementRefundFee; } @@ -396,19 +428,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { this.couponType = couponType; } - public String getCouponRefundFee() { + public Integer getCouponRefundFee() { return couponRefundFee; } - public void setCouponRefundFee(String couponRefundFee) { + public void setCouponRefundFee(Integer couponRefundFee) { this.couponRefundFee = couponRefundFee; } - public String getCouponRefundCount() { + public Integer getCouponRefundCount() { return couponRefundCount; } - public void setCouponRefundCount(String couponRefundCount) { + public void setCouponRefundCount(Integer couponRefundCount) { this.couponRefundCount = couponRefundCount; } @@ -446,6 +478,8 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { * 100 * 退款代金券批次ID ,$n为下标,$m为下标,从0开始编号 * + * + * @deprecated 貌似是被去掉了,但不知是何时! */ @XStreamAlias("coupon_refund_batch_id") private String couponRefundBatchId; @@ -474,9 +508,15 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { * */ @XStreamAlias("coupon_refund_fee") - private String couponRefundFee; + private Integer couponRefundFee; - public RefundCoupon(String couponRefundBatchId, String couponRefundId, String couponRefundFee) { + public RefundCoupon(String couponRefundId, Integer couponRefundFee) { + this.couponRefundId = couponRefundId; + this.couponRefundFee = couponRefundFee; + } + + @Deprecated + public RefundCoupon(String couponRefundBatchId, String couponRefundId, Integer couponRefundFee) { this.couponRefundBatchId = couponRefundBatchId; this.couponRefundId = couponRefundId; this.couponRefundFee = couponRefundFee; @@ -484,5 +524,6 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { } } + } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java index 31fc0c06..418b710b 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java @@ -13,8 +13,6 @@ import me.chanjar.weixin.mp.bean.pay.result.*; import org.testng.annotations.Guice; import org.testng.annotations.Test; -import java.io.File; - /** * 测试支付相关接口 * Created by Binary Wang on 2016/7/28. @@ -90,7 +88,6 @@ public class WxMpPayServiceImplTest { */ @Test public void testQueryRedpack() throws Exception { - File keyFile = new File("E:\\dlt.p12"); WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa"); System.err.println(redpackResult); } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java new file mode 100644 index 00000000..9427bd01 --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/pay/result/WxPayRefundQueryResultTest.java @@ -0,0 +1,49 @@ +package me.chanjar.weixin.mp.bean.pay.result; + + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + *
    + * Created by Binary Wang on 2016-12-29.
    + * @author binarywang(Binary Wang)
    + * 
    + */ +public class WxPayRefundQueryResultTest { + @Test + public void composeRefundRecords() throws Exception { + /* + 该xml字符串来自于官方文档示例 + */ + String xmlString = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 1\n" + + " 1\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + WxPayRefundQueryResult result = new WxPayRefundQueryResult(); + result.setRefundCount(1); + result.composeRefundRecords(xmlString); + + Assert.assertNotNull(result.getRefundRecords()); + Assert.assertEquals(result.getRefundRecords().size(), 1); + Assert.assertEquals(result.getRefundRecords().get(0).getRefundId(), "2008450740201411110000174436"); + Assert.assertEquals(result.getRefundRecords().get(0).getRefundFee().intValue(), 1); + Assert.assertEquals(result.getRefundRecords().get(0).getOutRefundNo(), "1415701182"); + Assert.assertEquals(result.getRefundRecords().get(0).getRefundStatus(), "PROCESSING"); + + } + +}