import { NextRequest, NextResponse } from "next/server"; import { abacatePay } from "@/lib/abacatepay"; import { DONATION_PRODUCTS, DonorData } from "@/types/donation"; import { createDonationSchema } from "@/lib/validation-schemas"; import { checkRateLimit, getClientIP, createRateLimitResponse, } from "@/lib/rate-limiter"; import { secureLogger } from "@/lib/secure-logger"; export async function POST(request: NextRequest) { try { // Rate limiting const ip = getClientIP(request); const rateLimit = checkRateLimit(ip, "/api/donations/create"); if (!rateLimit.allowed) { return createRateLimitResponse(rateLimit.resetAt); } const body = await request.json(); // Validação com Zod const validationResult = createDonationSchema.safeParse(body); if (!validationResult.success) { const errors = validationResult.error.issues.map((err: any) => ({ field: err.path.join("."), message: err.message, })); return NextResponse.json( { success: false, error: "Dados de entrada inválidos", details: errors, }, { status: 400 } ); } const validatedData = validationResult.data; const product = DONATION_PRODUCTS[validatedData.tier as keyof typeof DONATION_PRODUCTS]; // Calcular valor final let finalAmount: number; let finalDescription: string; if (validatedData.tier === "custom") { // Converter para centavos finalAmount = Math.round(validatedData.customAmount! * 100); finalDescription = `Doação Personalizada - R$ ${validatedData.customAmount!.toFixed( 2 )}`; } else { finalAmount = product.price; finalDescription = product.name; } let pixData; // Fluxo: Anônimo ou Identificado if (validatedData.anonymous === true) { // Doação anônima - sem customer pixData = await abacatePay.createPixQrCode({ amount: finalAmount, description: finalDescription, expiresIn: 600, }); secureLogger.info("PIX criado (anônimo)", { pixId: pixData.id, amount: finalAmount, tier: validatedData.tier, }); } else { // Doação identificada - dados já validados pelo Zod pixData = await abacatePay.createPixQrCode({ amount: finalAmount, description: finalDescription, expiresIn: 600, customer: { name: validatedData.donorName, email: validatedData.donorEmail, cellphone: validatedData.donorPhone, taxId: validatedData.donorTaxId, }, }); secureLogger.info("PIX criado (identificado)", { pixId: pixData.id, amount: finalAmount, tier: validatedData.tier, donor: { name: validatedData.donorName, email: validatedData.donorEmail, phone: validatedData.donorPhone, taxId: validatedData.donorTaxId, }, }); } return NextResponse.json({ success: true, pixId: pixData.id, brCode: pixData.brCode, brCodeBase64: pixData.brCodeBase64, expiresAt: pixData.expiresAt, }); } catch (error) { secureLogger.error("Donation creation error", error); return NextResponse.json( { success: false, error: error instanceof Error ? error.message : "Erro interno", }, { status: 500 } ); } }