完善查询退款接口,并重构部分支付接口的实现,简化代码

This commit is contained in:
Binary Wang 2016-12-29 19:05:21 +08:00
parent a638189ec8
commit 22723f9f2b
10 changed files with 349 additions and 208 deletions

View File

@ -1,73 +1,79 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project <project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0" 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">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-parent</artifactId> <artifactId>weixin-java-parent</artifactId>
<version>2.4.6.BETA</version> <version>2.4.6.BETA</version>
</parent> </parent>
<artifactId>weixin-java-mp</artifactId> <artifactId>weixin-java-mp</artifactId>
<name>WeiXin Java Tools - MP</name> <name>WeiXin Java Tools - MP</name>
<description>微信公众号Java SDK</description> <description>微信公众号Java SDK</description>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId> <artifactId>weixin-java-common</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testng</groupId> <groupId>org.testng</groupId>
<artifactId>testng</artifactId> <artifactId>testng</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId> <artifactId>mockito-all</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.inject</groupId> <groupId>com.google.inject</groupId>
<artifactId>guice</artifactId> <artifactId>guice</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId> <artifactId>jetty-server</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId> <artifactId>jetty-servlet</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>joda-time</groupId> <groupId>joda-time</groupId>
<artifactId>joda-time</artifactId> <artifactId>joda-time</artifactId>
<version>2.9.4</version> <version>2.9.4</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>io.rest-assured</groupId>
<artifactId>xml-path</artifactId>
<version>3.0.1</version>
</dependency>
<build> </dependencies>
<plugins>
<plugin> <build>
<groupId>org.apache.maven.plugins</groupId> <plugins>
<artifactId>maven-surefire-plugin</artifactId> <plugin>
<configuration> <groupId>org.apache.maven.plugins</groupId>
<suiteXmlFiles> <artifactId>maven-surefire-plugin</artifactId>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile> <configuration>
</suiteXmlFiles> <suiteXmlFiles>
</configuration> <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</plugin> </suiteXmlFiles>
</plugins> </configuration>
</build> </plugin>
</plugins>
</build>
</project> </project>

View File

