refactor(union): 银联通道去 direct 子包, 配置类与商户管理扁平化

- 删除 union/**/direct/ 子包, Controller/Service/Entity/Param/Result/Convert/Manager/Mapper 上移至模块根包

- UnionDirectConfigAssembler → UnionConfigAssembler, UnionDirectKeyConfig* → UnionKeyConfig*, UnionDirectChannelMerchant* → UnionChannelMerchant*

- 各 strategy/callback 引用同步更新

- pom 描述与产品策略注释「直连银联 ACP」→「银联 ACP」
This commit is contained in:
daxpay
2026-08-03 19:52:38 +08:00
parent e79dfbaef7
commit 63104c5fa7
25 changed files with 161 additions and 159 deletions

View File

@@ -12,5 +12,5 @@
<artifactId>daxpay-channel-union</artifactId>
<packaging>jar</packaging>
<description>云闪付(直连银联 ACP)支付通道</description>
<description>云闪付(银联 ACP)支付通道</description>
</project>

View File

@@ -6,9 +6,9 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.ComponentScan;
/// # 云闪付(直连银联 ACP)支付实现
/// # 云闪付(银联 ACP)支付实现
///
/// 云闪付直连银联全渠道支付平台, 通过证书签名支持主扫/被扫/H5 支付。
/// 云闪付对接银联全渠道支付平台, 通过证书签名支持主扫/被扫/H5 支付。
/// 主应用通过声明式 HTTP 客户端调用子应用 dax-pay-channel-one 完成实际通道交互。
@AutoConfiguration
@ConfigurationPropertiesScan

View File

@@ -5,7 +5,7 @@ import lombok.Data;
/// # 云闪付 SDK 凭证
///
/// 与子应用 dax-pay-channel-one 的 `UnionSdkCredential` 镜像, 跨 HTTP 传输时字段对齐。
/// 主应用从直连配置(union_direct_key_config)提取商户号、签名类型与三证书后组装, 下发给子应用。
/// 主应用从密钥配置(union_key_config)提取商户号、签名类型与三证书后组装, 下发给子应用。
///
/// 银联 ACP 采用 RSA2 证书签名(私钥证书 PKCS12 + 中级/根证书), 三证书均为 Base64 字符串。
@Data

View File

