Saltar al contenido principal

Checkout web y app

@finora/checkout es un Web Component sin dependencias (~18 KB min+gz) que dibuja la experiencia de pago de FINORA dentro de tu página: «¿Cómo quieres pagar?», tarjetas grandes por medio, campos guiados, espera al terminal, recibo. Es la misma experiencia de FINORA Caja y de la página alojada pago.finoracore.com, así que tu cliente la reconoce.

Instalación​

Etiqueta
<script src="https://pago.finoracore.com/sdk/finora-checkout.js"></script>
<!-- registra <finora-checkout> y el global FinoraCheckout -->
npm
npm i @finora/checkout
ESM
import { FinoraCheckout } from "@finora/checkout"; // registra <finora-checkout> al importar

Navegadores: Chrome/Edge 90+, Safari 15+, Firefox 90+. El SDK no carga fuentes, scripts ni imágenes externas: habla solo con base-url. Si tu CSP es estricta: connect-src https://pos.finoracore.com.

Tres formas de mostrarlo​

A. Redirigir a urlPago​

La respuesta de POST /api/v1/checkout/sesiones trae urlPago. Redirige al cliente y listo: al terminar vuelve a tu returnUrl con ?sesion={sesionId}&estado={estado}. La página alojada muestra el nombre de tu comercio en la cabecera.

B. <finora-checkout> en tu página​

<finora-checkout sesion="cs_…" token="tok_…" base-url="https://pos.finoracore.com"
tema="claro" idioma="es" teclado="auto" style="height: 40rem"></finora-checkout>
AtributoValoresPor defectoQué hace
sesionid de sesiónobligatorioLa sesión que creó tu servidor.
tokentoken de clienteobligatorioSolo sirve para esa sesión; vence con ella.
base-urlURLorigen de la páginaRaíz del Merchant: https://pos.finoracore.com.
temaclaro · oscuro · autoclaroauto sigue prefers-color-scheme.
idiomaes · enidioma del navegadorTextos del SDK. Los nombres de los medios vienen del Merchant.
tecladoauto · siempre · nuncaautoTeclado numérico en pantalla para cédula, teléfono y clave (auto = solo táctil).
modoincrustado · pantallaincrustadopantalla lo usa la página alojada.

El componente llena la altura de su contenedor: dale height. Por debajo de 760 px de ancho el resumen pasa a una barra superior y los medios a una columna.

C. Modal con FinoraCheckout.abrir​

const instancia = FinoraCheckout.abrir({
sesionId, token, baseUrl: "https://pos.finoracore.com",
modal: true, // por defecto si no hay `contenedor`
contenedor: "#pago", // elemento o selector; desactiva el modal
tema: "claro", idioma: "es",
onSesion: (sesion) => {}, // monto, comercio, medios: para pintar tu cabecera
onResultado: (r) => {}, // { sesionId, estado, riel, codigo, mensaje, autorizacion, recibo }
onCancelar: () => {},
onError: (e) => console.error(e.codigo, e.mensaje),
});

instancia.cancelar(); // cancela en el servidor
instancia.cerrar(); // desmonta sin cancelar (por ejemplo, tras onResultado)

Como modal: capa sobre la página (role="dialog", aria-modal), foco atrapado, Escape cancela solo mientras no hay dinero en vuelo. Tras onResultado cierra tú con cerrar() cuando hayas mostrado lo que quieras; el cliente ve el recibo hasta entonces.

Eventos​

Todos son CustomEvent, burbujean y cruzan el shadow DOM.

EventodetailCuándo
finora-sesionSesionDtoSe cargó la sesión: monto, comercio, medios.
finora-resultado{ sesionId, estado, riel, codigo, mensaje, autorizacion, recibo }La sesión terminó. estado ∈ APROBADA · RECHAZADA · EN_DUDA · CANCELADA · EXPIRADA; codigo es el DE 39 del banco («00», «51») o el motivo (CANCELADA_POR_CLIENTE).
finora-cancelar—El cliente canceló.
finora-error{ codigo, mensaje }Error que impide seguir: TOKEN_INVALIDO, SESION_NO_ENCONTRADA, red al cargar.
No entregues con onResultado

finora-resultado es JavaScript en el navegador del cliente. Entrega el pedido con el webhook firmado o consultando GET /api/v1/checkout/sesiones/{id} con tu clave.

Lo que hace por dentro​

GET /api/v1/checkout/sesiones/{id} ← medios, monto, campos requeridos
(cédula si payerIdMode = ANTES_DE_MEDIOS y no vino en `pagador`)
selector de medios · formulario por riel (campos desde `campos[]`)
POST /api/v1/checkout/sesiones/{id}/medio ← { riel, campos, tipoDocumento?, documento? }
GET /api/v1/checkout/sesiones/{id}/estado ← cada 2 s mientras haya un cobro en vuelo
POST /api/v1/checkout/sesiones/{id}/cancelar ← «Cancelar»

Reglas de la experiencia, heredadas de FINORA Caja:

  • Los medios no disponibles se ven atenuados con su motivo («Mínimo Bs 500,00», «Sin terminal asignado»), no se esconden.
  • RECHAZADA es final. Crea otra sesión si el cliente quiere intentar con otro medio.
  • Lo único que reabre el selector es el terminal que no toma la orden: la sesión vuelve a CREADA con codigo = TERMINAL_SIN_RESPUESTA.
  • EN_DUDA no ofrece reintentar: «no vuelvas a pagar». Reintentar un cobro que pudo ocurrir es cobrar dos veces.
  • Sin campo de tarjeta en ningún sitio. Tarjeta = «paga en el terminal» (terminalId de la sesión, por ejemplo TERM0042).

Tema​

El componente vive en un shadow root: tu CSS no lo toca. Lo único que lo atraviesa son las custom properties --fc-*:

finora-checkout {
--fc-color-primary: #0b6e4f; /* botón principal, borde al pasar */
--fc-color-primary-contrast: #fff;
--fc-color-accent: #ffb703; /* anillo de foco, paso activo del terminal */
--fc-font: "Inter", system-ui, sans-serif;
--fc-radius: 8px;
}
finora-checkout[tema="oscuro"] { --fc-color-bg: #000; }

Tokens disponibles: --fc-color-{primary,primary-contrast,accent,bg,surface,surface-2,text,text-2,text-3,line,line-2,ok,ok-bg,error,error-bg,warn,warn-bg}, --fc-font, --fc-font-mono, --fc-radius, --fc-radius-sm, --fc-shadow, y --fc-tint-{tarjeta,movil,transferencia,efectivo,qr,cripto,otro} para el icono de cada medio. La composición y los textos no se cambian a propósito: el cliente los reconoce de la Caja.

Accesibilidad​

role="region" con etiqueta, un h1 por paso, aria-live en la espera, role="alert" en errores, aria-invalid + aria-describedby en campos, foco al primer campo o al primero con error, teclas de 4,25 rem, contraste AA, prefers-reduced-motion respetado. En kiosco o tableta, con puntero táctil aparece el teclado numérico en pantalla.

Kiosco y app nativa​

En una WebView (Android, iOS, Electron) funciona igual: la app pide la sesión a tu servidor y monta el componente. Para una caja de escritorio en Windows que no quiera tocar HTML, mira FINORA Pago: la misma sesión, orquestada por una aplicación instalable con API local.