@ -310,20 +310,25 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
} }
@Override @Override
public void setSslContextFilePath(String filePath) throws Exception { public void setSslContextFilePath(String filePath) {
if (null == partnerId) { if (null == partnerId) {
throw new Exception("请先将partnerId进行赋"); throw new IllegalArgumentException("请设置partnerId的");
} }
File file = new File(filePath); File file = new File(filePath);
if (!file.exists()) { 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 @Override

View File

@ -1,14 +1,11 @@
package me.chanjar.weixin.mp.api.impl; 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.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.BeanUtils; 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.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpPayService; import me.chanjar.weixin.mp.api.WxMpPayService;
import me.chanjar.weixin.mp.api.WxMpService; 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.request.*;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@ -54,20 +51,16 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException { public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance(); this.initRequest(request);
xstream.processAnnotations(WxPayRefundRequest.class);
xstream.processAnnotations(WxPayRefundResult.class);
initRequest(request);
if (StringUtils.isBlank(request.getOpUserId())) { if (StringUtils.isBlank(request.getOpUserId())) {
request.setOpUserId(getConfig().getPartnerId()); request.setOpUserId(this.getConfig().getPartnerId());
} }
checkParameters(request); this.checkParameters(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/secapi/pay/refund"; String url = PAY_BASE_URL + "/secapi/pay/refund";
String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); String responseContent = this.executeWithKey(url, request.toXML());
WxPayRefundResult result = (WxPayRefundResult) xstream.fromXML(responseContent); WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@ -79,12 +72,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("transaction_id out_trade_noout_refund_no refund_id 必须四选一"); throw new IllegalArgumentException("transaction_id out_trade_noout_refund_no refund_id 必须四选一");
} }
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRefundQueryRequest.class);
xstream.processAnnotations(WxPayRefundQueryResult.class);
WxPayRefundQueryRequest request = new WxPayRefundQueryRequest(); WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
initRequest(request); this.initRequest(request);
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId)); request.setTransactionId(StringUtils.trimToNull(transactionId));
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo)); request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
@ -92,8 +81,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/pay/refundquery"; String url = PAY_BASE_URL + "/pay/refundquery";
String responseContent = this.executeRequest(url, xstream.toXML(request)); String responseContent = this.executeRequest(url, request.toXML());
WxPayRefundQueryResult result = (WxPayRefundQueryResult) xstream.fromXML(responseContent); WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class);
result.composeRefundRecords(responseContent); result.composeRefundRecords(responseContent);
this.checkResult(result); this.checkResult(result);
return result; return result;
@ -102,8 +91,9 @@ public class WxMpPayServiceImpl implements WxMpPayService {
private void checkResult(WxPayBaseResult result) throws WxErrorException { private void checkResult(WxPayBaseResult result) throws WxErrorException {
//校验返回结果签名 //校验返回结果签名
if (!checkSign(result.toMap())) { Map<String, String> map = result.toMap();
log.debug("校验结果签名失败,参数:{}", result.toMap()); if (!this.checkSign(map)) {
log.debug("校验结果签名失败,参数:{}", map);
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build()); throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
} }
@ -115,7 +105,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
+ result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: " + result.getReturnMsg() + ", 结果代码: " + result.getResultCode() + ", 错误代码: "
+ result.getErrCode() + ", 错误详情: " + result.getErrCodeDes()) + result.getErrCode() + ", 错误详情: " + result.getErrCodeDes())
.build(); .build();
log.error("结果业务代码异常,参数:{},详细:{}", result.toMap(), error); log.error("结果业务代码异常,参数:{},详细:{}", map, error);
throw new WxErrorException(error); throw new WxErrorException(error);
} }
} }
@ -138,10 +128,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException { public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException {
try { try {
log.trace("微信支付回调参数详细:{}", xmlData); log.trace("微信支付回调参数详细:{}", xmlData);
XStream xstream = XStreamInitializer.getInstance(); WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
xstream.processAnnotations(WxPayOrderNotifyResult.class);
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlData);
log.debug("微信支付回调结果对象:{}", result); log.debug("微信支付回调结果对象:{}", result);
this.checkResult(result); this.checkResult(result);
return result; return result;
@ -157,11 +144,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request)
throws WxErrorException { throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance(); this.initRequest(request);
xstream.processAnnotations(WxPaySendRedpackRequest.class);
xstream.processAnnotations(WxPaySendRedpackResult.class);
initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack"; String url = PAY_BASE_URL + "/mmpaymkttransfers/sendredpack";
@ -169,18 +152,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
//裂变红包 //裂变红包
url = PAY_BASE_URL + "/mmpaymkttransfers/sendgroupredpack"; url = PAY_BASE_URL + "/mmpaymkttransfers/sendgroupredpack";
} }
String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); String responseContent = this.executeWithKey(url, request.toXML());
WxPaySendRedpackResult result = (WxPaySendRedpackResult) xstream.fromXML(responseContent); WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@Override @Override
public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException { public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayRedpackQueryRequest.class);
xstream.processAnnotations(WxPayRedpackQueryResult.class);
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
request.setMchBillNo(mchBillNo); request.setMchBillNo(mchBillNo);
request.setBillType("MCHT"); request.setBillType("MCHT");
@ -188,8 +167,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo"; String url = PAY_BASE_URL + "/mmpaymkttransfers/gethbinfo";
String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); String responseContent = this.executeWithKey(url, request.toXML());
WxPayRedpackQueryResult result = (WxPayRedpackQueryResult) xstream.fromXML(responseContent); WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@ -201,10 +180,6 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一"); throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一");
} }
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderQueryRequest.class);
xstream.processAnnotations(WxPayOrderQueryResult.class);
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest(); WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId)); request.setTransactionId(StringUtils.trimToNull(transactionId));
@ -212,8 +187,8 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/pay/orderquery"; String url = PAY_BASE_URL + "/pay/orderquery";
String responseContent = this.executeRequest(url, xstream.toXML(request)); String responseContent = this.executeRequest(url, request.toXML());
WxPayOrderQueryResult result = (WxPayOrderQueryResult) xstream.fromXML(responseContent); WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class);
result.composeCoupons(responseContent); result.composeCoupons(responseContent);
this.checkResult(result); this.checkResult(result);
return result; return result;
@ -225,18 +200,14 @@ public class WxMpPayServiceImpl implements WxMpPayService {
throw new IllegalArgumentException("out_trade_no 不能为空"); throw new IllegalArgumentException("out_trade_no 不能为空");
} }
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderCloseRequest.class);
xstream.processAnnotations(WxPayOrderCloseResult.class);
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
initRequest(request); initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/pay/closeorder"; String url = PAY_BASE_URL + "/pay/closeorder";
String responseContent = this.executeRequest(url, xstream.toXML(request)); String responseContent = this.executeRequest(url, request.toXML());
WxPayOrderCloseResult result = (WxPayOrderCloseResult) xstream.fromXML(responseContent); WxPayOrderCloseResult result = WxPayOrderCloseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
@ -246,11 +217,7 @@ public class WxMpPayServiceImpl implements WxMpPayService {
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
throws WxErrorException { throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance(); this.initRequest(request);
xstream.processAnnotations(WxPayUnifiedOrderRequest.class);
xstream.processAnnotations(WxPayUnifiedOrderResult.class);
initRequest(request);
if (StringUtils.isBlank(request.getNotifyURL())) { if (StringUtils.isBlank(request.getNotifyURL())) {
request.setNotifyURL(getConfig().getNotifyURL()); request.setNotifyURL(getConfig().getNotifyURL());
} }
@ -261,12 +228,12 @@ public class WxMpPayServiceImpl implements WxMpPayService {
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/pay/unifiedorder"; String url = PAY_BASE_URL + "/pay/unifiedorder";
String xmlParam = xstream.toXML(request); String xmlParam = request.toXML();
log.debug("微信统一下单接口URL:{},参数:{}", url, xmlParam); log.debug("微信统一下单接口URL:{},参数:{}", url, xmlParam);
String responseContent = this.executeRequest(url, xmlParam); String responseContent = this.executeRequest(url, xmlParam);
log.debug("微信统一下单接口URL:{},结果:{}", url, responseContent); log.debug("微信统一下单接口URL:{},结果:{}", url, responseContent);
WxPayUnifiedOrderResult result = (WxPayUnifiedOrderResult) xstream.fromXML(responseContent); WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@ -324,35 +291,27 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException { public WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance(); this.initRequest(request);
xstream.processAnnotations(WxEntPayRequest.class);
xstream.processAnnotations(WxEntPayResult.class);
initRequest(request);
BeanUtils.checkRequiredFields(request); BeanUtils.checkRequiredFields(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers"; String url = PAY_BASE_URL + "/mmpaymkttransfers/promotion/transfers";
String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); String responseContent = this.executeWithKey(url, request.toXML());
WxEntPayResult result = (WxEntPayResult) xstream.fromXML(responseContent); WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class);
this.checkResult(result); this.checkResult(result);
return result; return result;
} }
@Override @Override
public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException { public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxEntPayQueryRequest.class);
xstream.processAnnotations(WxEntPayQueryResult.class);
WxEntPayQueryRequest request = new WxEntPayQueryRequest(); WxEntPayQueryRequest request = new WxEntPayQueryRequest();
initRequest(request); this.initRequest(request);
request.setSign(this.createSign(request)); request.setSign(this.createSign(request));
String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo"; String url = PAY_BASE_URL + "/mmpaymkttransfers/gettransferinfo";
String responseContent = this.executeRequestWithKeyFile(url, xstream.toXML(request)); String responseContent = this.executeWithKey(url, request.toXML());
WxEntPayQueryResult result = (WxEntPayQueryResult) xstream.fromXML(responseContent); WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class);
this.checkResult(result); this.checkResult(result);
return 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 { try {
SSLContext sslContext = getConfig().getSslContext(); SSLContext sslContext = getConfig().getSslContext();
if (null == sslContext) { if (null == sslContext) {
throw new Exception("请将配置类即WxMpConfigStorage的实现类中的SSLContext初始化"); throw new IllegalArgumentException("请先初始化配置类即WxMpConfigStorage的实现类中的SSLContext");
} }
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1"}, null,
@ -412,17 +371,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public String createSign(Object xmlBean) { public String createSign(Object xmlBean) {
return createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); return this.createSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
} }
@Override @Override
public String createSign(Object xmlBean, String signKey) { public String createSign(Object xmlBean, String signKey) {
return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); return this.createSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
} }
@Override @Override
public String createSign(Map<String, String> params) { public String createSign(Map<String, String> params) {
return createSign(params, getConfig().getPartnerKey()); return this.createSign(params, this.getConfig().getPartnerKey());
} }
@Override @Override
@ -443,17 +402,17 @@ public class WxMpPayServiceImpl implements WxMpPayService {
@Override @Override
public boolean checkSign(Object xmlBean) { public boolean checkSign(Object xmlBean) {
return checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey()); return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getPartnerKey());
} }
@Override @Override
public boolean checkSign(Object xmlBean, String signKey) { public boolean checkSign(Object xmlBean, String signKey) {
return checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey); return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
} }
@Override @Override
public boolean checkSign(Map<String, String> params) { public boolean checkSign(Map<String, String> params) {
return checkSign(params, getConfig().getPartnerKey()); return this.checkSign(params, getConfig().getPartnerKey());
} }
@Override @Override

