Files
pagodera/app/api/webhooks/abacatepay/route.ts
T

103 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NextRequest, NextResponse } from "next/server";
import { abacatePay } from "@/lib/abacatepay";
export async function POST(request: NextRequest) {
try {
const payload = await request.text();
const signature = request.headers.get("x-abacatepay-signature");
if (!signature || !abacatePay.verifyWebhookSignature(payload, signature)) {
return NextResponse.json(
{ error: "Assinatura inválida" },
{ status: 401 }
);
}
const event = JSON.parse(payload);
console.log("🔔 Webhook recebido:", JSON.stringify(event, null, 2));
// Verificar se é evento de pagamento confirmado
const isPaidEvent =
event.event === "billing.paid" ||
event.event === "pix.paid" ||
event.data?.pixQrCode?.status === "PAID";
if (isPaidEvent) {
// Extrair dados do PIX
const pixQrCode = event.data.pixQrCode;
const payment = event.data.payment;
if (!pixQrCode || pixQrCode.status !== "PAID") {
console.log("⚠️ Webhook recebido mas status não é PAID");
return NextResponse.json({ success: true });
}
console.log("✅ Doação confirmada via webhook:", pixQrCode.id);
// Detectar se é doação anônima ou identificada
const isAnonymous = !pixQrCode.customer;
// Log estruturado para futura persistência em banco de dados
const donationRecord: any = {
type: "donation_paid",
pixId: pixQrCode.id,
amount: pixQrCode.amount,
fee: payment?.fee,
method: payment?.method,
anonymous: isAnonymous,
paidAt: new Date().toISOString(),
createdAt: new Date().toISOString(),
devMode: event.devMode || false,
};
// Adicionar dados do customer se disponível (doação identificada)
if (!isAnonymous && pixQrCode.customer?.metadata) {
donationRecord.customer = {
id: pixQrCode.customer.id,
name: pixQrCode.customer.metadata.name,
email: pixQrCode.customer.metadata.email,
cellphone: pixQrCode.customer.metadata.cellphone,
taxId: pixQrCode.customer.metadata.taxId,
};
console.log(
"📧 Email disponível para agradecimento:",
pixQrCode.customer.metadata.email
);
}
console.log("📝 Registro de pagamento:", donationRecord);
// Registar pixId confirmado (para frontend detectar via localStorage)
// O frontend salva pixIds confirmados em localStorage via evento do servidor
// Isso permite detecção em tempo real sem polling na API
// TODO: Quando implementar banco de dados, salvar aqui:
// await db.donations.create(donationRecord);
// TODO: Quando implementar email, enviar aqui:
// if (!isAnonymous && donationRecord.customer?.email) {
// await sendThankYouEmail({
// to: donationRecord.customer.email,
// donorName: donationRecord.customer.name,
// amount: donationRecord.amount,
// });
// }
// TODO: Atualizar estatísticas
// await updateDonationStats(donationRecord.amount);
} else {
console.log("ℹ️ Evento de webhook (não é pagamento):", event.event);
}
return NextResponse.json({ success: true });
} catch (error) {
console.error("Webhook error:", error);
return NextResponse.json(
{ error: "Erro ao processar webhook" },
{ status: 500 }
);
}
}