mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-09 14:36:00 +08:00
feat(payment): 通道商户沙箱标记与全局沙箱开关
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,6 +29,9 @@ public class AlipayDirectChannelMerchant extends MchBaseEntity implements ToResu
|
||||
/// 支付宝商家唯一识别码(2088开头的16位数字)
|
||||
private String alipayUserId;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 转换
|
||||
@Override
|
||||
public AlipayDirectChannelMerchantResult toResult() {
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package cn.daxpay.open.channel.alipay.service.direct;
|
||||
|
||||
import cn.daxpay.open.channel.alipay.dao.direct.AlipayDirectAppManager;
|
||||
import cn.daxpay.open.channel.alipay.dao.direct.AlipayDirectChannelMerchantManager;
|
||||
import cn.daxpay.open.channel.alipay.client.credential.AlipaySdkCredential;
|
||||
import cn.daxpay.open.channel.alipay.entity.direct.AlipayDirectApp;
|
||||
import cn.daxpay.open.channel.alipay.entity.direct.AlipayDirectAppKeyConfig;
|
||||
import cn.daxpay.open.channel.alipay.entity.direct.AlipayDirectChannelMerchant;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductConfigManager;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
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.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -28,6 +32,7 @@ import java.util.Optional;
|
||||
public class AlipayDirectConfigAssembler {
|
||||
|
||||
private final AlipayDirectAppManager alipayDirectAppManager;
|
||||
private final AlipayDirectChannelMerchantManager alipayDirectChannelMerchantManager;
|
||||
private final AlipayDirectAppKeyConfigService alipayDirectAppKeyConfigService;
|
||||
private final AlipayDirectAppCapabilityService alipayDirectAppCapabilityService;
|
||||
private final PayProductConfigManager payProductConfigManager;
|
||||
@@ -45,6 +50,14 @@ public class AlipayDirectConfigAssembler {
|
||||
boolean sandbox = payProductConfigManager.findByProduct(ProductEnum.ALIPAY.getCode())
|
||||
.map(c -> PayEnvEnum.SANDBOX.getCode().equals(c.getActiveEnv()))
|
||||
.orElse(false);
|
||||
// 环境一致性校验: 通道商户绑定的沙箱标记需与产品当前生效环境一致
|
||||
AlipayDirectChannelMerchant channelMerchant = alipayDirectChannelMerchantManager.lambdaQuery()
|
||||
.eq(AlipayDirectChannelMerchant::getChannelMchNo, channelMchNo)
|
||||
.oneOpt()
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
AlipayDirectAppKeyConfig keyConfig = alipayDirectAppKeyConfigService.findByAlipayDirectAppId(app.getId(), sandbox);
|
||||
|
||||
var credential = new AlipaySdkCredential();
|
||||
|
||||
@@ -27,6 +27,9 @@ public class FuyouIsvChannelMerchant extends MchBaseEntity implements ToResult<F
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 富友商户号(mchnt_cd)
|
||||
private String fuyouMchNo;
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ public class FuyouIsvConfigAssembler {
|
||||
FuyouIsvChannelMerchant channelMerchant = fuyouIsvChannelMerchantManager.findByChannelMchNo(channelMchNo)
|
||||
// 富友: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
FuyouSdkCredential credential = new FuyouSdkCredential();
|
||||
// 服务商身份与密钥
|
||||
|
||||
@@ -27,6 +27,9 @@ public class HkrtIsvChannelMerchant extends MchBaseEntity implements ToResult<Hk
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 海科商户号(merch_no)
|
||||
private String merchNo;
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ public class HkrtIsvConfigAssembler {
|
||||
HkrtIsvChannelMerchant channelMerchant = hkrtIsvChannelMerchantManager.findByChannelMchNo(channelMchNo)
|
||||
// 海科融通: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
HkrtSdkCredential credential = new HkrtSdkCredential();
|
||||
// 服务商身份与密钥
|
||||
|
||||
@@ -27,6 +27,9 @@ public class HmpayIsvChannelMerchant extends MchBaseEntity implements ToResult<H
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 杉德商户编号
|
||||
private String merchantNo;
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import cn.daxpay.open.channel.hmpay.entity.isv.HmpayIsvChannelMerchant;
|
||||
import cn.daxpay.open.channel.hmpay.entity.isv.HmpayIsvKeyConfig;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductConfigManager;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.entity.PayProductConfig;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
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.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -51,6 +53,11 @@ public class HmpayIsvConfigAssembler {
|
||||
// 河马付: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("payment.error.channel.channelMerchantNotExist"));
|
||||
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
HmpaySdkCredential credential = new HmpaySdkCredential();
|
||||
// 服务商身份与密钥
|
||||
credential.setSandAppId(keyConfig.getSandAppId());
|
||||
|
||||
@@ -27,6 +27,9 @@ public class LakalaIsvChannelMerchant extends MchBaseEntity implements ToResult<
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 拉卡拉商户编号(merchantNo)
|
||||
private String lakalaMchNo;
|
||||
|
||||
|
||||
@@ -55,6 +55,10 @@ public class LakalaIsvConfigAssembler {
|
||||
LakalaIsvChannelMerchant channelMerchant = lakalaIsvChannelMerchantManager.findByChannelMchNo(channelMchNo)
|
||||
// 拉卡拉: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
LakalaSdkCredential credential = new LakalaSdkCredential();
|
||||
// 服务商身份与密钥
|
||||
|
||||
@@ -27,6 +27,9 @@ public class LeshuaIsvChannelMerchant extends MchBaseEntity implements ToResult<
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 乐刷商户编号(merchant_id)
|
||||
private String lsMchNo;
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import cn.daxpay.open.channel.leshua.entity.isv.LeshuaIsvChannelMerchant;
|
||||
import cn.daxpay.open.channel.leshua.entity.isv.LeshuaIsvKeyConfig;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductConfigManager;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.entity.PayProductConfig;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
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.BizInfoException;
|
||||
import cn.daxpay.open.platform.core.exception.DataNotExistException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -47,6 +49,14 @@ public class LeshuaIsvConfigAssembler {
|
||||
.orElse(false);
|
||||
// 服务商密钥(按生效环境取对应环境密钥, 含 lsMchNo + tradeKey + signType)
|
||||
LeshuaIsvKeyConfig keyConfig = leshuaIsvKeyConfigService.getByProductForPay(ProductEnum.LESHUA_PAY.getCode(), sandbox);
|
||||
// 通道商户绑定(校验环境一致性)
|
||||
LeshuaIsvChannelMerchant channelMerchant = leshuaIsvChannelMerchantManager.findByChannelMchNo(channelMchNo)
|
||||
// 乐刷: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
LeshuaSdkCredential credential = new LeshuaSdkCredential();
|
||||
credential.setLsMchNo(keyConfig.getLsMchNo());
|
||||
|
||||
@@ -27,6 +27,9 @@ public class VbillIsvChannelMerchant extends MchBaseEntity implements ToResult<V
|
||||
/// @see cn.daxpay.open.platform.core.enums.pay.channel.ProductEnum
|
||||
private String product;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
/// 天阙商户号(mno)
|
||||
private String vbillMchNo;
|
||||
|
||||
|
||||
@@ -56,6 +56,11 @@ public class VbillIsvConfigAssembler {
|
||||
// 随行付: 通道商户配置不存在
|
||||
.orElseThrow(() -> new DataNotExistException("error.payment.channel.channelMerchantNotExist"));
|
||||
|
||||
// 环境一致性校验
|
||||
if (channelMerchant.isSandbox() != sandbox) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "error.channel.envMismatch");
|
||||
}
|
||||
|
||||
VbillSdkCredential credential = new VbillSdkCredential();
|
||||
// 服务商身份与密钥
|
||||
credential.setOrgId(keyConfig.getOrgId());
|
||||
|
||||
@@ -43,6 +43,9 @@ public class ChannelMerchant extends MchBaseEntity implements ToResult<ChannelMe
|
||||
/// 申请单ID
|
||||
private Long applyId;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
private boolean sandbox;
|
||||
|
||||
public Boolean getEnable() {
|
||||
return Objects.equals(enable, true);
|
||||
}
|
||||
|
||||
@@ -29,4 +29,8 @@ public class ChannelMerchantQuery {
|
||||
@Schema(description = "所属商户")
|
||||
private String mchNo;
|
||||
|
||||
/// 是否沙箱环境商户
|
||||
@Schema(description = "是否沙箱环境商户")
|
||||
private Boolean sandbox;
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,11 @@ public class ChannelMerchantResult extends MchTradeBaseResult {
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean enable;
|
||||
|
||||
/// 当前生效环境(来自支付产品配置, 商户只读): prod/sandbox
|
||||
/// 是否沙箱环境商户
|
||||
@Schema(description = "是否沙箱环境商户")
|
||||
private boolean sandbox;
|
||||
|
||||
/// 当前生效环境(来自商户 sandbox 字段, 商户只读): prod/sandbox
|
||||
@Schema(description = "当前生效环境: prod/sandbox")
|
||||
private String activeEnv;
|
||||
|
||||
|
||||
@@ -13,10 +13,9 @@ import cn.daxpay.open.payment.channel.param.mch.ChannelMerchantQuery;
|
||||
import cn.daxpay.open.payment.channel.result.info.ChannelMerchantResult;
|
||||
import cn.daxpay.open.payment.masterdata.constants.channel.service.PayChannelService;
|
||||
import cn.daxpay.open.payment.masterdata.constants.channel.result.PayChannelResult;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductConfigManager;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.dao.PayProductManager;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.entity.PayProduct;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.entity.PayProductConfig;
|
||||
import cn.daxpay.open.platform.core.enums.pay.config.PayEnvEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -37,7 +36,6 @@ public class ChannelMerchantService {
|
||||
private final ChannelMerchantManager channelMerchantManager;
|
||||
private final PayChannelService payChannelService;
|
||||
private final MerchantPermissionService merchantPermissionService;
|
||||
private final PayProductConfigManager payProductConfigManager;
|
||||
private final PayProductManager payProductManager;
|
||||
|
||||
/// 分页
|
||||
@@ -99,7 +97,8 @@ public class ChannelMerchantService {
|
||||
return results;
|
||||
}
|
||||
|
||||
/// 批量填充生效环境与沙箱支持标志(来自支付产品配置, 商户只读)
|
||||
/// 批量填充生效环境与沙箱支持标志
|
||||
/// activeEnv 从商户自身的 sandbox 字段推导, sandboxSupport 从支付产品表读取
|
||||
private void fillEnvStatus(List<ChannelMerchantResult> results) {
|
||||
if (results.isEmpty()) {
|
||||
return;
|
||||
@@ -111,20 +110,15 @@ public class ChannelMerchantService {
|
||||
if (products.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 生效环境
|
||||
Map<String, String> envMap = payProductConfigManager.lambdaQuery()
|
||||
.in(PayProductConfig::getProduct, products)
|
||||
.list()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(PayProductConfig::getProduct, PayProductConfig::getActiveEnv, (a, b) -> a));
|
||||
// 沙箱支持标志
|
||||
// 沙箱支持标志(来自支付产品表, 决定前端是否显示环境标签)
|
||||
Map<String, Boolean> sandboxMap = payProductManager.lambdaQuery()
|
||||
.in(PayProduct::getCode, products)
|
||||
.list()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(PayProduct::getCode, p -> Boolean.TRUE.equals(p.getSandbox()), (a, b) -> a));
|
||||
results.forEach(r -> {
|
||||
r.setActiveEnv(envMap.get(r.getProduct()));
|
||||
// activeEnv 从商户自身的 sandbox 字段推导
|
||||
r.setActiveEnv(r.isSandbox() ? PayEnvEnum.SANDBOX.getCode() : PayEnvEnum.PROD.getCode());
|
||||
r.setSandboxSupport(sandboxMap.getOrDefault(r.getProduct(), false));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,12 +7,17 @@ import cn.daxpay.open.payment.masterdata.constants.product.entity.PayProductConf
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.param.PayProductConfigParam;
|
||||
import cn.daxpay.open.payment.masterdata.constants.product.result.PayProductConfigResult;
|
||||
import cn.daxpay.open.payment.core.strategy.product.AbsProductStrategy;
|
||||
import cn.daxpay.open.platform.common.config.properties.PlatformConfigProperties;
|
||||
import cn.daxpay.open.platform.common.i18n.util.I18nUtil;
|
||||
import cn.daxpay.open.platform.core.code.CommonErrorCode;
|
||||
import cn.daxpay.open.platform.core.enums.pay.channel.ChannelEnum;
|
||||
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.BizInfoException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -31,6 +36,8 @@ public class PayProductConfigService {
|
||||
|
||||
private final PayProductService payProductService;
|
||||
|
||||
private final PlatformConfigProperties platformConfigProperties;
|
||||
|
||||
/// 查询全部产品配置列表(卡片页使用)
|
||||
/// 融合 PayProduct + pay_md_product_config 表 + 策略信息
|
||||
public List<PayProductConfigResult> listAll() {
|
||||
@@ -46,6 +53,11 @@ public class PayProductConfigService {
|
||||
/// 切换产品的生效环境
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void switchEnv(String product, boolean sandbox) {
|
||||
// 全局沙箱开关校验
|
||||
if (sandbox && !platformConfigProperties.isSandboxEnabled()) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.env.sandboxDisabled");
|
||||
}
|
||||
|
||||
PayProductConfig config = payProductConfigManager.findByProduct(product)
|
||||
.orElseGet(() -> createDefaultConfig(product));
|
||||
|
||||
@@ -60,6 +72,12 @@ public class PayProductConfigService {
|
||||
/// 保存或更新配置
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveOrUpdate(PayProductConfigParam param) {
|
||||
// 全局沙箱开关校验
|
||||
if (PayEnvEnum.SANDBOX.getCode().equals(param.getActiveEnv())
|
||||
&& !platformConfigProperties.isSandboxEnabled()) {
|
||||
throw new BizInfoException(CommonErrorCode.VALIDATE_PARAMETERS_ERROR, "pay.env.sandboxDisabled");
|
||||
}
|
||||
|
||||
PayProductConfig config = payProductConfigManager.findByProduct(param.getProduct())
|
||||
.orElseGet(PayProductConfig::new);
|
||||
|
||||
@@ -71,6 +89,25 @@ public class PayProductConfigService {
|
||||
payProductConfigManager.saveOrUpdate(config);
|
||||
}
|
||||
|
||||
/// 应用启动后检查: 沙箱被全局禁用时, 将所有 activeEnv=sandbox 的产品强制重置为 prod
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void checkSandboxOnStartup() {
|
||||
if (platformConfigProperties.isSandboxEnabled()) {
|
||||
return;
|
||||
}
|
||||
List<PayProductConfig> sandboxConfigs = payProductConfigManager.lambdaQuery()
|
||||
.eq(PayProductConfig::getActiveEnv, PayEnvEnum.SANDBOX.getCode())
|
||||
.list();
|
||||
for (PayProductConfig config : sandboxConfigs) {
|
||||
config.setActiveEnv(PayEnvEnum.PROD.getCode());
|
||||
payProductConfigManager.updateById(config);
|
||||
}
|
||||
if (!sandboxConfigs.isEmpty()) {
|
||||
log.info("沙箱环境已禁用(daxpay.pay.env.sandbox-enabled=false), {} 个产品从 sandbox 重置为 prod", sandboxConfigs.size());
|
||||
}
|
||||
}
|
||||
|
||||
/// PayProduct + 库表 + 策略合并为配置结果
|
||||
private PayProductConfigResult toConfigResult(PayProduct payProduct, Map<String, PayProductConfig> configMap) {
|
||||
var result = new PayProductConfigResult()
|
||||
|
||||
@@ -74,6 +74,11 @@ public class NormalPayParam extends MerchantPaymentCommonParam {
|
||||
@Schema(description = "用户标识OpenId")
|
||||
private String openId;
|
||||
|
||||
/// 指定支付/认证使用的应用AppId, 优先级高于配置自动解析, 必须在系统中预先配置过
|
||||
@Size(max = 128, message = "{validation.field.opAppId.size}")
|
||||
@Schema(description = "指定应用AppId")
|
||||
private String opAppId;
|
||||
|
||||
/// 付款码(被扫支付必填)
|
||||
@Size(max = 128, message = "{validation.field.authCode.size}")
|
||||
@Schema(description = "付款码")
|
||||
|
||||
@@ -30,6 +30,9 @@ public class PlatformConfigProperties {
|
||||
@Valid
|
||||
private Encrypt encrypt = new Encrypt();
|
||||
|
||||
/// 沙箱环境全局开关(关闭后不可切换到沙箱, 已在沙箱的产品启动时自动重置为生产)
|
||||
private boolean sandboxEnabled = true;
|
||||
|
||||
/// # 平台公私钥配置
|
||||
///
|
||||
@Slf4j
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"official_account": "Official Account",
|
||||
"miniprogram": "Mini Program"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envMismatch": "Channel merchant environment does not match the product's active environment"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"sandboxDisabled": "Sandbox environment is disabled by system"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"official_account": "公众号",
|
||||
"miniprogram": "小程序"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envMismatch": "通道商户环境与支付产品当前生效环境不一致"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"sandboxDisabled": "沙箱环境已被系统关闭,无法切换"
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class NotifySseService {
|
||||
if (emitters.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
emitters.forEach((userId, set) -> sendAll(set, payload));
|
||||
emitters.forEach((_, set) -> sendAll(set, payload));
|
||||
}
|
||||
|
||||
/// 推送给指定用户(个人消息场景)
|
||||
|
||||
@@ -109,7 +109,7 @@ daxpay:
|
||||
# 查询模式: VECTOR_INDEX(推荐) 或 CACHE
|
||||
search-type: VECTOR_INDEX
|
||||
config:
|
||||
# 证书配置0
|
||||
# 平台公私钥(证书)配置, 用于接口请求/回调的 RSA 签名与验签
|
||||
key-config:
|
||||
# 私钥配置
|
||||
private-key: '-----BEGIN PRIVATE KEY-----
|
||||
@@ -150,11 +150,22 @@ daxpay:
|
||||
qEYdxyjbqztxm0SmYwl885mcGPBNPTt9ApoRWR3CGRfE8pcQieuB0YdsdSh9+ZSa
|
||||
IwIDAQAB
|
||||
-----END PUBLIC KEY-----'
|
||||
# 数据加密配置(数据库敏感字段透明加解密, AES-256-GCM, 由 MyBatis-Plus TypeHandler 自动处理)
|
||||
encrypt:
|
||||
# 是否启用数据加密; 启用后敏感字段写入自动加密、读取自动解密
|
||||
# 注意: 启用并写入加密数据后不要关闭, 否则历史密文读取时不再解密(以密文原文返回)
|
||||
enable: true
|
||||
# 密钥列表(支持密钥轮换, 列表内版本号不可重复)
|
||||
# 第一个为当前密钥(用于加密新数据), 其余为历史密钥(仅用于解密旧数据)
|
||||
# 密文格式: v{版本号}:{base64(IV + AES-GCM 密文)}, 解密时按版本前缀匹配对应密钥
|
||||
keys:
|
||||
# 32 位 AES 密钥(必须正好 32 个字符); 轮换时生成新密钥置于列表首位并使用更大的版本号
|
||||
- key: z0Vd8jDKB80pA6OOptGLO+qDVvWboEko
|
||||
# 密钥版本号(整数, 列表内唯一)
|
||||
version: 1
|
||||
# 沙箱环境全局开关: false=生产模式(本机开发默认), true=沙箱模式
|
||||
# 关闭后不可切换到沙箱; 若启动时已有产品处于沙箱, 将自动重置为生产环境
|
||||
sandbox-enabled: false
|
||||
# 通道适配子应用配置
|
||||
# 按支付通道拆分的独立部署子服务, 主服务通过 HTTP 调用对应子服务完成通道对接。
|
||||
# 拆分目的: 通道 SDK 依赖隔离(避免冲突) + 独立升级 + 弹性伸缩
|
||||
|
||||
Reference in New Issue
Block a user