HomeGuíasAPI ReferenceChangelog
Log In
Guías

Esta guía te lleva desde cero hasta una integración en producción con una Checkout Session. Si solo quieres ver código, salta al ejemplo mínimo. Los nombres exactos de cada parámetro están en la Referencia.

La integración tiene dos partes:

  1. Tu backend crea una Checkout Session. En ella defines qué se hace con la tarjeta (cobrar, inscribirla o ambas), el cliente, el monto y, si corresponde, la tarjeta ya guardada que se usa.
  2. Tu frontend monta el Checkout Form y llama a processCheckoutSession con el id de esa sesión. El formulario solo captura la tarjeta: todo lo demás sale de la sesión.

1. Prerrequisitos

Antes de escribir código necesitas:

QuéCómo lo obtienes
Dominios habilitadosEnvía a tu ejecutivo los dominios de staging y producción desde los que cargarás el formulario. Los iframes no se renderizan fuera de ellos.
API keyLa usa tu backend para crear la Checkout Session. Nunca la expongas en el frontend.
organizationId y accountIdIds públicos de tu organización y cuenta (org_…, acc_…). Te los entrega Toku.
id_customerId público del cliente (cus_…) dueño de la tarjeta. Lo obtienes al crear el Customer.
Webhook endpointPara confirmar el resultado server-side. Revisa Notificaciones y webhooks.

2. Ejemplo mínimo

Pago de una tarjeta nueva que además queda inscrita para cobros futuros.

Backend: crear la Checkout Session

curl --request POST 'https://api.trytoku.com/mx/checkout-sessions' \
  --header 'x-api-key: <tu API key>' \
  --header 'x-api-version: 2026-10-08' \
  --header 'content-type: application/json' \
  --data '{
    "mode": "PAYMENT",
    "billing_data": {
      "id_account": "acc_REEMPLAZAR",
      "id_customer": "cus_REEMPLAZAR",
      "amount": 1500,
      "currency": "MXN"
    },
    "payment_options_configuration": {
      "card": { "enable_toggle_switch": true }
    },
    "expiration_datetime": "2026-10-15T23:59:59"
  }'

La respuesta trae el id de la sesión. Entrégaselo a tu frontend como checkoutSessionId.

Frontend: procesar la sesión

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8" />
  <title>Pagar con tarjeta</title>
</head>
<body>
  <form id="cardForm">
    <label>Número de tarjeta</label>
    <div id="pan" style="width: 17em; height: 3em;"></div>

    <label for="expirationDate">Vencimiento (MM/YY)</label>
    <input type="text" id="expirationDate" placeholder="MM/YY" maxlength="5" autocomplete="cc-exp" />

    <label>CVV</label>
    <div id="cvv" style="width: 4em; height: 3em;"></div>

    <label for="cardholderName">Nombre del titular</label>
    <input type="text" id="cardholderName" autocomplete="cc-name" />

    <button id="submitButton" type="button">Pagar</button>
  </form>

  <script src="https://storage.googleapis.com/toku-embedded-portal/checkout-form.min.js"></script>
  <script>
    const ORGANIZATION_ID = 'org_REEMPLAZAR';
    const CHECKOUT_SESSION_ID = 'id-de-la-checkout-session';

    const form = new TokuCheckoutForm({
      environment: 'PROD',
      panDivId: 'pan',
      cvvDivId: 'cvv',
      cvvStyle: { width: '3em', height: '1.5em' },
      panStyle: { width: '15em', height: '1.5em' },
      organizationId: ORGANIZATION_ID,
      onSuccess: result => {
        console.log('Pago realizado', result.data.externalTransactionId);
      },
      onError: error => {
        console.error(error.errorCode, error.errorMessage);
      },
    });

    document.getElementById('submitButton').addEventListener('click', () => {
      try {
        form.processCheckoutSession({
          organizationId: ORGANIZATION_ID,
          checkoutSessionId: CHECKOUT_SESSION_ID,
          expirationDate: document.getElementById('expirationDate').value,
          customerName: document.getElementById('cardholderName').value,
        });
      } catch (validationError) {
        console.error(validationError.message);
      }
    });
  </script>
