From 33e4a811f3f1f0771a1b3e3dde843cfbd949a0a4 Mon Sep 17 00:00:00 2001 From: erio Date: Sun, 15 Mar 2026 02:56:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8F=90=E5=8F=96=20resolveEnabledPayme?= =?UTF-8?q?ntTypes=20=E5=85=B1=E4=BA=AB=E5=87=BD=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E4=B8=8B=E5=8D=95=E6=8E=A5=E5=8F=A3=E5=90=8C=E6=AD=A5=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=20+=20=E6=81=A2=E5=A4=8D=E5=B9=B6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 resolveEnabledPaymentTypes 提取到 src/lib/payment/resolve-enabled-types.ts - /api/orders 下单时也校验 ENABLED_PAYMENT_TYPES 配置,防止绕过前端直接调用 - /api/user 恢复 queryMethodLimits 与 getUser 并发执行,避免性能退化 --- src/app/api/orders/route.ts | 6 +++-- src/app/api/user/route.ts | 31 ++++++++++-------------- src/lib/payment/resolve-enabled-types.ts | 30 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 src/lib/payment/resolve-enabled-types.ts diff --git a/src/app/api/orders/route.ts b/src/app/api/orders/route.ts index 0e2593d..e97fd14 100644 --- a/src/app/api/orders/route.ts +++ b/src/app/api/orders/route.ts @@ -3,6 +3,7 @@ import { z } from 'zod'; import { createOrder } from '@/lib/order/service'; import { getEnv } from '@/lib/config'; import { paymentRegistry } from '@/lib/payment'; +import { getEnabledPaymentTypes } from '@/lib/payment/resolve-enabled-types'; import { getCurrentUserByToken } from '@/lib/sub2api/client'; import { handleApiError } from '@/lib/utils/api'; @@ -59,8 +60,9 @@ export async function POST(request: NextRequest) { } } - // Validate payment type is enabled - if (!paymentRegistry.getSupportedTypes().includes(payment_type)) { + // Validate payment type is enabled (registry + ENABLED_PAYMENT_TYPES config) + const enabledTypes = await getEnabledPaymentTypes(); + if (!enabledTypes.includes(payment_type)) { return NextResponse.json({ error: `不支持的支付方式: ${payment_type}` }, { status: 400 }); } diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index 36bf7f8..7157842 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -6,20 +6,8 @@ import { initPaymentProviders, paymentRegistry } from '@/lib/payment'; import { getPaymentDisplayInfo } from '@/lib/pay-utils'; import { resolveLocale } from '@/lib/locale'; import { getSystemConfig } from '@/lib/system-config'; +import { resolveEnabledPaymentTypes } from '@/lib/payment/resolve-enabled-types'; -function resolveEnabledPaymentTypes(supportedTypes: string[], configuredTypes: string | undefined): string[] { - if (configuredTypes === undefined) return supportedTypes; - - const configuredTypeSet = new Set( - configuredTypes - .split(',') - .map((type) => type.trim()) - .filter(Boolean), - ); - if (configuredTypeSet.size === 0) return supportedTypes; - - return supportedTypes.filter((type) => configuredTypeSet.has(type)); -} export async function GET(request: NextRequest) { const locale = resolveLocale(request.nextUrl.searchParams.get('lang')); @@ -55,14 +43,21 @@ export async function GET(request: NextRequest) { const env = getEnv(); initPaymentProviders(); const supportedTypes = paymentRegistry.getSupportedTypes(); - const [user, configuredPaymentTypesRaw, balanceDisabledVal] = await Promise.all([ - getUser(userId), + + // getUser 与 config 查询并行;config 完成后立即启动 queryMethodLimits + const configPromise = Promise.all([ getSystemConfig('ENABLED_PAYMENT_TYPES'), getSystemConfig('BALANCE_PAYMENT_DISABLED'), + ]).then(async ([configuredPaymentTypesRaw, balanceDisabledVal]) => { + const enabledTypes = resolveEnabledPaymentTypes(supportedTypes, configuredPaymentTypesRaw); + const methodLimits = await queryMethodLimits(enabledTypes); + return { enabledTypes, methodLimits, balanceDisabled: balanceDisabledVal === 'true' }; + }); + + const [user, { enabledTypes, methodLimits, balanceDisabled }] = await Promise.all([ + getUser(userId), + configPromise, ]); - const enabledTypes = resolveEnabledPaymentTypes(supportedTypes, configuredPaymentTypesRaw); - const methodLimits = await queryMethodLimits(enabledTypes); - const balanceDisabled = balanceDisabledVal === 'true'; // 收集 sublabel 覆盖 const sublabelOverrides: Record = {}; diff --git a/src/lib/payment/resolve-enabled-types.ts b/src/lib/payment/resolve-enabled-types.ts new file mode 100644 index 0000000..451e9ca --- /dev/null +++ b/src/lib/payment/resolve-enabled-types.ts @@ -0,0 +1,30 @@ +import { getSystemConfig } from '@/lib/system-config'; +import { initPaymentProviders, paymentRegistry } from '@/lib/payment'; + +/** + * 根据 ENABLED_PAYMENT_TYPES 配置过滤支持的支付类型。 + * configuredTypes 为 undefined 或空字符串时回退到全部支持类型。 + */ +export function resolveEnabledPaymentTypes(supportedTypes: string[], configuredTypes: string | undefined): string[] { + if (configuredTypes === undefined) return supportedTypes; + + const configuredTypeSet = new Set( + configuredTypes + .split(',') + .map((type) => type.trim()) + .filter(Boolean), + ); + if (configuredTypeSet.size === 0) return supportedTypes; + + return supportedTypes.filter((type) => configuredTypeSet.has(type)); +} + +/** + * 获取当前启用的支付类型(结合 registry 支持类型 + 数据库 ENABLED_PAYMENT_TYPES 配置)。 + */ +export async function getEnabledPaymentTypes(): Promise { + initPaymentProviders(); + const supportedTypes = paymentRegistry.getSupportedTypes(); + const configuredTypes = await getSystemConfig('ENABLED_PAYMENT_TYPES'); + return resolveEnabledPaymentTypes(supportedTypes, configuredTypes); +}