@@ -26,11 +26,6 @@ | |||||
<version>3.7</version> | <version>3.7</version> | ||||
<!-- 由于较新的3.8版本需要jdk8,故而此处采用较低版本 --> | <!-- 由于较新的3.8版本需要jdk8,故而此处采用较低版本 --> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>io.rest-assured</groupId> | |||||
<artifactId>xml-path</artifactId> | |||||
<version>3.0.1</version> | |||||
</dependency> | |||||
<dependency> | <dependency> | ||||
<groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
<artifactId>qrcode-utils</artifactId> | <artifactId>qrcode-utils</artifactId> | ||||
@@ -1,20 +1,26 @@ | |||||
package com.github.binarywang.wxpay.bean.result; | package com.github.binarywang.wxpay.bean.result; | ||||
import com.google.common.base.Joiner; | |||||
import com.google.common.collect.Maps; | import com.google.common.collect.Maps; | ||||
import com.thoughtworks.xstream.XStream; | import com.thoughtworks.xstream.XStream; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import io.restassured.internal.path.xml.NodeChildrenImpl; | |||||
import io.restassured.internal.path.xml.NodeImpl; | |||||
import io.restassured.path.xml.XmlPath; | |||||
import io.restassured.path.xml.element.Node; | |||||
import io.restassured.path.xml.exception.XmlPathException; | |||||
import me.chanjar.weixin.common.util.ToStringUtils; | import me.chanjar.weixin.common.util.ToStringUtils; | ||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer; | import me.chanjar.weixin.common.util.xml.XStreamInitializer; | ||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.NodeList; | |||||
import org.xml.sax.SAXException; | |||||
import javax.xml.parsers.DocumentBuilderFactory; | |||||
import javax.xml.parsers.ParserConfigurationException; | |||||
import javax.xml.xpath.XPathConstants; | |||||
import javax.xml.xpath.XPathExpressionException; | |||||
import javax.xml.xpath.XPathFactory; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.io.IOException; | |||||
import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
import java.util.Iterator; | |||||
import java.util.Map; | import java.util.Map; | ||||
/** | /** | ||||
@@ -82,6 +88,11 @@ public abstract class WxPayBaseResult { | |||||
@XStreamAlias("sign") | @XStreamAlias("sign") | ||||
private String sign; | private String sign; | ||||
/** | |||||
* xml的Document对象,用于解析xml文本 | |||||
*/ | |||||
private Document xmlDoc; | |||||
/** | /** | ||||
* 将单位分转换成单位圆 | * 将单位分转换成单位圆 | ||||
* | * | ||||
@@ -211,51 +222,74 @@ public abstract class WxPayBaseResult { | |||||
* 将bean通过保存的xml字符串转换成map | * 将bean通过保存的xml字符串转换成map | ||||
*/ | */ | ||||
public Map<String, String> toMap() { | public Map<String, String> toMap() { | ||||
Map<String, String> result = Maps.newHashMap(); | |||||
XmlPath xmlPath = new XmlPath(this.xmlString); | |||||
NodeImpl rootNode = null; | |||||
try { | |||||
rootNode = xmlPath.get("xml"); | |||||
} catch (XmlPathException e) { | |||||
if (StringUtils.isBlank(this.xmlString)) { | |||||
throw new RuntimeException("xml数据有问题,请核实!"); | throw new RuntimeException("xml数据有问题,请核实!"); | ||||
} | } | ||||
if (rootNode == null) { | |||||
throw new RuntimeException("xml数据有问题,请核实!"); | |||||
} | |||||
Map<String, String> result = Maps.newHashMap(); | |||||
Document doc = this.getXmlDoc(); | |||||
Iterator<Node> iterator = rootNode.children().nodeIterator(); | |||||
while (iterator.hasNext()) { | |||||
Node node = iterator.next(); | |||||
result.put(node.name(), node.value()); | |||||
try { | |||||
NodeList list = (NodeList) XPathFactory.newInstance().newXPath() | |||||
.compile("/xml/*") | |||||
.evaluate(doc, XPathConstants.NODESET); | |||||
int len = list.getLength(); | |||||
for (int i = 0; i < len; i++) { | |||||
result.put(list.item(i).getNodeName(), list.item(i).getTextContent()); | |||||
} | |||||
} catch (XPathExpressionException e) { | |||||
throw new RuntimeException("非法的xml文本内容:" + xmlString); | |||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
private String getXmlValue(XmlPath xmlPath, String path) { | |||||
if (xmlPath.get(path) instanceof NodeChildrenImpl) { | |||||
if (((NodeChildrenImpl) xmlPath.get(path)).size() == 0) { | |||||
return null; | |||||
} | |||||
/** | |||||
* 将xml字符串转换成Document对象,以便读取其元素值 | |||||
*/ | |||||
protected Document getXmlDoc() { | |||||
if (this.xmlDoc != null) { | |||||
return this.xmlDoc; | |||||
} | |||||
try { | |||||
this.xmlDoc = DocumentBuilderFactory | |||||
.newInstance() | |||||
.newDocumentBuilder() | |||||
.parse(new ByteArrayInputStream(this.xmlString.getBytes("UTF-8"))); | |||||
return xmlDoc; | |||||
} catch (SAXException | IOException | ParserConfigurationException e) { | |||||
throw new RuntimeException("非法的xml文本内容:" + this.xmlString); | |||||
} | } | ||||
return xmlPath.getString(path); | |||||
} | } | ||||
protected <T> T getXmlValue(XmlPath xmlPath, String path, Class<T> clz) { | |||||
String value = this.getXmlValue(xmlPath, path); | |||||
if (value == null) { | |||||
return null; | |||||
/** | |||||
* 获取xml中元素的值 | |||||
*/ | |||||
protected String getXmlValue(String... path) { | |||||
Document doc = this.getXmlDoc(); | |||||
String expression = String.format("/%s//text()", Joiner.on("/").join(path)); | |||||
try { | |||||
return (String) XPathFactory | |||||
.newInstance() | |||||
.newXPath() | |||||
.compile(expression) | |||||
.evaluate(doc, XPathConstants.STRING); | |||||
} catch (XPathExpressionException e) { | |||||
throw new RuntimeException("未找到相应路径的文本:" + expression); | |||||
} | } | ||||
} | |||||
switch (clz.getSimpleName()) { | |||||
case "String": | |||||
return (T) value; | |||||
case "Integer": | |||||
return (T) Integer.valueOf(value); | |||||
/** | |||||
* 获取xml中元素的值,作为int值返回 | |||||
*/ | |||||
protected Integer getXmlValueAsInt(String... path) { | |||||
String result = this.getXmlValue(path); | |||||
if (StringUtils.isBlank(result)) { | |||||
return null; | |||||
} | } | ||||
throw new UnsupportedOperationException("暂时不支持此种类型的数据"); | |||||
return Integer.valueOf(result); | |||||
} | } | ||||
} | } |
@@ -2,7 +2,6 @@ package com.github.binarywang.wxpay.bean.result; | |||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import io.restassured.path.xml.XmlPath; | |||||
import java.util.List; | import java.util.List; | ||||
@@ -395,11 +394,10 @@ public class WxPayOrderQueryResult extends WxPayBaseResult { | |||||
public void composeCoupons() { | public void composeCoupons() { | ||||
if (this.couponCount != null && this.couponCount > 0) { | if (this.couponCount != null && this.couponCount > 0) { | ||||
this.coupons = Lists.newArrayList(); | this.coupons = Lists.newArrayList(); | ||||
XmlPath xmlPath = new XmlPath(this.getXmlString()); | |||||
for (int i = 0; i < this.couponCount; i++) { | for (int i = 0; i < this.couponCount; i++) { | ||||
this.coupons.add(new Coupon(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class), | |||||
this.getXmlValue(xmlPath, "xml.coupon_id_" + i, String.class), | |||||
this.getXmlValue(xmlPath, "xml.coupon_fee_" + i, Integer.class))); | |||||
this.coupons.add(new Coupon(this.getXmlValue("xml/coupon_type_" + i), | |||||
this.getXmlValue("xml/coupon_id_" + i), | |||||
this.getXmlValueAsInt("xml/coupon_fee_" + i))); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -2,7 +2,6 @@ package com.github.binarywang.wxpay.bean.result; | |||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | import com.thoughtworks.xstream.annotations.XStreamAlias; | ||||
import io.restassured.path.xml.XmlPath; | |||||
import java.util.List; | import java.util.List; | ||||
@@ -190,22 +189,21 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { | |||||
public void composeRefundRecords() { | public void composeRefundRecords() { | ||||
if (this.refundCount != null && this.refundCount > 0) { | if (this.refundCount != null && this.refundCount > 0) { | ||||
this.refundRecords = Lists.newArrayList(); | this.refundRecords = Lists.newArrayList(); | ||||
XmlPath xmlPath = new XmlPath(this.getXmlString()); | |||||
for (int i = 0; i < this.refundCount; i++) { | for (int i = 0; i < this.refundCount; i++) { | ||||
RefundRecord refundRecord = new RefundRecord(); | RefundRecord refundRecord = new RefundRecord(); | ||||
this.refundRecords.add(refundRecord); | this.refundRecords.add(refundRecord); | ||||
refundRecord.setOutRefundNo(this.getXmlValue(xmlPath, "xml.out_refund_no_" + i, String.class)); | |||||
refundRecord.setRefundId(this.getXmlValue(xmlPath, "xml.refund_id_" + i, String.class)); | |||||
refundRecord.setRefundChannel(this.getXmlValue(xmlPath, "xml.refund_channel_" + i, String.class)); | |||||
refundRecord.setRefundFee(this.getXmlValue(xmlPath, "xml.refund_fee_" + i, Integer.class)); | |||||
refundRecord.setSettlementRefundFee(this.getXmlValue(xmlPath, "xml.settlement_refund_fee_" + i, Integer.class)); | |||||
refundRecord.setCouponType(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class)); | |||||
refundRecord.setCouponRefundFee(this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i, Integer.class)); | |||||
refundRecord.setCouponRefundCount(this.getXmlValue(xmlPath, "xml.coupon_refund_count_" + i, Integer.class)); | |||||
refundRecord.setRefundStatus(this.getXmlValue(xmlPath, "xml.refund_status_" + i, String.class)); | |||||
refundRecord.setRefundRecvAccout(this.getXmlValue(xmlPath, "xml.refund_recv_accout_" + i, String.class)); | |||||
refundRecord.setOutRefundNo(this.getXmlValue("xml/out_refund_no_" + i)); | |||||
refundRecord.setRefundId(this.getXmlValue("xml/refund_id_" + i)); | |||||
refundRecord.setRefundChannel(this.getXmlValue("xml/refund_channel_" + i)); | |||||
refundRecord.setRefundFee(this.getXmlValueAsInt("xml/refund_fee_" + i)); | |||||
refundRecord.setSettlementRefundFee(this.getXmlValueAsInt("xml/settlement_refund_fee_" + i)); | |||||
refundRecord.setCouponType(this.getXmlValue("xml/coupon_type_" + i)); | |||||
refundRecord.setCouponRefundFee(this.getXmlValueAsInt("xml/coupon_refund_fee_" + i)); | |||||
refundRecord.setCouponRefundCount(this.getXmlValueAsInt("xml/coupon_refund_count_" + i)); | |||||
refundRecord.setRefundStatus(this.getXmlValue("xml/refund_status_" + i)); | |||||
refundRecord.setRefundRecvAccout(this.getXmlValue("xml/refund_recv_accout_" + i)); | |||||
if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) { | if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) { | ||||
continue; | continue; | ||||
@@ -215,8 +213,8 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { | |||||
for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) { | for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) { | ||||
coupons.add( | coupons.add( | ||||
new RefundRecord.RefundCoupon( | new RefundRecord.RefundCoupon( | ||||
this.getXmlValue(xmlPath, "xml.coupon_refund_id_" + i + "_" + j, String.class), | |||||
this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i + "_" + j, Integer.class) | |||||
this.getXmlValue("xml/coupon_refund_id_" + i + "_" + j), | |||||
this.getXmlValueAsInt("xml/coupon_refund_fee_" + i + "_" + j) | |||||
) | ) | ||||
); | ); | ||||
} | } | ||||
@@ -1,6 +1,5 @@ | |||||
package com.github.binarywang.wxpay.bean.result; | package com.github.binarywang.wxpay.bean.result; | ||||
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult; | |||||
import org.testng.*; | import org.testng.*; | ||||
import org.testng.annotations.*; | import org.testng.annotations.*; | ||||
@@ -13,6 +12,15 @@ import java.util.Map; | |||||
* </pre> | * </pre> | ||||
*/ | */ | ||||
public class WxPayBaseResultTest { | public class WxPayBaseResultTest { | ||||
@Test | |||||
public void testGetXmlValue() throws Exception { | |||||
} | |||||
@Test | |||||
public void testXml2Doc() throws Exception { | |||||
} | |||||
@Test | @Test | ||||
public void testToMap() throws Exception { | public void testToMap() throws Exception { | ||||
WxPayOrderQueryResult result = new WxPayOrderQueryResult(); | WxPayOrderQueryResult result = new WxPayOrderQueryResult(); | ||||
@@ -40,11 +48,17 @@ public class WxPayBaseResultTest { | |||||
Map<String, String> map = result.toMap(); | Map<String, String> map = result.toMap(); | ||||
System.out.println(map); | System.out.println(map); | ||||
Assert.assertEquals("SUCCESS", map.get("return_code")); | |||||
Assert.assertEquals("订单额外描述", map.get("attach")); | |||||
Assert.assertEquals(map.get("return_code"), "SUCCESS"); | |||||
Assert.assertEquals(map.get("attach"), "订单额外描述"); | |||||
} | |||||
result.setXmlString(""); | |||||
System.out.println(result.toMap()); | |||||
@Test(expectedExceptions = {RuntimeException.class}) | |||||
public void testToMap_with_empty_xmlString() { | |||||
WxPayOrderQueryResult result = new WxPayOrderQueryResult(); | |||||
result.setXmlString(" "); | |||||
Map<String, String> map = result.toMap(); | |||||
System.out.println(map); | |||||
} | } | ||||
} | } |