</body>
</html>

3. Paso a paso

3.1 Crear la Checkout Session

Para revisar los detalles puedes revisar la documentación de Checkout Session. En esta guía te explicamos cómo usarlas para Checkout Form.

El mode define la operación:

SesiónQué haceamountQué devuelve en onSuccess
ENROLLMENTInscribe la tarjeta como medio de pago para cobros futuros.NopaymentMethodId (pm_…)
PAYMENTCobra el monto con la tarjeta, sin inscribirla.SíexternalTransactionId (trs_…)
PAYMENT con enable_toggle_switch: trueCobra el monto y además inscribe la misma tarjeta.SíexternalTransactionId (trs_…); la tarjeta queda inscrita como medio de pago

Campos de la sesión:

CampoObligatorioDescripción
modeSíENROLLMENT o PAYMENT.
billing_data.id_accountSíCuenta (acc_…) de la operación.
billing_data.id_customerSíCliente (cus_…) dueño de la tarjeta.
billing_data.amount y currencySolo en PAYMENTMonto a cobrar. También se pueden enviar ids_invoice o ids_subscription.
expiration_datetimeSíFecha y hora ISO 8601 en que expira la sesión.
payment_options_configuration.cardNoenable_toggle_switch (en PAYMENT, inscribe además la tarjeta; sin él solo se cobra) y selected_card (pin_…, tarjeta ya guardada del cliente).
external_idNoTexto libre (hasta 128 caracteres) para reconocer la operación, por ejemplo tu número de pedido.
unique_external_idNoIgual que external_id, pero hace idempotente la creación: si lo repites, se devuelve la sesión ya creada con ese valor.
additional_metadataNoObjeto JSON libre que queda guardado en la sesión y vuelve en sus respuestas.
customer_dataNoDatos de contacto del cliente, por ejemplo phone_number y mail.

Inscripción de una tarjeta nueva

{
  "mode": "ENROLLMENT",
  "billing_data": {
    "id_account": "acc_…",
    "id_customer": "cus_…"
  },
  "expiration_datetime": "2026-10-15T23:59:59",
  "external_id": "alta-tarjeta-987",
  "unique_external_id": "alta-tarjeta-987-intento-1",
  "additional_metadata": { "canal": "web" }
}

Pago e inscripción de una tarjeta ya guardada

Un PaymentInstrument es una tarjeta guardada en la bóveda PCI de Toku. Indícalo en selected_card; debe pertenecer al mismo cliente de la sesión.

{
  "mode": "PAYMENT",
  "billing_data": {
    "id_account": "acc_…",
    "id_customer": "cus_…",
    "amount": 1500,
    "currency": "MXN"
  },
  "payment_options_configuration": {
    "card": { "enable_toggle_switch": true, "selected_card": "pin_…" }
  },
  "expiration_datetime": "2026-10-15T23:59:59",
  "external_id": "pedido-12348",
  "unique_external_id": "pedido-12348-intento-1"
}
🚧

Reglas de la sesión

  • Una sesión sirve para un intento: si el intento falla, crea una sesión nueva (o usa un unique_external_id distinto).
  • Una sesión con selected_card no acepta número de tarjeta, y una sesión sin selected_card lo exige.
  • Si la tarjeta guardada no tiene nombre del titular ni vencimiento, la creación de la sesión se rechaza (409), salvo que tu organización tenga habilitada esa opción.
  • Una sesión expirada, cerrada o con algun error de validación responde error.

3.2 Cargar el script

AmbienteScript
PRODhttps://storage.googleapis.com/toku-embedded-portal/checkout-form.min.js

El script expone la clase global TokuCheckoutForm. Cárgalo antes del código que la usa.

3.3 Armar el formulario

Checkout Form inyecta un iframe dentro de los contenedores que le indiques para el número de tarjeta y el CVV. El resto de los campos son tuyos.

  • Crea un <div> para el PAN y otro para el CVV con width y height explícitos. El iframe ocupa el 100% del contenedor.
  • Agrega tus propios inputs para la fecha de expiración y el nombre del titular. Esos valores se los pasarás tú a processCheckoutSession.
📘

Sesión con tarjeta guardada

