Inyo

Integración por Iframe

Guía paso a paso para integrar la Hosted Payment Page en su sitio web mediante el iframe.

Resumen del flujo: su backend crea una sesión segura (autenticada vía OAuth 2.0) → recibe un sessionToken → su frontend carga el SDK y monta el iframe con ese token → el cliente paga → usted recibe el resultado vía callback o redirección → su backend confirma la transacción.


Requisitos Previos

Antes de comenzar, necesita las credenciales proporcionadas por Inyo:

CredencialDescripción
OAUTH_CLIENT_IDIdentificador de su tenant (cliente).
OAUTH_CLIENT_SECRETSecreto usado para autenticar la creación de sesiones.
URL del backendEndpoint de la API de sesiones (referido abajo como https://{HPP_API}).
URL del frontendOrigen de la página alojada que corre dentro del iframe (referido abajo como https://{HPP_HOST}).

El OAUTH_CLIENT_SECRET nunca debe aparecer en el frontend. Toda la creación de sesiones ocurre en su servidor.


Paso 1 — Crear una sesión de pago (en su backend)

Antes de mostrar el iframe, su servidor crea una sesión. Esta llamada está protegida por OAuth 2.0 Client Credentials (HTTP Basic Auth).

Endpoint: POST /api/sessions/create

Autenticación: encabezado Authorization: Basic base64(clientId:clientSecret)

Parámetros del cuerpo de la solicitud

ParámetroTipoRequeridoDescripción
amountNumberMonto de la transacción (p. ej. 50.00). Use 0 para card_validation.
currencyStringCódigo de moneda (actualmente solo USD).
transactionTypeStringpayment, card_validation o account_validation.
parentOriginStringOrigen HTTPS de la página que aloja el iframe (p. ej. https://your-site.com).
captureBooleanNotrue captura de inmediato; false solo autoriza (predeterminado).
tokenTypeStringNoone_time (predeterminado) o recurring.
customCssStringNoURL de un archivo CSS alojado para personalizar la apariencia.
billingPreferenceStringNoVisibilidad de los campos de facturación: editable (predeterminado), read_only o hidden.
billingDetailsObjectNoPrecarga los datos de facturación (nombre, correo, dirección, etc.).
threeDSDataObjectNoConfiguración de 3D Secure: { "enable": true, "successUrl": "...", "failUrl": "..." }.
metadataObjectNoDatos de seguimiento de formato libre (p. ej. orderId, customerId, uiOrder).

Ejemplo (Node.js)

const clientId = process.env.OAUTH_CLIENT_ID;
const clientSecret = process.env.OAUTH_CLIENT_SECRET;
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');

const response = await fetch('https://{HPP_API}/api/sessions/create', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 50.00,
    currency: 'USD',
    transactionType: 'payment',
    parentOrigin: 'https://your-site.com',
    billingPreference: 'editable',
    threeDSData: { enable: true },
    metadata: { orderId: 'ORD-789' }
  })
});

const session = await response.json();
// Devuelva SOLO el sessionToken a su frontend.

Respuesta

{
  "sessionToken": "eyJ...",
  "sessionId": "sess_uuid",
  "expiresAt": "2026-06-16T12:15:00Z",
  "tenant": {
    "name": "Your Company",
    "logoUrl": "https://...",
    "supportEmail": "support@...",
    "primaryColor": "#3b82f6",
    "paymentMethods": ["card", "ach"]
  }
}

El sessionToken expira en 15 minutos por defecto. Cree la sesión solo cuando el cliente esté listo para pagar.


Paso 2 — Cargar el SDK en su frontend

Incluya el script del SDK en la página donde se mostrará el checkout y añada un contenedor (un <div>) donde se montará el iframe.

<!-- Contenedor donde se insertará el iframe -->
<div id="checkout-container"></div>

<!-- SDK del checkout -->
<script src="https://{HPP_HOST}/iframe.min.js"></script>

Paso 3 — Inicializar y montar el iframe

Use el sessionToken obtenido en el Paso 1 para inicializar el SDK y montar el iframe en el contenedor.

<script>
  InyoCheckout.init({
    sessionToken: 'SESSION_TOKEN_FROM_BACKEND',

    // Se invoca cuando el pago es aprobado/autorizado
    onSuccess: (data) => {
      console.log('Payment approved!', data.transaction);
      // data.transaction = { status, paymentId, cardToken, billingInfo }
      // IMPORTANTE: confirme en su backend antes de completar el pedido (Paso 5).
    },

    // Se invoca cuando el pago es rechazado u ocurre un error
    onError: (error) => {
      console.error('Payment failed:', error);
    }
  });

  InyoCheckout.mount('#checkout-container');
</script>

Opciones aceptadas por init

OpciónDescripción
sessionTokenRequerido. Token devuelto en el Paso 1.
onSuccess(data)Callback de éxito. Recibe { transaction }.
onError(error)Callback de error/rechazo.
storeLaterUsetrue para mostrar la opción de "guardar tarjeta para uso futuro".
threeDSDataConfiguración de 3D Secure (refleja lo enviado en la sesión).

El sessionToken no va en la URL del iframe — el SDK lo envía internamente vía postMessage (INIT_SESSION) después de que el iframe carga. El iframe también se carga en modo sandbox por seguridad.


