mirror of
https://github.com/JetSprow/J-Board-Lite.git
synced 2026-05-01 01:14:10 +05:30
151 lines
4.5 KiB
TypeScript
151 lines
4.5 KiB
TypeScript
"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<string, string>,
|
||
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<string, unknown> | 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<PaymentActionResult> {
|
||
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<string, unknown>),
|
||
);
|
||
} 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, "更新支付开关失败") };
|
||
}
|
||
}
|