1
0
mirror of synced 2025-12-26 20:48:00 +08:00

微信支付相关代码独立成一个子模块

This commit is contained in:
Binary Wang
2017-03-05 22:49:17 +08:00
parent 8a270c8f7e
commit eee954b736
49 changed files with 1596 additions and 1308 deletions

View File

@@ -0,0 +1,50 @@
package com.github.binarywang.wxpay.bean.result;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import org.testng.*;
import org.testng.annotations.*;
import java.util.Map;
/**
* <pre>
* Created by Binary Wang on 2017-01-04.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayBaseResultTest {
@Test
public void testToMap() throws Exception {
WxPayOrderQueryResult result = new WxPayOrderQueryResult();
result.setXmlString("<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" +
" <device_info><![CDATA[1000]]></device_info>\n" +
" <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>\n" +
" <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>\n" +
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
" <trade_type><![CDATA[MICROPAY]]></trade_type>\n" +
" <bank_type><![CDATA[CCB_DEBIT]]></bank_type>\n" +
" <total_fee>1</total_fee>\n" +
" <fee_type><![CDATA[CNY]]></fee_type>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <attach><![CDATA[订单额外描述]]></attach>\n" +
" <time_end><![CDATA[20141111170043]]></time_end>\n" +
" <trade_state><![CDATA[SUCCESS]]></trade_state>\n" +
"</xml>");
Map<String, String> map = result.toMap();
System.out.println(map);
Assert.assertEquals("SUCCESS", map.get("return_code"));
Assert.assertEquals("订单额外描述", map.get("attach"));
result.setXmlString("");
System.out.println(result.toMap());
}
}

View File

@@ -0,0 +1,65 @@
package com.github.binarywang.wxpay.bean.result;
import org.testng.*;
import org.testng.annotations.*;
/**
* <pre>
* Created by Binary Wang on 2017-01-04.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public class WxPayOrderQueryResultTest {
@Test
public void testComposeCoupons() throws Exception {
/**
* xml样例字符串来自于官方文档并稍加改造加入了coupon相关的数据便于测试
*/
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" +
" <device_info><![CDATA[1000]]></device_info>\n" +
" <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>\n" +
" <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>\n" +
" <result_code><![CDATA[SUCCESS]]></result_code>\n" +
" <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>\n" +
" <is_subscribe><![CDATA[Y]]></is_subscribe>\n" +
" <trade_type><![CDATA[MICROPAY]]></trade_type>\n" +
" <bank_type><![CDATA[CCB_DEBIT]]></bank_type>\n" +
" <total_fee>1</total_fee>\n" +
" <fee_type><![CDATA[CNY]]></fee_type>\n" +
" <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>\n" +
" <out_trade_no><![CDATA[1415757673]]></out_trade_no>\n" +
" <attach><![CDATA[订单额外描述]]></attach>\n" +
" <time_end><![CDATA[20141111170043]]></time_end>\n" +
" <trade_state><![CDATA[SUCCESS]]></trade_state>\n" +
" <coupon_count>2</coupon_count>\n" +
" <coupon_type_0><![CDATA[CASH]]></coupon_type_0>\n" +
" <coupon_id_0>10000</coupon_id_0>\n" +
" <coupon_fee_0>100</coupon_fee_0>\n" +
" <coupon_type_1><![CDATA[NO_CASH]]></coupon_type_1>\n" +
" <coupon_id_1>10001</coupon_id_1>\n" +
" <coupon_fee_1>200</coupon_fee_1>\n" +
"</xml>";
WxPayOrderQueryResult orderQueryResult = WxPayOrderQueryResult.fromXML(xmlString, WxPayOrderQueryResult.class);
orderQueryResult.composeCoupons();
Assert.assertEquals(orderQueryResult.getCouponCount().intValue(), 2);
Assert.assertNotNull(orderQueryResult.getCoupons());
Assert.assertEquals(orderQueryResult.getCoupons().size(), 2);
Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponFee().intValue(), 100);
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponFee().intValue(), 200);
Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponType(), "CASH");
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponType(), "NO_CASH");
Assert.assertEquals(orderQueryResult.getCoupons().get(0).getCouponId(), "10000");
Assert.assertEquals(orderQueryResult.getCoupons().get(1).getCouponId(), "10001");
}
}

View File