Si la sesión trae selected_card, omite panDivId. El iframe del PAN se crea oculto y el cliente solo escribe el CVV y el vencimiento. Si el vencimiento cambió, se actualiza en la tarjeta guardada antes de operar.

3.4 Inicializar TokuCheckoutForm

const form = new TokuCheckoutForm({
  environment: 'PROD',
  panDivId: 'pan',
  cvvDivId: 'cvv',
  cvvStyle: { width: '3em', height: '1.5em' },
  panStyle: { width: '15em', height: '1.5em' },
  organizationId: 'org_…',
  onSuccess: result => {},
  onError: error => {},
});

Reglas que el constructor valida y lanza como Error si no se cumplen:

  • environment debe ser PROD.
  • cvvDivId y cvvStyle son obligatorios.
  • Los contenedores indicados en panDivId y cvvDivId deben existir en el DOM al momento de construir el objeto.

3.5 Procesar la Checkout Session

processCheckoutSession(parámetros) envía la tarjeta a la sesión. No recibe un tipo de operación: la sesión ya lo define. Valida los parámetros de forma síncrona y, si algo falta, lanza un Error.

form.processCheckoutSession({
  organizationId: 'org_…',
  checkoutSessionId: 'id de la Checkout Session',
  expirationDate: '09/28',
  customerName: 'Nombre del titular',
});
ParámetroObligatorioDescripción
organizationIdSíOrganización (org_…).
checkoutSessionIdSíid de la Checkout Session creada en el paso 3.1.
expirationDateSíVencimiento de la tarjeta, MM/YY.
customerNameNoNombre del titular de la tarjeta; viaja cifrado junto a la tarjeta.
installmentsNoMeses sin intereses, entero mayor o igual a 1.
customerInformationNoObjeto de textos (name, mail, phone_number, government_id); cada campo reemplaza el del cliente de la sesión.
additionalMetadataNoObjeto libre con datos propios del intento, por ejemplo un identificador antifraude. Queda guardado junto a la operación.

Ejemplo con todos los parámetros opcionales:

form.processCheckoutSession({
  organizationId: 'org_…',
  checkoutSessionId: 'id de la Checkout Session',
  expirationDate: '09/28',
  customerName: 'Nombre del titular',
  installments: 3,
  customerInformation: {
    name: 'Nombre Apellido',
    mail: '[email protected]',
    phone_number: '+525512345678',
    government_id: 'XXXX000000XXXXXX00',
  },
  additionalMetadata: {},
});

3.6 Manejar el resultado

Después de processCheckoutSession, Toku ejecuta la operación de la sesión y espera el resultado hasta 5 minutos.

onSuccess(result):

{
  "action": "OPERATION_FINISHED",
  "operationResult": "SUCCESS",
  "data": { "externalTransactionId": "…" }
}

En una sesión ENROLLMENT, data trae paymentMethodId en lugar de externalTransactionId.

onError(error):

{
  "action": "OPERATION_FINISHED",
  "operationResult": "FAILURE",
  "errorCode": "9999",
  "errorMessage": "An unexpected error ocurred"
}

errorMessage es el mensaje que Toku redacta para el cliente final. errorCode son los últimos cuatro caracteres del código de respuesta de Toku; 9999 con el mensaje genérico en inglés indica un error no clasificado (por ejemplo, una sesión expirada o ya usada).

Mientras esperas el resultado, deshabilita el botón de envío para evitar operaciones duplicadas.

3.7 Confirmar server-side

onSuccess corre en el navegador del cliente y puede no llegar a tu backend. Trata el webhook como fuente de verdad:

SesiónWebhook de éxitoWebhook de fallo
ENROLLMENTpayment_method.attachedpayment_method_inscription_intent.failed
PAYMENTtransaction.successtransaction.failed
PAYMENT con enable_toggle_switch: truetransaction.success y payment_method.attachedtransaction.failed

Cada transacción y medio de pago trae el id_checkout_session de la sesión que lo originó, para que lo cruces con tu pedido.

4. Personalizar estilos

Hay dos niveles, y se combinan:

