@baaskit/checkout-js
v0.1.3
Published
BaaskitCheckout SDK for embedding Baaskit card payments in merchant checkouts.
Downloads
651
Maintainers
Readme
BaaskitCheckout JS
@baaskit/checkout-js permite embeber Baaskit Tarjetas dentro del checkout existente de un comercio mediante un iframe controlado por SDK.
La V1 no procesa pagos reales en este repositorio. Incluye SDK, protocolo postMessage, mock local, ejemplos y tests para validar la arquitectura.
🤖 Para agentes de IA: este SDK trae un Skill de integración
Este paquete incluye un Skill de integración para agentes de IA (Claude, Cursor, Kiro, OpenCode, Antigravity, Copilot, Gemini, …). Es un conjunto de instrucciones autocontenidas que le permite a un agente integrar el checkout embebido de Baaskit end-to-end y sin soporte humano, en cualquier stack de e-commerce (Next.js, Remix/React Router, Shopify, Vue, Angular, PHP, vanilla JS, …). Si descargas o instalas este SDK, el agente puede leer el skill y dejar la integración funcionando solo.
Cómo lo descubre cada agente
| Archivo | Para qué sirve |
|---|---|
| AGENTS.md | Punto de entrada estándar cross-agent (lo leen Cursor, OpenCode y otros). Redirige al skill. |
| skills/baaskit-checkout-integration/SKILL.md | Skill canónico: mapa, reglas de oro, decisión de ui_mode, checklist y verificación. |
| .cursor/rules/baaskit-checkout.mdc | Puntero nativo para Cursor (descubrimiento automático). |
| .claude/skills/baaskit-checkout-integration/SKILL.md | Puntero nativo para Claude Code. |
Instalado como dependencia, el skill queda en
node_modules/@baaskit/checkout-js/skills/baaskit-checkout-integration/ (se incluye en el
paquete npm).
Qué cubre el skill
El skill (SKILL.md) más sus referencias en skills/baaskit-checkout-integration/references/:
| Referencia | Contenido |
|---|---|
| backend.md | OAuth2 client credentials, crear el OnlineCheckout (con ui_mode, cardholder, tokenization_enable), webhook y confirmación server-side, variables de entorno y ambientes. |
| frontend.md | Montar el SDK, botón "Pagar" del comercio, eventos, estados de UI y auto-resize. |
| security.md | PCI/SAQ A, CSP frame-ancestors, manejo de secretos, idempotencia. |
| troubleshooting.md | Fallos comunes y su solución (iframe que no carga, X-Frame-Options, pantalla en blanco, el pago no se confirma, error 502, …). |
El skill instruye al agente a preguntar primero el ui_mode (embedded_page embebido, por
defecto, o hosted_page con redirección) y a implementar la creación del OnlineCheckout en
consecuencia.
Cómo usarlo (agente)
- Lee
AGENTS.md. - Sigue
skills/baaskit-checkout-integration/SKILL.mdy abre las referencias según cada paso. - Pregunta el
ui_mode, detecta el stack del proyecto y traduce los patrones a ese stack.
Flujo correcto
La sesion Baaskit debe crearse cuando el cliente selecciona Baaskit Tarjetas como metodo de pago.
No debe crearse al cargar el carrito. Tampoco debe esperarse hasta que el cliente presione Pagar, porque el iframe necesita una sesion valida para inicializarse.
- Cliente selecciona
Baaskit Tarjetas. - Frontend del comercio llama a su backend:
POST /api/baaskit/session. - Backend valida carrito, stock, descuentos, shipping, impuestos, moneda y orden.
- Backend crea una sesion en Baaskit usando clave secreta.
- Frontend recibe
payment_link_url. - Frontend monta
BaaskitCheckout. - Baaskit procesa dentro del iframe.
- El iframe emite estado visual por
postMessage. - La orden se marca como pagada solo por webhook firmado o verificacion server-side.
Instalacion
npm install @baaskit/checkout-jsUso con bundler
import { BaaskitCheckout } from "@baaskit/checkout-js";
const checkout = await fetch("/api/baaskit/session", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
cartId: currentCart.id
})
}).then((response) => response.json());
BaaskitCheckout.mount("#baaskit-payment-container", {
paymentLinkUrl: checkout.payment_link_url,
environment: "production",
locale: "es-CL",
appearance: {
theme: "light",
borderRadius: "8px",
primaryColor: "#1155cc"
},
onReady: () => {
setUiState("ready");
},
onProcessing: () => {
setUiState("processing");
},
onSuccess: (payload) => {
setUiState("succeeded_pending_confirmation");
console.log("Pago aprobado visualmente", payload);
},
onError: (error) => {
setUiState(error.errorCode === "session_expired" ? "expired" : "failed");
},
onCancel: () => {
setUiState("failed");
}
});Uso con script
<script src="https://cdn.baaskit.com/checkout-js/v1/baaskit-checkout.umd.cjs"></script>
<script>
window.BaaskitCheckout.BaaskitCheckout.mount("#baaskit-payment-container", {
paymentLinkUrl: checkout.payment_link_url,
environment: "production"
});
</script>API
BaaskitCheckout.mount(selector, options);
BaaskitCheckout.unmount();
BaaskitCheckout.destroy();
BaaskitCheckout.openRedirectFallback();mount acepta un selector CSS o un HTMLElement. El SDK crea internamente el iframe; el comercio no debe insertarlo manualmente.
unmount remueve iframe, listeners y estado interno. Usalo cuando cambie el carrito, cantidad, cupon, shipping, total o moneda.
destroy hace lo mismo que unmount e invalida la instancia.
openRedirectFallback queda preparado para casos donde el flujo embebido no sea viable, por ejemplo 3DS bloqueado en iframe, WebView restrictiva o navegador incompatible.
Options
interface BaaskitCheckoutOptions {
paymentLinkUrl: string;
environment?: "development" | "production";
locale?: "es-CL" | "en-US";
appearance?: {
theme?: "light" | "dark" | "auto";
borderRadius?: string;
primaryColor?: string;
};
allowedOrigins?: string[];
embedBaseUrl?: string;
onReady?: () => void;
onProcessing?: (payload?: unknown) => void;
onSuccess?: (payload: {
paymentId: string;
sessionId: string;
orderId?: string;
}) => void;
onError?: (error: {
errorCode: string;
message: string;
recoverable: boolean;
}) => void;
onCancel?: () => void;
onResize?: (height: number) => void;
}embedBaseUrl existe para mocks locales y ambientes controlados. En integraciones reales se debe preferir environment.
Flujo POC /embebed
Para esta POC, el iframe se carga desde:
GET https://payment.dev.baaskit.com/embebed?id=JWTEl HTML del checkout se entrega y luego el JavaScript del iframe resuelve el OnlineCheckout llamando:
POST /onlinecheckout/token
Content-Type: application/json
{
"token": "JWT"
}Si /onlinecheckout/token responde correctamente, el iframe inicializa el formulario de tarjeta. Si falla, el iframe debe mostrar estado de checkout invalido, expirado o no disponible.
Esta decision es exclusiva de la POC. Para produccion, no recomiendo entregar el HTML completo antes de validar el JWT. El flujo productivo recomendado es:
GET /embebed?id=JWT
Backend valida el JWT con /onlinecheckout/token o validacion criptografica local
Si es valido, devuelve HTML del checkout
Si no es valido, devuelve error minimo sin cargar la superficie completa de pagoEstados sugeridos del comercio
type BaaskitUiState =
| "not_selected"
| "creating_session"
| "ready"
| "processing"
| "succeeded_pending_confirmation"
| "failed"
| "expired";succeeded_pending_confirmation significa exito preliminar en frontend. La orden real aun no debe considerarse pagada.
La pagina embebida debe ocultar los inputs de tarjeta al comenzar el procesamiento. Durante processing muestra un estado de espera y, tras baaskit.payment.succeeded, reemplaza el formulario por una confirmacion visual sin volver a exponer los datos ingresados. Si el pago falla y es recuperable, puede ofrecer volver al formulario para reintentar.
Backend de referencia del comercio
Crear sesion
POST /api/baaskit/session
Content-Type: application/json{
"cartId": "cart_123"
}Responsabilidades del backend:
- Buscar carrito server-side.
- Validar stock, precios, descuentos, shipping, impuestos, total y moneda.
- Crear o recuperar una orden pendiente.
- Crear
OnlineCheckouten Baaskit con clave secreta. - Retornar
payment_link_urlal frontend.
Respuesta:
{
"session_id": "bsk_chk_123",
"client_secret": "bsk_client_secret_xxx",
"expires_at": "2026-06-18T20:00:00Z"
}Webhook
POST /api/webhooks/baaskitResponsabilidades:
- Validar firma.
- Validar
event_ididempotente. - Validar
order_id. - Validar monto y moneda contra la orden local.
- Marcar la orden como pagada.
- Responder 2xx rapido.
- Ejecutar tareas largas en background.
API Baaskit conceptual
POST /v1/checkout/sessions
Authorization: Bearer sk_test_xxx
Idempotency-Key: UUID{
"order_id": "ORDER-10001",
"amount": 16295,
"currency": "CLP",
"description": "Compra ecommerce",
"customer": {
"email": "[email protected]"
},
"metadata": {
"cart_id": "cart_123",
"merchant_reference": "commerce_abc"
},
"return_url": "https://commerce.cl/checkout/result",
"webhook_url": "https://commerce.cl/api/webhooks/baaskit"
}Desarrollo local
npm install
npm test
npm run build
npm run devAbre http://localhost:5173/examples/vanilla/ para probar el mock.
TODO V1 hacia produccion
- Implementar
/embebedreal enpayment.baaskit.com. - Reemplazar mock por integracion real con Payment API y 3DS.
- Configurar CSP con
frame-ancestorspor comercio autorizado. - Implementar allowlist server-side de dominios merchant.
- Implementar firma de webhooks y validacion de idempotencia.
- Definir contrato final de errores recuperables y expiracion de sesion.
- Definir fallback redirect/modal para emisores o ACS que bloqueen iframe.
