Sesiones
Una CheckoutSession es con lo que interactúa el comprador: un objeto con límite de tiempo, de un solo uso, que posee la URL del checkout alojado. Es la más liviana de las tres entidades centrales. La mayor parte de tu lógica trabaja con Órdenes y los Payment Intents (ver abajo).
El modelo de datos de tres entidades
CheckoutSession ← 1:1 → Order ← 1:N → PaymentIntent
(comprador) (catálogo) (cada intento de pago)| Entidad | Propósito | Vida útil |
|---|---|---|
| CheckoutSession | De cara al comprador: tiene session_key, checkout_url, TTL | Minutos (por defecto 30) |
| Order | Estado de tu catálogo: line items, totales, reembolsos | Registro permanente |
| PaymentIntent | Un intento de pago en una cadena/activo | Horas; liquida o expira |
Creas una sesión y una orden juntas (vía
POST /b2b/v1/checkout-sessions/quick). Cada vez que el comprador
elige un activo en la página de checkout, se abre un PaymentIntent
fresco contra la cadena correcta. Si cambian de activo a mitad de
checkout, el intent anterior va a EXPIRED y empieza uno nuevo.
Identificador
Una sesión se identifica por su session_key:
cst_G-SO92J7HNWkwMHEHjD4oO1ZURL-safe, unos 24 caracteres tras el prefijo. La página de checkout
alojada es https://checkout.infraio.xyz/<session_key>: trata la
session key como una credencial bearer para ese único checkout.
Ciclo de vida — CheckoutSession
| Estado | Significa |
|---|---|
ACTIVE | Sesión creada y abierta. La URL del checkout es usable. |
COMPLETED | Un PaymentIntent de esta sesión liquidó. La Order ahora es PAID (o PARTIAL_PAID si pagaron de menos). |
EXPIRED | expires_at pasó sin liquidación. Cualquier Order abierta se cancela. |
CANCELED | Cancelación explícita: o el comprador pulsó “cancelar” o tú llamaste al endpoint de cancelación. |
Los tres estados terminales son mutuamente excluyentes y finales. Se puede crear una nueva CheckoutSession contra la misma Order si quieres reintentar (p. ej., tras un pago insuficiente).
TTL
- Por defecto: 30 minutos (configurable vía el campo
expires_inal crear, en segundos). - Límites: No se aplica mínimo ni máximo. Elige un valor que coincida con la ventana de decisión esperada de tu comprador: menos de 60 segundos arriesga que compradores legítimos se queden sin tiempo, y una sesión que permanece abierta más de 7 días casi con certeza está abandonada.
- Por defecto por comerciante: Puedes fijar un valor por defecto
en el dashboard, pero solo
POST /b2b/v1/checkout-sessions(dos pasos) lo honra.POST /b2b/v1/checkout-sessions/quickusa 30 minutos cuando se omiteexpires_in, independientemente del ajuste del dashboard. Para usar un valor por defecto distinto con/quick, envíaexpires_inen cada llamada. - Aplicación: Una sesión cuyo
expires_atha pasado se trata comoEXPIREDaunque su estado aún no se haya actualizado, así que no dependas del valor del estado en el momento exacto de la expiración.
Pago insuficiente
Si un comprador envía menos que el importe de la sesión, el
PaymentIntent aún liquida por el importe parcial y la Order
transiciona a PARTIAL_PAID. La CheckoutSession se mueve a
COMPLETED (un PaymentIntent liquidado), así que ya no es
reutilizable.
Para aceptar el déficit como pago completo, la orden puede
resolverse a PAID. Ver Conceptos → Órdenes
(resolver no está disponible a través de la API; para seguir en
self-serve, cobra el remanente en su lugar). Para cobrar el remanente, crea una
nueva CheckoutSession contra la misma Order con el importe
residual.
Sobrepago
Si el comprador envía más que el importe de la sesión (raro pero ocurre con transferencias manuales), InfraIO Pay detecta el sobrepago en 24 horas y te notifica. No se reembolsa automáticamente. Emite el reembolso vía la API de reembolso o el dashboard.
Pagos con activo equivocado
La dirección de depósito por pedido (CREATE2) se genera para una sesión, una red y un activo. Si un comprador envía un activo distinto a la dirección, el pago no se reconoce y el PaymentIntent permanece abierto hasta que la sesión expira. Soporte puede ayudar a recuperar los fondos, pero no es automático. Indica a los compradores que envíen el activo exacto mostrado en la página de checkout.
En TRON, Solana y TON no hay dirección de depósito, así que esto aplica solo a las redes EVM: el comprador paga directamente a tu wallet. Ver Redes de pago directo a la wallet.
Idempotencia al crear
POST /b2b/v1/checkout-sessions/quick acepta un campo
idempotency_key en el body de la petición (nota: campo del body,
no cabecera HTTP). Genera un UUID si no tienes una clave natural.
La clave deduplica la Order, no la CheckoutSession. En un
reintento con la misma clave, /quick devuelve la orden original
(order_id es estable) pero emite una CheckoutSession fresca:
una nueva session_key y checkout_url cada vez. Eso es
intencional: una Order puede respaldar varios intentos de checkout
(ver Órdenes), así que un /quick
reintentado entrega al comprador una sesión limpia sin duplicar la
orden.
Dos comportamientos a tener en cuenta:
- El body no se hashea ni compara. Reutilizar una clave con un
body distinto no devuelve
409: el servidor devuelve silenciosamente la orden ya almacenada bajo esa clave e ignora el nuevo body. Así que trata unidempotency_keycomo un token de un solo uso para una sola orden lógica; nunca lo recicles entre distintos carritos. - Solo la Order se deduplica, no la sesión. Si necesitas la
misma URL de checkout de vuelta, persiste
session_key/checkout_urlde la primera respuesta: llamar a/quickde nuevo no devolverá la antigua. Para enumerar cada sesión emitida contra una orden, usaGET /b2b/v1/checkout-sessions/by-order/:order_id.
Endpoints de la API
| Método | Ruta | Notas |
|---|---|---|
POST | /b2b/v1/checkout-sessions/quick | Crea order + session en una llamada |
POST | /b2b/v1/checkout-sessions | Crea sesión contra una orden existente |
GET | /b2b/v1/checkout-sessions/by-order/:order_id | Lista todas las sesiones de una orden (para historial de reintentos) |
Consulta el Inicio rápido para el body completo de la petición de creación y la firma.
Qué sigue
- Conceptos → Órdenes: la entidad Order (la que tratas como fuente de verdad para fulfillment).
- Conceptos → Cadenas y activos: redes soportadas y supuestos de finalidad por cadena.
- Webhooks → Resumen: qué eventos se disparan en cada transición de estado de sesión.