diff --git a/apps/daxpay-admin/src/api/payment/channel/lakala/channel-merchant.api.ts b/apps/daxpay-admin/src/api/payment/channel/lakala/channel-merchant.api.ts index 61c45dcfe..08bc0b841 100644 --- a/apps/daxpay-admin/src/api/payment/channel/lakala/channel-merchant.api.ts +++ b/apps/daxpay-admin/src/api/payment/channel/lakala/channel-merchant.api.ts @@ -3,13 +3,50 @@ import type { Result } from '#/types/web'; import { defHttp } from '#/api/request'; /** - * 拉卡拉通道商户创建 API + * 拉卡拉通道商户绑定 API */ -export const ChannelMerchantLakalaApi = { +export const LakalaChannelMerchantApi = { + /** + * 根据通道商户号查询拉卡拉通道商户配置 + */ + findByChannelMchNo(channelMchNo: string): Promise> { + return defHttp.get({ + url: '/admin/lakala/isv-channel-merchant/find-by-channel-mch-no', + params: { channelMchNo }, + }); + }, /** * 创建拉卡拉通道商户 */ - create(data: Record): Promise> { - return defHttp.post({ url: '/admin/lakala/channel-merchant/create', data }); + create(data: LakalaIsvChannelMerchantCreateParam): Promise> { + return defHttp.post({ url: '/admin/lakala/isv-channel-merchant/create', data }); }, }; + +/** 拉卡拉通道商户绑定 */ +export interface LakalaIsvChannelMerchant { + /** 主键 */ + id?: string; + /** 通道商户号 */ + channelMchNo?: string; + /** 所属支付产品 */ + product?: string; + /** 拉卡拉商户编号 */ + lakalaMchNo?: string; + /** 终端号 */ + termNo?: string; +} + +/** 拉卡拉通道商户创建参数 */ +export interface LakalaIsvChannelMerchantCreateParam { + /** 商户号 */ + mchNo: string; + /** 通道商户名称 */ + channelMerchantName: string; + /** 所属支付产品 */ + product: string; + /** 拉卡拉商户编号 */ + lakalaMchNo: string; + /** 终端号 */ + termNo?: string; +} diff --git a/apps/daxpay-admin/src/api/payment/channel/lakala/pay-config.api.ts b/apps/daxpay-admin/src/api/payment/channel/lakala/pay-config.api.ts index 8e0c5ba5c..47fff3767 100644 --- a/apps/daxpay-admin/src/api/payment/channel/lakala/pay-config.api.ts +++ b/apps/daxpay-admin/src/api/payment/channel/lakala/pay-config.api.ts @@ -1,43 +1,42 @@ -import type { MchEntity, Result } from '#/types/web'; +import type { Result } from '#/types/web'; import { defHttp } from '#/api/request'; /** - * 拉卡拉产品支付配置 API + * 拉卡拉服务商密钥配置 API */ export const LakalaPayConfigApi = { /** - * 查询拉卡拉产品配置详情 + * 查询拉卡拉服务商密钥配置 + * 平台为唯一服务商,密钥全局唯一 */ - findConfig(isvNo: string, product: string, sandbox: boolean): Promise> { - return defHttp.get({ url: '/admin/lakala/product-pay-config/find-config', params: { isvNo, product, sandbox } }); + findConfig(product: string): Promise> { + return defHttp.get({ url: '/admin/lakala/isv-key-config/find-config', params: { product } }); }, /** - * 保存拉卡拉产品配置 + * 保存拉卡拉服务商密钥配置 */ - saveConfig(data: LakalaProductConfig): Promise> { - return defHttp.post({ url: '/admin/lakala/product-pay-config/save-config', data }); + saveConfig(data: LakalaIsvKeyConfig): Promise> { + return defHttp.post({ url: '/admin/lakala/isv-key-config/save-config', data }); }, }; -/** 拉卡拉产品支付配置 */ -export interface LakalaProductConfig extends MchEntity { - /** 是否启用 */ - enable?: boolean; - /** 沙箱环境 */ - sandbox?: boolean; +/** 拉卡拉服务商密钥配置 */ +export interface LakalaIsvKeyConfig { + /** 主键 */ + id?: string; + /** 产品编码 */ + product?: string; /** 拉卡拉应用编号 */ lklAppId?: string; /** 商户证书序列号 */ mchSerialNo?: string; - /** 私钥 */ + /** 商户RSA私钥(PEM) */ privateKey?: string; - /** 公钥 */ + /** 拉卡拉RSA公钥证书(PEM) */ publicKey?: string; - /** sm4密钥 */ + /** SM4密钥(进件敏感字段加密用) */ sm4Key?: string; - /** 产品类型 */ - product?: string; - /** 通道 */ - channel?: string; + /** 是否沙箱环境 */ + sandbox?: boolean; } diff --git a/apps/daxpay-admin/src/constants/perm-codes.ts b/apps/daxpay-admin/src/constants/perm-codes.ts index 2d1961b64..c21caf7fa 100644 --- a/apps/daxpay-admin/src/constants/perm-codes.ts +++ b/apps/daxpay-admin/src/constants/perm-codes.ts @@ -117,6 +117,11 @@ export const PermCodes = { VIEW: 'payment:wechat:isv:view', MANAGE: 'payment:wechat:isv:manage', }, + /** 拉卡拉服务商 menuCode=payment:lakala:isv */ + Lakala: { + VIEW: 'payment:lakala:isv:view', + MANAGE: 'payment:lakala:isv:manage', + }, /** 支付主数据 menuCode=payment:platform:* */ Platform: { Product: { diff --git a/apps/daxpay-admin/src/locales/langs/en-US/payment/channel/lakalaIsv.json b/apps/daxpay-admin/src/locales/langs/en-US/payment/channel/lakalaIsv.json index 4822d2867..fd08c3315 100644 --- a/apps/daxpay-admin/src/locales/langs/en-US/payment/channel/lakalaIsv.json +++ b/apps/daxpay-admin/src/locales/langs/en-US/payment/channel/lakalaIsv.json @@ -1,7 +1,10 @@ { "title": "Lakala ISV Configuration", + "configTitle": "Lakala ISV Key Configuration", + "manageTitle": "Lakala ISV Management", "basicConfig": "Basic Configuration", "keyConfig": "Key Configuration", + "advancedConfig": "Advanced Configuration", "enable": "Enable", "lklAppId": "Lakala Application ID", "lklAppIdPlaceholder": "Please enter Lakala application ID", @@ -10,9 +13,15 @@ "privateKey": "Private Key Certificate", "publicKey": "Public Key Certificate", "sm4Key": "SM4 Key", - "sm4KeyPlaceholder": "Please enter SM4 key", + "sm4KeyPlaceholder": "Please enter SM4 key (for onboarding sensitive fields, optional)", "uploadPublicKey": "Upload Public Key Certificate", "uploadPrivateKey": "Upload Private Key Certificate", + "uploadKey": "Upload Private Key", + "sandbox": "Sandbox Environment", + "sandboxOn": "Sandbox", + "sandboxOff": "Production", + "cardMchKey": "ISV Key", + "cardMchKeyDesc": "Configure Lakala ISV application ID, private/public key certificates", "validation": { "enable": "Please select whether to enable", "lklAppId": "Please enter Lakala application ID", diff --git a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/channel/lakalaIsv.json b/apps/daxpay-admin/src/locales/langs/zh-CN/payment/channel/lakalaIsv.json index 1870052d2..0d4ce3cfd 100644 --- a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/channel/lakalaIsv.json +++ b/apps/daxpay-admin/src/locales/langs/zh-CN/payment/channel/lakalaIsv.json @@ -1,7 +1,10 @@ { "title": "拉卡拉服务商配置", + "configTitle": "拉卡拉服务商密钥配置", + "manageTitle": "拉卡拉服务商管理", "basicConfig": "基础配置", "keyConfig": "密钥配置", + "advancedConfig": "高级配置", "enable": "是否启用", "lklAppId": "拉卡拉应用编号", "lklAppIdPlaceholder": "请输入拉卡拉应用编号", @@ -10,9 +13,15 @@ "privateKey": "私钥证书", "publicKey": "公钥证书", "sm4Key": "SM4密钥", - "sm4KeyPlaceholder": "请输入SM4密钥", + "sm4KeyPlaceholder": "请输入SM4密钥(进件敏感字段加密用, 选填)", "uploadPublicKey": "上传公钥证书", "uploadPrivateKey": "上传私钥证书", + "uploadKey": "上传私钥", + "sandbox": "沙箱环境", + "sandboxOn": "沙箱", + "sandboxOff": "生产", + "cardMchKey": "服务商密钥", + "cardMchKeyDesc": "配置拉卡拉服务商应用编号、私钥公钥证书", "validation": { "enable": "请选择是否启用", "lklAppId": "请输入拉卡拉应用编号", diff --git a/apps/daxpay-admin/src/views/payment/channel/lakala/config/LakalaIsvConfigEdit.vue b/apps/daxpay-admin/src/views/payment/channel/lakala/config/LakalaIsvConfigEdit.vue index 77f1e55b1..d4049db88 100644 --- a/apps/daxpay-admin/src/views/payment/channel/lakala/config/LakalaIsvConfigEdit.vue +++ b/apps/daxpay-admin/src/views/payment/channel/lakala/config/LakalaIsvConfigEdit.vue @@ -5,11 +5,16 @@ import { IconifyIcon } from '@vben-core/icons'; - import { LakalaPayConfigApi, type LakalaProductConfig } from '#/api/payment/channel/lakala/pay-config.api'; - import { type IsvProductPayConfigResult } from '#/api/payment/config/pay-product-config.api'; + import { + type LakalaIsvKeyConfig, + LakalaPayConfigApi, + } from '#/api/payment/channel/lakala/pay-config.api'; + import { PermCodes } from '#/constants/perm-codes'; + import { ProductEnum } from '#/enums/payment/productEnum'; import { useFormEdit } from '#/hooks/useFormEdit'; import { useMessage } from '#/hooks/useMessage'; - import { readFileAsText } from '#/utils/file'; + import { usePermission } from '#/hooks/usePermission'; + import { readFileAsBase64 } from '#/utils/file'; defineOptions({ name: 'LakalaIsvConfigEdit' }); @@ -17,33 +22,27 @@ (e: 'saved'): void; }>(); - const { labelCol, wrapperCol, confirmLoading, visible, showable, handleCancel, diffForm } = useFormEdit(); + const { labelCol, wrapperCol, confirmLoading, visible, handleCancel, diffForm } = useFormEdit(); const { message } = useMessage(); + const { hasPermission } = usePermission(); - const isvNo = ref(''); - const productCode = ref(''); - const sandboxEnv = ref(false); const formRef = ref(); - const form = ref({} as LakalaProductConfig); + const form = ref({} as LakalaIsvKeyConfig); let rawForm: Record = {}; - const drawerTitle = computed(() => { - return $t('payment.channel.lakalaIsv.title'); - }); + const canEdit = computed(() => hasPermission(PermCodes.Payment.Lakala.MANAGE)); - const rules = computed(() => ({ - enable: [{ required: true, message: $t('payment.channel.lakalaIsv.validation.enable') }], + const drawerTitle = $t('payment.channel.lakalaIsv.configTitle'); + + const rules = { lklAppId: [{ required: true, message: $t('payment.channel.lakalaIsv.validation.lklAppId') }], - mchSerialNo: [{ required: true, message: $t('payment.channel.lakalaIsv.validation.mchSerialNo') }], privateKey: [{ required: true, message: $t('payment.channel.lakalaIsv.validation.privateKey') }], publicKey: [{ required: true, message: $t('payment.channel.lakalaIsv.validation.publicKey') }], - })); + }; - function init(no: string, _configInfo: IsvProductPayConfigResult, sandbox: boolean) { - isvNo.value = no; - productCode.value = _configInfo.product || ''; - sandboxEnv.value = sandbox; + /** 打开抽屉并加载拉卡拉服务商密钥配置(平台为唯一服务商,密钥全局唯一) */ + function init() { visible.value = true; resetForm(); loadConfig(); @@ -51,16 +50,13 @@ function loadConfig() { confirmLoading.value = true; - LakalaPayConfigApi.findConfig(isvNo.value, productCode.value, sandboxEnv.value) + LakalaPayConfigApi.findConfig(ProductEnum.LAKALA_PAY) .then(({ data }) => { rawForm = { ...data }; form.value = { - isvNo: isvNo.value, - product: productCode.value, - channel: 'lakala', - sandbox: sandboxEnv.value, + product: ProductEnum.LAKALA_PAY, ...data, - } as LakalaProductConfig; + } as LakalaIsvKeyConfig; }) .finally(() => { confirmLoading.value = false; @@ -72,11 +68,17 @@ confirmLoading.value = true; LakalaPayConfigApi.saveConfig({ ...form.value, - ...diffForm(rawForm, form.value, 'privateKey', 'publicKey', 'sm4Key'), - isvNo: isvNo.value, - product: productCode.value, - channel: 'lakala', - sandbox: sandboxEnv.value, + ...diffForm( + rawForm, + form.value, + 'lklAppId', + 'mchSerialNo', + 'privateKey', + 'publicKey', + 'sm4Key', + 'sandbox', + ), + product: ProductEnum.LAKALA_PAY, }) .then(() => { message.success($t('common.saveSuccess')); @@ -92,19 +94,13 @@ function handleUpload(info: { file: File }, fieldName: string) { const file = info.file; if (!file) return; - readFileAsText(file).then((content) => { + readFileAsBase64(file).then((content) => { (form.value as Record)[fieldName] = content; message.success($t('components.upload.uploadSuccess', { name: file.name })); formRef.value?.validateFields(fieldName); }); } - function truncateContent(content: string, maxLength = 500): string { - if (!content) return ''; - if (content.length <= maxLength) return content; - return content.slice(0, Math.max(0, maxLength)) + '...'; - } - function resetForm() { nextTick(() => { formRef.value?.resetFields(); @@ -121,6 +117,7 @@ size="large" :styles="{ footer: { textAlign: 'right' } }" :mask-closable="false" + destroy-on-hidden @close="handleCancel" > @@ -134,19 +131,10 @@ > {{ $t('payment.channel.lakalaIsv.basicConfig') }} - - - - @@ -154,79 +142,86 @@ {{ $t('payment.channel.lakalaIsv.keyConfig') }} + + + + + {{ $t('payment.channel.lakalaIsv.uploadKey') }} + + + + + + + - + {{ $t('payment.channel.lakalaIsv.uploadPublicKey') }} - - - - - + + + - - - - - {{ $t('payment.channel.lakalaIsv.uploadPrivateKey') }} - - - - - - - - + {{ $t('payment.channel.lakalaIsv.advancedConfig') }} + + + +