1. Crie um endpoint
curl -X POST https://api.pagozz.com/v1/webhooks \
-H "Content-Type: application/json" \
-H "Pagozz-Token: pgz_test_XXXXXXXXXXXXXXXXXXXXXXXX" \
-d '{
"url": "https://meusite.com/webhooks/pagozz",
"events": ["payment.succeeded", "payment.failed", "payment.expired"]
}'
O secret só é retornado na criação do endpoint. Guarde-o em um local seguro (variável de ambiente).
2. Implemente o handler
import { NextRequest, NextResponse } from 'next/server';
import { constructWebhookEvent } from '@pagozz/sdk';
const WEBHOOK_SECRET = process.env.PAGOZZ_WEBHOOK_SECRET!;
export async function POST(req: NextRequest) {
const body = await req.text();
const signature = req.headers.get('x-pagozz-signature')!;
const timestamp = Number(req.headers.get('x-pagozz-timestamp'));
// Verificar assinatura
let event;
try {
event = constructWebhookEvent(WEBHOOK_SECRET, signature, timestamp, body);
} catch {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
// Processar evento
switch (event.type) {
case 'payment.succeeded':
// Liberar acesso, enviar email, etc.
await handlePaymentSucceeded(event.data);
break;
case 'payment.failed':
await handlePaymentFailed(event.data);
break;
case 'payment.expired':
await handlePaymentExpired(event.data);
break;
}
return NextResponse.json({ received: true });
}
3. Verifique manualmente (sem SDK)
Se não usar o SDK, implemente a verificação:
import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhook(secret, signature, timestamp, body) {
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > 300) return false;
const signedContent = `${timestamp}.${body}`;
const expected = createHmac('sha256', secret)
.update(signedContent)
.digest('hex');
return timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex')
);
}
4. Teste o webhook
Envie um evento de teste para verificar seu endpoint:
curl -X POST https://api.pagozz.com/v1/webhooks/{endpoint_id}/test \
-H "Pagozz-Token: pgz_test_XXXXXXXXXXXXXXXXXXXXXXXX"
Boas práticas
Use o campo id do payload como chave de idempotência. Armazene os IDs processados e ignore duplicatas.
Retorne 200 imediatamente e processe o evento em background (fila, worker, etc.). O timeout do Pagozz é 10 segundos.
Se seu endpoint falhar, o Pagozz retenta até 8 vezes com backoff exponencial (até ~3.4 dias). Não se preocupe com falhas temporárias.
Crie endpoints separados para test e live. Eventos de test só são enviados para endpoints test e vice-versa.