From 59a71ba7a76d4cb40ac232122a72ef22f899860c Mon Sep 17 00:00:00 2001 From: DaxPay Dev Date: Fri, 10 Jul 2026 17:58:35 +0800 Subject: [PATCH] =?UTF-8?q?refactor(admin):=20=E7=A7=BB=E5=8A=A8=E7=AB=AF?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E9=85=8D=E7=BD=AE=E9=A1=B5=E4=BB=8E=20paymen?= =?UTF-8?q?t=20=E8=BF=81=E8=87=B3=20system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - API 改调 /platform/config/mobile-app - 页面与 locale 迁到 system/config/mobileApp、system.mobileApp --- .../config => system}/mobile-app.api.ts | 16 +- .../{payment/config => system}/mobileApp.json | 17 +- .../{payment/config => system}/mobileApp.json | 17 +- .../config/mobileApp/MobileAppConfig.vue | 12 +- .../mobileApp/detail/MobileAppDetail.vue | 361 ++++++++++++++++-- 5 files changed, 377 insertions(+), 46 deletions(-) rename apps/daxpay-admin/src/api/{payment/config => system}/mobile-app.api.ts (84%) rename apps/daxpay-admin/src/locales/langs/en-US/{payment/config => system}/mobileApp.json (74%) rename apps/daxpay-admin/src/locales/langs/zh-CN/{payment/config => system}/mobileApp.json (76%) rename apps/daxpay-admin/src/views/{payment => system}/config/mobileApp/MobileAppConfig.vue (91%) rename apps/daxpay-admin/src/views/{payment => system}/config/mobileApp/detail/MobileAppDetail.vue (53%) diff --git a/apps/daxpay-admin/src/api/payment/config/mobile-app.api.ts b/apps/daxpay-admin/src/api/system/mobile-app.api.ts similarity index 84% rename from apps/daxpay-admin/src/api/payment/config/mobile-app.api.ts rename to apps/daxpay-admin/src/api/system/mobile-app.api.ts index a15a153cb..feb457b02 100644 --- a/apps/daxpay-admin/src/api/payment/config/mobile-app.api.ts +++ b/apps/daxpay-admin/src/api/system/mobile-app.api.ts @@ -10,7 +10,7 @@ export const MobileAppApi = { * 查询全部(按端类型分组) */ list(): Promise> { - return defHttp.get({ url: '/admin/mobile-app/list' }); + return defHttp.get({ url: '/platform/config/mobile-app/list' }); }, /** @@ -18,7 +18,7 @@ export const MobileAppApi = { */ listByAppType(appType: string): Promise> { return defHttp.get({ - url: '/admin/mobile-app/list-by-app-type', + url: '/platform/config/mobile-app/list-by-app-type', params: { appType }, }); }, @@ -27,14 +27,20 @@ export const MobileAppApi = { * 查询单条详情 */ findById(id: string): Promise> { - return defHttp.get({ url: '/admin/mobile-app/get', params: { id } }); + return defHttp.get({ + url: '/platform/config/mobile-app/get', + params: { id }, + }); }, /** * 保存(按端类型+平台 upsert) */ save(param: MobileAppParam): Promise> { - return defHttp.post({ url: '/admin/mobile-app/save', data: param }); + return defHttp.post({ + url: '/platform/config/mobile-app/save', + data: param, + }); }, /** @@ -42,7 +48,7 @@ export const MobileAppApi = { */ updateEnabled(id: string, enable: boolean): Promise> { return defHttp.post({ - url: '/admin/mobile-app/update-enabled', + url: '/platform/config/mobile-app/update-enabled', params: { id, enable }, }); }, diff --git a/apps/daxpay-admin/src/locales/langs/en-US/payment/config/mobileApp.json b/apps/daxpay-admin/src/locales/langs/en-US/system/mobileApp.json similarity index 74% rename from apps/daxpay-admin/src/locales/langs/en-US/payment/config/mobileApp.json rename to apps/daxpay-admin/src/locales/langs/en-US/system/mobileApp.json index b0f101d13..d9da22499 100644 --- a/apps/daxpay-admin/src/locales/langs/en-US/payment/config/mobileApp.json +++ b/apps/daxpay-admin/src/locales/langs/en-US/system/mobileApp.json @@ -39,12 +39,25 @@ "originalIdPlaceholder": "Enter original ID (gh_..., optional)", "alipayAppId": "Mini Program AppId", "alipayAppIdPlaceholder": "Enter Alipay Mini Program AppId", + "authType": "Auth Type", + "authTypeKey": "Public Key", + "authTypeCert": "Certificate", + "authTypeRequired": "Please select auth type", "privateKey": "App Private Key", - "privateKeyPlaceholder": "Enter app private key", + "privateKeyPlaceholder": "Enter app private key (PEM, required for both modes)", "privateKeyRequired": "Please enter app private key", "alipayPublicKey": "Alipay Public Key", - "alipayPublicKeyPlaceholder": "Enter Alipay public key", + "alipayPublicKeyPlaceholder": "Enter Alipay public key (public key mode)", "alipayPublicKeyRequired": "Please enter Alipay public key", + "appCert": "App Public Key Certificate", + "appCertRequired": "Please upload app public key certificate", + "uploadAppCert": "Upload app public key certificate", + "alipayCert": "Alipay Public Key Certificate", + "alipayCertRequired": "Please upload Alipay public key certificate", + "uploadAlipayCert": "Upload Alipay public key certificate", + "alipayRootCert": "Alipay Root Certificate", + "alipayRootCertRequired": "Please upload Alipay root certificate", + "uploadRootCert": "Upload Alipay root certificate", "dyAppId": "Mini Program AppId", "dyAppIdPlaceholder": "Enter Douyin Mini Program AppId", "dyAppSecret": "Mini Program AppSecret", diff --git a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/config/mobileApp.json b/apps/daxpay-admin/src/locales/langs/zh-CN/system/mobileApp.json similarity index 76% rename from apps/daxpay-admin/src/locales/langs/zh-CN/payment/config/mobileApp.json rename to apps/daxpay-admin/src/locales/langs/zh-CN/system/mobileApp.json index 688b0b688..09f65ec31 100644 --- a/apps/daxpay-admin/src/locales/langs/zh-CN/payment/config/mobileApp.json +++ b/apps/daxpay-admin/src/locales/langs/zh-CN/system/mobileApp.json @@ -39,12 +39,25 @@ "originalIdPlaceholder": "请输入小程序原始 ID(gh_ 开头, 可选)", "alipayAppId": "小程序 AppId", "alipayAppIdPlaceholder": "请输入支付宝小程序 AppId", + "authType": "鉴权方式", + "authTypeKey": "公钥模式", + "authTypeCert": "证书模式", + "authTypeRequired": "请选择鉴权方式", "privateKey": "应用私钥", - "privateKeyPlaceholder": "请输入应用私钥", + "privateKeyPlaceholder": "请输入应用私钥(PEM 格式, 公钥与证书模式都需要)", "privateKeyRequired": "请输入应用私钥", "alipayPublicKey": "支付宝公钥", - "alipayPublicKeyPlaceholder": "请输入支付宝公钥", + "alipayPublicKeyPlaceholder": "请输入支付宝公钥(公钥模式使用)", "alipayPublicKeyRequired": "请输入支付宝公钥", + "appCert": "应用公钥证书", + "appCertRequired": "请上传应用公钥证书", + "uploadAppCert": "上传应用公钥证书", + "alipayCert": "支付宝公钥证书", + "alipayCertRequired": "请上传支付宝公钥证书", + "uploadAlipayCert": "上传支付宝公钥证书", + "alipayRootCert": "支付宝根证书", + "alipayRootCertRequired": "请上传支付宝根证书", + "uploadRootCert": "上传支付宝根证书", "dyAppId": "小程序 AppId", "dyAppIdPlaceholder": "请输入抖音小程序 AppId", "dyAppSecret": "小程序 AppSecret", diff --git a/apps/daxpay-admin/src/views/payment/config/mobileApp/MobileAppConfig.vue b/apps/daxpay-admin/src/views/system/config/mobileApp/MobileAppConfig.vue similarity index 91% rename from apps/daxpay-admin/src/views/payment/config/mobileApp/MobileAppConfig.vue rename to apps/daxpay-admin/src/views/system/config/mobileApp/MobileAppConfig.vue index cfcf95cd1..b89eb8467 100644 --- a/apps/daxpay-admin/src/views/payment/config/mobileApp/MobileAppConfig.vue +++ b/apps/daxpay-admin/src/views/system/config/mobileApp/MobileAppConfig.vue @@ -37,7 +37,7 @@ */ function handleEnter(appType: string, disabled: boolean) { if (disabled) return; - router.push({ path: `/payment/config/mobile-app/detail/${appType}` }); + router.push({ path: `/system/config/mobile-app/detail/${appType}` }); } /** @@ -60,7 +60,7 @@ @@ -77,7 +77,7 @@ >
- {{ $t('payment.config.mobileApp.card.comingSoon') }} + {{ $t('system.mobileApp.card.comingSoon') }}
@@ -90,15 +90,15 @@
- {{ $t(`payment.config.mobileApp.card.${card.appType}.name`) }} + {{ $t(`system.mobileApp.card.${card.appType}.name`) }}
- {{ $t(`payment.config.mobileApp.card.${card.appType}.desc`) }} + {{ $t(`system.mobileApp.card.${card.appType}.desc`) }}
- {{ $t('payment.config.mobileApp.card.enter') }} + {{ $t('system.mobileApp.card.enter') }}
diff --git a/apps/daxpay-admin/src/views/payment/config/mobileApp/detail/MobileAppDetail.vue b/apps/daxpay-admin/src/views/system/config/mobileApp/detail/MobileAppDetail.vue similarity index 53% rename from apps/daxpay-admin/src/views/payment/config/mobileApp/detail/MobileAppDetail.vue rename to apps/daxpay-admin/src/views/system/config/mobileApp/detail/MobileAppDetail.vue index 7f08b2845..1160bf863 100644 --- a/apps/daxpay-admin/src/views/payment/config/mobileApp/detail/MobileAppDetail.vue +++ b/apps/daxpay-admin/src/views/system/config/mobileApp/detail/MobileAppDetail.vue @@ -9,19 +9,30 @@ import { type MobileAppParam, MobileAppApi, - } from '#/api/payment/config/mobile-app.api'; + } from '#/api/system/mobile-app.api'; import { useFormEdit } from '#/hooks/useFormEdit'; import { useMessage } from '#/hooks/useMessage'; + import { readFileAsText } from '#/utils/file'; defineOptions({ name: 'MobileAppDetail' }); + // 鉴权方式: public_key(公钥模式) / cert(证书模式), 与 AlipayAuthTypeEnum 一致 + const AUTH_TYPE_KEY = 'public_key'; + const AUTH_TYPE_CERT = 'cert'; + /** 结构化配置字段(各平台共用, 按平台取用) */ interface StructuredConfig { appId: string; appSecret: string; originalId: string; + // 支付宝小程序: 鉴权方式 + authType: string; privateKey: string; alipayPublicKey: string; + // 证书模式三本证书 + appCert: string; + alipayCert: string; + alipayRootCert: string; } /** 已支持结构化表单的平台 */ @@ -83,9 +94,9 @@ // 端标题 const appTitle = computed(() => { if (appType.value) { - return $t(`payment.config.mobileApp.card.${appType.value}.name`); + return $t(`system.mobileApp.card.${appType.value}.name`); } - return $t('payment.config.mobileApp.detail.notSupportedAppType'); + return $t('system.mobileApp.detail.notSupportedAppType'); }); /** @@ -127,8 +138,13 @@ appId: '', appSecret: '', originalId: '', + // 默认公钥模式 + authType: AUTH_TYPE_KEY, privateKey: '', alipayPublicKey: '', + appCert: '', + alipayCert: '', + alipayRootCert: '', }; } @@ -143,8 +159,14 @@ result.appId = cfg.appId || ''; result.appSecret = cfg.appSecret || ''; result.originalId = cfg.originalId || ''; + // 鉴权方式: public_key / cert + result.authType = + cfg.authType === AUTH_TYPE_CERT ? AUTH_TYPE_CERT : AUTH_TYPE_KEY; result.privateKey = cfg.privateKey || ''; result.alipayPublicKey = cfg.alipayPublicKey || ''; + result.appCert = cfg.appCert || ''; + result.alipayCert = cfg.alipayCert || ''; + result.alipayRootCert = cfg.alipayRootCert || ''; } } catch { // 非合法 JSON 时保持空 @@ -152,6 +174,13 @@ return result; } + /** + * 是否证书模式 + */ + function isCertMode(structured: StructuredConfig): boolean { + return structured.authType === AUTH_TYPE_CERT; + } + /** * 按平台序列化 appConfig, 敏感字段仅在 diffForm 有新值时写入 */ @@ -169,12 +198,23 @@ obj.appSecret = sensitive.appSecret; } } else if (platform === 'alipay_mini') { + // 始终写入鉴权方式 + obj.authType = structured.authType || AUTH_TYPE_KEY; if (sensitive.privateKey !== undefined) { obj.privateKey = sensitive.privateKey; } if (sensitive.alipayPublicKey !== undefined) { obj.alipayPublicKey = sensitive.alipayPublicKey; } + if (sensitive.appCert !== undefined) { + obj.appCert = sensitive.appCert; + } + if (sensitive.alipayCert !== undefined) { + obj.alipayCert = sensitive.alipayCert; + } + if (sensitive.alipayRootCert !== undefined) { + obj.alipayRootCert = sensitive.alipayRootCert; + } } else if (platform === 'dy_mini') { if (sensitive.appSecret !== undefined) { obj.appSecret = sensitive.appSecret; @@ -192,27 +232,52 @@ original: StructuredConfig, ): boolean { if (!structured.appId?.trim()) { - message.warning($t('payment.config.mobileApp.fields.appIdRequired')); + message.warning($t('system.mobileApp.fields.appIdRequired')); return false; } if (platform === 'wx_mini' || platform === 'dy_mini') { if (!original.appSecret && !structured.appSecret?.trim()) { message.warning( - $t('payment.config.mobileApp.fields.appSecretRequired'), + $t('system.mobileApp.fields.appSecretRequired'), ); return false; } } if (platform === 'alipay_mini') { + if (!structured.authType?.trim()) { + message.warning($t('system.mobileApp.fields.authTypeRequired')); + return false; + } + // 应用私钥两种模式都需要; 已有脱敏原值则可不重填 if (!original.privateKey && !structured.privateKey?.trim()) { message.warning( - $t('payment.config.mobileApp.fields.privateKeyRequired'), + $t('system.mobileApp.fields.privateKeyRequired'), ); return false; } - if (!original.alipayPublicKey && !structured.alipayPublicKey?.trim()) { + if (isCertMode(structured)) { + // 证书模式: 三本证书必填 + if (!original.appCert && !structured.appCert?.trim()) { + message.warning($t('system.mobileApp.fields.appCertRequired')); + return false; + } + if (!original.alipayCert && !structured.alipayCert?.trim()) { + message.warning($t('system.mobileApp.fields.alipayCertRequired')); + return false; + } + if (!original.alipayRootCert && !structured.alipayRootCert?.trim()) { + message.warning( + $t('system.mobileApp.fields.alipayRootCertRequired'), + ); + return false; + } + } else if ( + !original.alipayPublicKey && + !structured.alipayPublicKey?.trim() + ) { + // 公钥模式: 支付宝公钥必填 message.warning( - $t('payment.config.mobileApp.fields.alipayPublicKeyRequired'), + $t('system.mobileApp.fields.alipayPublicKeyRequired'), ); return false; } @@ -220,6 +285,43 @@ return true; } + /** + * 上传证书文件, 读取文本内容写入对应字段 + */ + function handleCertUpload( + platform: string, + fieldName: 'appCert' | 'alipayCert' | 'alipayRootCert', + info: { file: File }, + ) { + const file = info.file; + if (!file) { + return; + } + const structured = structuredMap[platform]; + if (!structured) { + return; + } + readFileAsText(file).then((content) => { + structured[fieldName] = content; + message.success( + $t('components.upload.uploadSuccess', { name: file.name }), + ); + }); + } + + /** + * 截断证书内容用于 tooltip 预览 + */ + function truncateContent(content: string, maxLength = 500): string { + if (!content) { + return ''; + } + if (content.length <= maxLength) { + return content; + } + return `${content.slice(0, Math.max(0, maxLength))}...`; + } + /** * 加载该端所有平台配置 */ @@ -300,7 +402,13 @@ // 按平台敏感字段做 diffForm const sensitiveKeys = platform === 'alipay_mini' - ? (['privateKey', 'alipayPublicKey'] as const) + ? ([ + 'privateKey', + 'alipayPublicKey', + 'appCert', + 'alipayCert', + 'alipayRootCert', + ] as const) : (['appSecret'] as const); const sensitive = diffForm( originalStructured, @@ -322,7 +430,7 @@ saving.value = true; try { await MobileAppApi.save(submit); - message.success($t('payment.config.mobileApp.detail.saveSuccess')); + message.success($t('system.mobileApp.detail.saveSuccess')); isEditing.value = false; await loadData(true); } finally { @@ -336,7 +444,7 @@ * 返回卡片页 */ function handleBack() { - router.push({ path: '/payment/config/mobile-app' }); + router.push({ path: '/system/config/mobile-app' }); } // 切 Tab 时退出编辑并重载, 避免脏数据串平台 @@ -407,7 +515,7 @@ @@ -424,7 +532,7 @@ @@ -442,19 +550,19 @@ - +