@dariomvg/create
mercadopagopagospago-unicocheckout-prointegracion

Mercado Pago — Módulo de Pagos Únicos

Módulo completo para manejar pagos únicos a través de Mercado Pago (Checkout Pro) en un proyecto de Next.js App Router. Sin suscripciones ni facturación: solo checkout, consulta de pagos, cancelación, reembolsos, métodos de pago y webhooks.

Dependencia

Este módulo usa el SDK oficial de Node de Mercado Pago:

  • mercadopago (v2)

Estructura de archivos

lib/mercadopago/
  service.ts   Direct Mercado Pago SDK calls. Internal only — don't import
               this from components, go through actions.ts or client.ts.
  actions.ts   Server-side functions ready to import into server components
               (or call as Server Actions from client components).
  types.ts     Shared TypeScript types for preferences, payments, refunds,
               payment methods, and webhook payloads.
  client.ts    The one client-side helper this module needs: redirecting
               the browser to the Mercado Pago checkout page.

app/api/webhooks/mercadopago/route.ts
  Receives and validates Mercado Pago's payment notifications.

.env.local
  Environment variables (see below).

Variables de entorno

VariableDónde encontrarla
MERCADOPAGO_ACCESS_TOKENMercado Pago Developer Dashboard → Your application → Production/Test credentials → Access Token
MERCADOPAGO_WEBHOOK_SECRETDeveloper Dashboard → Your application → Webhooks → Signature secret
NEXT_PUBLIC_APP_URLLa URL base pública de tu propia app (por ejemplo https://yourapp.com, o una URL de ngrok/túnel mientras probás webhooks en local)

Usá credenciales de prueba mientras desarrollás: el sandbox de Mercado Pago te permite simular pagos aprobados/rechazados/pendientes con tarjetas de prueba, sin tocar la API de producción.

Cómo funciona el flujo

  1. Crear un checkout — llamá a createCheckout de actions.ts con tus ítems y back_urls. Devuelve initPoint (producción) y sandboxInitPoint (credenciales de prueba).
  2. Redirigir al usuario — desde un client component, pasale esa URL a redirectToCheckout en client.ts.
  3. El usuario paga en la página de checkout alojada por Mercado Pago.
  4. Mercado Pago redirige de vuelta a la entrada de back_urls que coincida con el resultado (success, failure o pending), agregando un query param payment_id.
  5. Vos resolvés el resultado leyendo payment_id de la URL en esa página y llamando a checkPaymentSuccess / checkPaymentFailure / getPaymentStatus de actions.ts. Son funciones simples, no páginas generadas: conectalas a la UI de éxito/fallo que ya tengas.
  6. Mercado Pago también llama a tu webhook (app/api/webhooks/mercadopago/route.ts) de forma independiente a la redirección: tratá al webhook como tu fuente de verdad para cumplir el pedido, y a la redirección solo como la UX de cara al usuario. El usuario puede saltearse la redirección (cerrando la pestaña, etc.); el webhook no.

Notas de nomenclatura (específicas de Mercado Pago)

  • "Checkout" corresponde al recurso Preference de Mercado Pago (Checkout Pro). No hay un paso separado de "crear pago" de nuestro lado: Mercado Pago crea el recurso Payment real de su lado cuando el usuario paga; nosotros solo lo leemos (getPayment, getPaymentStatus).
  • La cancelación no es un endpoint dedicado: consiste en actualizar el status de un pago a cancelled, y solo funciona mientras el pago está pending o in_process. Un pago approved no se puede cancelar, solo reembolsar.
  • Refund y partial refund usan el mismo endpoint subyacente: omitir amount hace un reembolso total, pasarlo hace uno parcial. actions.ts los expone como dos funciones separadas (refundPayment, partialRefundPayment) por claridad.
  • Payment methods (getPaymentMethods) lista los métodos habilitados para tu cuenta/país de Mercado Pago; no está atado a un pago específico.

Configuración del webhook

  1. En el Developer Dashboard, andá a tu application → Webhooks.
  2. Definí la URL de notificación como https://yourdomain.com/api/webhooks/mercadopago.
  3. Suscribite al topic payments.
  4. Copiá el signature secret que aparece ahí en MERCADOPAGO_WEBHOOK_SECRET.

El route handler verifica el header x-signature en cada request y rechaza todo lo que no coincida antes de tocar el pago: mirá el comentario en verifyWebhookSignature de service.ts para ver cómo se calcula la firma.

Para completar tu propia lógica de negocio (marcar un pedido como pagado, enviar un email de confirmación, etc.), editá el bloque comentado dentro de app/api/webhooks/mercadopago/route.ts.

Opcional: una tabla de "orders"

Este módulo solo habla con Mercado Pago: no persiste nada. Si querés registrar las compras en tu propia base de datos, una tabla genérica mínima se ve así:

CREATE TABLE orders (
  id                  UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  external_reference  TEXT UNIQUE NOT NULL,   -- pass this as externalReference to createCheckout
  mp_payment_id       TEXT,                   -- filled in once the webhook resolves the payment
  status              TEXT NOT NULL DEFAULT 'pending', -- pending | approved | cancelled | refunded
  amount              NUMERIC NOT NULL,
  currency            TEXT NOT NULL,
  created_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

Flujo típico: creá una fila con status = 'pending' justo antes de llamar a createCheckout, y después actualizá status y mp_payment_id dentro del handler del webhook una vez que leas el estado real del pago.

Manejo de errores

Cada función de service.ts y actions.ts devuelve un objeto de resultado en lugar de lanzar errores:

{ success: true, data: T } | { success: false, error: string, code?: string }

Verificá siempre result.success antes de usar result.data.