From e30d9493ff00f15786b447cf6a71c7cb0292c16b Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Sun, 26 Oct 2025 23:24:46 -0300 Subject: [PATCH 1/2] feat: enhance donation creation logging and adjust amount limits - Add detailed secure logging throughout the donation creation API route for production debugging, including request receipt, validation results, amount calculations, PIX creation success, and error handling - Update custom donation amount schema to allow minimum 0.01 and maximum 100,000 for broader donation flexibility - Modify secure logger to always output data in production for improved monitoring and troubleshooting --- app/api/donations/create/route.ts | 48 +++++++++++++++++++++++++++++-- lib/secure-logger.ts | 10 ++++--- lib/validation-schemas.ts | 8 +++--- types/donation.ts | 4 +-- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/app/api/donations/create/route.ts b/app/api/donations/create/route.ts index 3f74fad..9ad5208 100644 --- a/app/api/donations/create/route.ts +++ b/app/api/donations/create/route.ts @@ -21,6 +21,13 @@ export async function POST(request: NextRequest) { const body = await request.json(); + // Log detalhado para debug em produção + secureLogger.info("📥 POST /api/donations/create - Recebido", { + ip, + body: JSON.stringify(body), + timestamp: new Date().toISOString(), + }); + // Validação com Zod const validationResult = createDonationSchema.safeParse(body); @@ -30,6 +37,12 @@ export async function POST(request: NextRequest) { message: err.message, })); + secureLogger.error("❌ Validação falhou", { + body: JSON.stringify(body), + errors: JSON.stringify(errors), + timestamp: new Date().toISOString(), + }); + return NextResponse.json( { success: false, @@ -42,6 +55,13 @@ export async function POST(request: NextRequest) { const validatedData = validationResult.data; + secureLogger.info("✅ Validação passou", { + tier: validatedData.tier, + anonymous: validatedData.anonymous, + customAmount: validatedData.customAmount, + timestamp: new Date().toISOString(), + }); + const product = DONATION_PRODUCTS[validatedData.tier as keyof typeof DONATION_PRODUCTS]; @@ -55,9 +75,21 @@ export async function POST(request: NextRequest) { finalDescription = `Doação Personalizada - R$ ${validatedData.customAmount!.toFixed( 2 )}`; + + secureLogger.info("💰 Valor customizado calculado", { + valor_original: validatedData.customAmount, + valor_centavos: finalAmount, + description: finalDescription, + }); } else { finalAmount = product.price; finalDescription = product.name; + + secureLogger.info("💰 Valor fixo", { + tier: validatedData.tier, + amount: product.amount, + price_centavos: finalAmount, + }); } let pixData; @@ -103,15 +135,27 @@ export async function POST(request: NextRequest) { }); } - return NextResponse.json({ + const response = { success: true, pixId: pixData.id, brCode: pixData.brCode, brCodeBase64: pixData.brCodeBase64, expiresAt: pixData.expiresAt, + }; + + secureLogger.info("✅ PIX criado com sucesso", { + pixId: pixData.id, + expiresAt: pixData.expiresAt, }); + + return NextResponse.json(response); } catch (error) { - secureLogger.error("Donation creation error", error); + secureLogger.error("❌ Erro ao criar doação", { + error: error instanceof Error ? error.message : "Erro desconhecido", + stack: error instanceof Error ? error.stack : undefined, + timestamp: new Date().toISOString(), + }); + return NextResponse.json( { success: false, diff --git a/lib/secure-logger.ts b/lib/secure-logger.ts index 0ed0757..890757d 100644 --- a/lib/secure-logger.ts +++ b/lib/secure-logger.ts @@ -155,9 +155,10 @@ function maskSensitiveData(obj: any, options: MaskOptions = {}): any { export const secureLogger = { /** * Log info com mascaramento automático + * SEMPRE exibe em produção para debug */ info(message: string, data?: any) { - if (isProduction && data) { + if (data) { const masked = maskSensitiveData(data, { maskEmail: true, maskDocument: true, @@ -165,15 +166,16 @@ export const secureLogger = { }); console.log(`ℹ️ ${message}`, JSON.stringify(masked, null, 2)); } else { - console.log(`ℹ️ ${message}`, data ? JSON.stringify(data, null, 2) : ""); + console.log(`ℹ️ ${message}`, ""); } }, /** * Log debug com mascaramento automático + * SEMPRE exibe em produção para debug */ debug(message: string, data?: any) { - if (isProduction && data) { + if (data) { const masked = maskSensitiveData(data, { maskEmail: true, maskDocument: true, @@ -181,7 +183,7 @@ export const secureLogger = { }); console.debug(`🔍 ${message}`, JSON.stringify(masked, null, 2)); } else { - console.debug(`🔍 ${message}`, data ? JSON.stringify(data, null, 2) : ""); + console.debug(`🔍 ${message}`, ""); } }, diff --git a/lib/validation-schemas.ts b/lib/validation-schemas.ts index 5792821..2925951 100644 --- a/lib/validation-schemas.ts +++ b/lib/validation-schemas.ts @@ -75,8 +75,8 @@ export const donationTierSchema = z.enum( // Schema para valor customizado export const customAmountSchema = z .number() - .min(5, "Valor mínimo é R$ 5,00") - .max(500, "Valor máximo é R$ 500,00"); + .min(0.01, "Valor mínimo é R$ 0,01") + .max(100000, "Valor máximo é R$ 100.000,00"); // Schema completo para criação de doação export const createDonationSchema = z @@ -116,12 +116,12 @@ export const createDonationSchema = z (data) => { // Se tier for custom, customAmount deve estar no range válido if (data.tier === "custom" && data.customAmount) { - return data.customAmount >= 5 && data.customAmount <= 500; + return data.customAmount >= 0.01 && data.customAmount <= 100000; } return true; }, { - message: "Valor deve estar entre R$ 5,00 e R$ 500,00", + message: "Valor deve estar entre R$ 0,01 e R$ 100.000,00", path: ["customAmount"], } ); diff --git a/types/donation.ts b/types/donation.ts index fcd4aa4..3f739da 100644 --- a/types/donation.ts +++ b/types/donation.ts @@ -39,8 +39,8 @@ export const DONATION_PRODUCTS = { name: "Valor Personalizado", amount: 0, price: 0, - minAmount: 1, // R$ 1,00 - maxAmount: 10000, // R$ 10.000,00 + minAmount: 0.01, // R$ 0,01 + maxAmount: 100000, // R$ 100.000,00 }, } as const; From 8b5817e8ca89284bc906a1a7f973678c692171ec Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Sun, 26 Oct 2025 23:31:06 -0300 Subject: [PATCH 2/2] feat(donation): increase minimum custom donation amount to R$ 5.00 - Updated customAmountSchema min value from 0.01 to 5 - Adjusted validation logic and error messages to reflect new minimum - Modified DONATION_PRODUCTS minAmount for custom tier to 5 - Ensures donations meet the new minimum threshold for processing --- lib/validation-schemas.ts | 6 +++--- types/donation.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/validation-schemas.ts b/lib/validation-schemas.ts index 2925951..025c689 100644 --- a/lib/validation-schemas.ts +++ b/lib/validation-schemas.ts @@ -75,7 +75,7 @@ export const donationTierSchema = z.enum( // Schema para valor customizado export const customAmountSchema = z .number() - .min(0.01, "Valor mínimo é R$ 0,01") + .min(5, "Valor mínimo é R$ 5,00") .max(100000, "Valor máximo é R$ 100.000,00"); // Schema completo para criação de doação @@ -116,12 +116,12 @@ export const createDonationSchema = z (data) => { // Se tier for custom, customAmount deve estar no range válido if (data.tier === "custom" && data.customAmount) { - return data.customAmount >= 0.01 && data.customAmount <= 100000; + return data.customAmount >= 5 && data.customAmount <= 100000; } return true; }, { - message: "Valor deve estar entre R$ 0,01 e R$ 100.000,00", + message: "Valor deve estar entre R$ 5,00 e R$ 100.000,00", path: ["customAmount"], } ); diff --git a/types/donation.ts b/types/donation.ts index 3f739da..36c1db3 100644 --- a/types/donation.ts +++ b/types/donation.ts @@ -39,7 +39,7 @@ export const DONATION_PRODUCTS = { name: "Valor Personalizado", amount: 0, price: 0, - minAmount: 0.01, // R$ 0,01 + minAmount: 5, // R$ 5,00 maxAmount: 100000, // R$ 100.000,00 }, } as const;