@@ -1,10 +1,10 @@
package cn.daxpay.open.channel.union.controller.direct;
package cn.daxpay.open.channel.union.controller;
import cn.daxpay.open.channel.union.param.direct.UnionDirectChannelMerchantCreateParam;
import cn.daxpay.open.channel.union.param.direct.UnionDirectKeyConfigParam;
import cn.daxpay.open.channel.union.result.direct.UnionDirectKeyConfigResult;
import cn.daxpay.open.channel.union.service.direct.UnionDirectChannelMerchantService;
import cn.daxpay.open.channel.union.service.direct.UnionDirectKeyConfigService;
import cn.daxpay.open.channel.union.param.UnionChannelMerchantCreateParam;
import cn.daxpay.open.channel.union.param.UnionKeyConfigParam;
import cn.daxpay.open.channel.union.result.UnionKeyConfigResult;
import cn.daxpay.open.channel.union.service.UnionChannelMerchantService;
import cn.daxpay.open.channel.union.service.UnionKeyConfigService;
import cn.daxpay.open.platform.core.annotation.PermCode;
import cn.daxpay.open.platform.core.code.PermCodes;
import cn.daxpay.open.platform.core.rest.Res;
@@ -21,36 +21,36 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/// # 云闪付直连通道商户管理
/// # 云闪付通道商户管理
///
/// 提供通道商户创建和 RSA2 证书配置管理
/// 银联商户号(merId)创建时录入, 私钥/中级/根证书由密钥配置维护
@PermCode(menuCode = PermCodes.Channel.Merchant.MENU)
@Validated
@Tag(name = "云闪付直连通道商户管理")
@Tag(name = "云闪付通道商户管理")
@RestController
@RequestMapping("/admin/union/direct-channel-merchant")
@RequestMapping("/admin/union/channel-merchant")
@RequiredArgsConstructor
public class UnionDirectChannelMerchantController {
public class UnionChannelMerchantController {
private final UnionDirectChannelMerchantService unionDirectChannelMerchantService;
private final UnionDirectKeyConfigService unionDirectKeyConfigService;
private final UnionChannelMerchantService unionChannelMerchantService;
private final UnionKeyConfigService unionKeyConfigService;
@PermCode(code = PermCodes.Action.MANAGE)
@Operation(summary = "创建云闪付直连通道商户")
@Operation(summary = "创建云闪付通道商户")
@PostMapping("/create")
public Result<Void> create(@RequestBody @Validated UnionDirectChannelMerchantCreateParam param) {
unionDirectChannelMerchantService.create(param);
public Result<Void> create(@RequestBody @Validated UnionChannelMerchantCreateParam param) {
unionChannelMerchantService.create(param);
return Res.ok();
}
@PermCode(code = PermCodes.Action.VIEW)
@Operation(summary = "根据通道商户号查询证书配置")
@GetMapping("/find-key-config")
public Result<UnionDirectKeyConfigResult> findKeyConfig(
public Result<UnionKeyConfigResult> findKeyConfig(
@NotBlank(message = "{validation.field.channelMerchantNo.notBlank}") String channelMchNo,
@NotNull(message = "{validation.field.sandbox.notNull}") Boolean sandbox) {
var config = unionDirectKeyConfigService.findByChannelMchNo(channelMchNo, sandbox);
var config = unionKeyConfigService.findByChannelMchNo(channelMchNo, sandbox);
var result = config.toResult();
result.setKeyPrivateCertConfigured(config.getKeyPrivateCert() != null);
result.setKeyPrivateCertPwdConfigured(config.getKeyPrivateCertPwd() != null);
@@ -60,8 +60,8 @@ public class UnionDirectChannelMerchantController {
@PermCode(code = PermCodes.Action.MANAGE)
@Operation(summary = "保存证书配置")
@PostMapping("/save-key-config")
public Result<Void> saveKeyConfig(@RequestBody @Validated UnionDirectKeyConfigParam param) {
unionDirectKeyConfigService.save(param);
public Result<Void> saveKeyConfig(@RequestBody @Validated UnionKeyConfigParam param) {
unionKeyConfigService.save(param);
return Res.ok();
}
}

View File

@@ -0,0 +1,19 @@
package cn.daxpay.open.channel.union.convert;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import cn.daxpay.open.channel.union.param.UnionKeyConfigParam;
import cn.daxpay.open.channel.union.result.UnionKeyConfigResult;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
/// # 云闪付密钥配置转换
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface UnionKeyConfigConvert {
UnionKeyConfigConvert CONVERT = Mappers.getMapper(UnionKeyConfigConvert.class);
UnionKeyConfigResult toResult(UnionKeyConfig entity);
void copy(UnionKeyConfigParam param, @MappingTarget UnionKeyConfig entity);
}

View File

@@ -1,19 +0,0 @@
package cn.daxpay.open.channel.union.convert.direct;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import cn.daxpay.open.channel.union.param.direct.UnionDirectKeyConfigParam;
import cn.daxpay.open.channel.union.result.direct.UnionDirectKeyConfigResult;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
/// # 云闪付直连密钥配置转换
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface UnionDirectKeyConfigConvert {
UnionDirectKeyConfigConvert CONVERT = Mappers.getMapper(UnionDirectKeyConfigConvert.class);
UnionDirectKeyConfigResult toResult(UnionDirectKeyConfig entity);
void copy(UnionDirectKeyConfigParam param, @MappingTarget UnionDirectKeyConfig entity);
}

View File

@@ -0,0 +1,27 @@
package cn.daxpay.open.channel.union.dao;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import cn.daxpay.open.platform.common.mybatisplus.impl.BaseManager;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/// # 云闪付密钥配置
@Repository
public class UnionKeyConfigManager extends BaseManager<UnionKeyConfigMapper, UnionKeyConfig> {
/// 根据通道商户号和沙箱标志查询(双环境并存)
public Optional<UnionKeyConfig> findByChannelMchNoAndSandbox(String channelMchNo, boolean sandbox) {
return lambdaQuery()
.eq(UnionKeyConfig::getChannelMchNo, channelMchNo)
.eq(UnionKeyConfig::getSandbox, sandbox)
.oneOpt();
}
/// 根据通道商户号删除
public void deleteByChannelMchNo(String channelMchNo) {
lambdaUpdate()
.eq(UnionKeyConfig::getChannelMchNo, channelMchNo)
.remove();
}
}

View File

@@ -0,0 +1,10 @@
package cn.daxpay.open.channel.union.dao;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/// # 云闪付密钥配置
@Mapper
public interface UnionKeyConfigMapper extends MPJBaseMapper<UnionKeyConfig> {
}

View File

@@ -1,27 +0,0 @@
package cn.daxpay.open.channel.union.dao.direct;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import cn.daxpay.open.platform.common.mybatisplus.impl.BaseManager;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/// # 云闪付直连密钥配置
@Repository
public class UnionDirectKeyConfigManager extends BaseManager<UnionDirectKeyConfigMapper, UnionDirectKeyConfig> {
/// 根据通道商户号和沙箱标志查询(双环境并存)
public Optional<UnionDirectKeyConfig> findByChannelMchNoAndSandbox(String channelMchNo, boolean sandbox) {
return lambdaQuery()
.eq(UnionDirectKeyConfig::getChannelMchNo, channelMchNo)
.eq(UnionDirectKeyConfig::getSandbox, sandbox)
.oneOpt();
}
/// 根据通道商户号删除
public void deleteByChannelMchNo(String channelMchNo) {
lambdaUpdate()
.eq(UnionDirectKeyConfig::getChannelMchNo, channelMchNo)
.remove();
}
}

View File

@@ -1,10 +0,0 @@
package cn.daxpay.open.channel.union.dao.direct;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/// # 云闪付直连密钥配置
@Mapper
public interface UnionDirectKeyConfigMapper extends MPJBaseMapper<UnionDirectKeyConfig> {
}

View File

@@ -1,7 +1,7 @@
package cn.daxpay.open.channel.union.entity.direct;
package cn.daxpay.open.channel.union.entity;
import cn.daxpay.open.channel.union.convert.direct.UnionDirectKeyConfigConvert;
import cn.daxpay.open.channel.union.result.direct.UnionDirectKeyConfigResult;
import cn.daxpay.open.channel.union.convert.UnionKeyConfigConvert;
import cn.daxpay.open.channel.union.result.UnionKeyConfigResult;
import cn.daxpay.open.payment.common.entity.MchBaseEntity;
import cn.daxpay.open.platform.common.mybatisplus.function.ToResult;
import cn.daxpay.open.platform.common.mybatisplus.handler.encrypt.DataEncryptTypeHandler;
@@ -12,9 +12,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/// # 云闪付直连配置
/// # 云闪付密钥配置
///
/// 直连商户维度的通道配置, 含银联商户号(merId) RSA2 三证书, 敏感字段(私钥证书/密码)加密存储
/// 商户维度的通道配置, 含银联商户号(merId) RSA2 三证书, 敏感字段(私钥证书/密码)加密存储
/// merId 创建时录入不可修改, 三证书由密钥配置维护
///
/// 银联 ACP 签名依赖证书(区别于银联商务的 HmacSHA256 无证书模式):
@@ -23,8 +23,8 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName(value = "union_direct_key_config", autoResultMap = true)
public class UnionDirectKeyConfig extends MchBaseEntity implements ToResult<UnionDirectKeyConfigResult> {
@TableName(value = "union_key_config", autoResultMap = true)
public class UnionKeyConfig extends MchBaseEntity implements ToResult<UnionKeyConfigResult> {
/// 通道商户号
@TableField(updateStrategy = FieldStrategy.NEVER)
@@ -58,7 +58,7 @@ public class UnionDirectKeyConfig extends MchBaseEntity implements ToResult<Unio
private Boolean sandbox;
@Override
public UnionDirectKeyConfigResult toResult() {
return UnionDirectKeyConfigConvert.CONVERT.toResult(this);
public UnionKeyConfigResult toResult() {
return UnionKeyConfigConvert.CONVERT.toResult(this);
}
}

View File

@@ -1,19 +1,19 @@
package cn.daxpay.open.channel.union.param.direct;
package cn.daxpay.open.channel.union.param;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.experimental.Accessors;
/// # 云闪付直连通道商户绑定创建参数
/// # 云闪付通道商户绑定创建参数
///
/// 创建时仅录入银联商户号(merId)与商户名称,
/// RSA2 三证书(私钥/中级/)由密钥配置单独维护,
/// 沙箱环境由支付产品配置(pay_md_product_config.activeEnv)决定
@Data
@Accessors(chain = true)
@Schema(title = "云闪付直连通道商户绑定创建参数")
public class UnionDirectChannelMerchantCreateParam {
@Schema(title = "云闪付通道商户绑定创建参数")
public class UnionChannelMerchantCreateParam {
@NotBlank(message = "{validation.field.mchNo.notBlank}")
@Schema(description = "商户号")

View File

@@ -1,4 +1,4 @@
package cn.daxpay.open.channel.union.param.direct;
package cn.daxpay.open.channel.union.param;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
@@ -6,14 +6,14 @@ import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
/// # 云闪付直连密钥配置保存参数
/// # 云闪付密钥配置保存参数
///
/// channelMchNo(通道商户号) 作为唯一标识定位记录,
/// mchNo/merId(银联商户号) 为不可变身份字段, 创建时写入后永不可改, 不参与保存
@Data
@Accessors(chain = true)
@Schema(title = "云闪付直连密钥配置保存参数")
public class UnionDirectKeyConfigParam {
@Schema(title = "云闪付密钥配置保存参数")
public class UnionKeyConfigParam {
@NotBlank(message = "{validation.field.channelMerchantNo.notBlank}")
@Schema(description = "通道商户号")

View File

@@ -1,14 +1,14 @@
package cn.daxpay.open.channel.union.result.direct;
package cn.daxpay.open.channel.union.result;
import cn.daxpay.open.platform.common.json.sensitive.SensitiveInfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/// # 云闪付直连密钥配置返回结果
/// # 云闪付密钥配置返回结果
@Data
@Accessors(chain = true)
public class UnionDirectKeyConfigResult {
public class UnionKeyConfigResult {
/// 通道商户号
private String channelMchNo;

View File

@@ -1,9 +1,9 @@
package cn.daxpay.open.channel.union.service.direct;
package cn.daxpay.open.channel.union.service;
import cn.daxpay.open.channel.union.code.UnionCode;
import cn.daxpay.open.channel.union.dao.direct.UnionDirectKeyConfigManager;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import cn.daxpay.open.channel.union.param.direct.UnionDirectChannelMerchantCreateParam;
import cn.daxpay.open.channel.union.dao.UnionKeyConfigManager;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import cn.daxpay.open.channel.union.param.UnionChannelMerchantCreateParam;
import cn.daxpay.open.payment.merchant.dao.channel.ChannelMerchantManager;
import cn.daxpay.open.payment.masterdata.dao.product.PayProductConfigManager;
import cn.daxpay.open.payment.merchant.entity.channel.ChannelMerchant;
@@ -14,25 +14,25 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/// # 云闪付直连通道商户管理
/// # 云闪付通道商户管理
///
/// 管理通道商户绑定的创建银联商户号(merId)在创建时录入直连配置表,
/// 管理通道商户绑定的创建银联商户号(merId)在创建时录入密钥配置表,
/// RSA2 三证书(私钥/中级/)由密钥配置单独维护
@Slf4j
@Service
@RequiredArgsConstructor
public class UnionDirectChannelMerchantService {
public class UnionChannelMerchantService {
private final ChannelMerchantManager channelMerchantManager;
private final PayProductConfigManager payProductConfigManager;
private final UnionDirectKeyConfigManager unionDirectKeyConfigManager;
private final UnionKeyConfigManager unionKeyConfigManager;
/// 创建通道商户绑定
///
/// 同时写入通用通道商户主表和云闪付直连配置表(含银联商户号 merId)
/// 同时写入通用通道商户主表和云闪付密钥配置表(含银联商户号 merId)
/// 三证书由密钥配置单独维护
@Transactional(rollbackFor = Exception.class)
public void create(UnionDirectChannelMerchantCreateParam param) {
public void create(UnionChannelMerchantCreateParam param) {
// 生成通道商户号: 通道前缀 + 雪花ID
String channelMchNo = ChannelMchNoGenerateUtil.generate("UNIONPAY");
// 写通用通道商户主表
@@ -47,14 +47,15 @@ public class UnionDirectChannelMerchantService {
boolean sandbox = payProductConfigManager.isSandboxActive(param.getProduct());
channelMerchant.setSandbox(sandbox);
channelMerchantManager.save(channelMerchant);
// 写云闪付直连配置(仅银联商户号 merId, 三证书由密钥配置单独维护)
var keyConfig = new UnionDirectKeyConfig()
// 写云闪付密钥配置(仅银联商户号 merId, 三证书由密钥配置单独维护)
var keyConfig = new UnionKeyConfig()
.setChannelMchNo(channelMchNo)
.setMerId(param.getMerId())
.setSignType(UnionCode.SIGN_TYPE_RSA2)
.setCertSign(true);
// mchNo 继承自 MchBaseEntity, 链式返回父类型, 单独赋值
keyConfig.setMchNo(param.getMchNo());
unionDirectKeyConfigManager.save(keyConfig);
unionKeyConfigManager.save(keyConfig);
}
}

View File

@@ -1,7 +1,7 @@
package cn.daxpay.open.channel.union.service.direct;
package cn.daxpay.open.channel.union.service;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import cn.daxpay.open.payment.merchant.dao.channel.ChannelMerchantManager;
import cn.daxpay.open.payment.merchant.entity.channel.ChannelMerchant;
import cn.daxpay.open.platform.core.exception.DataNotExistException;
@@ -9,25 +9,25 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/// # 云闪付直连通道凭证组装器
/// # 云闪付通道凭证组装器
///
/// 从通用通道商户主表([ChannelMerchant])读取固化 sandbox 标识,
/// 直连配置([UnionDirectKeyConfig])读取银联商户号(merId) RSA2 三证书,
/// 密钥配置([UnionKeyConfig])读取银联商户号(merId) RSA2 三证书,
/// 组装为下发给子应用的通道调用凭证 [UnionSdkCredential]
///
/// 沙箱标识直接读通道商户固化的 [ChannelMerchant#isSandbox]
@Slf4j
@Service
@RequiredArgsConstructor
public class UnionDirectConfigAssembler {
public class UnionConfigAssembler {
private final UnionDirectKeyConfigService keyConfigService;
private final UnionKeyConfigService keyConfigService;
private final ChannelMerchantManager channelMerchantManager;
/// 组装直连商户的通道调用凭证(下发给子应用)
/// 组装商户的通道调用凭证(下发给子应用)
///
/// @param mchNo 商户号(定位通用通道商户主表)
/// @param channelMchNo 通道商户号(定位直连配置)
/// @param channelMchNo 通道商户号(定位密钥配置)
/// @param capability 支付能力编码(保留对齐签名, 银联不使用)
/// @return 云闪付 SDK 凭证
public UnionSdkCredential buildConfig(String mchNo, String channelMchNo, String capability) {
@@ -35,8 +35,8 @@ public class UnionDirectConfigAssembler {
ChannelMerchant channelMerchant = channelMerchantManager.findByMchNoAndChannelMchNo(mchNo, channelMchNo)
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
boolean sandbox = channelMerchant.isSandbox();
// 2. 直连配置(银联商户号 merId + RSA2 三证书)
UnionDirectKeyConfig keyConfig = keyConfigService.findByChannelMchNo(channelMchNo, sandbox);
// 2. 密钥配置(银联商户号 merId + RSA2 三证书)
UnionKeyConfig keyConfig = keyConfigService.findByChannelMchNo(channelMchNo, sandbox);
// 3. 组装凭证
var credential = new UnionSdkCredential();
credential.setMerId(keyConfig.getMerId());

View File

@@ -1,35 +1,35 @@
package cn.daxpay.open.channel.union.service.direct;
package cn.daxpay.open.channel.union.service;
import cn.daxpay.open.channel.union.code.UnionCode;
import cn.daxpay.open.channel.union.convert.direct.UnionDirectKeyConfigConvert;
import cn.daxpay.open.channel.union.dao.direct.UnionDirectKeyConfigManager;
import cn.daxpay.open.channel.union.entity.direct.UnionDirectKeyConfig;
import cn.daxpay.open.channel.union.param.direct.UnionDirectKeyConfigParam;
import cn.daxpay.open.channel.union.convert.UnionKeyConfigConvert;
import cn.daxpay.open.channel.union.dao.UnionKeyConfigManager;
import cn.daxpay.open.channel.union.entity.UnionKeyConfig;
import cn.daxpay.open.channel.union.param.UnionKeyConfigParam;
import cn.daxpay.open.payment.merchant.dao.channel.ChannelMerchantManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/// # 云闪付直连密钥配置
/// # 云闪付密钥配置
///
/// 管理直连商户维度的银联证书配置, 查询时不存在则创建默认记录, 保存时合并证书字段
/// 管理商户维度的银联证书配置, 查询时不存在则创建默认记录, 保存时合并证书字段
@Slf4j
@Service
@RequiredArgsConstructor
public class UnionDirectKeyConfigService {
public class UnionKeyConfigService {
private final UnionDirectKeyConfigManager unionDirectKeyConfigManager;
private final UnionKeyConfigManager unionKeyConfigManager;
private final ChannelMerchantManager channelMerchantManager;
/// 根据通道商户号查询密钥配置, 不存在则创建默认记录
@Transactional(rollbackFor = Exception.class)
public UnionDirectKeyConfig findByChannelMchNo(String channelMchNo, boolean sandbox) {
var existing = unionDirectKeyConfigManager.findByChannelMchNoAndSandbox(channelMchNo, sandbox);
public UnionKeyConfig findByChannelMchNo(String channelMchNo, boolean sandbox) {
var existing = unionKeyConfigManager.findByChannelMchNoAndSandbox(channelMchNo, sandbox);
if (existing.isPresent()) {
return existing.get();
}
var config = new UnionDirectKeyConfig()
var config = new UnionKeyConfig()
.setChannelMchNo(channelMchNo)
.setSignType(UnionCode.SIGN_TYPE_RSA2)
.setCertSign(true)
@@ -37,7 +37,7 @@ public class UnionDirectKeyConfigService {
// 查询通用通道商户主表填充平台商户号(运营端写 MchBaseEntity 必须显式 mchNo)
channelMerchantManager.findByChannelMchNo(channelMchNo)
.ifPresent(mch -> config.setMchNo(mch.getMchNo()));
unionDirectKeyConfigManager.save(config);
unionKeyConfigManager.save(config);
return config;
}
@@ -46,14 +46,15 @@ public class UnionDirectKeyConfigService {
/// channelMchNo 定位记录, 仅更新证书字段;
/// mchNo/merId 为不可变身份字段(实体 FieldStrategy.NEVER), findByChannelMchNo DB 加载后保持不变
@Transactional(rollbackFor = Exception.class)
public void save(UnionDirectKeyConfigParam param) {
public void save(UnionKeyConfigParam param) {
var config = this.findByChannelMchNo(param.getChannelMchNo(), Boolean.TRUE.equals(param.getSandbox()));
UnionDirectKeyConfigConvert.CONVERT.copy(param, config);
unionDirectKeyConfigManager.updateById(config);
UnionKeyConfigConvert.CONVERT.copy(param, config);
unionKeyConfigManager.updateById(config);
}
/// 根据通道商户号删除密钥配置
public void deleteByChannelMchNo(String channelMchNo) {
unionDirectKeyConfigManager.deleteByChannelMchNo(channelMchNo);
unionKeyConfigManager.deleteByChannelMchNo(channelMchNo);
}
}

View File

@@ -5,7 +5,7 @@ import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.req.UnionCallbackParseReq;
import cn.daxpay.open.channel.union.client.resp.UnionCallbackParseResp;
import cn.daxpay.open.channel.union.code.UnionCode;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.util.UnionDateUtil;
import cn.daxpay.open.payment.common.result.DaxResult;
import cn.daxpay.open.payment.trade.record.service.PayCallbackRecordService;
@@ -34,7 +34,7 @@ import java.util.Map;
public class UnionPayCallbackService {
private final UnionChannelClient unionChannelClient;
private final UnionDirectConfigAssembler configAssembler;
private final UnionConfigAssembler configAssembler;
private final PayCallbackService payCallbackService;
private final PayCallbackRecordService payCallbackRecordService;

View File

@@ -5,7 +5,7 @@ import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.req.UnionCallbackParseReq;
import cn.daxpay.open.channel.union.client.resp.UnionCallbackParseResp;
import cn.daxpay.open.channel.union.code.UnionCode;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.payment.common.result.DaxResult;
import cn.daxpay.open.payment.trade.record.service.PayCallbackRecordService;
import cn.daxpay.open.payment.trade.runtime.bo.RefundCallbackData;
@@ -31,7 +31,7 @@ import java.util.Objects;
public class UnionRefundCallbackService {
private final UnionChannelClient unionChannelClient;
private final UnionDirectConfigAssembler configAssembler;
private final UnionConfigAssembler configAssembler;
private final RefundCallbackService refundCallbackService;
private final PayCallbackRecordService payCallbackRecordService;

View File

@@ -2,7 +2,7 @@ package cn.daxpay.open.channel.union.strategy.pay;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.enums.UnionPayMethod;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.service.payment.close.UnionCloseService;
import cn.daxpay.open.channel.union.strategy.UnionStrategySupport;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
@@ -23,12 +23,12 @@ import org.springframework.stereotype.Service;
public class UnionPayCloseStrategy extends AbsPayCloseStrategy {
private final UnionCloseService unionCloseService;
private final UnionDirectConfigAssembler unionDirectConfigAssembler;
private final UnionConfigAssembler unionConfigAssembler;
@Override
public CloseTypeEnum doClose(PayStrategyContext context, boolean useCancel) {
PayTrade trade = context.getTrade();
UnionSdkCredential credential = unionDirectConfigAssembler.buildConfig(
UnionSdkCredential credential = unionConfigAssembler.buildConfig(
trade.getMchNo(), context.getChannelMchNo(), context.getCapability());
UnionPayMethod method = UnionStrategySupport.resolveMethod(context.getCapability());
return unionCloseService.close(trade, credential, useCancel, method);

View File

@@ -1,7 +1,7 @@
package cn.daxpay.open.channel.union.strategy.pay;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.service.payment.pay.UnionPayService;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
import cn.daxpay.open.payment.strategy.pay.AbsNormalPayStrategy;
@@ -22,13 +22,13 @@ import org.springframework.stereotype.Service;
public class UnionPayPayStrategy extends AbsNormalPayStrategy {
private final UnionPayService unionPayService;
private final UnionDirectConfigAssembler unionDirectConfigAssembler;
private final UnionConfigAssembler unionConfigAssembler;
/// 支付前预处理: 组装通道凭证写入上下文
@Override
public void doBeforePay(PayStrategyContext context) {
NormalPayParam payParam = context.getPayParam();
UnionSdkCredential credential = unionDirectConfigAssembler.buildConfig(
UnionSdkCredential credential = unionConfigAssembler.buildConfig(
payParam.getMchNo(), payParam.getChannelMchNo(), payParam.getCapability());
context.setChannelConfig(credential);
}

View File

@@ -14,7 +14,7 @@ import java.util.Map;
/// # 云闪付产品策略
///
/// 云闪付为单一产品(直连银联 ACP), 含主扫([PayMethodEnum#UNION_QR]) / H5([PayMethodEnum#UNION_H5])
/// 云闪付为单一产品(银联 ACP), 含主扫([PayMethodEnum#UNION_QR]) / H5([PayMethodEnum#UNION_H5])
/// / 被扫([PayMethodEnum#UNION_BARCODE]) 三种支付方式, 方式→能力一对一同码。
@Slf4j
@Service

View File

@@ -2,7 +2,7 @@ package cn.daxpay.open.channel.union.strategy.refund;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.enums.UnionPayMethod;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.service.payment.refund.UnionRefundService;
import cn.daxpay.open.channel.union.strategy.UnionStrategySupport;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
@@ -22,11 +22,11 @@ import org.springframework.stereotype.Service;
public class UnionPayRefundStrategy extends AbsRefundStrategy {
private final UnionRefundService unionRefundService;
private final UnionDirectConfigAssembler unionDirectConfigAssembler;
private final UnionConfigAssembler unionConfigAssembler;
@Override
public RefundResultBo doRefund(RefundOrder refundOrder) {
UnionSdkCredential credential = unionDirectConfigAssembler.buildConfig(
UnionSdkCredential credential = unionConfigAssembler.buildConfig(
refundOrder.getMchNo(), refundOrder.getChannelMchNo(), refundOrder.getCapability());
UnionPayMethod method = UnionStrategySupport.resolveMethod(refundOrder.getCapability());
return unionRefundService.refund(refundOrder, credential, method);

View File

@@ -2,7 +2,7 @@ package cn.daxpay.open.channel.union.strategy.refund;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.enums.UnionPayMethod;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.service.payment.refund.UnionRefundSyncService;
import cn.daxpay.open.channel.union.strategy.UnionStrategySupport;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
@@ -22,11 +22,11 @@ import org.springframework.stereotype.Service;
public class UnionPaySyncRefundStrategy extends AbsSyncRefundStrategy {
private final UnionRefundSyncService unionRefundSyncService;
private final UnionDirectConfigAssembler unionDirectConfigAssembler;
private final UnionConfigAssembler unionConfigAssembler;
@Override
public RefundResultBo doSync(RefundOrder refundOrder) {
UnionSdkCredential credential = unionDirectConfigAssembler.buildConfig(
UnionSdkCredential credential = unionConfigAssembler.buildConfig(
refundOrder.getMchNo(), refundOrder.getChannelMchNo(), refundOrder.getCapability());
UnionPayMethod method = UnionStrategySupport.resolveMethod(refundOrder.getCapability());
return unionRefundSyncService.sync(refundOrder, credential, method);

View File

@@ -2,7 +2,7 @@ package cn.daxpay.open.channel.union.strategy.sync;
import cn.daxpay.open.channel.union.client.credential.UnionSdkCredential;
import cn.daxpay.open.channel.union.client.enums.UnionPayMethod;
import cn.daxpay.open.channel.union.service.direct.UnionDirectConfigAssembler;
import cn.daxpay.open.channel.union.service.UnionConfigAssembler;
import cn.daxpay.open.channel.union.service.payment.sync.UnionSyncService;
import cn.daxpay.open.channel.union.strategy.UnionStrategySupport;
import cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum;
@@ -22,11 +22,11 @@ import org.springframework.stereotype.Service;
public class UnionPaySyncStrategy extends AbsSyncPayOrderStrategy {
private final UnionSyncService unionSyncService;
private final UnionDirectConfigAssembler unionDirectConfigAssembler;
private final UnionConfigAssembler unionConfigAssembler;
@Override
public PaySyncResultBo doSync(PayStrategyContext context) {
UnionSdkCredential credential = unionDirectConfigAssembler.buildConfig(
UnionSdkCredential credential = unionConfigAssembler.buildConfig(
context.getTrade().getMchNo(), context.getChannelMchNo(), context.getCapability());
UnionPayMethod method = UnionStrategySupport.resolveMethod(context.getCapability());
return unionSyncService.sync(context.getTrade(), credential, method);