mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-10 06:46:04 +08:00
refactor(payment): 移除商户产品配置模块,功能整合到产品主数据管理
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
Target Server Version : 160009 (160009)
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 13/06/2026 15:50:03
|
||||
Date: 13/06/2026 17:02:31
|
||||
*/
|
||||
|
||||
|
||||
@@ -138,12 +138,39 @@ INSERT INTO "public"."iam_perm_menu" VALUES (4040112, 40401, 'payment:merchant:c
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (4040113, 40401, 'payment:merchant:channelMerchant:wechatApp', 'admin', 'WechatMchAppManage', '微信通道商户应用', 'WeChat Channel Merchant App', 'menu.payment.merchant.channelMerchant.wechatApp', NULL, 't', 'f', '/payment/channel/wechat/manage/mch/app/WechatMchAppManage', '/payment/merchant/channel-merchant/wechat-app-manage', NULL, 11, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-07 23:57:13.620205+00', '2026-06-07 23:57:13.620205+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (4040114, 40401, 'payment:merchant:channelMerchant:alipayApp', 'admin', 'AlipayMchAppManage', '支付宝通道商户应用', 'Alipay Channel Merchant App', 'menu.payment.merchant.channelMerchant.alipayApp', NULL, 't', 'f', '/payment/channel/alipay/manage/mch/app/AlipayMchAppManage', '/payment/merchant/channel-merchant/alipay-app-manage', NULL, 12, 'f', 't', 'f', 1, 1, 0, 'f', 'subpage', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-11 22:28:11.274785+00', '2026-06-11 22:28:11.274785+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (404, NULL, 'payment:merchant', 'admin', 'PaymentMerchant', '商户管理', 'Merchant Management', 'menu.payment.merchant', 'lucide:store', 'f', 'f', NULL, '/payment/merchant', NULL, 4, 't', 't', 'f', 0, NULL, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-04-05 16:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (402, 4, 'payment:isv:basic', 'admin', 'IsvBasic', '基础管理', 'Basic Management', 'menu.payment.isv.basic', 'lucide:layers', 'f', 'f', NULL, '/payment/isv/basic', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (403, 4, 'payment:isv:pay-config', 'admin', 'IsvPayConfig', '支付配置', 'Payment Config', 'menu.payment.isv.payConfig', 'lucide:settings-2', 'f', 'f', NULL, '/payment/isv/pay-config', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (405, 4, 'payment:isv:business', 'admin', 'IsvBusiness', '业务配置', 'Business Config', 'menu.payment.isv.business', 'lucide:briefcase', 'f', 'f', NULL, '/payment/isv/business', NULL, 4, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (40201, 402, 'payment:isv:user', 'admin', 'IsvUserList', '用户管理', 'User Management', 'menu.payment.isv.basic.user', 'lucide:users', 'f', 'f', '/_core/fallback/coming-soon', '/payment/isv/user', NULL, 1, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (40203, 402, 'payment:isv:site', 'admin', 'IsvSiteConfig', '站点配置', 'Site Config', 'menu.payment.isv.basic.site', 'lucide:globe', 'f', 'f', '/_core/fallback/coming-soon', '/payment/isv/site', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (40301, 403, 'payment:isv:product', 'admin', 'IsvProductConfig', '支付产品管理', 'Payment Product', 'menu.payment.isv.payConfig.product', 'lucide:package', 'f', 'f', '/_core/fallback/coming-soon', '/payment/isv/product', NULL, 1, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (30403, 304, 'system:credential:config', 'admin', 'PlatformCredentialConfig', '对接配置', 'Credential Config', 'menu.system.config.credential', 'lucide:key-round', 'f', 'f', '/system/config/credential/PlatformCredentialConfig', '/system/config/credential', NULL, 3, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-13 00:00:00+00', '2026-06-13 00:00:00+00');
|
||||
|
||||
-- 支付配置目录
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (405, 4, 'payment:config', 'admin', 'PaymentConfig', '支付配置', 'Payment Config', 'menu.payment.config', 'lucide:settings-2', 'f', 'f', NULL, '/payment/config', NULL, 2, 'f', 't', 'f', 1, 1, 0, 'f', 'catalog', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00')
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
menu_code = EXCLUDED.menu_code,
|
||||
name = EXCLUDED.name,
|
||||
title_cn = EXCLUDED.title_cn,
|
||||
title_en = EXCLUDED.title_en,
|
||||
i18n_key = EXCLUDED.i18n_key,
|
||||
icon = EXCLUDED.icon,
|
||||
path = EXCLUDED.path,
|
||||
sort_no = EXCLUDED.sort_no,
|
||||
keep_alive = EXCLUDED.keep_alive,
|
||||
menu_type = EXCLUDED.menu_type,
|
||||
last_modified_time = EXCLUDED.last_modified_time;
|
||||
|
||||
-- 支付配置:支付产品管理(卡片式)
|
||||
INSERT INTO "public"."iam_perm_menu" VALUES (40105, 405, 'payment:config:productConfig', 'admin', 'ProductConfig', '支付产品管理', 'Payment Product Management', 'menu.payment.config.productConfig', 'lucide:layout-grid', 'f', 'f', '/payment/config/product/ProductConfig', '/payment/config/product', NULL, 1, 'f', 't', 'f', 1, 1, 0, 'f', 'menu', NULL, NULL, NULL, NULL, NULL, NULL, '2026-06-14 00:00:00+00', '2026-06-14 00:00:00+00')
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
pid = EXCLUDED.pid,
|
||||
menu_code = EXCLUDED.menu_code,
|
||||
name = EXCLUDED.name,
|
||||
title_cn = EXCLUDED.title_cn,
|
||||
title_en = EXCLUDED.title_en,
|
||||
i18n_key = EXCLUDED.i18n_key,
|
||||
icon = EXCLUDED.icon,
|
||||
component = EXCLUDED.component,
|
||||
path = EXCLUDED.path,
|
||||
sort_no = EXCLUDED.sort_no,
|
||||
keep_alive = EXCLUDED.keep_alive,
|
||||
menu_type = EXCLUDED.menu_type,
|
||||
last_modified_time = EXCLUDED.last_modified_time;
|
||||
|
||||
-- ----------------------------
|
||||
-- Primary Key structure for table iam_perm_menu
|
||||
|
||||
@@ -53,4 +53,12 @@ public class PayProductMasterDataController {
|
||||
return Res.ok(payProductMasterDataService.dropdown());
|
||||
}
|
||||
|
||||
/// 全量查询支付产品列表(卡片式管理页使用)
|
||||
@PermCode(code = "view", nameCn = "产品查看", nameEn = "Product View")
|
||||
@Operation(summary = "全量查询支付产品")
|
||||
@GetMapping("/list-all")
|
||||
public Result<List<PayProductResult>> listAll() {
|
||||
return Res.ok(payProductMasterDataService.listAll());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.dromara.daxpay.payment.admin.controller.merchant.config;
|
||||
|
||||
import org.dromara.daxpay.platform.core.annotation.PermCode;
|
||||
import org.dromara.daxpay.platform.core.rest.Res;
|
||||
import org.dromara.daxpay.platform.core.rest.result.Result;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigBatchParam;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigEnableParam;
|
||||
import org.dromara.daxpay.payment.merchant.result.config.MchProductConfigResult;
|
||||
import org.dromara.daxpay.payment.merchant.service.config.MchProductConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 商户产品配置管理控制器
|
||||
///
|
||||
@PermCode(menuCode = "payment:merchant")
|
||||
@Validated
|
||||
@Tag(name = "商户产品配置管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/merchant/product/config")
|
||||
@RequiredArgsConstructor
|
||||
public class MchProductConfigAdminController {
|
||||
|
||||
private final MchProductConfigService service;
|
||||
|
||||
@PermCode(code = "view", nameCn = "商户查看", nameEn = "Merchant View")
|
||||
@Operation(summary = "根据商户号查询产品配置列表")
|
||||
@GetMapping("/all-by-mch-no")
|
||||
public Result<List<MchProductConfigResult>> findAllByMchNo(@NotBlank(message = "{validation.field.mchNo.notBlank}") String mchNo) {
|
||||
return Res.ok(service.findAllByMchNo(mchNo));
|
||||
}
|
||||
|
||||
@PermCode(code = "product_config_update", nameCn = "产品配置更新", nameEn = "Product Config Update")
|
||||
@Operation(summary = "更新启用状态,如果配置不存在则自动创建")
|
||||
@PostMapping("/update-enable")
|
||||
public Result<Void> updateEnable(@RequestBody @Validated MchProductConfigEnableParam param) {
|
||||
service.updateEnable(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@PermCode(code = "product_config_update", nameCn = "产品配置更新", nameEn = "Product Config Update")
|
||||
@Operation(summary = "批量保存商户产品配置")
|
||||
@PostMapping("/save-batch")
|
||||
public Result<Void> saveBatch(@RequestBody @Validated MchProductConfigBatchParam param) {
|
||||
service.saveBatch(param);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -62,12 +62,12 @@ public class PayProductMasterDataService {
|
||||
}
|
||||
|
||||
/// 返回全部支付产品,按 sortNo、id 排序
|
||||
/// 策略存在时补全特性字段,不存在时仅返回枚举与数据库基础信息
|
||||
public List<PayProductResult> listAll() {
|
||||
Map<String, PayProduct> dbMap = payProductManager.lambdaQuery().list().stream()
|
||||
.collect(Collectors.toMap(PayProduct::getCode, p -> p, (a, b) -> a));
|
||||
|
||||
return Arrays.stream(ProductEnum.values())
|
||||
.filter(e -> PaymentStrategyFactory.existsByProduct(e.getCode(), AbsProductStrategy.class))
|
||||
.map(e -> toProductResult(e, dbMap))
|
||||
.sorted(Comparator.comparing(PayProductResult::getSortNo,
|
||||
Comparator.nullsLast(Comparator.naturalOrder()))
|
||||
@@ -91,7 +91,6 @@ public class PayProductMasterDataService {
|
||||
|
||||
/// 枚举与库表合并为产品结果
|
||||
private PayProductResult toProductResult(ProductEnum product, Map<String, PayProduct> dbMap) {
|
||||
var strategy = PaymentStrategyFactory.createByProduct(product.getCode(), AbsProductStrategy.class);
|
||||
PayProductResult result = new PayProductResult()
|
||||
.setCode(product.getCode())
|
||||
.setChannel(product.getChannel())
|
||||
@@ -111,7 +110,10 @@ public class PayProductMasterDataService {
|
||||
} else {
|
||||
result.setSortNo(0);
|
||||
}
|
||||
applyStrategyFields(strategy, result);
|
||||
AbsProductStrategy strategy = resolveStrategy(product.getCode());
|
||||
if (strategy != null) {
|
||||
applyStrategyFields(strategy, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.controller.config;
|
||||
|
||||
import org.dromara.daxpay.platform.core.rest.Res;
|
||||
import org.dromara.daxpay.platform.core.rest.result.Result;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigBatchParam;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigEnableParam;
|
||||
import org.dromara.daxpay.payment.merchant.result.config.MchProductConfigResult;
|
||||
import org.dromara.daxpay.payment.merchant.service.config.MchProductConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@Validated
|
||||
@Tag(name = "商户产品配置")
|
||||
@RestController
|
||||
@RequestMapping("/merchant/product/config")
|
||||
@RequiredArgsConstructor
|
||||
public class MchProductConfigController {
|
||||
private final MchProductConfigService service;
|
||||
|
||||
@Operation(summary = "根据商户号查询产品配置列表")
|
||||
@GetMapping("/all-by-mch-no")
|
||||
public Result<List<MchProductConfigResult>> findAllByMchNo(@NotBlank(message = "{validation.field.mchNo.notBlank}") String mchNo){
|
||||
return Res.ok(service.findAllByMchNo(mchNo));
|
||||
}
|
||||
|
||||
@Operation(summary = "更新启用状态,如果配置不存在则自动创建")
|
||||
@PostMapping("/update-enable")
|
||||
public Result<Void> updateEnable(@RequestBody @Validated MchProductConfigEnableParam param){
|
||||
service.updateEnable(param);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "批量保存商户产品配置")
|
||||
@PostMapping("/save-batch")
|
||||
public Result<Void> saveBatch(@RequestBody @Validated MchProductConfigBatchParam param){
|
||||
service.saveBatch(param);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.convert.config;
|
||||
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.result.config.MchProductConfigResult;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/// # 商户产品配置转换
|
||||
///
|
||||
@Mapper
|
||||
public interface MchProductConfigConvert {
|
||||
|
||||
MchProductConfigConvert CONVERT = Mappers.getMapper(MchProductConfigConvert.class);
|
||||
|
||||
MchProductConfigResult toResult(MchProductConfig entity);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.dao.config;
|
||||
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.platform.common.mybatisplus.impl.BaseManager;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@Repository
|
||||
public class MchProductConfigManager extends BaseManager<MchProductConfigMapper, MchProductConfig> {
|
||||
|
||||
/// 根据商户号查询产品配置列表
|
||||
public List<MchProductConfig> findByMchNo(String mchNo) {
|
||||
return lambdaQuery()
|
||||
.eq(MchProductConfig::getMchNo, mchNo)
|
||||
.list();
|
||||
}
|
||||
|
||||
/// 根据商户号和产品编码查询产品配置
|
||||
public Optional<MchProductConfig> findByMchNoAndProduct(String mchNo, String product) {
|
||||
return lambdaQuery()
|
||||
.eq(MchProductConfig::getMchNo, mchNo)
|
||||
.eq(MchProductConfig::getProduct, product)
|
||||
.oneOpt();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.dao.config;
|
||||
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import com.github.yulichang.base.MPJBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@Mapper
|
||||
public interface MchProductConfigMapper extends MPJBaseMapper<MchProductConfig> {
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.entity.config;
|
||||
|
||||
import org.dromara.daxpay.platform.common.mybatisplus.function.ToResult;
|
||||
import org.dromara.daxpay.payment.common.entity.merchant.MchBaseEntity;
|
||||
import org.dromara.daxpay.payment.merchant.convert.config.MchProductConfigConvert;
|
||||
import org.dromara.daxpay.payment.merchant.result.config.MchProductConfigResult;
|
||||
import org.dromara.daxpay.platform.core.enums.pay.channel.ProductEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("mch_product_config")
|
||||
public class MchProductConfig extends MchBaseEntity implements ToResult<MchProductConfigResult> {
|
||||
|
||||
/// 产品编码
|
||||
/// @see ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 通道编码
|
||||
private String channel;
|
||||
|
||||
/// 是否启用
|
||||
private boolean enable;
|
||||
|
||||
@Override
|
||||
public MchProductConfigResult toResult() {
|
||||
return MchProductConfigConvert.CONVERT.toResult(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.param.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/// # 商户产品配置批量保存参数
|
||||
///
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户产品配置批量保存参数")
|
||||
public class MchProductConfigBatchParam {
|
||||
|
||||
@Schema(description = "商户号")
|
||||
@NotBlank(message = "{validation.field.mchNo.notBlank}")
|
||||
private String mchNo;
|
||||
|
||||
@Schema(description = "产品配置列表")
|
||||
private List<MchProductConfigItem> items;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.param.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/// # 商户产品配置启用状态参数
|
||||
///
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户产品配置启用状态参数")
|
||||
public class MchProductConfigEnableParam {
|
||||
|
||||
@Schema(description = "商户号")
|
||||
@NotBlank(message = "{validation.field.mchNo.notBlank}")
|
||||
private String mchNo;
|
||||
|
||||
@Schema(description = "产品编码")
|
||||
@NotBlank(message = "{validation.field.product.notBlank}")
|
||||
private String product;
|
||||
|
||||
@Schema(description = "通道编码")
|
||||
@NotBlank(message = "{validation.field.channel.notBlank}")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enable;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.param.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/// # 商户产品配置项
|
||||
///
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户产品配置项")
|
||||
public class MchProductConfigItem {
|
||||
|
||||
@Schema(description = "产品编码")
|
||||
private String product;
|
||||
|
||||
@Schema(description = "通道编码")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enable;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.result.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "商户产品配置")
|
||||
public class MchProductConfigResult {
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品编码")
|
||||
private String product;
|
||||
|
||||
@Schema(description = "产品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "通道编码")
|
||||
private String channel;
|
||||
|
||||
@Schema(description = "通道名称")
|
||||
private String channelName;
|
||||
|
||||
@Schema(description = "商户号")
|
||||
private String mchNo;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enable;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package org.dromara.daxpay.payment.merchant.service.config;
|
||||
|
||||
import org.dromara.daxpay.payment.merchant.dao.config.MchProductConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.dao.info.MerchantInfoManager;
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.entity.info.MerchantInfo;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigBatchParam;
|
||||
import org.dromara.daxpay.payment.merchant.param.config.MchProductConfigEnableParam;
|
||||
import org.dromara.daxpay.payment.merchant.result.config.MchProductConfigResult;
|
||||
import org.dromara.daxpay.payment.pay.service.masterdata.product.PayProductMasterDataService;
|
||||
import org.dromara.daxpay.platform.common.mybatisplus.function.CollectorsFunction;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/// # 商户产品配置
|
||||
///
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MchProductConfigService {
|
||||
|
||||
private final MchProductConfigManager productConfigManager;
|
||||
|
||||
private final PayProductMasterDataService PayProductMasterDataService;
|
||||
|
||||
private final MerchantInfoManager merchantInfoManager;
|
||||
|
||||
/// 产品配置列表, 根据商户进行查询, 默认返回所有产品配置, 未配置的产品默认启用状态为false
|
||||
public List<MchProductConfigResult> findAllByMchNo(String mchNo){
|
||||
Map<String, MchProductConfig> productConfigMap = productConfigManager.findByMchNo(mchNo)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(MchProductConfig::getProduct, Function.identity(), CollectorsFunction::retainFirst));
|
||||
var productList = PayProductMasterDataService.listAllByApply();
|
||||
MerchantInfo merchantInfo = merchantInfoManager.findByMchNo(mchNo)
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.merchant.merchantNotExist"));
|
||||
return productList.stream().map(o -> {
|
||||
var productConfig = productConfigMap.get(o.getCode());
|
||||
if (Objects.isNull(productConfig)) {
|
||||
return new MchProductConfigResult()
|
||||
.setProduct(o.getCode())
|
||||
.setName(o.getName())
|
||||
.setChannel(o.getChannel())
|
||||
.setChannelName(o.getChannelName())
|
||||
.setMchNo(merchantInfo.getMchNo())
|
||||
.setEnable(false);
|
||||
}
|
||||
return productConfig.toResult()
|
||||
.setName(o.getName())
|
||||
.setChannel(o.getChannel())
|
||||
.setChannelName(o.getChannelName())
|
||||
.setMchNo(merchantInfo.getMchNo());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/// 更新启用状态,如果配置不存在则自动创建
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateEnable(MchProductConfigEnableParam param) {
|
||||
Optional<MchProductConfig> optional = productConfigManager
|
||||
.findByMchNoAndProduct(param.getMchNo(), param.getProduct());
|
||||
if (optional.isPresent()) {
|
||||
MchProductConfig config = optional.get();
|
||||
config.setEnable(param.getEnable());
|
||||
productConfigManager.updateById(config);
|
||||
} else {
|
||||
MchProductConfig config = new MchProductConfig();
|
||||
config.setMchNo(param.getMchNo());
|
||||
config.setProduct(param.getProduct());
|
||||
config.setChannel(param.getChannel());
|
||||
config.setEnable(param.getEnable());
|
||||
productConfigManager.save(config);
|
||||
}
|
||||
}
|
||||
|
||||
/// 批量保存商户产品配置
|
||||
/// 已有的配置更新启用状态,没有的则新增
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveBatch(MchProductConfigBatchParam param) {
|
||||
String mchNo = param.getMchNo();
|
||||
for (var item : param.getItems()) {
|
||||
Optional<MchProductConfig> existingConfig = productConfigManager.findByMchNoAndProduct(mchNo, item.getProduct());
|
||||
if (existingConfig.isPresent()) {
|
||||
MchProductConfig config = existingConfig.get();
|
||||
config.setEnable(item.getEnable());
|
||||
productConfigManager.updateById(config);
|
||||
}
|
||||
else {
|
||||
MchProductConfig config = new MchProductConfig();
|
||||
config.setMchNo(mchNo);
|
||||
config.setProduct(item.getProduct());
|
||||
config.setChannel(item.getChannel());
|
||||
config.setEnable(item.getEnable());
|
||||
productConfigManager.save(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ package org.dromara.daxpay.payment.merchant.service.route.basic;
|
||||
|
||||
import org.dromara.daxpay.payment.common.util.PaymentStrategyFactory;
|
||||
import org.dromara.daxpay.payment.merchant.dao.appinfo.MchAppInfoManager;
|
||||
import org.dromara.daxpay.payment.merchant.dao.config.MchProductConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.dao.route.basic.PayRouteBasicConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.dao.route.strategy.PayRouteStrategyManager;
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.entity.route.basic.PayRouteBasicConfig;
|
||||
import org.dromara.daxpay.payment.merchant.entity.route.strategy.PayRouteStrategy;
|
||||
import org.dromara.daxpay.payment.merchant.param.route.basic.PayRouteBasicConfigBatchParam;
|
||||
@@ -14,6 +12,7 @@ import org.dromara.daxpay.payment.merchant.result.route.basic.PayRouteBasicConfi
|
||||
import org.dromara.daxpay.payment.merchant.service.route.support.PayRouteConfigProviders;
|
||||
import org.dromara.daxpay.payment.pay.strategy.AbsProductStrategy;
|
||||
import org.dromara.daxpay.platform.core.enums.pay.channel.PayProviderEnum;
|
||||
import org.dromara.daxpay.platform.core.enums.pay.channel.ProductEnum;
|
||||
import org.dromara.daxpay.platform.core.exception.BizInfoException;
|
||||
import org.dromara.daxpay.platform.core.exception.DataNotExistException;
|
||||
import org.dromara.daxpay.platform.core.code.CommonErrorCode;
|
||||
@@ -22,14 +21,15 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/// # 通道路由基础模式配置
|
||||
///
|
||||
/// 按支付渠道配置默认支付产品,保存前校验商户已开通产品能力。
|
||||
///
|
||||
/// 按支付渠道配置默认支付产品,保存前校验产品策略能力。
|
||||
/// 开源版:所有产品默认可用,不再检查商户启用状态。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayRouteBasicConfigService {
|
||||
@@ -37,25 +37,21 @@ public class PayRouteBasicConfigService {
|
||||
private final PayRouteStrategyManager strategyManager;
|
||||
private final PayRouteBasicConfigManager basicConfigManager;
|
||||
private final MchAppInfoManager mchAppInfoManager;
|
||||
private final MchProductConfigManager mchProductConfigManager;
|
||||
|
||||
/// 查询基础模式面板数据(已保存 product + 各渠道可选 products)
|
||||
public List<PayRouteBasicConfigResult> listBasicByAppId(String appId) {
|
||||
PayRouteStrategy strategy = requireStrategy(appId);
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(appId);
|
||||
List<MchProductConfig> mchProducts = enabledMchProducts(mchNo);
|
||||
Map<String, String> productMap = basicConfigManager.findByStrategyId(strategy.getId()).stream()
|
||||
.filter(config -> StrUtil.isNotBlank(config.getProvider()))
|
||||
.collect(Collectors.toMap(PayRouteBasicConfig::getProvider, PayRouteBasicConfig::getProduct, (a, b) -> a));
|
||||
return PayRouteConfigProviders.enumsInWhitelistOrder().stream()
|
||||
.map(provider -> toPanelResult(provider, productMap.get(provider.getCode()), mchProducts))
|
||||
.map(provider -> toPanelResult(provider, productMap.get(provider.getCode())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 批量保存基础模式配置(先删后插)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveBasicBatch(PayRouteBasicConfigBatchParam param) {
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(param.getAppId());
|
||||
PayRouteStrategy strategy = requireStrategy(param.getAppId());
|
||||
basicConfigManager.deleteByStrategyId(strategy.getId());
|
||||
for (PayRouteBasicConfigItem item : param.getItems()) {
|
||||
@@ -63,7 +59,7 @@ public class PayRouteBasicConfigService {
|
||||
continue;
|
||||
}
|
||||
PayProviderEnum provider = validateBasicPayProviderCode(item.getProvider());
|
||||
validateBasicProduct(mchNo, item.getProduct(), provider);
|
||||
validateBasicProduct(item.getProduct(), provider);
|
||||
PayRouteBasicConfig config = new PayRouteBasicConfig();
|
||||
config.setStrategyId(strategy.getId());
|
||||
config.setProvider(item.getProvider());
|
||||
@@ -72,11 +68,14 @@ public class PayRouteBasicConfigService {
|
||||
}
|
||||
}
|
||||
|
||||
/// 校验产品属于该商户且支持指定支付渠道
|
||||
public void validateBasicProduct(String mchNo, String product, PayProviderEnum provider) {
|
||||
List<MchProductConfig> mchProducts = enabledMchProducts(mchNo);
|
||||
List<String> products = productsForProvider(mchProducts, provider);
|
||||
if (!products.contains(product)) {
|
||||
/// 校验产品存在且支持指定支付渠道(开源版:不再检查商户启用状态)
|
||||
public void validateBasicProduct(String product, PayProviderEnum provider) {
|
||||
ProductEnum productEnum = ProductEnum.findByCode(product);
|
||||
if (productEnum == null) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.productInvalid", product);
|
||||
}
|
||||
if (!PaymentStrategyFactory.productSupportsProvider(product, provider)) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.basicProductNotAvailable", provider.getCode());
|
||||
}
|
||||
@@ -96,36 +95,26 @@ public class PayRouteBasicConfigService {
|
||||
}
|
||||
|
||||
/// 组装单渠道基础模式面板行:已保存 product + 该渠道下可选 products
|
||||
private PayRouteBasicConfigResult toPanelResult(
|
||||
PayProviderEnum provider,
|
||||
String savedProduct,
|
||||
List<MchProductConfig> mchProducts) {
|
||||
List<String> products = productsForProvider(mchProducts, provider);
|
||||
private PayRouteBasicConfigResult toPanelResult(PayProviderEnum provider, String savedProduct) {
|
||||
List<String> products = productsForProvider(provider);
|
||||
return new PayRouteBasicConfigResult()
|
||||
.setProvider(provider.getCode())
|
||||
.setProduct(savedProduct)
|
||||
.setProducts(products);
|
||||
}
|
||||
|
||||
/// 从商户已开通产品中筛出支持指定支付渠道的产品编码
|
||||
private List<String> productsForProvider(List<MchProductConfig> mchProducts, PayProviderEnum provider) {
|
||||
return mchProducts.stream()
|
||||
.map(MchProductConfig::getProduct)
|
||||
/// 从产品枚举中筛出支持指定支付渠道的产品编码(开源版:所有产品默认可用)
|
||||
private List<String> productsForProvider(PayProviderEnum provider) {
|
||||
return Arrays.stream(ProductEnum.values())
|
||||
.map(ProductEnum::getCode)
|
||||
.filter(product -> PaymentStrategyFactory.productSupportsProvider(product, provider))
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 查询商户已启用的支付产品配置
|
||||
private List<MchProductConfig> enabledMchProducts(String mchNo) {
|
||||
return mchProductConfigManager.findByMchNo(mchNo).stream()
|
||||
.filter(MchProductConfig::isEnable)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// 按应用号加载路由策略,不存在则抛业务异常
|
||||
private PayRouteStrategy requireStrategy(String appId) {
|
||||
return strategyManager.findByAppId(appId)
|
||||
.orElseThrow(() -> new DataNotExistException("pay.route.error.routeStrategyNotExist"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.dromara.daxpay.payment.merchant.service.route.basic;
|
||||
|
||||
import org.dromara.daxpay.payment.common.util.PaymentStrategyFactory;
|
||||
import org.dromara.daxpay.payment.merchant.dao.config.MchProductConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.entity.route.basic.PayRouteBasicConfig;
|
||||
import org.dromara.daxpay.payment.merchant.service.route.support.PayRouteCapabilityService;
|
||||
import org.dromara.daxpay.payment.merchant.service.route.model.RouteHit;
|
||||
@@ -22,12 +20,12 @@ import java.util.Objects;
|
||||
|
||||
/// # 基础模式通道路由匹配器
|
||||
///
|
||||
/// 按已配置的支付渠道与支付产品,结合产品策略解析通道与支付方式
|
||||
/// 按已配置的支付渠道与支付产品,结合产品策略解析通道与支付方式。
|
||||
/// 开源版:所有产品默认可用,不再检查商户启用状态。
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PayRouteBasicMatcher {
|
||||
|
||||
private final MchProductConfigManager productConfigManager;
|
||||
private final PayRouteProductResolver productResolver;
|
||||
private final PayRouteCapabilityService payRouteCapabilityService;
|
||||
|
||||
@@ -45,7 +43,7 @@ public class PayRouteBasicMatcher {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.basicProductNotConfigured", PayRouteI18nHelper.provider(payParam.getProvider()));
|
||||
}
|
||||
assertProductConfigured(payParam.getMchNo(), product, provider);
|
||||
assertProductConfigured(product, provider);
|
||||
if (!PaymentStrategyFactory.existsByProduct(product, AbsProductStrategy.class)) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.productStrategyMissing");
|
||||
@@ -75,18 +73,11 @@ public class PayRouteBasicMatcher {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/// 路由配置的产品仍须在商户已开通产品范围内,且产品策略支持该支付渠道
|
||||
private void assertProductConfigured(String mchNo, String product, PayProviderEnum provider) {
|
||||
boolean mchEnabled = productConfigManager.findByMchNo(mchNo).stream()
|
||||
.filter(MchProductConfig::isEnable)
|
||||
.anyMatch(config -> Objects.equals(config.getProduct(), product));
|
||||
if (!mchEnabled) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.basicProductNotAvailable", PayRouteI18nHelper.provider(provider.getCode()));
|
||||
}
|
||||
/// 校验产品策略支持该支付渠道(开源版:不再检查商户启用状态)
|
||||
private void assertProductConfigured(String product, PayProviderEnum provider) {
|
||||
if (!PaymentStrategyFactory.productSupportsProvider(product, provider)) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.basicProductNotAvailable", PayRouteI18nHelper.provider(provider.getCode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.dromara.daxpay.payment.merchant.service.route.runtime;
|
||||
|
||||
import org.dromara.daxpay.payment.merchant.dao.config.MchProductConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.service.route.support.PayRouteStrategyCapabilitySupport;
|
||||
import org.dromara.daxpay.platform.core.enums.pay.channel.PayMethodEnum;
|
||||
import org.dromara.daxpay.platform.core.enums.pay.channel.ProductEnum;
|
||||
@@ -11,23 +9,23 @@ import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/// # 通道路由产品解析器
|
||||
///
|
||||
/// 开源版:所有产品默认可用,直接从产品枚举中按通道+支付方式解析产品编码。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayRouteProductResolver {
|
||||
|
||||
private final MchProductConfigManager productConfigManager;
|
||||
private final PayRouteStrategyCapabilitySupport payRouteStrategyCapabilitySupport;
|
||||
|
||||
/// 根据商户已开通产品及支付方式解析产品编码
|
||||
/// 根据通道及支付方式解析产品编码(开源版:所有产品默认可用)
|
||||
public String resolve(String mchNo, String channel, String method) {
|
||||
return productConfigManager.findByMchNo(mchNo).stream()
|
||||
.filter(MchProductConfig::isEnable)
|
||||
.filter(config -> Objects.equals(config.getChannel(), channel))
|
||||
.map(MchProductConfig::getProduct)
|
||||
return Arrays.stream(ProductEnum.values())
|
||||
.filter(pe -> Objects.equals(pe.getChannel(), channel))
|
||||
.map(ProductEnum::getCode)
|
||||
.filter(product -> payRouteStrategyCapabilitySupport.routeProductSupportsMethod(
|
||||
product, PayMethodEnum.findByCode(method)))
|
||||
.findFirst()
|
||||
@@ -54,4 +52,4 @@ public class PayRouteProductResolver {
|
||||
}
|
||||
return productEnum.getChannel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ public class PayRouteSceneConfigService {
|
||||
PayRouteI18nHelper.payMethod(item.getMethod()), PayRouteI18nHelper.product(item.getProduct()));
|
||||
}
|
||||
payRouteStrategyCapabilitySupport.validateSceneCapability(
|
||||
mchNo, item.getProvider(), item.getMethod(), item.getProduct(), item.getCapability());
|
||||
item.getProvider(), item.getMethod(), item.getProduct(), item.getCapability());
|
||||
var route = sceneRouteResolver.resolve(item.getProduct(), item.getProvider(), item.getMethod());
|
||||
channel = route.channel();
|
||||
method = route.method();
|
||||
@@ -143,7 +143,7 @@ public class PayRouteSceneConfigService {
|
||||
return List.of();
|
||||
}
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(appId);
|
||||
return payRouteStrategyCapabilitySupport.listSceneProductCandidates(mchNo, provider, method);
|
||||
return payRouteStrategyCapabilitySupport.listSceneProductCandidates(provider, method);
|
||||
}
|
||||
|
||||
/// 按目录项与支付产品筛选支付能力候选(策略 Map ∩ DB,不落库)
|
||||
@@ -153,7 +153,7 @@ public class PayRouteSceneConfigService {
|
||||
return List.of();
|
||||
}
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(appId);
|
||||
return payRouteStrategyCapabilitySupport.listSceneCapabilityCandidates(mchNo, provider, method, product);
|
||||
return payRouteStrategyCapabilitySupport.listSceneCapabilityCandidates(provider, method, product);
|
||||
}
|
||||
|
||||
/// 回显推断支付能力(候选唯一时返回编码)
|
||||
@@ -162,7 +162,7 @@ public class PayRouteSceneConfigService {
|
||||
return null;
|
||||
}
|
||||
String mchNo = mchAppInfoManager.requireMchNoByAppIdNotTenant(appId);
|
||||
return payRouteStrategyCapabilitySupport.inferSceneCapability(mchNo, provider, method, product);
|
||||
return payRouteStrategyCapabilitySupport.inferSceneCapability(provider, method, product);
|
||||
}
|
||||
|
||||
/// 校验批量保存项:provider + method 在策略内唯一
|
||||
@@ -210,7 +210,7 @@ public class PayRouteSceneConfigService {
|
||||
if (provider == null) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.route.error.basicProviderInvalid");
|
||||
}
|
||||
basicConfigService.validateBasicProduct(mchNo, product, provider);
|
||||
basicConfigService.validateBasicProduct(product, provider);
|
||||
}
|
||||
|
||||
/// 校验通道+方式可解析为商户产品且存在对应产品策略
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.dromara.daxpay.payment.merchant.service.route.support;
|
||||
|
||||
import org.dromara.daxpay.payment.common.util.PaymentStrategyFactory;
|
||||
import org.dromara.daxpay.payment.merchant.dao.config.MchProductConfigManager;
|
||||
import org.dromara.daxpay.payment.merchant.entity.config.MchProductConfig;
|
||||
import org.dromara.daxpay.payment.merchant.param.route.scene.PayRouteSceneCapabilityBatchItem;
|
||||
import org.dromara.daxpay.payment.pay.dao.masterdata.capability.PayCapabilityManager;
|
||||
import org.dromara.daxpay.payment.pay.dao.masterdata.capability.PayProductCapabilityManager;
|
||||
@@ -26,19 +24,20 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/// # 通道路由:策略方式→能力与 DB/商户求交
|
||||
/// # 通道路由:策略方式→能力与 DB 求交
|
||||
///
|
||||
/// 统一场景模式产品/能力候选及保存校验,数据源为 {@link AbsProductStrategy#methodCapabilityMapping()}。
|
||||
/// 开源版:所有产品默认可用,不再检查商户启用状态。
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayRouteStrategyCapabilitySupport {
|
||||
|
||||
private final MchProductConfigManager mchProductConfigManager;
|
||||
private final PayProviderMethodService payProviderMethodService;
|
||||
private final PayProductCapabilityService payProductCapabilityService;
|
||||
private final PayProductCapabilityManager payProductCapabilityManager;
|
||||
@@ -54,7 +53,7 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
String provider = entry.getProviderCode();
|
||||
String method = entry.getMethodCode();
|
||||
String key = PayProviderMethodManager.pairKey(provider, method);
|
||||
index.put(key, listSceneProductCandidates(mchNo, provider, method));
|
||||
index.put(key, listSceneProductCandidates(provider, method));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@@ -72,7 +71,7 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
String key = capabilityBatchKey(item.getProvider(), item.getMethod(), item.getProduct());
|
||||
index.put(key, listSceneCapabilityCandidates(
|
||||
mchNo, item.getProvider(), item.getMethod(), item.getProduct()));
|
||||
item.getProvider(), item.getMethod(), item.getProduct()));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@@ -82,23 +81,19 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
return provider + "|" + method + "|" + product;
|
||||
}
|
||||
|
||||
/// 目录项下商户可用支付产品候选
|
||||
public List<LabelValue> listSceneProductCandidates(String mchNo, String provider, String method) {
|
||||
/// 目录项下可用支付产品候选(开源版:所有产品默认可用)
|
||||
public List<LabelValue> listSceneProductCandidates(String provider, String method) {
|
||||
if (!payProviderMethodService.contains(provider, method)) {
|
||||
return List.of();
|
||||
}
|
||||
PayMethodEnum methodEnum = PayMethodEnum.findByCode(method);
|
||||
List<LabelValue> results = new ArrayList<>();
|
||||
for (MchProductConfig config : mchProductConfigManager.findByMchNo(mchNo)) {
|
||||
if (!config.isEnable() || StrUtil.isBlank(config.getProduct())) {
|
||||
continue;
|
||||
}
|
||||
String product = config.getProduct();
|
||||
for (ProductEnum pe : ProductEnum.values()) {
|
||||
String product = pe.getCode();
|
||||
if (!routeProductSupportsMethod(product, methodEnum)) {
|
||||
continue;
|
||||
}
|
||||
ProductEnum productEnum = ProductEnum.findByCode(product);
|
||||
String label = productEnum != null ? I18nUtil.getEnumName(productEnum) : product;
|
||||
String label = I18nUtil.getEnumName(pe);
|
||||
if (results.stream().noneMatch(item -> Objects.equals(item.getValue(), product))) {
|
||||
results.add(new LabelValue(label, product));
|
||||
}
|
||||
@@ -107,13 +102,11 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
|
||||
/// 指定产品+目录项下支付能力候选(策略 Map ∩ DB ∩ 能力主数据启用)
|
||||
public List<LabelValue> listSceneCapabilityCandidates(String mchNo, String provider, String method, String product) {
|
||||
/// 开源版:不再检查商户产品启用状态
|
||||
public List<LabelValue> listSceneCapabilityCandidates(String provider, String method, String product) {
|
||||
if (!payProviderMethodService.contains(provider, method)) {
|
||||
return List.of();
|
||||
}
|
||||
if (!merchantProductEnabled(mchNo, product)) {
|
||||
return List.of();
|
||||
}
|
||||
if (!PaymentStrategyFactory.existsByProduct(product, AbsProductStrategy.class)) {
|
||||
return List.of();
|
||||
}
|
||||
@@ -126,8 +119,8 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
|
||||
/// 候选唯一时返回能力编码(仅供回显)
|
||||
public String inferSceneCapability(String mchNo, String provider, String method, String product) {
|
||||
List<LabelValue> candidates = listSceneCapabilityCandidates(mchNo, provider, method, product);
|
||||
public String inferSceneCapability(String provider, String method, String product) {
|
||||
List<LabelValue> candidates = listSceneCapabilityCandidates(provider, method, product);
|
||||
if (candidates.size() == 1) {
|
||||
return candidates.getFirst().getValue();
|
||||
}
|
||||
@@ -135,12 +128,12 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
}
|
||||
|
||||
/// 校验场景配置项所选能力在候选集合内
|
||||
public void validateSceneCapability(String mchNo, String provider, String method, String product, String capability) {
|
||||
public void validateSceneCapability(String provider, String method, String product, String capability) {
|
||||
if (StrUtil.isBlank(capability)) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR,
|
||||
"pay.route.error.sceneCapabilityRequired");
|
||||
}
|
||||
boolean matched = listSceneCapabilityCandidates(mchNo, provider, method, product).stream()
|
||||
boolean matched = listSceneCapabilityCandidates(provider, method, product).stream()
|
||||
.anyMatch(item -> Objects.equals(item.getValue(), capability));
|
||||
if (!matched) {
|
||||
PayCapabilityEnum capabilityEnum = PayCapabilityEnum.findByCode(capability);
|
||||
@@ -173,11 +166,6 @@ public class PayRouteStrategyCapabilitySupport {
|
||||
return routeProductSupportsMethod(product, PayMethodEnum.findByCode(methodCode));
|
||||
}
|
||||
|
||||
private boolean merchantProductEnabled(String mchNo, String product) {
|
||||
return mchProductConfigManager.findByMchNo(mchNo).stream()
|
||||
.anyMatch(config -> config.isEnable() && Objects.equals(config.getProduct(), product));
|
||||
}
|
||||
|
||||
private boolean productCapabilityEnabled(String productCode, String capabilityCode) {
|
||||
if (!payProductCapabilityManager.exists(productCode, capabilityCode)) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user