Browse Source

添加扫码支付生成二维码的接口及其单元测试,#113

master
Binary Wang 8 years ago
parent
commit
c142daa734
5 changed files with 115 additions and 14 deletions
  1. +5
    -1
      weixin-java-mp/pom.xml
  2. +29
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java
  3. +38
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java
  4. +0
    -1
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java
  5. +43
    -12
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java

+ 5
- 1
weixin-java-mp/pom.xml View File

@@ -59,7 +59,11 @@
<artifactId>xml-path</artifactId> <artifactId>xml-path</artifactId>
<version>3.0.1</version> <version>3.0.1</version>
</dependency> </dependency>

<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>qrcode-utils</artifactId>
<version>1.0</version>
</dependency>
</dependencies> </dependencies>


<build> <build>


+ 29
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java View File

@@ -7,6 +7,7 @@ import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest; import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;


import java.io.File;
import java.util.Map; import java.util.Map;


/** /**
@@ -235,4 +236,32 @@ public interface WxMpPayService {
*/ */
WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException; WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException;


/**
* <pre>
* 扫码支付模式一生成二维码的方法
* 二维码中的内容为链接,形式为:
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
* 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
* </pre>
* @param productId 产品Id
* @param sideLength 要生成的二维码的边长,如果为空,则取默认值400
* @param logoFile 商户logo图片的文件对象,可以为空
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength);

/**
* <pre>
* 扫码支付模式二生成二维码的方法
* 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
* 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
* </pre>
* @param codeUrl 微信返回的交易会话的二维码链接
* @param logoFile 商户logo图片的文件对象,可以为空
* @param sideLength 要生成的二维码的边长,如果为空,则取默认值400
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength);
} }

+ 38
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java View File

@@ -1,5 +1,7 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.google.common.collect.Maps;
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;
@@ -25,6 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;


import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;


@@ -316,6 +319,41 @@ public class WxMpPayServiceImpl implements WxMpPayService {
return result; return result;
} }


@Override
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
//weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?");
Map<String, String> params = Maps.newHashMap();
params.put("appid", this.getConfig().getAppId());
params.put("mch_id", this.getConfig().getPartnerId());
params.put("product_id", productId);
params.put("time_stamp", String.valueOf(System.currentTimeMillis()));
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));

String sign = this.createSign(params);
params.put("sign", sign);

for (String key : params.keySet()) {
codeUrl.append(key + "=" + params.get(key) + "&");
}

String content = codeUrl.toString().substring(0, codeUrl.length() - 1);
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(content, logoFile);
}

return QrcodeUtils.createQrcode(content, sideLength, logoFile);
}

@Override
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(codeUrl, logoFile);
}

return QrcodeUtils.createQrcode(codeUrl, sideLength, logoFile);
}

private String executeRequest(String url, String requestStr) throws WxErrorException { private String executeRequest(String url, String requestStr) throws WxErrorException {
HttpPost httpPost = new HttpPost(url); HttpPost httpPost = new HttpPost(url);
if (this.wxMpService.getHttpProxy() != null) { if (this.wxMpService.getHttpProxy() != null) {


+ 0
- 1
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java View File

@@ -19,7 +19,6 @@ public class ApiTestModule implements Module {
WxXmlMpInMemoryConfigStorage config = this WxXmlMpInMemoryConfigStorage config = this
.fromXml(WxXmlMpInMemoryConfigStorage.class, is1); .fromXml(WxXmlMpInMemoryConfigStorage.class, is1);
config.setAccessTokenLock(new ReentrantLock()); config.setAccessTokenLock(new ReentrantLock());
config.setSslContextFilePath(config.getKeyPath());
WxMpService wxService = new WxMpServiceImpl(); WxMpService wxService = new WxMpServiceImpl();
wxService.setWxMpConfigStorage(config); wxService.setWxMpConfigStorage(config);




+ 43
- 12
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java View File

@@ -1,5 +1,6 @@
package me.chanjar.weixin.mp.api.impl; package me.chanjar.weixin.mp.api.impl;


import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.ApiTestModule; import me.chanjar.weixin.mp.api.ApiTestModule;
@@ -10,9 +11,13 @@ import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest; import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest; import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
import me.chanjar.weixin.mp.bean.pay.result.*; import me.chanjar.weixin.mp.bean.pay.result.*;
import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;


import java.nio.file.Files;
import java.nio.file.Path;

/** /**
* 测试支付相关接口 * 测试支付相关接口
* Created by Binary Wang on 2016/7/28. * Created by Binary Wang on 2016/7/28.
@@ -22,7 +27,6 @@ import org.testng.annotations.Test;
@Test @Test
@Guice(modules = ApiTestModule.class) @Guice(modules = ApiTestModule.class)
public class WxMpPayServiceImplTest { public class WxMpPayServiceImplTest {

@Inject @Inject
protected WxMpService wxService; protected WxMpService wxService;


@@ -32,9 +36,17 @@ public class WxMpPayServiceImplTest {
} }


/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest)} .
* 需要证书的接口需要先执行该方法
*/ */
@Test @Test
public void setSSLKey(){
WxXmlMpInMemoryConfigStorage config = (WxXmlMpInMemoryConfigStorage) this.wxService.getWxMpConfigStorage();
config.setSslContextFilePath(config.getKeyPath());
}
/**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refund(WxPayRefundRequest)} .
*/
@Test(dependsOnMethods = {"setSSLKey"})
public void testRefund() throws Exception { public void testRefund() throws Exception {
WxPayRefundRequest request = new WxPayRefundRequest(); WxPayRefundRequest request = new WxPayRefundRequest();
request.setOutRefundNo("aaa"); request.setOutRefundNo("aaa");
@@ -45,7 +57,6 @@ public class WxMpPayServiceImplTest {
System.err.println(result); System.err.println(result);
} }



/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} . * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#refundQuery(String, String, String, String)} .
*/ */
@@ -63,15 +74,10 @@ public class WxMpPayServiceImplTest {
System.err.println(result); System.err.println(result);
} }