Paso 4 — Recibir el resultado del pago

Puede manejar el resultado de dos formas (use una o ambas).

Opción A — Callbacks de JavaScript

El SDK dispara onSuccess u onError automáticamente. El objeto data.transaction contiene:

{
  status: 'APPROVED' | 'AUTHORIZED' | 'DECLINED' | 'CHALLENGE' | 'PENDING',
  paymentId: 'pay_12345',
  cardToken: { token: '...', schemeId: 'VISA', lastFourDigits: '4242' },
  billingInfo: { /* dirección de facturación completada */ }
}

Ejemplo:

onSuccess: (data) => {
  const { status, paymentId } = data.transaction;
  if (status === 'APPROVED' || status === 'AUTHORIZED') {
    window.location.href = `/confirmation?pid=${paymentId}`;
  }
}

Opción B — Redirección (del lado del servidor)

Si proporcionó successUrl / failUrl al crear la sesión (dentro de threeDSData o en la configuración de la sesión), el iframe redirige la página completa al final, agregando los parámetros:

https://your-site.com/success?sessionId=sess_123&paymentId=pay_456

Estados posibles

EstadoSignificado
AUTHORIZEDAutorizado (aún no capturado).
APPROVED / CAPTUREDPago completado.
DECLINEDTarjeta rechazada.
CHALLENGERequiere verificación 3D Secure (manejada automáticamente por el iframe).
PENDINGPago asíncrono (p. ej. ACH) a la espera de confirmación.

Paso 5 — Confirmar la transacción en su backend (requerido)

Nunca complete el pedido basándose únicamente en el callback del frontend. Siempre confirme el estado desde su servidor.

Opción 1 — Consultar el estado de la sesión

GET /api/sessions/:sessionId Encabezado: x-session-token: <sessionToken>

const res = await fetch(`https://{HPP_API}/api/sessions/${sessionId}`, {
  headers: { 'x-session-token': sessionToken }
});
const session = await res.json();

if (session.status === 'completed') {
  // Complete el pedido con seguridad.
}

Opción 2 — Verificar contra el gateway por paymentId

POST /api/verify-transaction Encabezado: x-session-token: <sessionToken> Cuerpo: { "paymentId": "pay_123" }


Personalización visual

La apariencia del checkout es totalmente personalizable:

  • CSS personalizado: envíe un customCss (URL de una hoja de estilos alojada) al crear la sesión para sobrescribir los estilos predeterminados.
  • Color de marca: definido en el registro del tenant (primaryColor), aplicado a botones y elementos destacados.
  • Campos de facturación: controle la visibilidad con billingPreference (editable, read_only, hidden) y precargue con billingDetails.
  • Orden de secciones: controle el orden de las secciones de facturación y pago mediante metadata.uiOrder (p. ej. ["billing", "payment"]).

Comportamiento automático del iframe

  • Redimensionamiento: el iframe ajusta su propia altura conforme el contenido cambia (vía el mensaje RESIZE_IFRAME). No establezca una altura fija.
  • 3D Secure: cuando se requiere, el iframe maneja la redirección al banco y la verificación ACS automáticamente, validando el resultado en el backend antes de disparar onSuccess / onError. Vea Manejo de 3D Secure para el comportamiento subyacente del gateway.

Protocolo postMessage (referencia)

El SDK y el iframe se comunican mediante window.postMessage. Normalmente usted no los maneja directamente — el SDK los traduce a los callbacks de init — pero se documentan aquí para depuración.

Direccióntype del mensajePayload
Padre → iframeINIT_SESSION{ sessionToken }
iframe → PadreRESIZE_IFRAME{ height }
iframe → PadrePAYMENT_SUCCESS{ transaction } → dispara onSuccess
iframe → PadrePAYMENT_ERROR{ error } → dispara onError

Lista de verificación de integración

  • [ ] Credenciales OAuth (clientId / clientSecret) guardadas solo en el backend.
  • [ ] Sesión creada vía POST /api/sessions/create en el servidor.
  • [ ] parentOrigin configurado correctamente (HTTPS en producción).
  • [ ] SDK (iframe.min.js) cargado e iframe montado con el sessionToken.
  • [ ] onSuccess / onError (o redirecciones) manejados en el frontend.
  • [ ] Transacción confirmada en el backend antes de completar el pedido.

Ejemplo completo (condensado)

Backend (crea la sesión):

const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
const r = await fetch('https://{HPP_API}/api/sessions/create', {
  method: 'POST',
  headers: { 'Authorization': `Basic ${credentials}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    amount: 29.99,
    currency: 'USD',
    transactionType: 'payment',
    parentOrigin: 'https://your-site.com',
    metadata: { orderId: 'ORD-123' }
  })
});
const { sessionToken } = await r.json();
// envíe el sessionToken al frontend

Frontend (monta el iframe):

<div id="checkout"></div>
<script src="https://{HPP_HOST}/iframe.min.js"></script>
<script>
  InyoCheckout.init({
    sessionToken: sessionTokenFromBackend,
    onSuccess: async (data) => {
      await fetch('/api/confirm-payment', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ paymentId: data.transaction.paymentId })
      });
    },
    onError: (err) => alert('Payment not completed.')
  });
  InyoCheckout.mount('#checkout');
</script>