OpciónQué controlaEjemplo
panStyle / cvvStyleEstilos inline del <input> dentro del iframe. Objeto con propiedades CSS.{ width: '15em', height: '1.5em', border: '1px solid #ccc', 'border-radius': '8px' }
panStylesheet / cvvStylesheetUna hoja de estilos completa que se inyecta en el iframe. Útil para :focus, ::placeholder y fuentes.'input { font-family: Inter, sans-serif } input:focus { outline: 2px solid #aa90fe }'
options.panPlaceholder / options.cvvPlaceholderTexto del placeholder de cada campo.'Número de tarjeta'
options.maskPanOculta el número cuando el campo pierde el foco.true

Puedes cambiar estilos en runtime con setPanStyle, setCvvStyle, setPanStylesheet y setCvvStylesheet, por ejemplo para marcar un campo en rojo desde onPanBlur cuando luhnCheck es false.

Las fuentes de tu página no están disponibles dentro del iframe. Decláralas en el stylesheet con @import o @font-face.

5. Salir a producción

  • Usar los ids y la API key de producción.
  • Crear la Checkout Session desde tu backend, nunca desde el navegador.
  • Confirmar con tu ejecutivo que el dominio de producción está habilitado.
  • Tener el webhook endpoint de producción suscrito a los eventos de la tabla del paso 3.7.
  • Crear una sesión nueva por cada intento de pago o inscripción.
  • Deshabilitar el botón de envío mientras la operación está en curso.
  • Mostrar mensaje de error al cliente cuando llegue onError.
Deprecado: integración sin Checkout Session (processOperation)
❗️

Integración deprecada

Esta integración se mantiene solo por compatibilidad. Las integraciones nuevas deben usar una Checkout Session y processCheckoutSession.

Antes de la Checkout Session, el frontend indicaba el tipo de operación y todos sus datos en processOperation(tipo, parámetros). Si processOperation recibe un checkoutSessionId, se procesa como processCheckoutSession e ignora el tipo y el resto de los parámetros.

Prerrequisitos adicionales

QuéCómo lo obtienes
customerIdId público del cliente (cus_…). Lo obtienes al crear el Customer.
subscriptionIdId público de la suscripción (sub_…) a la que se inscribe la tarjeta o que se cobra. Lo obtienes al crear la Subscription. Solo para pagos sobre invoices.
invoiceIdsIds públicos de las deudas a pagar (in_…). Solo para pagos sobre invoices.

El constructor de TokuCheckoutForm recibe además accountId: 'acc_…'.

Inscripción

form.processOperation('INSCRIPTION', {
  organizationId: 'org_…',
  accountId: 'acc_…',
  customerId: 'cus_…',
  subscriptionId: 'sub_…',
  tokuProducts: ['cards_batch_mx_recurring_pst'],
  expirationDate: '09/28',
  customerName: 'Nombre del titular',
});

Pago con tarjeta nueva

form.processOperation('PAYMENT', {
  organizationId: 'org_…',
  accountId: 'acc_…',
  customerId: 'cus_…',
  amount: 1500,
  tokuProducts: ['payment_orchestration'],
  expirationDate: '09/28',
  customerName: 'Nombre del titular',
});

Los demás parámetros que no están indicados en los ejemplos son opcionales:

  • invoiceIds: las deudas que paga este cobro. Recomendado para que el pago quede asociado a tus deudas.
  • flowName: nombre del flujo de pago, solo si Toku te indicó uno.

Pago con tarjeta guardada

Construye el formulario sin panDivId y entrega el PaymentInstrument en paymentInstrumentId. El cliente solo escribe el CVV; la fecha de expiración que envíes actualiza la tarjeta que tiene guardada.

form.processOperation('PAYMENT', {
  organizationId: 'org_…',
  accountId: 'acc_…',
  customerId: 'cus_…',
  amount: 1500,
  tokuProducts: ['payment_orchestration'],
  paymentInstrumentId: 'pin_…',
  expirationDate: '09/28',
  flowName: '0'
});

El resultado (onSuccess / onError) y los webhooks son los mismos que en los pasos 3.6 y 3.7, usando INSCRIPTION y PAYMENT en vez de los modos de la sesión.


Did this page help you?