Al final de esta guía tendrás un endpoint en tu backend que redirige al comprador a un checkout de Onflay y confirma el pago por webhook.
1. Instala el SDK
pnpm add @onflay/node @onflay/webhooks
Requiere Node.js 20 o superior.
2. Agrega tu API key
Copia tu secret key de sandbox desde el dashboard y agrégala a tu .env:
ONFLAY_API_KEY=sk_test_...
Las sk_* son secretas. No las incluyas en código del navegador, apps móviles ni repositorios públicos. Solo viven en tu backend.
La key determina el entorno — sk_test_ apunta a sandbox y sk_live_ a producción. No necesitas configurar nada más.
3. Crea una sesión de checkout
Cuando el usuario hace click en “Comprar”, tu backend crea una sesión y lo redirige a la URL que devuelve Onflay. El comprador llega a un checkout hospedado por Onflay — tú no manejas datos de tarjeta.
// app/api/checkout/route.ts (Next.js App Router)
import { Onflay } from '@onflay/node';
const onflay = new Onflay(process.env.ONFLAY_API_KEY!);
export async function POST(request: Request) {
const { userId, listingId } = await request.json();
const session = await onflay.checkoutSessions.create(
{
listingId,
customerEmail: 'comprador@ejemplo.com',
successUrl: 'https://tu-app.com/gracias',
cancelUrl: 'https://tu-app.com/cancelado',
},
{
// Protección contra duplicados — ver nota abajo
idempotencyKey: `checkout:${userId}:${listingId}`,
}
);
return Response.redirect(session.url, 303);
}
Qué es la idempotency key
Imagina que el usuario hace click en “Comprar”, tu servidor llama a Onflay, pero la red falla antes de recibir respuesta. Tu servidor no sabe si la sesión se creó o no. Sin protección, al reintentar podrías crear dos sesiones para el mismo usuario comprando lo mismo.
La idempotencyKey es una cadena que identifica esta operación específica. Si llegas a llamar a checkoutSessions.create dos veces con la misma key, Onflay devuelve la misma sesión que creó la primera vez, sin duplicar nada.
Regla práctica: combina entidades que hacen única la operación —usuario + lo que está comprando—:
checkout:user_123:lst_456 ← un usuario comprando un listing
checkout:order_789 ← un ID de orden que ya es único en tu sistema
No uses un valor aleatorio ni uno generado por cada retry — la clave debe ser la misma en todos los intentos de la misma operación.
4. Confirma el pago por webhook
La URL successUrl solo sirve para mostrarle una pantalla de éxito al usuario. No es una confirmación de pago. Un usuario podría llegar ahí por error o manipulando la URL.
El evento payment.completed que envía Onflay es la única fuente confiable de confirmación. Úsalo para activar acceso, entregar el producto o marcar la orden como pagada.
// app/api/webhooks/onflay/route.ts
import { createNextWebhookHandler } from '@onflay/webhooks/next';
export const POST = createNextWebhookHandler({
secret: process.env.ONFLAY_WEBHOOK_SECRET!,
onEvent: async (event) => {
if (event.type === 'payment.completed') {
const { listingId, customerEmail, amountInCents } = event.data;
// Activa acceso, entrega el producto o actualiza tu base de datos.
}
},
});
Agrega el webhook secret a tu .env:
ONFLAY_WEBHOOK_SECRET=whsec_...
Para pruebas locales, usa la CLI para generar un secret temporal y recibir eventos en tu servidor:
npx onflay listen --forward-to http://localhost:3000/api/webhooks/onflay
La CLI imprime un whsec_dev_... temporal. Úsalo en .env.local durante el desarrollo. En producción configura el secret permanente desde el dashboard.
Siguiente paso
Con esto ya tienes el flujo completo: checkout → pago → confirmación por webhook.
Si quieres gestionar tu catálogo de productos o precios desde código en lugar del dashboard, ve a la guía de la CLI.