@Test
public void testCheckJSSDKCallbackDataSignature() throws Exception {

}

/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest)} . * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#sendRedpack(WxPaySendRedpackRequest)} .
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public void testSendRedpack() throws Exception { public void testSendRedpack() throws Exception {
WxPaySendRedpackRequest request = new WxPaySendRedpackRequest(); WxPaySendRedpackRequest request = new WxPaySendRedpackRequest();
request.setActName("abc"); request.setActName("abc");
@@ -86,7 +92,7 @@ public class WxMpPayServiceImplTest {
/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String)}. * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryRedpack(String)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public void testQueryRedpack() throws Exception { public void testQueryRedpack() throws Exception {
WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa"); WxPayRedpackQueryResult redpackResult = this.wxService.getPayService().queryRedpack("aaaa");
System.err.println(redpackResult); System.err.println(redpackResult);
@@ -125,7 +131,7 @@ public class WxMpPayServiceImplTest {
/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest)}. * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#entPay(WxEntPayRequest)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public final void testEntPay() throws WxErrorException { public final void testEntPay() throws WxErrorException {
WxEntPayRequest request = new WxEntPayRequest(); WxEntPayRequest request = new WxEntPayRequest();
System.err.println(this.wxService.getPayService().entPay(request)); System.err.println(this.wxService.getPayService().entPay(request));
@@ -134,8 +140,33 @@ public class WxMpPayServiceImplTest {
/** /**
* Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryEntPay(String)}. * Test method for {@link me.chanjar.weixin.mp.api.impl.WxMpPayServiceImpl#queryEntPay(String)}.
*/ */
@Test
@Test(dependsOnMethods = {"setSSLKey"})
public final void testQueryEntPay() throws WxErrorException { public final void testQueryEntPay() throws WxErrorException {
System.err.println(this.wxService.getPayService().queryEntPay("11212121")); System.err.println(this.wxService.getPayService().queryEntPay("11212121"));
} }

@Test
public void testCreateScanPayQrcodeMode1() throws Exception {
String productId = "abc";
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode1(productId, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);
String qrcodeContent = QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile());
System.out.println(qrcodeContent);

Assert.assertTrue(qrcodeContent.startsWith("weixin://wxpay/bizpayurl?"));
Assert.assertTrue(qrcodeContent.contains("product_id=" + productId));
}

@Test
public void testCreateScanPayQrcodeMode2() throws Exception {
String qrcodeContent = "abc";
byte[] bytes = this.wxService.getPayService().createScanPayQrcodeMode2(qrcodeContent, null, null);
Path qrcodeFilePath = Files.createTempFile("qrcode_", ".jpg");
Files.write(qrcodeFilePath, bytes);

Assert.assertEquals(QrcodeUtils.decodeQrcode(qrcodeFilePath.toFile()), qrcodeContent);
}


} }

Loading…
Cancel
Save