Skip to Content
SDKsJavaScript / Navegador
View as Markdown

SDK de JavaScript / Navegador

@lartech/infraio-checkout-js es el único SDK que publicamos hoy. Corre en el navegador y abre nuestro checkout alojado. Todavía no hay un SDK de backend. Llama directamente a la API; el Inicio rápido incluye un helper de firma HMAC. HMAC.

  • Versión actual: 0.1.1-beta.17 (pre-1.0; espera rupturas menores)
  • Formatos: ESM (index.js), CJS (index.cjs), IIFE (index.global.js)
  • Tipos incluidos (index.d.ts)
  • Cero peers en runtime: sin React, jQuery u otras dependencias

No hay entry point del lado servidor. Los helpers de verificación de firma para webhooks no se incluyen: impleméntalos tú mismo con crypto (la página de verificación de firma tiene código copia-pega en 4 lenguajes).

Instalación

npm install @lartech/infraio-checkout-js

loadInfraIo(publicKey, options?)

Devuelve un Promise<InfraIoInstance>.

import { loadInfraIo } from "@lartech/infraio-checkout-js"; const sdk = await loadInfraIo("pk_live_yourkeyhere", { // Opcional. Sobreescribe solo cuando apuntes a un entorno no-prod. checkoutUrl: "https://checkout-dev.infraio.xyz", });
ParamTipoRequeridoNotas
publicKeystring✓Debe coincidir con pk_(live|test)_…
options.checkoutUrlstring—Sobreescribe la URL base del checkout. Por defecto: https://checkout.infraio.xyz. La página de checkout se conecta automáticamente a la API correspondiente.

sdk.checkout({ … })

Abre el checkout alojado. Devuelve void (usa callbacks para el estado).

CampoTipoRequeridoNotas
sessionIdstring✓session_key devuelta por POST /b2b/v1/checkout-sessions/quick
checkoutUrlstring—URL completa devuelta por el mismo endpoint. Si se omite, el SDK la construye a partir del checkoutUrl de loadInfraIo() (o el por defecto) + sessionId
mode"popup" | "redirect" | "embed"—Por defecto "popup"
containerstring | HTMLElementsolo embedSelector CSS o elemento DOM donde se monta el iframe
widthnumber—Solo popup. Por defecto 560. Acotado a [320, 1280]
heightnumber—Solo popup. Por defecto 780. Acotado a [400, 1000]
timeoutMsnumber—Solo popup. Timeout de carga del iframe. Por defecto 30000. Pasa 0 para deshabilitar
localestring—Tag BCP-47 reenviado como ?locale= a la página de checkout (en, vi, ja, ko, es, pt-BR, ru, tr, zh-CN, zh-TW)
hideSummaryboolean—Oculta la columna de resumen de orden. Por defecto false
hideHeaderboolean—Oculta el header de InfraIO Pay y el botón de conexión de wallet integrado. Por defecto false. Combina con walletAddress para white-label total
walletAddressstring—Pre-conecta una wallet de comprador. Requiere onSignRequest
walletChainIdnumber—Chain ID EVM para la wallet pre-conectada
onReady() => void—Se dispara una vez que el iframe es interactivo. Solo popup/embed
onSignRequest(req: { method: string; params: unknown[] }) => Promise<string>cuando walletAddress está fijadoEl SDK reenvía los RPCs de wallet a tu handler; devuelve el hex firmado
onSuccess({ sessionId }) => void—Se dispara en pago exitoso. No es autoritativo: el webhook lo es
onCancel() => void—Se dispara cuando el comprador cierra el popup/embed sin pagar
onError(err: InfraIoError) => void—Se dispara en fallo de carga del iframe (modos popup + embed). Los argumentos inválidos se lanzan de forma síncrona, no se entregan aquí. El modo redirect no tiene superficie de error en runtime: el fallo se observa en la página redirigida.

onSuccess no es autoritativo. Puede dispararse incluso cuando el webhook luego determina que el pago falló (reorgs de testnet, timing del lado comprador). Úsalo solo para UX (mostrar “¡Gracias!”, redirigir). Confirma siempre vía webhook antes de cumplir.

sdk.close()

Descarta programáticamente un popup o embed abierto. No-op para el modo redirect.

sdk.checkout({ sessionId, mode: "popup", /* … */ }); // más tarde, p. ej. cuando el usuario navega fuera sdk.close();

sdk.openRefundRequest({ … })

Abre el formulario de solicitud de reembolso alojado para un token de un solo uso que tu backend emitió vía POST /b2b/v1/merchants/{merchant_id}/refund-requests. El comprador rellena su dirección de destino del reembolso + razón + metadatos (opcional) en nuestra página; tu página solo maneja el ciclo de vida de apertura/cierre. Devuelve una función close(): llámala para descartar programáticamente el popup o separar el iframe embed. En modo redirect la función devuelta es un no-op.

El formulario vive en https://checkout.infraio.xyz/refund-request/:token. Este método solo envuelve esa URL en un popup / redirect / embed para que el comprador nunca deje tu dominio (en popup / embed) o regrese automáticamente (en redirect). El endpoint que tu backend pega para emitir el token es POST /b2b/v1/merchants/{merchant_id}/refund-requests: firmado con HMAC con tu clave secreta, misma auth que el resto de la superficie B2B. Consulta Conceptos → Reembolsos.

import { loadInfraIo } from "@lartech/infraio-checkout-js"; const sdk = await loadInfraIo("pk_live_yourkeyhere"); // Emite el token en el lado servidor, luego entrégaselo al SDK en el navegador. const { token } = await fetch("/api/mint-refund-token", { method: "POST" }).then(r => r.json()); const close = sdk.openRefundRequest({ token, mode: "popup", onSuccess: ({ linkToken, refundId }) => { // El comprador envió el formulario. // linkToken → página de estado /r/:linkToken (compartir con el comprador). // refundId → usar con la API B2B para aprobar / rechazar. window.location.href = `/r/${linkToken}`; }, onCancel: () => { /* el comprador cerró sin enviar */ }, }); // Descartar programáticamente el popup más tarde si es necesario: // close();
CampoTipoRequeridoNotas
tokenstring✓El token rfqt_… devuelto por POST /b2b/v1/merchants/{merchant_id}/refund-requests
mode"popup" | "redirect" | "embed"—Por defecto "popup". Misma semántica de superficie que sdk.checkout(): consulta Notas de modo
containerstring | HTMLElementsolo embedSelector CSS o elemento DOM donde se monta el iframe
localestring—Tag BCP-47 reenviado como ?locale= (en, vi, ja, ko, es, pt-BR, ru, tr, zh-CN, zh-TW)
hideHeaderboolean—Oculta el header de InfraIO Pay dentro del iframe. En popup/embed el SDK dibuja su propio chrome de modal, así que el header de la página suele ser innecesario. Por defecto false
hideSummaryboolean—Oculta la columna de Resumen de Orden, mostrando solo el formulario de reembolso. Por defecto false
walletAddressstring—Pre-rellena el campo de wallet de destino (?wallet_address=). Deja que un comerciante que ya conoce la wallet del comprador salte el re-tipeo manual
onSuccess(data: { linkToken: string; refundId: string }) => void—Se dispara tras el envío del formulario por el comprador. linkToken → página de estado /r/:linkToken para compartir con el comprador. refundId → usar con la API B2B para aprobar / rechazar
onCancel() => void—Se dispara cuando el comprador cierra el popup/embed sin enviar
onError(err: InfraIoError) => void—Se dispara en fallo de carga del iframe o args inválidos. La expiración / cancelación del token la maneja la página alojada, no vía onError

Estados del token expuestos vía onError

Si el comprador abre un token caducado, la propia página maneja la visualización (renderiza un prompt “Expirado: solicita un enlace nuevo”, etc.), y el SDK no dispara onError para esos casos: el comprador está dentro del flujo del formulario y tu código no necesita reaccionar. onError solo se dispara para cosas sobre las que tu código puede actuar (argumentos incorrectos, fallo de red al cargar el iframe).

openRefundRequest registra la intención del reembolso: no mueve fondos. Tras onSuccess, la fila de reembolso es PENDING (o APPROVED si tu config de comerciante auto-aprueba reembolsos de cliente). Aún necesitas firmar y difundir la transferencia on-chain desde tu wallet de Tesorería, luego publicar el tx hash en POST /b2b/v1/refunds/:id/submit-tx. Consulta Conceptos → Reembolsos para el ciclo de vida completo.

Clase de error

import { InfraIoError } from "@lartech/infraio-checkout-js"; sdk.checkout({ sessionId, onError: (err: InfraIoError) => { switch (err.code) { case "invalid_request_error": /* sessionId / args malos */ break; case "iframe_load_error": /* el iframe falló al cargar */ break; case "iframe_timeout_error": /* excedió timeoutMs */ break; case "already_open_error": /* otro checkout ya está abierto */ break; case "network_error": /* problema de red transitorio hablando con el origin del checkout */ break; case "api_error": /* el backend devolvió un no-2xx para una llamada emitida por el SDK */ break; } }, });

sdk.openRefundRequest() solo lanza invalid_request_error (token / args ausentes o inválidos), de forma síncrona. iframe_load_error (el iframe de solicitud de reembolso falló al cargar) se entrega de forma asíncrona vía onError, no se lanza. No emite iframe_timeout_error ni already_open_error: el popup de solicitud de reembolso no tiene timeout de carga y permite múltiples popups concurrentes.

Notas de modo

  • Overlay centrado con un fondo oscuro semi-transparente
  • z-index: 2147483647 (max int32): se sienta encima de todo lo demás
  • El scroll del body se bloquea mientras está abierto; se restaura al cerrar
  • El botón de cerrar recibe el foco inicial; Tab queda atrapado en el popup
  • Se cierra por: botón de cerrar, Escape, clic fuera, sdk.close(). Todos ellos llaman a onCancel
  • La página de checkout puede solicitar redimensión vía postMessage: el SDK acota dentro de los límites de width/height

Redirect

  • Navegación dura vía window.location.href
  • Añade automáticamente ?return_url=<página-actual> para que el comprador regrese de donde vino. Si tu success_url / cancel_url en la sesión ya cubren esto, el viaje de ida y vuelta ignora return_url

Embed

  • iframe con allow="payment; clipboard-write" (directivas de Feature Policy HTML5, no el atributo sandbox). El iframe se sirve desde el origin del checkout, así que los popups de wallet y las escrituras al portapapeles desde el lado del comprador funcionan sin opt-in adicional.
  • El ancho del contenedor es 100%; la altura se autodimensiona vía postMessage INFRAIO_RESIZE, acotado a [200, 2000]px
  • Sin aislamiento CSS más allá del borde del iframe: los estilos de tu página padre no se filtran
  • Cablea siempre onReady para que puedas ocultar tu propio estado de carga cuando el checkout se vuelva interactivo

TypeScript

Todos los tipos están incluidos. Las exportaciones más útiles:

import type { CheckoutOptions, RefundRequestOptions, LoadOptions, InfraIoInstance, InfraIoErrorCode, } from "@lartech/infraio-checkout-js"; import { loadInfraIo, InfraIoError, VERSION } from "@lartech/infraio-checkout-js";

VERSION es la cadena de versión del propio SDK: útil en reportes de bug.