mirror of
https://gitee.com/bootx/dax-pay-ui
synced 2026-08-11 07:05:33 +08:00
refactor(payment): 通道密钥环境跟随支付产品生效环境(只读)
新增 resolveProductSandbox 工具统一从 pay_md_product_config.activeEnv 读取生效环境, adapay/alipay/ums/yeepay 四家直连密钥配置页把环境 radio 改为只读 tag, 禁止在密钥页切换环境; UmsDirectMchManage 透传 product 参数; payment/common 补 envFollowProductHint 六语种; 顺带 prettier 格式化 gateway-order.api.ts
This commit is contained in:
@@ -9,7 +9,9 @@ export const GatewayOrderApi = {
|
||||
/**
|
||||
* 分页查询网关业务订单
|
||||
*/
|
||||
page(params: GatewayOrderQuery & { current?: number; size?: number }): Promise<Result<PageResult<GatewayOrderResult>>> {
|
||||
page(
|
||||
params: GatewayOrderQuery & { current?: number; size?: number },
|
||||
): Promise<Result<PageResult<GatewayOrderResult>>> {
|
||||
return defHttp.get({ url: '/admin/order/gateway-pay/page', params });
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "Follows the payment product setting. Switch the active environment in Product Configuration."
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "決済製品設定に従います。有効環境は「決済製品設定」で切り替えてください"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "결제 상품 설정을 따릅니다. 유효 환경은 「결제 상품 설정」에서 전환하세요"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "跟随支付产品配置,请在「支付产品配置」中切换生效环境"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "跟隨支付產品配置,請在「支付產品配置」中切換生效環境"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"envFollowProductHint": "跟隨支付產品配置,請在「支付產品配置」中切換生效環境"
|
||||
}
|
||||
15
apps/daxpay-admin/src/utils/pay-product-env.ts
Normal file
15
apps/daxpay-admin/src/utils/pay-product-env.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { PayProductConfigApi } from '#/api/payment/config/pay-product-config.api';
|
||||
|
||||
/**
|
||||
* 读取支付产品当前生效环境是否为沙箱
|
||||
* 生效环境唯一真相源: pay_md_product_config.activeEnv
|
||||
* 商户/密钥配置层禁止自行切换环境, 只能跟随产品
|
||||
*/
|
||||
export async function resolveProductSandbox(product: string): Promise<boolean> {
|
||||
if (!product) {
|
||||
return false;
|
||||
}
|
||||
const { data } = await PayProductConfigApi.listAll();
|
||||
const cfg = (data || []).find((item) => item.product === product);
|
||||
return cfg?.activeEnv === 'sandbox';
|
||||
}
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
import { AdapayDirectChannelMerchantApi, type AdapayDirectKeyConfig } from '#/api/payment/channel/adapay/channel-merchant.api';
|
||||
import { PermCodes } from '#/constants/perm-codes';
|
||||
import { ProductEnum } from '#/enums/payment/productEnum';
|
||||
import { useFormEdit } from '#/hooks/useFormEdit';
|
||||
import { useMessage } from '#/hooks/useMessage';
|
||||
import { usePermission } from '#/hooks/usePermission';
|
||||
import { resolveProductSandbox } from '#/utils/pay-product-env';
|
||||
|
||||
defineOptions({ name: 'AdapayDirectKeyConfigEdit' });
|
||||
|
||||
@@ -28,7 +30,7 @@
|
||||
const form = ref<AdapayDirectKeyConfig>({} as AdapayDirectKeyConfig);
|
||||
let rawForm: Record<string, any> = {};
|
||||
|
||||
// 是否沙箱环境
|
||||
// 跟随支付产品生效环境(只读, 禁止在密钥页切换)
|
||||
const sandbox = ref(false);
|
||||
|
||||
const canEdit = computed(() => hasPermission(PermCodes.Channel.Merchant.MANAGE));
|
||||
@@ -41,26 +43,27 @@
|
||||
privateKey: [{ required: true, message: $t('payment.channel.adapay.validation.privateKey') }],
|
||||
};
|
||||
|
||||
/** 打开抽屉并加载密钥配置 */
|
||||
function init() {
|
||||
/** 打开抽屉并加载密钥配置(自动跟随产品生效环境) */
|
||||
async function init() {
|
||||
visible.value = true;
|
||||
// 默认加载生产环境配置
|
||||
sandbox.value = false;
|
||||
resetForm();
|
||||
loadConfig();
|
||||
await loadConfig();
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
async function loadConfig() {
|
||||
if (!props.channelMchNo) return;
|
||||
confirmLoading.value = true;
|
||||
AdapayDirectChannelMerchantApi.findKeyConfig(props.channelMchNo, sandbox.value)
|
||||
.then(({ data }) => {
|
||||
rawForm = { ...data };
|
||||
form.value = { ...data } as AdapayDirectKeyConfig;
|
||||
})
|
||||
.finally(() => {
|
||||
confirmLoading.value = false;
|
||||
});
|
||||
try {
|
||||
sandbox.value = await resolveProductSandbox(ProductEnum.ADA_PAY);
|
||||
const { data } = await AdapayDirectChannelMerchantApi.findKeyConfig(
|
||||
props.channelMchNo,
|
||||
sandbox.value,
|
||||
);
|
||||
rawForm = { ...data };
|
||||
form.value = { ...data } as AdapayDirectKeyConfig;
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleOk() {
|
||||
@@ -116,12 +119,18 @@
|
||||
>
|
||||
<a-divider orientation="left">{{ $t('payment.channel.adapayManage.keyConfigSection') }}</a-divider>
|
||||
|
||||
<!-- 国际化: 环境(生产/沙箱切换) -->
|
||||
<!-- 国际化: 跟随支付产品生效环境(只读) -->
|
||||
<a-form-item :label="$t('payment.channel.adapayManage.environment')">
|
||||
<a-radio-group v-model:value="sandbox" button-style="solid" @change="loadConfig">
|
||||
<a-radio-button :value="false">{{ $t('payment.channel.adapayManage.prodEnv') }}</a-radio-button>
|
||||
<a-radio-button :value="true">{{ $t('payment.channel.adapayManage.sandboxEnv') }}</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-tag :color="sandbox ? 'orange' : 'blue'">
|
||||
{{
|
||||
sandbox
|
||||
? $t('payment.channel.adapayManage.sandboxEnv')
|
||||
: $t('payment.channel.adapayManage.prodEnv')
|
||||
}}
|
||||
</a-tag>
|
||||
<span class="ml-2 text-xs text-muted-foreground">
|
||||
{{ $t('payment.common.envFollowProductHint') }}
|
||||
</span>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 国际化: Adapay 商户号(创建时录入, 不可修改) -->
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
|
||||
import { AlipayMchAppApi, type AlipayMchAppKeyConfig } from '#/api/payment/channel/alipay/mch-app.api';
|
||||
import { PermCodes } from '#/constants/perm-codes';
|
||||
import { ProductEnum } from '#/enums/payment/productEnum';
|
||||
import { useDict } from '#/hooks/useDict';
|
||||
import { useFormEdit } from '#/hooks/useFormEdit';
|
||||
import { useMessage } from '#/hooks/useMessage';
|
||||
import { usePermission } from '#/hooks/usePermission';
|
||||
import { readFileAsText } from '#/utils/file';
|
||||
import { resolveProductSandbox } from '#/utils/pay-product-env';
|
||||
|
||||
const props = defineProps<{
|
||||
aliAppId?: string;
|
||||
@@ -28,7 +30,7 @@
|
||||
const loading = ref(false);
|
||||
const saving = ref(false);
|
||||
const isEditing = ref(false);
|
||||
// 是否沙箱环境
|
||||
// 跟随支付产品生效环境(只读, 禁止在密钥页切换)
|
||||
const sandbox = ref(false);
|
||||
const formRef = ref();
|
||||
const formState = ref<AlipayMchAppKeyConfig>({
|
||||
@@ -67,26 +69,30 @@
|
||||
],
|
||||
}));
|
||||
|
||||
/** 加载密钥配置 */
|
||||
function loadConfig() {
|
||||
/** 加载密钥配置(自动跟随支付宝直连产品生效环境) */
|
||||
async function loadConfig() {
|
||||
if (!props.alipayDirectAppId) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
AlipayMchAppApi.findKeyConfigByAlipayDirectAppId(props.alipayDirectAppId, sandbox.value)
|
||||
.then(({ data }) => {
|
||||
formState.value = {
|
||||
authType: 'public_key',
|
||||
...data,
|
||||
alipayDirectAppId: props.alipayDirectAppId,
|
||||
mchNo: props.mchNo,
|
||||
channelMchNo: props.channelMchNo,
|
||||
};
|
||||
originalForm.value = { ...formState.value };
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
try {
|
||||
// 环境由支付产品配置决定, 商户密钥页不可切换
|
||||
sandbox.value = await resolveProductSandbox(ProductEnum.ALIPAY);
|
||||
const { data } = await AlipayMchAppApi.findKeyConfigByAlipayDirectAppId(
|
||||
props.alipayDirectAppId,
|
||||
sandbox.value,
|
||||
);
|
||||
formState.value = {
|
||||
authType: 'public_key',
|
||||
...data,
|
||||
alipayDirectAppId: props.alipayDirectAppId,
|
||||
mchNo: props.mchNo,
|
||||
channelMchNo: props.channelMchNo,
|
||||
};
|
||||
originalForm.value = { ...formState.value };
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
@@ -177,8 +183,6 @@
|
||||
() => props.alipayDirectAppId,
|
||||
(alipayDirectAppId) => {
|
||||
if (alipayDirectAppId) {
|
||||
// 切换应用默认加载生产环境配置
|
||||
sandbox.value = false;
|
||||
isEditing.value = false;
|
||||
loadConfig();
|
||||
}
|
||||
@@ -221,12 +225,18 @@
|
||||
>
|
||||
<a-divider orientation="left">{{ $t('payment.channel.alipayIsv.basicConfig') }}</a-divider>
|
||||
|
||||
<!-- 国际化: 环境(生产/沙箱切换) -->
|
||||
<!-- 国际化: 跟随支付产品生效环境(只读, 不可在此切换) -->
|
||||
<a-form-item :label="$t('payment.channel.alipayIsv.environment')">
|
||||
<a-radio-group v-model:value="sandbox" button-style="solid" @change="loadConfig">
|
||||
<a-radio-button :value="false">{{ $t('payment.channel.alipayIsv.prodEnv') }}</a-radio-button>
|
||||
<a-radio-button :value="true">{{ $t('payment.channel.alipayIsv.sandboxEnv') }}</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-tag :color="sandbox ? 'orange' : 'blue'">
|
||||
{{
|
||||
sandbox
|
||||
? $t('payment.channel.alipayIsv.sandboxEnv')
|
||||
: $t('payment.channel.alipayIsv.prodEnv')
|
||||
}}
|
||||
</a-tag>
|
||||
<span class="ml-2 text-xs text-muted-foreground">
|
||||
{{ $t('payment.common.envFollowProductHint') }}
|
||||
</span>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item :label="$t('payment.channel.alipayIsv.aliAppId')">
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
import { useFormEdit } from '#/hooks/useFormEdit';
|
||||
import { useMessage } from '#/hooks/useMessage';
|
||||
import { usePermission } from '#/hooks/usePermission';
|
||||
import { resolveProductSandbox } from '#/utils/pay-product-env';
|
||||
|
||||
defineOptions({ name: 'UmsDirectKeyConfigEdit' });
|
||||
|
||||
const props = defineProps<{
|
||||
channelMchNo: string;
|
||||
/** 支付产品编码(银联商务多产品, 用于读取生效环境) */
|
||||
product?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -28,7 +31,7 @@
|
||||
const form = ref<UmsDirectKeyConfig>({} as UmsDirectKeyConfig);
|
||||
let rawForm: Record<string, any> = {};
|
||||
|
||||
// 是否沙箱环境
|
||||
// 跟随支付产品生效环境(只读, 禁止在密钥页切换)
|
||||
const sandbox = ref(false);
|
||||
|
||||
const canEdit = computed(() => hasPermission(PermCodes.Channel.Merchant.MANAGE));
|
||||
@@ -42,26 +45,29 @@
|
||||
secretKey: [{ required: true, message: $t('payment.channel.ums.validation.secretKey') }],
|
||||
};
|
||||
|
||||
/** 打开抽屉并加载密钥配置 */
|
||||
function init() {
|
||||
/** 打开抽屉并加载密钥配置(自动跟随产品生效环境) */
|
||||
async function init() {
|
||||
visible.value = true;
|
||||
// 默认加载生产环境配置
|
||||
sandbox.value = false;
|
||||
resetForm();
|
||||
loadConfig();
|
||||
await loadConfig();
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
async function loadConfig() {
|
||||
if (!props.channelMchNo) return;
|
||||
confirmLoading.value = true;
|
||||
UmsDirectChannelMerchantApi.findKeyConfig(props.channelMchNo, sandbox.value)
|
||||
.then(({ data }) => {
|
||||
rawForm = { ...data };
|
||||
form.value = { ...data } as UmsDirectKeyConfig;
|
||||
})
|
||||
.finally(() => {
|
||||
confirmLoading.value = false;
|
||||
});
|
||||
try {
|
||||
// 银联商务多产品, 优先用通道商户所属 product
|
||||
const product = props.product || 'ums_qrcode';
|
||||
sandbox.value = await resolveProductSandbox(product);
|
||||
const { data } = await UmsDirectChannelMerchantApi.findKeyConfig(
|
||||
props.channelMchNo,
|
||||
sandbox.value,
|
||||
);
|
||||
rawForm = { ...data };
|
||||
form.value = { ...data } as UmsDirectKeyConfig;
|
||||
} finally {
|
||||
confirmLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleOk() {
|
||||
@@ -117,12 +123,18 @@
|
||||
>
|
||||
<a-divider orientation="left">{{ $t('payment.channel.umsManage.keyConfigSection') }}</a-divider>
|
||||
|
||||
<!-- 国际化: 环境(生产/沙箱切换) -->
|
||||
<!-- 国际化: 跟随支付产品生效环境(只读) -->
|
||||
<a-form-item :label="$t('payment.channel.umsManage.environment')">
|
||||
<a-radio-group v-model:value="sandbox" button-style="solid" @change="loadConfig">
|
||||
<a-radio-button :value="false">{{ $t('payment.channel.umsManage.prodEnv') }}</a-radio-button>
|
||||
<a-radio-button :value="true">{{ $t('payment.channel.umsManage.sandboxEnv') }}</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-tag :color="sandbox ? 'orange' : 'blue'">
|
||||
{{
|
||||
sandbox
|
||||
? $t('payment.channel.umsManage.sandboxEnv')
|
||||
: $t('payment.channel.umsManage.prodEnv')
|
||||
}}
|
||||
</a-tag>
|
||||
<span class="ml-2 text-xs text-muted-foreground">
|
||||
{{ $t('payment.common.envFollowProductHint') }}
|
||||
</span>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 国际化: 银联商务商户号(mid, 创建时录入, 不可修改) -->
|
||||
|
||||
@@ -153,7 +153,11 @@
|
||||
|
||||
<ChannelMerchantNameEditModal ref="editNameRef" :channel-merchant="channelMerchant" @success="emit('success')" />
|
||||
|
||||
<UmsDirectKeyConfigEdit ref="keyConfigRef" :channel-mch-no="channelMchNo" />
|
||||
<UmsDirectKeyConfigEdit
|
||||
ref="keyConfigRef"
|
||||
:channel-mch-no="channelMchNo"
|
||||
:product="channelMerchant.product"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
type YeepayDirectKeyConfigParam,
|
||||
} from '#/api/payment/channel/yeepay/channel-merchant.api';
|
||||
import { useMessage } from '#/hooks/useMessage';
|
||||
import { resolveProductSandbox } from '#/utils/pay-product-env';
|
||||
|
||||
defineOptions({ name: 'YeepayKeyConfigEdit' });
|
||||
|
||||
@@ -19,7 +20,9 @@ const formRef = ref();
|
||||
|
||||
// 当前编辑的通道商户号
|
||||
const channelMchNo = ref('');
|
||||
// 是否沙箱环境
|
||||
// 所属支付产品(用于读取生效环境)
|
||||
const product = ref('');
|
||||
// 跟随支付产品生效环境(只读, 禁止在密钥页切换)
|
||||
const sandbox = ref(false);
|
||||
// 已配置标志(回显用)
|
||||
const configured = ref({
|
||||
@@ -55,11 +58,12 @@ const rules = {
|
||||
],
|
||||
};
|
||||
|
||||
/** 由通用框架初始化(传入通道商户号后加载密钥配置并打开弹窗) */
|
||||
async function init(mchNo: string) {
|
||||
/** 由通用框架初始化(传入通道商户号与产品编码后加载密钥配置并打开弹窗) */
|
||||
async function init(mchNo: string, productCode?: string) {
|
||||
channelMchNo.value = mchNo;
|
||||
// 默认加载生产环境配置
|
||||
sandbox.value = false;
|
||||
product.value = productCode || 'yee_pay';
|
||||
// 跟随支付产品生效环境
|
||||
sandbox.value = await resolveProductSandbox(product.value);
|
||||
visible.value = true;
|
||||
form.value = {
|
||||
channelMchNo: mchNo,
|
||||
@@ -73,7 +77,7 @@ async function init(mchNo: string) {
|
||||
await loadConfig();
|
||||
}
|
||||
|
||||
/** 加载当前环境(生产/沙箱)的密钥配置(脱敏返回) */
|
||||
/** 加载当前产品生效环境对应的密钥配置(脱敏返回) */
|
||||
async function loadConfig() {
|
||||
if (!channelMchNo.value) return;
|
||||
const { data } = await YeepayChannelMerchantApi.findKeyConfig(channelMchNo.value, sandbox.value);
|
||||
@@ -113,12 +117,14 @@ defineExpose({ init });
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<a-form ref="formRef" :model="form" :rules="rules" layout="vertical">
|
||||
<!-- 国际化: 环境(生产/沙箱切换) -->
|
||||
<!-- 国际化: 跟随支付产品生效环境(只读) -->
|
||||
<a-form-item :label="$t('payment.channel.yeepay.environment')">
|
||||
<a-radio-group v-model:value="sandbox" button-style="solid" @change="loadConfig">
|
||||
<a-radio-button :value="false">{{ $t('payment.channel.yeepay.prodEnv') }}</a-radio-button>
|
||||
<a-radio-button :value="true">{{ $t('payment.channel.yeepay.sandboxEnv') }}</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-tag :color="sandbox ? 'orange' : 'blue'">
|
||||
{{ sandbox ? $t('payment.channel.yeepay.sandboxEnv') : $t('payment.channel.yeepay.prodEnv') }}
|
||||
</a-tag>
|
||||
<span class="ml-2 text-xs text-muted-foreground">
|
||||
{{ $t('payment.common.envFollowProductHint') }}
|
||||
</span>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('payment.channel.yeepay.appKey')" name="appKey">
|
||||
<a-textarea
|
||||
|
||||
Reference in New Issue
Block a user