🎨 #1390 微信支付增加XML转换的快速模式,发送请求以及组装响应对象的时候不再依赖反射机制
* 增加XML的快速模式,发送请求以及组装响应对象的时候,不再依赖java的反射机制。 1:提升性能 2:可以通过 graalvm 生成native image. 本次完成:全部BaseWxPayRequest的改造,部分BaseWxPayResult子类的改造。 * clean code * 标记 xmlDoc 为 transient 否则toString()方法中Gson可能会堆栈溢出 * 完成大多数BaseWxPayResult子类的改造。还有 notify.*Result下面留了两个TODO需要处理。 * toXML时遗漏了sign参数 * 使用dom4j简化了toXML,同时根据本版本构建native-image的demo已经提交: https://github.com/outersky/wx-micronaut-graal.git 供参考。 * 完成了最后两个Result的xml解析。
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package com.github.binarywang.wxpay.bean.notify;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import org.testng.*;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
@@ -57,6 +59,27 @@ public class WxPayOrderNotifyResultTest {
|
||||
|
||||
Assert.assertEquals(result.getCouponList().get(0).getCouponId(), "10000");
|
||||
Assert.assertEquals(result.getCouponList().get(1).getCouponId(), "10001");
|
||||
|
||||
//fast mode test
|
||||
XmlConfig.fastMode = true;
|
||||
try {
|
||||
result = BaseWxPayResult.fromXML(xmlString, WxPayOrderNotifyResult.class);
|
||||
|
||||
Assert.assertEquals(result.getCouponCount().intValue(), 2);
|
||||
Assert.assertNotNull(result.getCouponList());
|
||||
Assert.assertEquals(result.getCouponList().size(), 2);
|
||||
|
||||
Assert.assertEquals(result.getCouponList().get(0).getCouponFee().intValue(), 100);
|
||||
Assert.assertEquals(result.getCouponList().get(1).getCouponFee().intValue(), 200);
|
||||
|
||||
Assert.assertEquals(result.getCouponList().get(0).getCouponType(), "CASH");
|
||||
Assert.assertEquals(result.getCouponList().get(1).getCouponType(), "NO_CASH");
|
||||
|
||||
Assert.assertEquals(result.getCouponList().get(0).getCouponId(), "10000");
|
||||
Assert.assertEquals(result.getCouponList().get(1).getCouponId(), "10001");
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
@@ -78,4 +80,50 @@ public class WxPayRefundNotifyResultTest {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
System.out.println(Base64.encodeBase64String(cipher.doFinal(xml.getBytes(StandardCharsets.UTF_8))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test from xml.
|
||||
* fast mode
|
||||
*
|
||||
* @throws WxPayException the wx pay exception
|
||||
*/
|
||||
public void testFromXMLFastMode() throws WxPayException {
|
||||
String xmlString = "<xml>" +
|
||||
"<return_code>SUCCESS</return_code>" +
|
||||
"<appid><![CDATA[****]]></appid>" +
|
||||
"<mch_id><![CDATA[****]]></mch_id>" +
|
||||
"<nonce_str><![CDATA[1ee38e38b04990449808688cf3a763b7]]></nonce_str>" +
|
||||
"<req_info><![CDATA[q1QZlV5j/4I7CsJ3voq1zDgVAuzNM/Gg5JYHcpMZCLtg9KQlB6vShzsh8tgK60dU6yG2WVa0zeSDlK4B7wJCad1lUUP8Ar0Hm18M1ZEjw5vQU17wMzypRM0M9A4CcRLBezRZYzCka9CAH90E2FZ74y6VRe4DNR87t5n3DWVtSbWTBoaFUexHtNs6pyrqX77VvbilIyLZMv5ZYQYOobbQ1U3kime5He7ShEWZ0GPI3gq+z/ZOLsnIdJ5bsT4kokhq/531hSoZ5006vxRGGXnhJt8IYiG7R+oSQxZOYqYR5SKWF+0z2/g0zzM2QQlT2ynLWvBKvdVCLlgCjFN1DF4z/7IEK5FAISFP0GGF51hYw/LofL3ftlD7h7jvjOIgH5viJ0yFGmGCEFHcLKqg0DPXmzwXIrkgQSSQPsuZ6UbHUUG0L8YTRgLnl2FwNFskJIaNx0179Il6xveR1sCXbwSDGvGN78sFuQMztbnx+gFu6VYgv7C+5pFr87wHFAeuDXGTkVM6ucAwSanP7HuxSVvf7SrSrcovKslyqj869pSqn/AB0atiQ4eoq3kWaOqx87NHOV1st9SQW1SYH7SKz4jd9uhrQyDuPb6KJSg1Z2B4sU4187NjPzL4NpzZySgiYk2yXpWKhCLIz6BdZuWX79zgqxLbGxJJnhyy3tOzRWIlMkDOppGJyh8LO0LOqhXzwyrCYzPA+h2xcr7xN5WIW1IGJSZqHdURUtlemcB+yZivuzARNH0LE2MGUfuoNgZ5j1Osn7K88IrkAyKupcIEmG3ktVnPOd1A9RQ9eWbU+C7yKrl6u5ZRZOX0eElVszKfBFy4tu3XHlT7hd/zMFK5NJt8sE89k5m7M8KCGSgJ+Y90ZnUclQvDVtoR5CFkfqsP9fSpA1L+aKYsl2ESq5+fzcqsYRL3YLEhIipBKKrvg6Gy698oNeG+9oCIyuiFexJDq8ycBZ/AWiR+pFQVbNRaFbfKPR9zCW8gHwYOGnENNY9gABuuENqxxXDx9tEYkACd0H9ezLnu9psC6AuR41ACfo6wGKUA1TnpVEHsDbdvJBWDcw60l1hkmHQN2lYFy+eMusEX]]></req_info></xml>";
|
||||
|
||||
String xmlDecryptedReqInfo = "<root>\n" +
|
||||
"<out_refund_no><![CDATA[R4001312001201707262674894706_4]]></out_refund_no>\n" +
|
||||
"<out_trade_no><![CDATA[201707260201501501005710775]]></out_trade_no>\n" +
|
||||
"<refund_account><![CDATA[REFUND_SOURCE_UNSETTLED_FUNDS]]></refund_account>\n" +
|
||||
"<refund_fee><![CDATA[15]]></refund_fee>\n" +
|
||||
"<refund_id><![CDATA[50000203702017072601461713166]]></refund_id>\n" +
|
||||
"<refund_recv_accout><![CDATA[用户零钱]]></refund_recv_accout>\n" +
|
||||
"<refund_request_source><![CDATA[API]]></refund_request_source>\n" +
|
||||
"<refund_status><![CDATA[SUCCESS]]></refund_status>\n" +
|
||||
"<settlement_refund_fee><![CDATA[15]]></settlement_refund_fee>\n" +
|
||||
"<settlement_total_fee><![CDATA[100]]></settlement_total_fee>\n" +
|
||||
"<success_time><![CDATA[2017-07-26 02:45:49]]></success_time>\n" +
|
||||
"<total_fee><![CDATA[100]]></total_fee>\n" +
|
||||
"<transaction_id><![CDATA[4001312001201707262674894706]]></transaction_id>\n" +
|
||||
"</root>";
|
||||
|
||||
XmlConfig.fastMode = true;
|
||||
try {
|
||||
WxPayRefundNotifyResult refundNotifyResult = BaseWxPayResult.fromXML(xmlString, WxPayRefundNotifyResult.class);
|
||||
System.out.println(refundNotifyResult.getReqInfoString());
|
||||
|
||||
refundNotifyResult.loadReqInfo(xmlDecryptedReqInfo);
|
||||
assertEquals(refundNotifyResult.getReqInfo().getRefundFee().intValue(), 15);
|
||||
assertEquals(refundNotifyResult.getReqInfo().getRefundStatus(), "SUCCESS");
|
||||
assertEquals(refundNotifyResult.getReqInfo().getRefundRecvAccout(), "用户零钱");
|
||||
System.out.println(refundNotifyResult);
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.binarywang.wxpay.bean.notify;
|
||||
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
|
||||
@@ -50,4 +51,38 @@ public class WxScanPayNotifyResultTest {
|
||||
assertThat(result.getSign()).isEqualTo("C380BEC2BFD727A4B6845133519F3AD6");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test from xml.
|
||||
* fast mode.
|
||||
*/
|
||||
@Test
|
||||
public void testFromXMLFastMode() {
|
||||
String xmlString = "<xml>\n" +
|
||||
" <appid><![CDATA[wx8888888888888888]]></appid>\n" +
|
||||
" <openid><![CDATA[o8GeHuLAsgefS_80exEr1cTqekUs]]></openid>\n" +
|
||||
" <mch_id><![CDATA[1900000109]]></mch_id>\n" +
|
||||
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
|
||||
" <nonce_str><![CDATA[5K8264ILTKCH16CQ2502SI8ZNMTM67VS]]></nonce_str>\n" +
|
||||
" <product_id><![CDATA[88888]]></product_id>\n" +
|
||||
" <sign><![CDATA[C380BEC2BFD727A4B6845133519F3AD6]]></sign>\n" +
|
||||
"</xml>";
|
||||
|
||||
XmlConfig.fastMode = true;
|
||||
try {
|
||||
WxScanPayNotifyResult result = BaseWxPayResult.fromXML(xmlString, WxScanPayNotifyResult.class);
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
|
||||
assertThat(result.getAppid()).isEqualTo("wx8888888888888888");
|
||||
assertThat(result.getOpenid()).isEqualTo("o8GeHuLAsgefS_80exEr1cTqekUs");
|
||||
assertThat(result.getMchId()).isEqualTo("1900000109");
|
||||
assertThat(result.getNonceStr()).isEqualTo("5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
|
||||
assertThat(result.getProductId()).isEqualTo("88888");
|
||||
assertThat(result.getSign()).isEqualTo("C380BEC2BFD727A4B6845133519F3AD6");
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -42,8 +43,8 @@ public class WxPayRedpackQueryResultTest {
|
||||
"</hblist>\n" +
|
||||
"</xml>";
|
||||
|
||||
WxPayRedpackQueryResult orderQueryResult = WxPayRedpackQueryResult.fromXML(xmlString, WxPayRedpackQueryResult.class);
|
||||
System.out.println(orderQueryResult);
|
||||
WxPayRedpackQueryResult orderQueryResult = BaseWxPayResult.fromXML(xmlString, WxPayRedpackQueryResult.class);
|
||||
// System.out.println(orderQueryResult);
|
||||
assertThat(orderQueryResult).isNotNull();
|
||||
|
||||
assertThat(orderQueryResult.getRedpackList()).isNotEmpty();
|
||||
@@ -51,4 +52,65 @@ public class WxPayRedpackQueryResultTest {
|
||||
assertThat(orderQueryResult.getRedpackList().get(0).getOpenid()).isEqualTo("o3yHF0uHuckI3yE6lwWiFQBQdVDI");
|
||||
assertThat(orderQueryResult.getRedpackList().get(0).getReceiveTime()).isEqualTo("2018-01-23 13:45:31");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test from xml.
|
||||
* FastMode
|
||||
*/
|
||||
@Test
|
||||
public void testFromXMLFastMode() {
|
||||
XmlConfig.fastMode = true;
|
||||
String xmlString = "<xml>\n" +
|
||||
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
|
||||
"<return_msg><![CDATA[OK]]></return_msg>\n" +
|
||||
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
|
||||
"<err_code><![CDATA[SUCCESS]]></err_code>\n" +
|
||||
"<err_code_des><![CDATA[OK]]></err_code_des>\n" +
|
||||
"<mch_billno><![CDATA[1473919402201801230145075410]]></mch_billno>\n" +
|
||||
"<mch_id><![CDATA[1497236182]]></mch_id>\n" +
|
||||
"<detail_id><![CDATA[1000041701201801233000139830103]]></detail_id>\n" +
|
||||
"<status><![CDATA[RECEIVED]]></status>\n" +
|
||||
"<send_type><![CDATA[API]]></send_type>\n" +
|
||||
"<hb_type><![CDATA[NORMAL]]></hb_type>\n" +
|
||||
"<total_num>1</total_num>\n" +
|
||||
"<total_amount>100</total_amount>\n" +
|
||||
"<send_time><![CDATA[2018-01-23 13:45:08]]></send_time>\n" +
|
||||
"<hblist>\n" +
|
||||
"<hbinfo>\n" +
|
||||
"<openid><![CDATA[o3yHF0uHuckI3yE6lwWiFQBQdVDI]]></openid>\n" +
|
||||
"<amount>100</amount>\n" +
|
||||
"<rcv_time><![CDATA[2018-01-23 13:45:31]]></rcv_time>\n" +
|
||||
"</hbinfo>\n" +
|
||||
"</hblist>\n" +
|
||||
"</xml>";
|
||||
|
||||
try {
|
||||
WxPayRedpackQueryResult orderQueryResult = BaseWxPayResult.fromXML(xmlString, WxPayRedpackQueryResult.class);
|
||||
// System.out.println(orderQueryResult);
|
||||
assertThat(orderQueryResult).isNotNull();
|
||||
|
||||
assertThat(orderQueryResult.getRedpackList()).isNotEmpty();
|
||||
assertThat(orderQueryResult.getRedpackList().get(0).getAmount()).isEqualTo(100);
|
||||
assertThat(orderQueryResult.getRedpackList().get(0).getOpenid()).isEqualTo("o3yHF0uHuckI3yE6lwWiFQBQdVDI");
|
||||
assertThat(orderQueryResult.getRedpackList().get(0).getReceiveTime()).isEqualTo("2018-01-23 13:45:31");
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void benchmark() {
|
||||
long now = System.currentTimeMillis();
|
||||
int loops = 10000;
|
||||
for (int i = 0; i < loops; i++) {
|
||||
testFromXML();
|
||||
}
|
||||
System.out.println(" reflect mode:\t" + (System.currentTimeMillis() - now) + " (ms) ");
|
||||
|
||||
now = System.currentTimeMillis();
|
||||
for (int i = 0; i < loops; i++) {
|
||||
testFromXMLFastMode();
|
||||
}
|
||||
System.out.println(" fast mode:\t" + (System.currentTimeMillis() - now) + " (ms) ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.github.binarywang.wxpay.bean.result;
|
||||
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -40,11 +41,67 @@ public class WxPayRefundResultTest {
|
||||
" <refund_fee>2</refund_fee> \n" +
|
||||
"</xml>";
|
||||
|
||||
WxPayRefundResult result = WxPayRefundResult.fromXML(xmlString);
|
||||
|
||||
WxPayRefundResult result = BaseWxPayResult.fromXML(xmlString, WxPayRefundResult.class);
|
||||
result.composeRefundCoupons();
|
||||
assertThat(result.getRefundCoupons()).isNotEmpty();
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponRefundId()).isEqualTo("123");
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponType()).isEqualTo("CASH");
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponRefundFee()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromXMLFastMode() {
|
||||
/*
|
||||
该xml字符串来自于官方文档示例,稍加改造,加上代金卷
|
||||
refund_channel 是个什么鬼,官方文档只字不提
|
||||
*/
|
||||
String xmlString = "<xml>\n" +
|
||||
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
|
||||
" <return_msg><![CDATA[OK]]></return_msg>\n" +
|
||||
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
|
||||
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
|
||||
" <nonce_str><![CDATA[NfsMFbUFpdbEhPXP]]></nonce_str>\n" +
|
||||
" <sign><![CDATA[B7274EB9F8925EB93100DD2085FA56C0]]></sign>\n" +
|
||||
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
|
||||
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
|
||||
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
|
||||
" <out_refund_no><![CDATA[1415701182]]></out_refund_no>\n" +
|
||||
" <refund_id><![CDATA[2008450740201411110000174436]]></refund_id>\n" +
|
||||
" <refund_channel><![CDATA[]]></refund_channel>\n" +
|
||||
" <coupon_refund_fee>1</coupon_refund_fee>\n" +
|
||||
" <coupon_refund_count>1</coupon_refund_count>\n" +
|
||||
" <coupon_refund_id_0>123</coupon_refund_id_0>\n" +
|
||||
" <coupon_refund_fee_0>1</coupon_refund_fee_0>\n" +
|
||||
" <coupon_type_0><![CDATA[CASH]]></coupon_type_0>\n" +
|
||||
" <refund_fee>2</refund_fee> \n" +
|
||||
"</xml>";
|
||||
XmlConfig.fastMode = true;
|
||||
try {
|
||||
WxPayRefundResult result = BaseWxPayResult.fromXML(xmlString, WxPayRefundResult.class);
|
||||
result.composeRefundCoupons();
|
||||
assertThat(result.getRefundCoupons()).isNotEmpty();
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponRefundId()).isEqualTo("123");
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponType()).isEqualTo("CASH");
|
||||
assertThat(result.getRefundCoupons().get(0).getCouponRefundFee()).isEqualTo(1);
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void benchmark() {
|
||||
long now = System.currentTimeMillis();
|
||||
int loops = 10000;
|
||||
for (int i = 0; i < loops; i++) {
|
||||
testFromXML();
|
||||
}
|
||||
System.out.println(" reflect mode:\t" + (System.currentTimeMillis() - now) + " (ms) ");
|
||||
|
||||
now = System.currentTimeMillis();
|
||||
for (int i = 0; i < loops; i++) {
|
||||
testFromXMLFastMode();
|
||||
}
|
||||
System.out.println(" fast mode:\t" + (System.currentTimeMillis() - now) + " (ms) ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import com.github.binarywang.wxpay.testbase.ApiTestModule;
|
||||
import com.github.binarywang.wxpay.testbase.XmlWxPayConfig;
|
||||
import com.github.binarywang.wxpay.util.XmlConfig;
|
||||
import com.google.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
@@ -566,8 +567,18 @@ public class BaseWxPayServiceImplTest {
|
||||
" <coupon_fee_1>200</coupon_fee_1>\n" +
|
||||
"</xml>";
|
||||
|
||||
WxPayOrderNotifyResult result = this.payService.parseOrderNotifyResult(xmlString);
|
||||
XmlConfig.fastMode = true;
|
||||
WxPayOrderNotifyResult result;
|
||||
try {
|
||||
result = BaseWxPayResult.fromXML(xmlString, WxPayOrderNotifyResult.class);
|
||||
System.out.println(result);
|
||||
} finally {
|
||||
XmlConfig.fastMode = false;
|
||||
}
|
||||
|
||||
result = this.payService.parseOrderNotifyResult(xmlString);
|
||||
System.out.println(result);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user