# Conflicts:
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java
This commit is contained in:
YunaiV
2024-07-26 09:17:51 +08:00
12 changed files with 980 additions and 540 deletions

View File

@@ -23,9 +23,10 @@ public interface PayClientFactory {
* @param channelId 渠道编号
* @param channelCode 渠道编码
* @param config 支付配置
* @return 支付客户端
*/
<Config extends PayClientConfig> void createOrUpdatePayClient(Long channelId, String channelCode,
Config config);
<Config extends PayClientConfig> PayClient createOrUpdatePayClient(Long channelId, String channelCode,
Config config);
/**
* 注册支付客户端 Class用于模块中实现的 PayClient

View File

@@ -71,8 +71,8 @@ public class PayClientFactoryImpl implements PayClientFactory {
@Override
@SuppressWarnings("unchecked")
public <Config extends PayClientConfig> void createOrUpdatePayClient(Long channelId, String channelCode,
Config config) {
public <Config extends PayClientConfig> PayClient createOrUpdatePayClient(Long channelId, String channelCode,
Config config) {
AbstractPayClient<Config> client = (AbstractPayClient<Config>) clients.get(channelId);
if (client == null) {
client = this.createPayClient(channelId, channelCode, config);
@@ -81,6 +81,7 @@ public class PayClientFactoryImpl implements PayClientFactory {
} else {
client.refresh(config);
}
return client;
}
@SuppressWarnings("unchecked")

View File

@@ -36,6 +36,7 @@ import java.util.Objects;
import static cn.hutool.core.date.DatePattern.*;
import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V2;
import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig.API_VERSION_V3;
/**
* 微信支付抽象类,实现微信统一的接口、以及部分实现(退款)
@@ -59,19 +60,14 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
protected void doInit(String tradeType) {
// 创建 config 配置
WxPayConfig payConfig = new WxPayConfig();
BeanUtil.copyProperties(config, payConfig, "keyContent", "privateKeyContent", "privateCertContent");
BeanUtil.copyProperties(config, payConfig, "keyContent", "privateKeyContent");
payConfig.setTradeType(tradeType);
// weixin-pay-java 无法设置内容,只允许读取文件,所以这里要创建临时文件来解决
if (Base64.isBase64(config.getKeyContent())) {
if (Objects.equals(config.getApiVersion(), API_VERSION_V2)) {
payConfig.setKeyPath(FileUtils.createTempFile(Base64.decode(config.getKeyContent())).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {
} else if (Objects.equals(config.getApiVersion(), API_VERSION_V3)) {
payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
}
if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {
payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());
}
// payConfig.setCertSerialNo();
// 创建 client 客户端
client = new WxPayServiceImpl();
@@ -86,7 +82,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doUnifiedOrderV2(reqDTO);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return doUnifiedOrderV3(reqDTO);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
@@ -157,7 +153,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doParseOrderNotifyV2(body);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return doParseOrderNotifyV3(body);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
@@ -192,7 +188,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doGetOrderV2(outTradeNo);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return doGetOrderV3(outTradeNo);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
@@ -261,7 +257,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doUnifiedRefundV2(reqDTO);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return doUnifiedRefundV3(reqDTO);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
@@ -321,7 +317,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doParseRefundNotifyV2(body);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return parseRefundNotifyV3(body);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
@@ -358,7 +354,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
switch (config.getApiVersion()) {
case API_VERSION_V2:
return doGetRefundV2(outTradeNo, outRefundNo);
case WxPayClientConfig.API_VERSION_V3:
case API_VERSION_V3:
return doGetRefundV3(outTradeNo, outRefundNo);
default:
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));

View File

@@ -34,7 +34,8 @@ public class WxNativePayClient extends AbstractWxPayClient {
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO);
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO)
.setProductId(reqDTO.getOutTradeNo()); // V2 必须传递 productId无需在微信配置。该参数在 V3 简化,无需传递!
// 执行请求
WxPayNativeOrderResult response = client.createOrder(request);

View File

@@ -1,15 +1,11 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import javax.validation.Validator;
import javax.validation.constraints.NotBlank;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* 微信支付的 PayClientConfig 实现类
* 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性
@@ -71,16 +67,19 @@ public class WxPayClientConfig implements PayClientConfig {
*/
@NotBlank(message = "apiclient_key 不能为空", groups = V3.class)
private String privateKeyContent;
/**
* apiclient_cert.pem 证书文件的对应的字符串
*/
@NotBlank(message = "apiclient_cert 不能为空", groups = V3.class)
private String privateCertContent;
/**
* apiV3 密钥值
*/
@NotBlank(message = "apiV3 密钥值不能为空", groups = V3.class)
private String apiV3Key;
/**
* 证书序列号
*/
@NotBlank(message = "证书序列号不能为空", groups = V3.class)
private String certSerialNo;
@Deprecated // TODO 芋艿V2.3.0 进行移除
private String privateCertContent;
/**
* 分组校验 v2版本
@@ -100,11 +99,4 @@ public class WxPayClientConfig implements PayClientConfig {
API_VERSION_V2.equals(this.getApiVersion()) ? V2.class : V3.class);
}
public static void main(String[] args) throws FileNotFoundException {
String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12";
/// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem";
/// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem";
System.out.println(IoUtil.readUtf8(new FileInputStream(path)));
}
}