mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-12 07:25:39 +08:00
style 支付宝功能对接
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package cn.daxpay.open.channel.alipay.service.isv;
|
||||
|
||||
import cn.daxpay.open.channel.alipay.client.credential.AlipaySdkCredential;
|
||||
import cn.daxpay.open.channel.alipay.dao.isv.AlipayIsvAppManager;
|
||||
import cn.daxpay.open.channel.alipay.dao.isv.AlipayIsvChannelMerchantManager;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvApp;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvAppKeyConfig;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvChannelMerchant;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductConfigManager;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
|
||||
import cn.daxpay.open.platform.core.enums.pay.config.PayEnvEnum;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 支付宝服务商通道凭证组装器
|
||||
///
|
||||
/// 从服务商应用([AlipayIsvApp] + [AlipayIsvAppKeyConfig])与子商户授权绑定([AlipayIsvChannelMerchant])
|
||||
/// 组装下发给子应用的通道调用凭证 [AlipaySdkCredential]。
|
||||
///
|
||||
/// 服务商代调用模式: appId / 私钥 / 证书取自服务商应用, 应用授权令牌(appAuthToken)取自子商户授权绑定,
|
||||
/// 子应用据此以服务商身份代子商户发起支付宝请求。
|
||||
///
|
||||
/// 供服务商支付/同步/关闭策略组装通道调用凭证。
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayIsvConfigAssembler {
|
||||
|
||||
private final AlipayIsvChannelMerchantManager alipayIsvChannelMerchantManager;
|
||||
private final AlipayIsvAppManager alipayIsvAppManager;
|
||||
private final AlipayIsvAppKeyConfigService alipayIsvAppKeyConfigService;
|
||||
private final PayProductConfigManager payProductConfigManager;
|
||||
|
||||
/// 组装服务商模式的通道调用凭证(下发给子应用)
|
||||
///
|
||||
/// @param mchNo 平台商户号(定位子商户授权绑定)
|
||||
/// @return 支付宝 SDK 凭证, 字段对齐子应用 AlipaySdkCredential
|
||||
public AlipaySdkCredential buildConfig(String mchNo) {
|
||||
// 子商户授权绑定(含 appAuthToken)
|
||||
AlipayIsvChannelMerchant isvMerchant = alipayIsvChannelMerchantManager.findByMchNo(mchNo)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.mchAppNotFound"));
|
||||
// 服务商应用(appId 来源)
|
||||
AlipayIsvApp isvApp = alipayIsvAppManager.findById(isvMerchant.getIsvAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
// 服务商应用密钥/证书配置
|
||||
AlipayIsvAppKeyConfig keyConfig = alipayIsvAppKeyConfigService.findByAlipayIsvAppId(isvMerchant.getIsvAppId());
|
||||
|
||||
AlipaySdkCredential credential = new AlipaySdkCredential();
|
||||
credential.setAliAppId(isvApp.getAliAppId());
|
||||
credential.setPrivateKey(keyConfig.getPrivateKey());
|
||||
credential.setAlipayPublicKey(keyConfig.getAlipayPublicKey());
|
||||
credential.setAuthType(keyConfig.getAuthType());
|
||||
credential.setAppCert(keyConfig.getAppCert());
|
||||
credential.setAlipayCert(keyConfig.getAlipayCert());
|
||||
credential.setAlipayRootCert(keyConfig.getAlipayRootCert());
|
||||
// 应用授权令牌(服务商代子商户调用接口的凭据)
|
||||
credential.setAppAuthToken(isvMerchant.getAppAuthToken());
|
||||
// 读取服务商支付产品当前生效环境, 判断是否沙箱
|
||||
boolean sandbox = payProductConfigManager.findByProduct(ProductEnum.ALIPAY_ISV.getCode())
|
||||
.map(c -> PayEnvEnum.SANDBOX.getCode().equals(c.getActiveEnv()))
|
||||
.orElse(false);
|
||||
credential.setSandbox(sandbox);
|
||||
return credential;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.daxpay.open.channel.alipay.strategy.isv;
|
||||
|
||||
import cn.daxpay.open.channel.alipay.client.credential.AlipaySdkCredential;
|
||||
import cn.daxpay.open.channel.alipay.service.isv.AlipayIsvConfigAssembler;
|
||||
import cn.daxpay.open.channel.alipay.service.payment.close.AlipayCloseService;
|
||||
import cn.daxpay.open.payment.pay.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.strategy.pay.AbsPayCloseStrategy;
|
||||
import cn.daxpay.open.platform.core.enums.pay.pay.CloseTypeEnum;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 支付宝服务商支付关闭策略
|
||||
///
|
||||
/// 支付宝服务商模式(ProductEnum.ALIPAY_ISV)下的支付关闭策略。
|
||||
/// 组装通道凭证(委托 [AlipayIsvConfigAssembler]), 关闭执行委托给 [AlipayCloseService]。
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayIsvCloseStrategy extends AbsPayCloseStrategy {
|
||||
|
||||
private final AlipayCloseService alipayCloseService;
|
||||
private final AlipayIsvConfigAssembler alipayIsvConfigAssembler;
|
||||
|
||||
@Override
|
||||
public ProductEnum getProduct() {
|
||||
return ProductEnum.ALIPAY_ISV;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseTypeEnum doClose(PayTrade trade, boolean useCancel) {
|
||||
// 组装服务商模式通道调用凭证(含应用授权令牌)
|
||||
AlipaySdkCredential credential = alipayIsvConfigAssembler.buildConfig(trade.getMchNo());
|
||||
return alipayCloseService.close(trade, credential, useCancel);
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,36 @@
|
||||
package cn.daxpay.open.channel.alipay.strategy.isv;
|
||||
|
||||
import cn.daxpay.open.channel.alipay.dao.isv.AlipayIsvAppManager;
|
||||
import cn.daxpay.open.channel.alipay.dao.isv.AlipayIsvChannelMerchantManager;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvApp;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvAppKeyConfig;
|
||||
import cn.daxpay.open.channel.alipay.entity.isv.AlipayIsvChannelMerchant;
|
||||
import cn.daxpay.open.channel.alipay.service.isv.AlipayIsvAppKeyConfigService;
|
||||
import cn.daxpay.open.channel.alipay.service.isv.AlipayIsvConfigAssembler;
|
||||
import cn.daxpay.open.channel.alipay.service.payment.pay.AlipayPayService;
|
||||
import cn.daxpay.open.payment.common.context.PayStrategyContext;
|
||||
import cn.daxpay.open.payment.pay.bo.PayTradeResultBo;
|
||||
import cn.daxpay.open.payment.strategy.pay.AbsPayStrategy;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.PayMethodEnum;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/// # 支付宝服务商支付策略
|
||||
///
|
||||
/// 支付宝服务商模式(ProductEnum.ALIPAY_ISV)下发起支付的具体执行策略。
|
||||
/// 负责服务商配置组装(含应用授权令牌), 支付执行委托给 [AlipayPayService]。
|
||||
///
|
||||
/// 负责服务商配置组装(含应用授权令牌, 委托 [AlipayIsvConfigAssembler]), 支付执行委托给 [AlipayPayService]。
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayIsvPayStrategy extends AbsPayStrategy {
|
||||
|
||||
private final AlipayPayService alipayPayService;
|
||||
private final AlipayIsvChannelMerchantManager alipayIsvChannelMerchantManager;
|
||||
private final AlipayIsvAppManager alipayIsvAppManager;
|
||||
private final AlipayIsvAppKeyConfigService alipayIsvAppKeyConfigService;
|
||||
private final AlipayIsvConfigAssembler alipayIsvConfigAssembler;
|
||||
|
||||
@Override
|
||||
public ProductEnum getProduct() {
|
||||
return ProductEnum.ALIPAY_ISV;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBeforePay(PayStrategyContext context) {
|
||||
mapMethod(context.getPayParam().getMethod());
|
||||
// 前置阶段构建配置,存入上下文供 doPay 使用
|
||||
context.setChannelConfig(buildConfig(context.getTrade().getMchNo()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayTradeResultBo doPay(PayStrategyContext context) {
|
||||
return alipayPayService.pay(context.getTrade(), context.getPayParam(), context.getChannelConfig());
|
||||
}
|
||||
|
||||
private Map<String, Object> buildConfig(String mchNo) {
|
||||
AlipayIsvChannelMerchant isvMerchant = alipayIsvChannelMerchantManager.findByMchNo(mchNo)
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.mchAppNotFound"));
|
||||
AlipayIsvApp isvApp = alipayIsvAppManager.findById(isvMerchant.getIsvAppId())
|
||||
.orElseThrow(() -> new DataNotExistException("error.channel.alipay.appNotFound"));
|
||||
AlipayIsvAppKeyConfig keyConfig = alipayIsvAppKeyConfigService.findByAlipayIsvAppId(isvMerchant.getIsvAppId());
|
||||
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("aliAppId", isvApp.getAliAppId());
|
||||
config.put("privateKey", keyConfig.getPrivateKey());
|
||||
config.put("alipayPublicKey", keyConfig.getAlipayPublicKey());
|
||||
config.put("authType", keyConfig.getAuthType());
|
||||
config.put("appCert", keyConfig.getAppCert());
|
||||
config.put("alipayCert", keyConfig.getAlipayCert());
|
||||
config.put("alipayRootCert", keyConfig.getAlipayRootCert());
|
||||
config.put("appAuthToken", isvMerchant.getAppAuthToken());
|
||||
return config;
|
||||
}
|
||||
|
||||
private static String mapMethod(String methodCode) {
|
||||
PayMethodEnum m = PayMethodEnum.findByCode(methodCode);
|
||||
return switch (m) {
|
||||
case ALIPAY_PC -> "alipay_page";
|
||||
case ALIPAY_H5 -> "alipay_wap";
|
||||
case ALIPAY_APP -> "alipay_app";
|
||||
case ALIPAY_QR, ALIPAY_ORDER_QR -> "alipay_qr";
|
||||
default -> throw new UnsupportedOperationException(
|
||||
"暂不支持的支付宝支付方式: " + methodCode);
|
||||
};
|
||||
// 组装服务商模式通道调用凭证(含应用授权令牌), 支付执行委托 AlipayPayService
|
||||
return alipayPayService.pay(context.getTrade(), context.getPayParam(),
|
||||
alipayIsvConfigAssembler.buildConfig(context.getTrade().getMchNo()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.daxpay.open.channel.alipay.strategy.isv;
|
||||
|
||||
import cn.daxpay.open.channel.alipay.client.credential.AlipaySdkCredential;
|
||||
import cn.daxpay.open.channel.alipay.service.isv.AlipayIsvConfigAssembler;
|
||||
import cn.daxpay.open.channel.alipay.service.payment.sync.AlipaySyncService;
|
||||
import cn.daxpay.open.payment.pay.bo.PaySyncResultBo;
|
||||
import cn.daxpay.open.payment.pay.order.entity.PayTrade;
|
||||
import cn.daxpay.open.payment.strategy.sync.AbsSyncPayOrderStrategy;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/// # 支付宝服务商支付同步策略
|
||||
///
|
||||
/// 支付宝服务商模式(ProductEnum.ALIPAY_ISV)下的支付同步策略。
|
||||
/// 组装通道凭证(委托 [AlipayIsvConfigAssembler]), 同步执行委托给 [AlipaySyncService]。
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayIsvSyncStrategy extends AbsSyncPayOrderStrategy {
|
||||
|
||||
private final AlipaySyncService alipaySyncService;
|
||||
private final AlipayIsvConfigAssembler alipayIsvConfigAssembler;
|
||||
|
||||
@Override
|
||||
public ProductEnum getProduct() {
|
||||
return ProductEnum.ALIPAY_ISV;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaySyncResultBo doSync(PayTrade trade) {
|
||||
// 组装服务商模式通道调用凭证(含应用授权令牌)
|
||||
AlipaySdkCredential credential = alipayIsvConfigAssembler.buildConfig(trade.getMchNo());
|
||||
return alipaySyncService.sync(trade, credential);
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,4 @@ public class PayStrategyContext {
|
||||
public PayStrategyContext(NormalPayParam payParam) {
|
||||
this.payParam = payParam;
|
||||
}
|
||||
|
||||
/// 读取通道配置(各通道策略 cast 自己的配置类型)
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getChannelConfig() {
|
||||
return (T) channelConfig;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user