| @@ -26,11 +26,6 @@ | |||
| <version>3.7</version> | |||
| <!-- 由于较新的3.8版本需要jdk8,故而此处采用较低版本 --> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>io.rest-assured</groupId> | |||
| <artifactId>xml-path</artifactId> | |||
| <version>3.0.1</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.github.binarywang</groupId> | |||
| <artifactId>qrcode-utils</artifactId> | |||
| @@ -1,20 +1,26 @@ | |||
| package com.github.binarywang.wxpay.bean.result; | |||
| import com.google.common.base.Joiner; | |||
| import com.google.common.collect.Maps; | |||
| import com.thoughtworks.xstream.XStream; | |||
| 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.xml.XStreamInitializer; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| 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.util.Iterator; | |||
| import java.util.Map; | |||
| /** | |||
| @@ -82,6 +88,11 @@ public abstract class WxPayBaseResult { | |||
| @XStreamAlias("sign") | |||
| private String sign; | |||
| /** | |||
| * xml的Document对象,用于解析xml文本 | |||
| */ | |||
| private Document xmlDoc; | |||
| /** | |||
| * 将单位分转换成单位圆 | |||
| * | |||
| @@ -211,51 +222,74 @@ public abstract class WxPayBaseResult { | |||
| * 将bean通过保存的xml字符串转换成map | |||
| */ | |||
| 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数据有问题,请核实!"); | |||
| } | |||
| 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; | |||
| } | |||
| 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.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import io.restassured.path.xml.XmlPath; | |||
| import java.util.List; | |||
| @@ -395,11 +394,10 @@ public class WxPayOrderQueryResult extends WxPayBaseResult { | |||
| public void composeCoupons() { | |||
| if (this.couponCount != null && this.couponCount > 0) { | |||
| this.coupons = Lists.newArrayList(); | |||
| XmlPath xmlPath = new XmlPath(this.getXmlString()); | |||
| 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.thoughtworks.xstream.annotations.XStreamAlias; | |||
| import io.restassured.path.xml.XmlPath; | |||
| import java.util.List; | |||
| @@ -190,22 +189,21 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { | |||
| public void composeRefundRecords() { | |||
| if (this.refundCount != null && this.refundCount > 0) { | |||
| this.refundRecords = Lists.newArrayList(); | |||
| XmlPath xmlPath = new XmlPath(this.getXmlString()); | |||
| for (int i = 0; i < this.refundCount; i++) { | |||
| RefundRecord refundRecord = new 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) { | |||
| continue; | |||
| @@ -215,8 +213,8 @@ public class WxPayRefundQueryResult extends WxPayBaseResult { | |||
| for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) { | |||
| coupons.add( | |||
| 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; | |||
| import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult; | |||
| import org.testng.*; | |||
| import org.testng.annotations.*; | |||
| @@ -13,6 +12,15 @@ import java.util.Map; | |||
| * </pre> | |||
| */ | |||
| public class WxPayBaseResultTest { | |||
| @Test | |||
| public void testGetXmlValue() throws Exception { | |||
| } | |||
| @Test | |||
| public void testXml2Doc() throws Exception { | |||
| } | |||
| @Test | |||
| public void testToMap() throws Exception { | |||
| WxPayOrderQueryResult result = new WxPayOrderQueryResult(); | |||
| @@ -40,11 +48,17 @@ public class WxPayBaseResultTest { | |||
| Map<String, String> map = result.toMap(); | |||
| 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); | |||
| } | |||
| } | |||