SDKs

Web

Integra el Web SDK: campos de tarjeta seguros, tarjetas guardadas y métodos alternativos.

El SDK Web de Tonder (@tonder.io/web-sdk) es un SDK de navegador en TypeScript para aceptar pagos: campos de tarjeta seguros, pagos con tarjeta nueva y guardada, presentación hosted/3DS, descubrimiento de métodos de pago, consulta de transacciones y respuestas compatibles con webhooks.

¿Prefieres que un agente de IA haga la integración por ti? Instala el plugin Tonder Web SDK en Claude Code, Claude Desktop o Codex.

Antes de empezar

Necesitas:

  • Tu llave API pública de Tonder. Nunca pongas llaves secretas en código de navegador.
  • Un navegador moderno: Chrome, Safari, Firefox o Edge.
  • Un endpoint en tu servidor que genere un secure_token de corta vida, si usarás tarjetas guardadas / Card-on-File.
  • Un endpoint de webhooks para confirmar pagos de forma confiable.

Instalación

npm install @tonder.io/web-sdk
import { createTonder, AppError, ErrorKeyEnum } from '@tonder.io/web-sdk';

Sin bundler, carga el build global del navegador desde el CDN del entorno:

EntornoURL del CDN
Stagehttps://zplit-stage.s3.us-east-1.amazonaws.com/web-sdk/v1/tonder-web-sdk.min.js
Producciónhttps://zplit-prod.s3.us-east-1.amazonaws.com/web-sdk/v1/tonder-web-sdk.min.js
<script src="https://zplit-stage.s3.us-east-1.amazonaws.com/web-sdk/v1/tonder-web-sdk.min.js"></script>
<script>
  const { createTonder } = window.Tonder;
</script>

En un proyecto TypeScript que usa el CDN, puedes instalar @tonder.io/web-sdk como devDependency solo para los tipos (npm install -D @tonder.io/web-sdk + import type), manteniendo el runtime en el CDN. No importes código de runtime del paquete en ese caso.

Inicio rápido: pago con tarjeta

Agrega los contenedores para los campos de tarjeta

<form id="checkout-form">
  <div id="collect-cardholder-name" class="card-field"></div>
  <div id="collect-card-number" class="card-field"></div>
  <div id="collect-expiration-month" class="card-field"></div>
  <div id="collect-expiration-year" class="card-field"></div>
  <div id="collect-cvv" class="card-field"></div>

  <button type="submit">Pagar</button>
</form>

Limita la altura de cada contenedor para que el iframe seguro no crezca visualmente mientras se acomoda al layout:

.card-field {
  width: 100%;
  max-height: 90px;
}

Inicializa, monta y paga

import { createTonder } from '@tonder.io/web-sdk';

const tonder = createTonder({
  api_key: 'pk_test_...',
  environment: 'sandbox',
  session: {
    customer: {
      email: 'ada@example.com',
      first_name: 'Ada',
      last_name: 'Lovelace',
    },
  },
});

await tonder.init();

const card_fields = tonder.create('card_fields');

await card_fields.mount();

const transaction = await tonder.pay({
  amount: 150,
  currency: 'MXN',
  return_url: 'https://yourstore.example/checkout/return',
  client_reference: 'order_1001',
  metadata: { cart_id: 'cart_789' },
  payment_method: { type: 'card' },
});

Maneja el resultado

if (transaction.status === 'Success' || transaction.status === 'Authorized') {
  // Muestra la confirmación.
} else if (transaction.status === 'Pending') {
  // El cliente puede necesitar completar 3DS o un método asíncrono.
  // Confirma el estado final con webhooks o getTransaction().
} else {
  // Muestra un mensaje de pago recuperable.
  console.warn(transaction.decline_code, transaction.decline_reason);
}

Los rechazos no se lanzan como error — se devuelven como transacciones: lee transaction.status. Los fallos del SDK sí se lanzan como AppError (consulta Errores).

Los montos del SDK Web son unidades decimales (150 = MXN 150.00). Consulta Dinero, monedas y montos.

Configuración

createTonder(config) crea una instancia para un comprador/sesión. Recrea el SDK si cambia el cliente, el secure_token o el entorno.

CampoRequeridoDescripción
api_keyLlave pública de Tonder para integraciones de navegador.
environment'sandbox', 'stage' o 'production'.
session.customerPara pay() y tarjetas guardadasIdentidad del cliente. Omítelo en páginas de retorno de solo lectura que solo llaman getTransaction().
session.secure_tokenPara tarjetas guardadasToken de corta vida generado por tu backend.
presentation_modeNo'redirect' por defecto, o 'embedded' para el modal del SDK.
events.presentationNoCallbacks on_open / on_close de la vista hosted embebida.
customization.card_fieldsNoEtiquetas, placeholders, estilos y mensajes de validación de los campos seguros.

La tabla completa de personalización (estilos por campo, mensajes de error, icono de la tarjeta) está en la Referencia SDK · Web.

Modo de presentación

Cuando un pago requiere un paso hosted (3DS, instrucciones de APM), el SDK usa presentation_mode:

ModoComportamiento
redirectEl navegador navega a la página hosted. Usa return_url, getTransaction() y webhooks para confirmar el estado final.
embeddedEl SDK abre un modal a pantalla completa. El 3DS de tarjeta espera la transacción final; las instrucciones hosted de APM/SPEI pueden devolver Pending de inmediato.