@@ -0,0 +1,48 @@
package com.github.binarywang.wxpay.bean.result;
import org.testng.*;
import org.testng.annotations.*;
/**
* <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 = WxPayRefundQueryResult.fromXML(xmlString, WxPayRefundQueryResult.class);
result.composeRefundRecords();
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");
}
}

View File

@@ -0,0 +1,60 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.testng.*;
import org.testng.annotations.*;
public class WxPaySendRedpackResultTest {
private XStream xstream;
@BeforeTest
public void setup() {
this.xstream = XStreamInitializer.getInstance();
this.xstream.processAnnotations(WxPaySendRedpackResult.class);
}
@Test
public void loadSuccessResult() {
final String successSample = "<xml>\n" +
"<return_code><![CDATA[SUCCESS]]></return_code>\n" +
"<return_msg><![CDATA[发放成功.]]></return_msg>\n" +
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
"<err_code><![CDATA[0]]></err_code>\n" +
"<err_code_des><![CDATA[发放成功.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046545]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"<send_listid>100000000020150520314766074200</send_listid>\n" +
"<send_time>20150520102602</send_time>\n" +
"</xml>";
WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(successSample);
Assert.assertEquals("SUCCESS", wxMpRedpackResult.getReturnCode());
Assert.assertEquals("SUCCESS", wxMpRedpackResult.getResultCode());
Assert.assertEquals("20150520102602", wxMpRedpackResult.getSendTime());
}
@Test
public void loadFailureResult() {
final String failureSample = "<xml>\n" +
"<return_code><![CDATA[FAIL]]></return_code>\n" +
"<return_msg><![CDATA[系统繁忙,请稍后再试.]]></return_msg>\n" +
"<result_code><![CDATA[FAIL]]></result_code>\n" +
"<err_code><![CDATA[268458547]]></err_code>\n" +
"<err_code_des><![CDATA[系统繁忙,请稍后再试.]]></err_code_des>\n" +
"<mch_billno><![CDATA[0010010404201411170000046542]]></mch_billno>\n" +
"<mch_id>10010404</mch_id>\n" +
"<wxappid><![CDATA[wx6fa7e3bab7e15415]]></wxappid>\n" +
"<re_openid><![CDATA[onqOjjmM1tad-3ROpncN-yUfa6uI]]></re_openid>\n" +
"<total_amount>1</total_amount>\n" +
"</xml>";
WxPaySendRedpackResult wxMpRedpackResult = (WxPaySendRedpackResult) this.xstream.fromXML(failureSample);
Assert.assertEquals("FAIL", wxMpRedpackResult.getReturnCode());
Assert.assertEquals("FAIL", wxMpRedpackResult.getResultCode());
Assert.assertEquals("onqOjjmM1tad-3ROpncN-yUfa6uI", wxMpRedpackResult.getReOpenid());
Assert.assertEquals(1, wxMpRedpackResult.getTotalAmount());
}
}

View File

@@ -0,0 +1,196 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.testbase.ApiTestModule;
import com.github.binarywang.wxpay.testbase.TestPayConfig;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.*;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.testng.Assert.*;
/**
* 测试支付相关接口
* Created by Binary Wang on 2016/7/28.
*
* @author binarywang (https://github.com/binarywang)
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMpPayServiceImplTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Inject
protected WxPayService wxService;
@Test
public void testGetPayInfo() throws Exception {
}
@Test
public void testDownloadBill() throws Exception {
File file = this.wxService.downloadBill("20170101", "ALL", "GZIP", "1111111");
assertNotNull(file);
//必填字段为空时,抛出异常
this.wxService.downloadBill("", "", "", null);
}
@Test
public void testReport() throws Exception {
WxPayReportRequest request = new WxPayReportRequest();
request.setInterfaceUrl("hahahah");
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
request.setExecuteTime(1000);
request.setReturnCode("aaa");
request.setResultCode("aaa");
request.setUserIp("8.8.8");
this.wxService.report(request);
}
/**
* Test method for {@link WxPayService#refund(WxPayRefundRequest)} .
*/
@Test//(dependsOnMethods = {"setSSLKey"})
public void testRefund() throws Exception {
WxPayRefundResult result = this.wxService.refund(
WxPayRefundRequest.newBuilder()
.outRefundNo("aaa")
.outTradeNo("1111")
.totalFee(1222)
.refundFee(111)
.build());
this.logger.info(result.toString());
}
/**
* Test method for {@link WxPayService#refundQuery(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} .
*/
@Test
public void testRefundQuery() throws Exception {
WxPayRefundQueryResult result;
result = this.wxService.refundQuery("1", "", "", "");
this.logger.info(result.toString());
result = this.wxService.refundQuery("", "2", "", "");
this.logger.info(result.toString());
result = this.wxService.refundQuery("", "", "3", "");
this.logger.info(result.toString());
result = this.wxService.refundQuery("", "", "", "4");
this.logger.info(result.toString());
//测试四个参数都填的情况,应该报异常的
result = this.wxService.refundQuery("1", "2", "3", "4");
this.logger.info(result.toString());
}
/**
* Test method for {@link WxPayService#sendRedpack(WxPaySendRedpackRequest)} .
*/
@Test//(dependsOnMethods = {"setSSLKey"})
public void testSendRedpack() throws Exception {
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
request.setActName("abc");
request.setClientIp("aaa");
request.setMchBillNo("aaaa");
request.setReOpenid(((TestPayConfig) this.wxService.getConfig()).getOpenid());
WxPaySendRedpackResult redpackResult = this.wxService.sendRedpack(request);
this.logger.info(redpackResult.toString());
}
/**
* Test method for {@link WxPayService#queryRedpack(java.lang.String)}.
*/
@Test//(dependsOnMethods = {"setSSLKey"})
public void testQueryRedpack() throws Exception {
WxPayRedpackQueryResult redpackResult = this.wxService.queryRedpack("aaaa");
this.logger.info(redpackResult.toString());
}
/**
* Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}.
*/
@Test
public void testUnifiedOrder() throws WxErrorException {
WxPayUnifiedOrderResult result = this.wxService
.unifiedOrder(WxPayUnifiedOrderRequest.builder()
.body("我去")
.totalFee(1)
.spbillCreateIp("111111")
.notifyURL("111111")
.tradeType("JSAPI")
.openid("122")
.outTradeNo("111111")
.build());
this.logger.info(result.toString());
}
/**
* Test method for {@link WxPayService#queryOrder(java.lang.String, java.lang.String)} .
*/
@Test
public void testQueryOrder() throws WxErrorException {
this.logger.info(this.wxService.queryOrder("11212121", null).toString());
this.logger.info(this.wxService.queryOrder(null, "11111").toString());
}
/**
* Test method for {@link WxPayService#closeOrder(java.lang.String)} .
*/
@Test
public void testCloseOrder() throws WxErrorException {
this.logger.info(this.wxService.closeOrder("11212121").toString());
}
/**
* Test method for {@link WxPayService#entPay(WxEntPayRequest)}.
*/
@Test//(dependsOnMethods = {"setSSLKey"})
public void testEntPay() throws WxErrorException {
WxEntPayRequest request = new WxEntPayRequest();
this.logger.info(this.wxService.entPay(request).toString());
}
/**
* Test method for {@link WxPayService#queryEntPay(java.lang.String)}.
*/
@Test//(dependsOnMethods = {"setSSLKey"})
public void testQueryEntPay() throws WxErrorException {
this.logger.info(this.wxService.queryEntPay("11212121").toString());
}
@Test
public void testCreateScanPayQrcodeMode1() throws Exception {
String productId = "abc";
byte[] bytes = this.wxService.createScanPayQrcodeMode1(productId, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);
String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
this.logger.info(qrcodeContent);
assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
assertTrue(qrcodeContent.contains("product_id=" + productId));
}
@Test
public void testCreateScanPayQrcodeMode2() throws Exception {
String qrcodeContent = "abc";
byte[] bytes = this.wxService.createScanPayQrcodeMode2(qrcodeContent, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);
assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
}
}

