Webhook do Mercado Pago no Next.js 16: o guia que a doc nao tem
No post anterior eu mostrei como criar pagamento Pix com Mercado Pago no Next.js. Mas criar pagamento e so metade do trabalho. A outra metade? Saber quando o cliente pagou.
E ai que entram os webhooks. A doc do Mercado Pago cobre webhooks genericamente, mas nao mostra como implementar num Next.js 16 com App Router. Esse guia preenche essa lacuna.
O que vamos construir
- Route Handler que recebe notificacoes do Mercado Pago
- Verificacao de assinatura HMAC-SHA256 (seguranca)
- Processamento do pagamento (consulta de status)
- Idempotencia (evitar processar duplicatas)
- Setup pra desenvolvimento local com ngrok
O fluxo
Cliente paga Pix → MP processa → POST no seu webhook → Valida assinatura → Consulta status → Atualiza banco
O Mercado Pago envia um POST com o ID do pagamento. Voce precisa consultar a API pra pegar os detalhes. O payload do webhook e minimo (so o ID), entao mesmo se alguem interceptar, nao tem dados sensiveis.
Route Handler basico
// app/api/webhooks/mercadopago/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const body = await request.json();
const xSignature = request.headers.get("x-signature");
const xRequestId = request.headers.get("x-request-id");
if (\!xSignature || \!xRequestId || \!body.data?.id) {
return NextResponse.json({ received: true });
}
// Validar assinatura HMAC (codigo completo no blog)
const isValid = validateSignature(xSignature, xRequestId, body.data.id);
if (\!isValid) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (body.type === "payment") {
handlePaymentNotification(body.data.id).catch(console.error);
}
return NextResponse.json({ received: true });
}
As armadilhas que ninguem conta
Timeout de 22 segundos: O MP espera resposta rapida. Retorne 200 imediatamente e processe de forma assincrona. Se nao retornar em 22s, ele reenvia a notificacao a cada 15 minutos.
Retornar 200 mesmo com erro: Se a notificacao e valida mas seu processamento falhou, retorne 200 e trate o erro depois. Caso contrario recebe a mesma notificacao dezenas de vezes.
Idempotencia: O MP pode enviar a mesma notificacao mais de uma vez. Guarde o ID no banco e verifique antes de processar. Sem isso voce vai liberar acesso duplicado, enviar email duplicado, etc.
Comparacao de hash: Muita gente usa === pra comparar hashes. Funciona, mas e vulneravel a timing attacks. Use crypto.timingSafeEqual sempre.
Ambiente teste vs producao: URLs separadas. Se configurou URL de teste com credenciais de producao (ou vice-versa), as notificacoes nao chegam.
Post completo
O tutorial completo com validacao HMAC-SHA256, processamento de todos os status (approved, rejected, cancelled, refunded), idempotencia com banco de dados, e checklist de producao esta no blog: blog.zilvo.com.br/posts/webhook-mercado-pago-nextjs-16
Esse post faz parte de uma serie sobre integracao de pagamentos BR no Next.js 16.