"use server"; import { prisma } from "@/lib/prisma"; import { requireAdmin } from "@/lib/require-auth"; import { revalidatePath } from "next/cache"; import { decryptPaymentConfigForUse, getPaymentProviderName, normalizePaymentConfig, parsePaymentConfig, preparePaymentConfigForStorage, } from "@/services/payment/catalog"; import { actorFromSession, recordAuditLog } from "@/services/audit"; import { getErrorMessage } from "@/lib/errors"; import { z } from "zod"; type PaymentActionResult = { ok: true } | { ok: false; error: string }; function formatPaymentConfigError(error: unknown, fallback: string) { if (error instanceof z.ZodError) { const details = error.issues.map((issue) => issue.message).filter(Boolean).join(";"); return details || getErrorMessage(error, fallback); } return getErrorMessage(error, fallback); } export async function savePaymentConfig( provider: string, config: Record, enabled: boolean ) { const session = await requireAdmin(); const normalizedConfig = normalizePaymentConfig(config); const current = await prisma.paymentConfig.findUnique({ where: { provider }, select: { config: true }, }); const storageConfig = preparePaymentConfigForStorage( provider, normalizedConfig, current?.config as Record | undefined, ); if (enabled) { try { parsePaymentConfig(provider, decryptPaymentConfigForUse(provider, storageConfig)); } catch (error) { if (error instanceof z.ZodError) { const messages = error.issues.map((e) => e.message).join(";"); throw new Error(messages); } throw error; } } const jsonConfig = JSON.parse(JSON.stringify(storageConfig)); await prisma.paymentConfig.upsert({ where: { provider }, create: { provider, config: jsonConfig, enabled }, update: { config: jsonConfig, enabled }, }); await recordAuditLog({ actor: actorFromSession(session), action: "payment.config", targetType: "PaymentConfig", targetId: provider, targetLabel: getPaymentProviderName(provider), message: `${enabled ? "启用并更新" : "更新"}支付配置 ${getPaymentProviderName(provider)}`, }); revalidatePath("/admin/payments"); } export async function setPaymentConfigEnabled( provider: string, enabled: boolean, ): Promise { try { const session = await requireAdmin(); if (provider === "balance") { const current = await prisma.paymentConfig.findUnique({ where: { provider }, select: { enabled: true, config: true }, }); if (current?.enabled !== enabled) { await prisma.paymentConfig.upsert({ where: { provider }, create: { provider, enabled, config: current?.config ?? {} }, update: { enabled }, }); await recordAuditLog({ actor: actorFromSession(session), action: "payment.toggle", targetType: "PaymentConfig", targetId: provider, targetLabel: getPaymentProviderName(provider), message: `${enabled ? "启用" : "停用"}支付方式 ${getPaymentProviderName(provider)}`, }); } revalidatePath("/admin/payments"); return { ok: true }; } const current = await prisma.paymentConfig.findUnique({ where: { provider }, select: { config: true, enabled: true }, }); if (!current) { if (!enabled) return { ok: true }; throw new Error("请先编辑并保存完整支付配置,再启用该支付方式"); } if (enabled) { try { parsePaymentConfig( provider, decryptPaymentConfigForUse(provider, current.config as Record), ); } catch (error) { if (error instanceof z.ZodError) { throw new Error("请先编辑并保存完整支付配置,再启用该支付方式"); } throw error; } } if (current.enabled !== enabled) { await prisma.paymentConfig.update({ where: { provider }, data: { enabled }, }); await recordAuditLog({ actor: actorFromSession(session), action: "payment.toggle", targetType: "PaymentConfig", targetId: provider, targetLabel: getPaymentProviderName(provider), message: `${enabled ? "启用" : "停用"}支付方式 ${getPaymentProviderName(provider)}`, }); } revalidatePath("/admin/payments"); return { ok: true }; } catch (error) { return { ok: false, error: formatPaymentConfigError(error, "更新支付开关失败") }; } }