View File

@@ -0,0 +1,38 @@
package com.github.binarywang.wxpay.testbase;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.io.IOException;
import java.io.InputStream;
public class ApiTestModule implements Module {
@Override
public void configure(Binder binder) {
try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) {
TestPayConfig config = this.fromXml(TestPayConfig.class, is1);
WxPayService wxService = new WxPayServiceImpl();
wxService.setConfig(config);
binder.bind(WxPayService.class).toInstance(wxService);
binder.bind(WxPayConfig.class).toInstance(config);
} catch (IOException e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
private <T> T fromXml(Class<T> clazz, InputStream is) {
XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", clazz);
xstream.processAnnotations(clazz);
return (T) xstream.fromXML(is);
}
}

View File

@@ -0,0 +1,31 @@
package com.github.binarywang.wxpay.testbase;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
@XStreamAlias("xml")
public class TestPayConfig extends WxPayConfig {
private String openid;
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
@Override
public boolean useSandboxForWxPay() {
//沙箱环境不成熟,有问题无法使用,暂时屏蔽掉
// return true;
return false;
}
}

View File

@@ -0,0 +1,16 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
<logger name="com.github.binarywang.wxpay" level="debug"/>
</configuration>

View File

@@ -0,0 +1,13 @@
<xml>
<appId>公众号appid</appId>
<mchId>微信商户平台ID</mchId>
<mchKey>商户平台设置的API密钥</mchKey>
<!---
以下为官网文档所提供样例参数,仅供部分接口测试使用
<appId>wxd930ea5d5a258f4f</appId>
<mchId>10000100</mchId>
<mchKey>192006250b4c09247ec02edce69f6a2d</mchKey>
-->
<keyPath>商户平台的证书文件地址</keyPath>
<openid>某个openId</openid>
</xml>