From c065ad212fba5d4f3958d892fb785195fd63214e Mon Sep 17 00:00:00 2001 From: 0katekate0 <32161300+0katekate0@users.noreply.github.com> Date: Wed, 19 Apr 2023 22:06:00 +0800 Subject: [PATCH] =?UTF-8?q?:art:=20#2980=E3=80=90=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E3=80=91=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E7=9B=B8=E5=85=B3=E7=9A=84=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- weixin-java-pay/pom.xml | 4 + .../wxpay/bean/request/BaseWxPayRequest.java | 8 ++ .../wxpay/constant/WxPayConstants.java | 11 +++ .../binarywang/wxpay/util/RequestUtils.java | 49 +++++++++++++ .../impl/BaseWxPayServiceImplTest.java | 73 +++++++++++++++++-- 5 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java diff --git a/weixin-java-pay/pom.xml b/weixin-java-pay/pom.xml index 0a40c4adf..b51185a42 100644 --- a/weixin-java-pay/pom.xml +++ b/weixin-java-pay/pom.xml @@ -68,6 +68,10 @@ com.google.code.gson gson + + javax.servlet + javax.servlet-api + diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java index fde7f7150..6d227f636 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/BaseWxPayRequest.java @@ -22,6 +22,7 @@ import java.io.Serializable; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static com.github.binarywang.wxpay.constant.WxPayConstants.SignType.ALL_SIGN_TYPES; @@ -149,6 +150,13 @@ public abstract class BaseWxPayRequest implements Serializable { return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue(); } + /** + * 元转分 + */ + public static Integer yuan2Fen(BigDecimal yuan) { + return yuan.multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue(); + } + /** * 检查请求参数内容,包括必填参数以及特殊约束. */ diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java index ffd17efe4..59dd17ed6 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java @@ -26,6 +26,17 @@ public class WxPayConstants { */ public static final Format QUERY_COMMENT_DATE_FORMAT = FastDateFormat.getInstance("yyyyMMddHHmmss"); + /** + * 币种类型. + */ + public static class CurrencyType { + /** + * 人民币. + */ + public static final String CNY = "CNY"; + + } + /** * 校验用户姓名选项,企业付款时使用. */ diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java new file mode 100644 index 000000000..b641cbe53 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/RequestUtils.java @@ -0,0 +1,49 @@ +package com.github.binarywang.wxpay.util; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; + +/** + *
+ * 请求工具类.
+ * Created by Wang_Wong on 2023-04-14.
+ * 
+ * + * @author Wang_Wong + */ +public class RequestUtils { + + /** + * 获取请求头数据,微信V3版本回调使用 + * + * @param request + * @return 字符串 + */ + public static String readData(HttpServletRequest request) { + BufferedReader br = null; + StringBuilder result = new StringBuilder(); + try { + br = request.getReader(); + for (String line; (line = br.readLine()) != null; ) { + if (result.length() > 0) { + result.append("\n"); + } + result.append(line); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return result.toString(); + } + +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java index e25efe5cb..10781cf6e 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImplTest.java @@ -2,8 +2,7 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.utils.qrcode.QrcodeUtils; import com.github.binarywang.wxpay.bean.coupon.*; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResultTest; +import com.github.binarywang.wxpay.bean.notify.*; import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; @@ -11,6 +10,7 @@ import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.constant.WxPayConstants.AccountType; import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; @@ -19,6 +19,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.RequestUtils; import com.github.binarywang.wxpay.util.XmlConfig; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -29,10 +30,14 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Path; import java.util.Calendar; import java.util.Date; +import java.util.Optional; import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType; import static org.assertj.core.api.Assertions.assertThat; @@ -728,9 +733,9 @@ public class BaseWxPayServiceImplTest { //构建金额信息 WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount(); //设置币种信息 - amount.setCurrency("CNY"); + amount.setCurrency(WxPayConstants.CurrencyType.CNY); //设置金额 - amount.setTotal(1); + amount.setTotal(BaseWxPayRequest.yuan2Fen(BigDecimal.ONE)); request.setAmount(amount); WxPayUnifiedOrderV3Result.JsapiResult result = this.payService.createOrderV3(TradeTypeEnum.JSAPI, request); @@ -767,6 +772,63 @@ public class BaseWxPayServiceImplTest { System.out.println(GSON.toJson(result)); } + /** + * 测试V3支付成功回调 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_5.shtml + * + * @throws Exception the exception + */ + @Test + public void testParseOrderNotifyV3Result(HttpServletRequest request, HttpServletResponse response) throws Exception { + + String timestamp = request.getHeader("Wechatpay-Timestamp"); + Optional.ofNullable(timestamp).orElseThrow(() -> new RuntimeException("时间戳不能为空")); + + String nonce = request.getHeader("Wechatpay-Nonce"); + Optional.ofNullable(nonce).orElseThrow(() -> new RuntimeException("nonce不能为空")); + + String serialNo = request.getHeader("Wechatpay-Serial"); + Optional.ofNullable(serialNo).orElseThrow(() -> new RuntimeException("serialNo不能为空")); + + String signature = request.getHeader("Wechatpay-Signature"); + Optional.ofNullable(signature).orElseThrow(() -> new RuntimeException("signature不能为空")); + + log.info("请求头参数为:timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + + // V2版本请参考com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResultTest里的单元测试 + final WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = this.payService.parseOrderNotifyV3Result(RequestUtils.readData(request), + new SignatureHeader(timestamp, nonce, signature, serialNo)); + log.info(GSON.toJson(wxPayOrderNotifyV3Result)); + } + + /** + * 测试V3退款成功回调 + * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_11.shtml + * + * @throws Exception the exception + */ + @Test + public void testParseRefundNotifyV3Result(HttpServletRequest request, HttpServletResponse response) throws Exception { + + String timestamp = request.getHeader("Wechatpay-Timestamp"); + Optional.ofNullable(timestamp).orElseThrow(() -> new RuntimeException("时间戳不能为空")); + + String nonce = request.getHeader("Wechatpay-Nonce"); + Optional.ofNullable(nonce).orElseThrow(() -> new RuntimeException("nonce不能为空")); + + String serialNo = request.getHeader("Wechatpay-Serial"); + Optional.ofNullable(serialNo).orElseThrow(() -> new RuntimeException("serialNo不能为空")); + + String signature = request.getHeader("Wechatpay-Signature"); + Optional.ofNullable(signature).orElseThrow(() -> new RuntimeException("signature不能为空")); + + log.info("支付请求头参数为:timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + + final WxPayRefundNotifyV3Result wxPayRefundNotifyV3Result = this.payService.parseRefundNotifyV3Result(RequestUtils.readData(request), + new SignatureHeader(timestamp, nonce, signature, serialNo)); + log.info(GSON.toJson(wxPayRefundNotifyV3Result)); + } + @Test public void testRefundQueryV3() throws WxPayException { WxPayRefundQueryV3Request request = new WxPayRefundQueryV3Request(); @@ -778,10 +840,11 @@ public class BaseWxPayServiceImplTest { /** * 测试包含正向代理的测试 + * * @throws WxPayException */ @Test - public void testQueryOrderV3WithProxy() { + public void testQueryOrderV3WithProxy() { try { WxPayOrderQueryV3Request request = new WxPayOrderQueryV3Request(); request.setOutTradeNo("n1ZvYqjAg3D3LUBa");