Pagos · modules/billing

Adapter listo para producción

MercadoPago,
cableado como corresponde.

La mayoría de los starters de SaaS en Next.js son Stripe-first. Cuando necesitás cobrar en pesos o reales, pegar MercadoPago a Next.js a mano es donde viven los bugs clásicos — webhooks sin verificar, handlers no idempotentes y un sandbox que te pelea. UseDeploy trae el adapter para que heredes la plomería, no el dolor.

El dolor que ya nos comimos

Integrar MercadoPago tiene mala fama, y los foros de developers se la ganan: "de longe essa é a mais complexa e difícil de testar." El webhook asíncrono es donde muerde — la verdad sobre un pago llega después del redirect, en una request firmada aparte que tenés que verificar y reconciliar contra tu propia base de datos. El adapter de UseDeploy es una implementación real y funcional de ese flujo: preferencias de Checkout Pro para el redirect, un chequeo HMAC en tiempo constante en cada notificación entrante, y un fetch del estado del pago que mapea el resultado al mismo BillingEvent normalizado que emite cualquier otro proveedor. Vos cableás tu access token; el riel ya está construido.

Webhooks firmados, verificados antes de confiar en ellos

Cada notificación de MercadoPago se verifica contra el manifest x-signature / x-request-id con HMAC-SHA256 y una comparación en tiempo constante antes de traer el pago y mapearlo a un BillingEvent. Una llamada sin firma o manipulada se rechaza con un 400 — las clases de doble cobro y webhook falsificado quedan cerradas por defecto.

mercado-pago-payment-provider.ts
 1  const manifest = `id:${dataId};request-id:${xRequestId};ts:${ts};`;
 2  const expected = crypto
 3    .createHmac('sha256', this.cfg.webhookSecret)
 4    .update(manifest)
 5    .digest('hex');
 6  
 7  // constant-time comparison — never a naive === on the digest
 8  return crypto.timingSafeEqual(hashBuf, expectedBuf);

Lo que el adapter hace hoy

Redirect de Checkout Pro

createCheckoutSession hace un POST a la API /checkout/preferences y devuelve la URL init_point. El modo de pago único está activo; currency_id cubre ARS, BRL, MXN, USD y EUR.

Webhooks asíncronos firmados

parseWebhook verifica la firma HMAC, trae /v1/payments/:id, y emite invoice.paid o invoice.payment_failed al event bus de billing.

Un solo contrato tipado

MercadoPago implementa el mismo port IPaymentProvider que Stripe y Polar — cambiar de proveedor es un cambio de un solo archivo en el composition root.

Event bus durable

Los eventos de billing fluyen por el outbox durable, así un webhook que llega dos veces o fuera de orden se reconcilia contra tu DB en vez de aplicarse dos veces.

Catálogo de planes desde Prisma

listPlans lee la tabla BillingPlan, así tu pricing vive en tu base de datos — no hardcodeado por proveedor.

Docs de producto trilingües

El sitio Fumadocs trae páginas reales EN / ES / PT (convención dot-parser, EN canónico), no solo ruteo de locale sobre copy en inglés.

Respuestas directas

¿Soporta suscripciones recurrentes (preapproval)?+
Todavía no. A julio de 2026, el adapter de MercadoPago implementa pagos únicos de Checkout Pro; el modo suscripción devuelve un error explícito de "aún no soportado" en vez de cobrar mal en silencio. El contrato tipado ya modela suscripciones, así que preapproval es un agregado a nivel de adapter — Stripe y Polar cubren el billing recurrente hoy.
¿Cómo pruebo sin tocar producción?+
Apuntás MERCADO_PAGO_ACCESS_TOKEN a tus credenciales de sandbox. Como la selección de proveedor es una única factory manejada por env, cambiar entre sandbox y live es un cambio de config, no de código.
¿Puedo correr MercadoPago y Stripe al mismo tiempo?+
El boilerplate selecciona un PAYMENT_PROVIDER activo por deployment. Los tres adapters vienen en el árbol detrás de la misma interfaz, así que elegís por entorno (por ejemplo MercadoPago para tu tenant de LATAM, Stripe o Polar para global).

Referencia de configuración

Variables de entorno

  • PAYMENT_PROVIDERrequerida

    Set to mercado-pago

  • MERCADO_PAGO_ACCESS_TOKENrequerida
  • MERCADO_PAGO_WEBHOOK_SECRETrequerida

    HMAC secret for x-signature verification

Dónde vive

  • apps/server/src/modules/billing/infrastructure/providers/mercado-pago-payment-provider.ts
  • apps/server/src/modules/billing/infrastructure/providers/index.ts

Dejá de pegar MercadoPago a Next.js a mano.

Arrancá sobre una base donde el checkout, los webhooks firmados y el contrato de billing ya están cableados — y localizados en EN, ES y PT.