Tarjetas guardadas (secure_token)

Las operaciones con tarjetas guardadas (getCustomerCards(), enrollCard(), removeCustomerCard(), pagar con saved_card) requieren session.customer y session.secure_token. Genera el token llamando a /api/secure-token/ desde tu backend con tu llave secreta:

fetch("https://stage.tonder.io/api/secure-token/", {
  method: 'POST',
  headers: {
    'Authorization': 'Token YOUR_SECRET_KEY',
    'Content-Type': 'application/json'
  }
})
  .then(response => response.json())
  .then(result => {
    const secureToken = result.access;
    // Pásalo al frontend como session.secure_token
  });
fetch("https://app.tonder.io/api/secure-token/", {
  method: 'POST',
  headers: {
    'Authorization': 'Token YOUR_SECRET_KEY',
    'Content-Type': 'application/json'
  }
})
  .then(response => response.json())
  .then(result => {
    const secureToken = result.access;
  });

El secure_token generado es válido por 1 hora. Úsalo dentro de ese plazo; si lo cacheas o reutilizas después, genera uno nuevo.

Pagar con una tarjeta guardada

const tonder = createTonder({
  api_key: 'pk_test_...',
  environment: 'sandbox',
  session: {
    customer: { email: 'ada@example.com' },
    secure_token: await getSecureTokenFromYourBackend(),
  },
});

await tonder.init();

const cards = await tonder.getCustomerCards();
const selected_card = cards[0];

// Monta el CVV de la tarjeta guardada solo cuando la tarjeta no puede cobrarse
// por una suscripción Card-on-File existente.
if (!selected_card.subscription_id) {
  const cvv = tonder.create('card_fields', {
    card_id: selected_card.card_id,
    fields: ['cvv'],
  });

  await cvv.mount();
}

const transaction = await tonder.pay({
  amount: 150,
  currency: 'MXN',
  return_url: 'https://yourstore.example/checkout/return',
  client_reference: 'order_1001',
  payment_method: { type: 'saved_card', card_id: selected_card.card_id },
});

Guardar una tarjeta nueva

const card_fields = tonder.create('card_fields');

await card_fields.mount();

const enrollment = await tonder.enrollCard();
// { card_id: 'card_123', subscription_id: 'sub_123' }

Referencia de la API

POST
/secure-token/

Autorización

SecretKeyAuth
Authorization<token>

Tu SECRET key con prefijo Token , p. ej. Token <SECRET_KEY> — distinta de la API key

In: header

Cuerpo de la respuesta

application/json

curl -X POST "https://example.com/secure-token/"
{
  "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzI3NzI3MTM3LCJpYXQiOjE3Mjc3MjM1MzcsImp0aSI6IjFjZTBkZmExODgwNzQzNGI4MDk2MzdlNTliNmM1NWMzIiwidXNlcl9pZCI6NDYxfQ.DFGNJr7JT6z3cp976PDBT57uX7LaYJLYBsdK8kaSAOI"
}

Métodos de pago alternativos

Si tu checkout ya sabe qué método ofrecer, pasa el código directamente a pay():

const transaction = await tonder.pay({
  amount: 150,
  currency: 'MXN',
  return_url: 'https://yourstore.example/checkout/return',
  client_reference: 'order_1001',
  payment_method: { type: 'oxxopay' },
});

Usa getPaymentMethods() (opcional) para renderizar los métodos habilitados de tu negocio, y getPaymentMethodBanks() para los métodos SafetyPay respaldados por banco:

const banks = await tonder.getPaymentMethodBanks();
const bank = banks.cash[0];

const transaction = await tonder.pay({
  amount: 150,
  currency: 'MXN',
  return_url: 'https://yourstore.example/checkout/return',
  client_reference: 'order_1001',
  payment_method: {
    type: 'safetypayCash',
    config: {
      country: bank.country, // p. ej. 'Mexico'
      channel: bank.channel, // 'WP' efectivo, 'OL' transferencia
      bank_ids: [{ id: bank.code }], // p. ej. [{ id: '8186' }]
    },
  },
});

Los métodos APM/SPEI suelen liquidar de forma asíncrona. Usa webhooks para el cumplimiento de pedidos.

Demos

Prueba cada flujo en el portal de demos del SDK:

FlujoDemo
Pago con tarjetaweb/card-payment
Enrolamiento de tarjetaweb/enroll-card
Tarjetas guardadasweb/saved-cards
Métodos de pagoweb/payment-methods
Bancos SafetyPayweb/safetypay-banks

Los demos legacy (Web SDK Lite e Inline) usan versiones anteriores del SDK y se conservan solo como referencia — para integraciones nuevas usa los demos de arriba. Si todavía estás en el SDK anterior, sigue la guía de migración.

Conciliación

  • client_reference es requerido: es tu referencia de orden y aparece en dashboards, exportes, webhooks y reportes de transacciones.
  • Usa un idempotency_key estable por intento de checkout para que los reintentos no dupliquen cargos. No reutilices client_reference como llave de idempotencia.
  • Los webhooks del SDK Web usan el payload plano (campos de nivel superior) con event_type: payment_Success / payment_Pending. Consulta el catálogo de eventos.

Siguientes pasos

¿Te resultó útil esta página?

En esta página