View File

@ -1,7 +1,9 @@
package me.chanjar.weixin.mp.bean.pay.request; package me.chanjar.weixin.mp.bean.pay.request;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -17,6 +19,7 @@ import java.math.BigDecimal;
* <li>示例值 * <li>示例值
* <li>描述 * <li>描述
* </pre> * </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/ */
public abstract class WxPayBaseRequest { public abstract class WxPayBaseRequest {
@ -69,12 +72,22 @@ public abstract class WxPayBaseRequest {
@XStreamAlias("sign") @XStreamAlias("sign")
protected String 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() { public String getAppid() {
return this.appid; return this.appid;
} }
/** /**
* 如果配置中已经设置可以不设置值 * 如果配置中已经设置可以不设置值
*
* @param appid 微信公众号appid * @param appid 微信公众号appid
*/ */
public void setAppid(String appid) { public void setAppid(String appid) {
@ -87,6 +100,7 @@ public abstract class WxPayBaseRequest {
/** /**
* 如果配置中已经设置可以不设置值 * 如果配置中已经设置可以不设置值
*
* @param mchId 微信商户号 * @param mchId 微信商户号
*/ */
public void setMchId(String mchId) { public void setMchId(String mchId) {
@ -99,6 +113,7 @@ public abstract class WxPayBaseRequest {
/** /**
* 默认采用时间戳为随机字符串可以不设置 * 默认采用时间戳为随机字符串可以不设置
*
* @param nonceStr 随机字符串 * @param nonceStr 随机字符串
*/ */
public void setNonceStr(String nonceStr) { public void setNonceStr(String nonceStr) {
@ -113,17 +128,14 @@ public abstract class WxPayBaseRequest {
this.sign = sign; 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 @Override
public String toString() { public String toString() {
return ToStringUtils.toSimpleString(this); return ToStringUtils.toSimpleString(this);
} }
public String toXML() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(this.getClass());
return xstream.toXML(this);
}
} }

View File

@ -1,7 +1,6 @@
package me.chanjar.weixin.mp.bean.pay.request; package me.chanjar.weixin.mp.bean.pay.request;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required; import me.chanjar.weixin.common.annotation.Required;
/** /**
@ -144,8 +143,6 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
@XStreamAlias("refund_account") @XStreamAlias("refund_account")
private String refundAccount; private String refundAccount;
public String getDeviceInfo() { public String getDeviceInfo() {
return this.deviceInfo; return this.deviceInfo;
} }
@ -217,4 +214,5 @@ public class WxPayRefundRequest extends WxPayBaseRequest {
public void setRefundAccount(String refundAccount) { public void setRefundAccount(String refundAccount) {
this.refundAccount = refundAccount; this.refundAccount = refundAccount;
} }
} }

View File

@ -1,10 +1,19 @@
package me.chanjar.weixin.mp.bean.pay.result; 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 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.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
/** /**
@ -15,65 +24,90 @@ import java.util.Map;
* </pre> * </pre>
*/ */
public abstract class WxPayBaseResult { public abstract class WxPayBaseResult {
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
/** /**
* 返回状态码 * 返回状态码
*/ */
@XStreamAlias("return_code") @XStreamAlias("return_code")
protected String returnCode; protected String returnCode;
/** /**
* 返回信息 * 返回信息
*/ */
@XStreamAlias("return_msg") @XStreamAlias("return_msg")
protected String returnMsg; protected String returnMsg;
private String xmlString;
/** /**
* 业务结果 * 业务结果
*/ */
@XStreamAlias("result_code") @XStreamAlias("result_code")
private String resultCode; private String resultCode;
/** /**
* 错误代码 * 错误代码
*/ */
@XStreamAlias("err_code") @XStreamAlias("err_code")
private String errCode; private String errCode;
/** /**
* 错误代码描述 * 错误代码描述
*/ */
@XStreamAlias("err_code_des") @XStreamAlias("err_code_des")
private String errCodeDes; private String errCodeDes;
/** /**
* 公众账号ID * 公众账号ID
*/ */
@XStreamAlias("appid") @XStreamAlias("appid")
private String appid; private String appid;
/** /**
* 商户号 * 商户号
*/ */
@XStreamAlias("mch_id") @XStreamAlias("mch_id")
private String mchId; private String mchId;
/** /**
* 随机字符串 * 随机字符串
*/ */
@XStreamAlias("nonce_str") @XStreamAlias("nonce_str")
private String nonceStr; private String nonceStr;
/** /**
* 签名 * 签名
*/ */
@XStreamAlias("sign") @XStreamAlias("sign")
private String 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 extends WxPayBaseResult> T fromXML(String xmlString, Class<T> 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() { public String getReturnCode() {
return this.returnCode; return this.returnCode;
} }
@ -147,14 +181,43 @@ public abstract class WxPayBaseResult {
} }
/** /**
* 将单位分转换成单位圆 * 将bean通过保存的xml字符串转换成map
* @param fee 将要被转换为元的分的数值
*/ */
public static String feeToYuan(Integer fee) { public Map<String, String> toMap() {
return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString(); Map<String, String> result = Maps.newHashMap();
XmlPath xmlPath = new XmlPath(this.xmlString);
NodeChildren nodeChildren = xmlPath.getNodeChildren("xml");
Iterator<Node> iterator = nodeChildren.nodeIterator();
while (iterator.hasNext()) {
Node node = iterator.next();
result.put(node.name(), node.value());
}
return result;
} }
public Map<String,String> toMap(){ private String getXmlValueIfExists(XmlPath xmlPath, String path) {
return BeanUtils.xmlBean2Map(this); if (xmlPath.get(path) instanceof NodeChildrenImpl) {
if (((NodeChildrenImpl) xmlPath.get(path)).size() == 0) {
return null;
}
}
return xmlPath.getString(path);
}
protected <T> T getXmlValueIfExists(XmlPath xmlPath, String path, Class<T> 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("暂时不支持此种类型的数据");
} }
} }

View File

@ -1,10 +1,12 @@
package me.chanjar.weixin.mp.bean.pay.result; package me.chanjar.weixin.mp.bean.pay.result;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.BeanUtils; 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 me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyCoupon;
import org.apache.commons.lang3.builder.ToStringBuilder; import me.chanjar.weixin.mp.bean.pay.WxPayOrderNotifyResultConverter;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@ -376,6 +378,15 @@ public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializ
@Override @Override
public String toString() { 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;
}
} }

View File

@ -2,6 +2,7 @@ package me.chanjar.weixin.mp.bean.pay.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;
@ -186,7 +187,38 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
public void composeRefundRecords(String xmlString) { public void composeRefundRecords(String xmlString) {
if (this.refundCount != null && this.refundCount > 0) { if (this.refundCount != null && this.refundCount > 0) {
this.refundRecords = Lists.newArrayList(); 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<RefundRecord.RefundCoupon> 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 {
* </pre> * </pre>
*/ */
@XStreamAlias("refund_fee") @XStreamAlias("refund_fee")
private String refundFee; private Integer refundFee;
/** /**
* <pre> * <pre>
@ -254,7 +286,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("settlement_refund_fee") @XStreamAlias("settlement_refund_fee")
private String settlementRefundFee; private Integer settlementRefundFee;
/** /**
* <pre> * <pre>
@ -293,7 +325,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_fee") @XStreamAlias("coupon_refund_fee")
private String couponRefundFee; private Integer couponRefundFee;
/** /**
* <pre> * <pre>
@ -306,7 +338,7 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_count") @XStreamAlias("coupon_refund_count")
private String couponRefundCount; private Integer couponRefundCount;
private List<RefundCoupon> refundCoupons; private List<RefundCoupon> refundCoupons;
@ -364,19 +396,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
this.refundChannel = refundChannel; this.refundChannel = refundChannel;
} }
public String getRefundFee() { public Integer getRefundFee() {
return refundFee; return refundFee;
} }
public void setRefundFee(String refundFee) { public void setRefundFee(Integer refundFee) {
this.refundFee = refundFee; this.refundFee = refundFee;
} }
public String getSettlementRefundFee() { public Integer getSettlementRefundFee() {
return settlementRefundFee; return settlementRefundFee;
} }
public void setSettlementRefundFee(String settlementRefundFee) { public void setSettlementRefundFee(Integer settlementRefundFee) {
this.settlementRefundFee = settlementRefundFee; this.settlementRefundFee = settlementRefundFee;
} }
@ -396,19 +428,19 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
this.couponType = couponType; this.couponType = couponType;
} }
public String getCouponRefundFee() { public Integer getCouponRefundFee() {
return couponRefundFee; return couponRefundFee;
} }
public void setCouponRefundFee(String couponRefundFee) { public void setCouponRefundFee(Integer couponRefundFee) {
this.couponRefundFee = couponRefundFee; this.couponRefundFee = couponRefundFee;
} }
public String getCouponRefundCount() { public Integer getCouponRefundCount() {
return couponRefundCount; return couponRefundCount;
} }
public void setCouponRefundCount(String couponRefundCount) { public void setCouponRefundCount(Integer couponRefundCount) {
this.couponRefundCount = couponRefundCount; this.couponRefundCount = couponRefundCount;
} }
@ -446,6 +478,8 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* 100 * 100
* 退款代金券批次ID ,$n为下标$m为下标从0开始编号 * 退款代金券批次ID ,$n为下标$m为下标从0开始编号
* </pre> * </pre>
*
* @deprecated 貌似是被去掉了但不知是何时
*/ */
@XStreamAlias("coupon_refund_batch_id") @XStreamAlias("coupon_refund_batch_id")
private String couponRefundBatchId; private String couponRefundBatchId;
@ -474,9 +508,15 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
* </pre> * </pre>
*/ */
@XStreamAlias("coupon_refund_fee") @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.couponRefundBatchId = couponRefundBatchId;
this.couponRefundId = couponRefundId; this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee; this.couponRefundFee = couponRefundFee;
@ -484,5 +524,6 @@ public class WxPayRefundQueryResult extends WxPayBaseResult {
} }
} }
} }

View File

@ -13,8 +13,6 @@ import me.chanjar.weixin.mp.bean.pay.result.*;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.File;
/** /**
* 测试支付相关接口 * 测试支付相关接口
* Created by Binary Wang on 2016/7/28. * Created by Binary Wang on 2016/7/28.
@ -90,7 +88,6 @@ public class WxMpPayServiceImplTest {
*/ */
@Test @Test
public void testQueryRedpack() throws Exception { public void testQueryRedpack() throws Exception {
File keyFile = new File("E:\\dlt.p12");
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa"); WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa");
System.err.println(redpackResult); System.err.println(redpackResult);
} }

View File

@ -0,0 +1,49 @@
package me.chanjar.weixin.mp.bean.pay.result;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* <pre>
* Created by Binary Wang on 2016-12-29.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayRefundQueryResultTest {
@Test
public void composeRefundRecords() throws Exception {
/*
该xml字符串来自于官方文档示例
*/
String xmlString = "<xml>\n" +
" <appid><![CDATA[wx2421b1c4370ec43b]]></appid>\n" +
" <mch_id><![CDATA[10000100]]></mch_id>\n" +
" <nonce_str><![CDATA[TeqClE3i0mvn3DrK]]></nonce_str>\n" +
" <out_refund_no_0><![CDATA[1415701182]]></out_refund_no_0>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <refund_count>1</refund_count>\n" +
" <refund_fee_0>1</refund_fee_0>\n" +
" <refund_id_0><![CDATA[2008450740201411110000174436]]></refund_id_0>\n" +
" <refund_status_0><![CDATA[PROCESSING]]></refund_status_0>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
" <sign><![CDATA[1F2841558E233C33ABA71A961D27561C]]></sign>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
"</xml>";
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");
}
}