import { prisma } from '../../config/database'; import type { PaymentSettings } from '@prisma/client'; import type { UpdatePaymentSettingsInput } from './payments.schemas'; import { encrypt, decrypt } from '../../utils/crypto'; import { resetStripeClient } from '../../services/stripe.client'; const ENCRYPTED_FIELDS = ['stripeSecretKey', 'stripeWebhookSecret'] as const; const SENSITIVE_FIELDS = ['stripeSecretKey', 'stripeWebhookSecret'] as const; function decryptSettings(settings: PaymentSettings): PaymentSettings { for (const field of ENCRYPTED_FIELDS) { const value = settings[field]; if (typeof value === 'string' && value) { (settings as Record)[field] = decrypt(value); } } return settings; } export const paymentSettingsService = { /** Full settings with decrypted secrets (admin use) */ async get(): Promise { let settings = await prisma.paymentSettings.findFirst(); if (!settings) { settings = await prisma.paymentSettings.create({ data: {} }); } return decryptSettings(settings); }, /** Public-safe settings (strips secret keys) */ async getPublic() { const settings = await this.get(); const result = { ...settings } as Record; for (const field of SENSITIVE_FIELDS) { delete result[field]; } return result; }, async update(data: UpdatePaymentSettingsInput): Promise { const toWrite = { ...data } as Record; // Encrypt sensitive fields for (const field of ENCRYPTED_FIELDS) { if (field in toWrite && typeof toWrite[field] === 'string' && toWrite[field]) { toWrite[field] = encrypt(toWrite[field] as string); } } // Handle donationSuggestedAmounts as JSON if (data.donationSuggestedAmounts) { toWrite.donationSuggestedAmounts = JSON.stringify(data.donationSuggestedAmounts); } const existing = await prisma.paymentSettings.findFirst(); let settings: PaymentSettings; if (existing) { settings = await prisma.paymentSettings.update({ where: { id: existing.id }, data: toWrite, }); } else { settings = await prisma.paymentSettings.create({ data: toWrite }); } // Reset Stripe client so it picks up new keys resetStripeClient(); return decryptSettings(settings); }, };