mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-10 14:56:06 +08:00
refactor(route): 删除冗余字段enable/name与废弃i18n, 优化能力候选批量接口
PayRouteStrategy 删除开源版不需要的 enable/name 字段(实体/param/result/convert/创建逻辑/运行时isEnable检查); 删除 strategyDisabled 及 18 个历次重构遗留废弃 i18n key; routeProductSupportsMethod 2参版降 private; listSceneCapabilityCandidatesBatch 预加载优化(删 mchNo 无用参数, 循环内零查库); PayRouteStrategyConvert 删重复 import; update-tables.sql 追加 DROP COLUMN。
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
-- 支付通道路由策略表:移除开源版不需要的 enable/name 字段
|
||||
ALTER TABLE pay_route_strategy DROP COLUMN IF EXISTS enable;
|
||||
ALTER TABLE pay_route_strategy DROP COLUMN IF EXISTS name;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package cn.daxpay.open.payment.merchant.convert.route.strategy;
|
||||
|
||||
import cn.daxpay.open.payment.merchant.entity.route.strategy.PayRouteStrategy;
|
||||
import cn.daxpay.open.payment.merchant.result.route.strategy.PayRouteStrategyResult;
|
||||
import cn.daxpay.open.payment.merchant.entity.route.strategy.PayRouteStrategy;
|
||||
import cn.daxpay.open.payment.merchant.param.route.strategy.PayRouteStrategyParam;
|
||||
import cn.daxpay.open.payment.merchant.result.route.strategy.PayRouteStrategyResult;
|
||||
|
||||
@@ -29,12 +29,6 @@ public class PayRouteStrategy extends MchBaseEntity implements ToResult<PayRoute
|
||||
/// @see PayRouteModeEnum
|
||||
private String mode;
|
||||
|
||||
/// 是否启用
|
||||
private boolean enable;
|
||||
|
||||
/// 策略名称
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public PayRouteStrategyResult toResult() {
|
||||
return PayRouteStrategyConvert.CONVERT.toResult(this);
|
||||
|
||||
@@ -13,9 +13,6 @@ import lombok.experimental.Accessors;
|
||||
@Schema(title = "支付通道路由策略参数")
|
||||
public class PayRouteStrategyParam {
|
||||
|
||||
@Schema(description = "主键,更新时传入")
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "{validation.field.appId.notBlank}")
|
||||
@Size(max = 32)
|
||||
@Schema(description = "应用号")
|
||||
@@ -23,10 +20,4 @@ public class PayRouteStrategyParam {
|
||||
|
||||
@Schema(description = "路由模式:basic/scene")
|
||||
private String mode;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enable;
|
||||
|
||||
@Schema(description = "策略名称")
|
||||
private String name;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,4 @@ public class PayRouteStrategyResult extends BaseResult {
|
||||
|
||||
@Schema(description = "路由模式")
|
||||
private String mode;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private boolean enable;
|
||||
|
||||
@Schema(description = "策略名称")
|
||||
private String name;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ public class PayRouteConfigService {
|
||||
strategy.setAppId(appId);
|
||||
strategy.setMchNo(mchAppInfoManager.requireMchNoByAppIdNotTenant(appId));
|
||||
strategy.setMode(PayRouteModeEnum.BASIC.getCode());
|
||||
strategy.setEnable(true);
|
||||
strategy.setName("默认策略");
|
||||
strategyManager.save(strategy);
|
||||
return strategy.toResult();
|
||||
}
|
||||
|
||||
@@ -60,9 +60,6 @@ public class PayRouteService implements PayRouteFacade {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.route.error.strategyNotFound");
|
||||
}
|
||||
PayRouteStrategy strategy = bundle.getStrategy();
|
||||
if (!strategy.isEnable()) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.route.error.strategyDisabled");
|
||||
}
|
||||
RouteHit hit = resolveByMode(bundle, payParam, strategy.getMode());
|
||||
if (hit == null) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.route.error.noMatch");
|
||||
|
||||
@@ -120,8 +120,8 @@ public class PayRouteSceneConfigService {
|
||||
|
||||
/// 按目录项+通道商户批量返回支付能力候选
|
||||
public Map<String, List<LabelValue>> listSceneCapabilityCandidatesBatch(PayRouteSceneCapabilityBatchParam param) {
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(param.getAppId());
|
||||
return payRouteStrategyCapabilitySupport.listSceneCapabilityCandidatesBatch(mchNo, param.getItems());
|
||||
mchAppInfoManager.requireMchNoByAppIdNotTenant(param.getAppId());
|
||||
return payRouteStrategyCapabilitySupport.listSceneCapabilityCandidatesBatch(param.getItems());
|
||||
}
|
||||
|
||||
/// 按目录项(支付渠道+支付方式)筛选商户已开通的通道商户候选
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/// # 通道路由:策略方式→通道商户与能力候选
|
||||
///
|
||||
@@ -67,22 +68,64 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
|
||||
/// 按目录项+通道商户批量返回支付能力候选
|
||||
public Map<String, List<LabelValue>> listSceneCapabilityCandidatesBatch(
|
||||
String mchNo, List<PayRouteSceneCapabilityBatchItem> items) {
|
||||
///
|
||||
/// 优化:目录、策略、产品能力及 channelMchNo→product 映射在循环外一次性预加载,
|
||||
/// 循环内仅做内存集合求交,避免逐 item 重复查库与扫描 Spring 容器。
|
||||
public Map<String, List<LabelValue>> listSceneCapabilityCandidatesBatch(List<PayRouteSceneCapabilityBatchItem> items) {
|
||||
Map<String, List<LabelValue>> index = new LinkedHashMap<>();
|
||||
if (CollUtil.isEmpty(items)) {
|
||||
return index;
|
||||
}
|
||||
RouteBatchContext ctx = buildRouteBatchContext(payProviderMethodService.listDirectoryEntries());
|
||||
// 批量预加载 channelMchNo → product,替代逐次 productOfChannelMchNo 查库
|
||||
Set<String> channelMchNos = new HashSet<>();
|
||||
for (PayRouteSceneCapabilityBatchItem item : items) {
|
||||
if (item != null && StrUtil.isNotBlank(item.getChannelMchNo())) {
|
||||
channelMchNos.add(item.getChannelMchNo());
|
||||
}
|
||||
}
|
||||
Map<String, String> productByChannelMchNo = channelMerchantManager.lambdaQuery()
|
||||
.select(ChannelMerchant::getChannelMchNo, ChannelMerchant::getProduct)
|
||||
.in(ChannelMerchant::getChannelMchNo, channelMchNos)
|
||||
.list()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ChannelMerchant::getChannelMchNo, ChannelMerchant::getProduct, (a, b) -> a));
|
||||
for (PayRouteSceneCapabilityBatchItem item : items) {
|
||||
if (item == null || StrUtil.hasBlank(item.getProvider(), item.getMethod(), item.getChannelMchNo())) {
|
||||
continue;
|
||||
}
|
||||
String key = capabilityBatchKey(item.getProvider(), item.getMethod(), item.getChannelMchNo());
|
||||
index.put(key, listSceneCapabilityCandidates(item.getProvider(), item.getMethod(), item.getChannelMchNo()));
|
||||
if (!ctx.directoryPairKeys().contains(PayProviderMethodManager.pairKey(item.getProvider(), item.getMethod()))) {
|
||||
index.put(key, List.of());
|
||||
continue;
|
||||
}
|
||||
String product = productByChannelMchNo.get(item.getChannelMchNo());
|
||||
if (StrUtil.isBlank(product)) {
|
||||
index.put(key, List.of());
|
||||
continue;
|
||||
}
|
||||
index.put(key, capabilitiesForMethodWithCtx(ctx, product, PayMethodEnum.findByCode(item.getMethod())));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/// 用预加载上下文计算支付能力候选(策略声明能力 ∩ DB 挂载启用),零查库
|
||||
private List<LabelValue> capabilitiesForMethodWithCtx(RouteBatchContext ctx, String product, PayMethodEnum method) {
|
||||
AbsProductStrategy strategy = ctx.strategyByProduct().get(product);
|
||||
if (strategy == null) {
|
||||
return List.of();
|
||||
}
|
||||
List<PayCapabilityEnum> declared = ProductStrategySupport.capabilitiesForMethod(strategy, method);
|
||||
if (CollUtil.isEmpty(declared)) {
|
||||
return List.of();
|
||||
}
|
||||
Set<String> mounted = ctx.capabilityCodesByProduct().getOrDefault(product, Set.of());
|
||||
return declared.stream()
|
||||
.filter(capability -> mounted.contains(capability.getCode()))
|
||||
.map(capability -> new LabelValue(I18nUtil.getEnumName(capability), capability.getCode()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 能力批量候选 Map 的 key:provider|method|channelMchNo
|
||||
public static String capabilityBatchKey(String provider, String method, String channelMchNo) {
|
||||
return provider + "|" + method + "|" + channelMchNo;
|
||||
@@ -206,7 +249,7 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
|
||||
/// 通道路由:产品是否支持目录支付方式(策略 Map ∧ DB)
|
||||
public boolean routeProductSupportsMethod(String product, PayMethodEnum method) {
|
||||
private boolean routeProductSupportsMethod(String product, PayMethodEnum method) {
|
||||
if (!PaymentStrategyFactory.existsByProduct(product, AbsProductStrategy.class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,37 +1,18 @@
|
||||
{
|
||||
"strategyNotFound": "Payment route strategy not configured for this app",
|
||||
"strategyDisabled": "Payment route strategy is disabled",
|
||||
"noMatch": "No available payment product matched",
|
||||
"providerRequired": "Pay brand is required when product is not specified",
|
||||
"methodRequiredWhenProductSet": "Pay method is required when product is specified",
|
||||
"basicProviderInvalid": "Invalid pay brand",
|
||||
"basicProductNotAvailable": "No available product for pay brand [{0}]; check merchant product, channel merchant and app channel config",
|
||||
"basicProductNotConfigured": "No payment product configured for pay brand [{0}]; configure it in basic route mode",
|
||||
"basicProductAmbiguous": "Multiple available products for pay brand [{0}]; specify product explicitly",
|
||||
"methodNotSupportedForProduct": "Product \"{0}\" has no available payment methods",
|
||||
"duplicateSceneConfig": "Duplicate pay brand configuration in scene mode",
|
||||
"duplicatePayProvider": "Duplicate configuration for pay brand [{0}]",
|
||||
"duplicatePayProviderMethod": "Duplicate configuration for pay brand [{0}] and method [{1}]",
|
||||
"sceneDirectoryIncomplete": "Payment product is required for pay brand [{0}] and method [{1}]",
|
||||
"scenePayProviderRequiredForMethod": "Pay brand is required for method [{0}]",
|
||||
"sceneGenericMethodNoPayProvider": "Generic pay method [{0}] cannot be bound to a pay brand",
|
||||
"sceneMethodPayProviderMismatch": "Pay method [{0}] does not match pay brand [{1}]",
|
||||
"sceneProductRequired": "Payment product is required in scene routing mode",
|
||||
"sceneMethodRequired": "Pay method is required in scene routing mode",
|
||||
"sceneMethodProductMismatch": "Pay method [{0}] is not supported by product [{1}]",
|
||||
"sceneProductCapabilityPair": "For pay brand [{0}] and method [{1}], select both payment product and capability, or leave both empty",
|
||||
"sceneCapabilityRequired": "Payment capability is required in scene routing mode",
|
||||
"sceneCapabilityProductMismatch": "Payment capability [{0}] does not match product [{1}] and method [{2}]",
|
||||
"sceneChannelMethodRequired": "Generic pay route requires channel and pay method",
|
||||
"providerRequiredForScene": "Pay brand is required in scene routing mode",
|
||||
"productNotResolved": "Cannot resolve product for channel [{0}] and method [{1}]",
|
||||
"productMismatch": "Specified product [{0}] does not match resolved [{1}]",
|
||||
"productInvalid": "Invalid payment product [{0}]",
|
||||
"productStrategyMissing": "Payment product strategy not found",
|
||||
"routeStrategyNotExist": "Route strategy not found",
|
||||
"routeModeNotExist": "Route mode not found: {0}",
|
||||
"businessSceneNotExist": "Business scene not found: {0}",
|
||||
"terminalSceneNotExist": "Terminal scene not found: {0}",
|
||||
"channelMchNoRequired": "Channel merchant no cannot be blank",
|
||||
"channelMchNotExist": "Channel merchant [{0}] not found",
|
||||
"channelMchDisabled": "Channel merchant [{0}] is disabled",
|
||||
|
||||
@@ -1,37 +1,18 @@
|
||||
{
|
||||
"strategyNotFound": "应用未配置通道路由策略",
|
||||
"strategyDisabled": "通道路由策略已禁用",
|
||||
"noMatch": "未匹配到可用支付产品",
|
||||
"providerRequired": "未指定支付产品时,支付渠道不能为空",
|
||||
"methodRequiredWhenProductSet": "指定支付产品时,支付方式不能为空",
|
||||
"basicProviderInvalid": "支付渠道无效",
|
||||
"basicProductNotAvailable": "支付渠道[{0}]下无可用支付产品,请检查商户产品、通道商户及应用通道配置",
|
||||
"basicProductNotConfigured": "支付渠道[{0}]未配置支付产品,请在通道路由基础模式中完成配置",
|
||||
"basicProductAmbiguous": "支付渠道[{0}]下存在多个可用支付产品,请指定 product 参数",
|
||||
"methodNotSupportedForProduct": "产品「{0}」无可用支付方式",
|
||||
"duplicateSceneConfig": "场景模式下同一支付渠道存在多条配置",
|
||||
"duplicatePayProvider": "支付渠道[{0}]配置重复",
|
||||
"duplicatePayProviderMethod": "支付渠道[{0}]下支付方式[{1}]配置重复",
|
||||
"sceneDirectoryIncomplete": "须为支付渠道[{0}]的支付方式[{1}]配置支付产品",
|
||||
"scenePayProviderRequiredForMethod": "非通用支付方式[{0}]须指定支付渠道",
|
||||
"sceneGenericMethodNoPayProvider": "通用支付方式[{0}]不能绑定支付渠道",
|
||||
"sceneMethodPayProviderMismatch": "支付方式[{0}]与支付渠道[{1}]不匹配",
|
||||
"sceneProductRequired": "场景模式下须选择支付产品",
|
||||
"sceneMethodRequired": "场景模式下须选择支付方式",
|
||||
"sceneMethodProductMismatch": "支付方式[{0}]与产品[{1}]不匹配",
|
||||
"sceneProductCapabilityPair": "支付渠道[{0}]支付方式[{1}]须同时选择支付产品与支付能力,或同时留空",
|
||||
"sceneCapabilityRequired": "场景模式下须选择支付能力",
|
||||
"sceneCapabilityProductMismatch": "支付能力[{0}]与产品[{1}]、支付方式[{2}]不匹配",
|
||||
"sceneChannelMethodRequired": "通用支付配置须指定通道与支付方式",
|
||||
"providerRequiredForScene": "场景模式下,支付渠道不能为空",
|
||||
"productNotResolved": "通道[{0}]与支付方式[{1}]无法解析支付产品",
|
||||
"productMismatch": "指定产品[{0}]与解析结果[{1}]不一致",
|
||||
"productInvalid": "支付产品[{0}]无效",
|
||||
"productStrategyMissing": "支付产品策略不存在",
|
||||
"routeStrategyNotExist": "路由策略不存在",
|
||||
"routeModeNotExist": "路由模式不存在: {0}",
|
||||
"businessSceneNotExist": "业务场景不存在: {0}",
|
||||
"terminalSceneNotExist": "终端场景不存在: {0}",
|
||||
"channelMchNoRequired": "通道商户号不能为空",
|
||||
"channelMchNotExist": "通道商户号[{0}]不存在",
|
||||
"channelMchDisabled": "通道商户号[{0}]未启用",
|
||||
|
||||
Reference in New Issue
Block a user