SDK JavaScript / Navegador
@lartech/infraio-checkout-js é o único SDK que a gente publica
hoje. Roda no navegador e abre o nosso checkout hospedado. SDKs de
backend (Node, Go, Python) estão no roadmap; até lá, fale direto com
o gateway — veja o Início rápido
para um helper de assinatura HMAC.
- Versão atual:
0.1.1-beta.17(pré-1.0; espere pequenas quebras) - Formatos: ESM (
index.js), CJS (index.cjs), IIFE (index.global.js) - Tipos embutidos (
index.d.ts) - Zero dependências de runtime — sem React, jQuery ou outras deps
Não existe ponto de entrada do lado do servidor. Helpers de
verificação de assinatura para webhooks não vêm embutidos —
implemente você mesmo com crypto (a página de verificação de
assinatura tem código
pronto para copiar e colar em 4 linguagens).
Instalação
npm
npm install @lartech/infraio-checkout-jsloadInfraIo(publicKey, options?)
Retorna uma Promise<InfraIoInstance>.
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere", {
// Opcional. Sobrescreva só quando apontar para um ambiente não-prod.
checkoutUrl: "https://checkout-dev.infraio.xyz",
});| Param | Tipo | Obrigatório | Notas |
|---|---|---|---|
publicKey | string | ✓ | Precisa combinar com pk_(live|test)_… |
options.checkoutUrl | string | — | Sobrescreve a URL base do checkout. Padrão: https://checkout.infraio.xyz. A URL de gateway correspondente é determinada pela página de checkout em runtime — cada deploy checkout(-dev).infraio.xyz carrega o seu NEXT_PUBLIC_API_URL de tempo de compilação, então escolher o hostname certo aqui escolhe o backend certo automaticamente. Não há uma opção gatewayUrl separada. |
sdk.checkout({ … })
Abre o checkout hospedado. Retorna void (use callbacks para
estado).
| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
sessionId | string | ✓ | session_key retornado por POST /b2b/v1/checkout-sessions/quick |
checkoutUrl | string | — | URL completa retornada pelo mesmo endpoint. Se omitida, o SDK constrói a partir do checkoutUrl de loadInfraIo() (ou do padrão) + sessionId |
mode | "popup" | "redirect" | "embed" | — | Padrão "popup" |
container | string | HTMLElement | só embed | Seletor CSS ou elemento do DOM onde o iframe é montado |
width | number | — | Só popup. Padrão 560. Limitado a [320, 1280] |
height | number | — | Só popup. Padrão 780. Limitado a [400, 1000] |
timeoutMs | number | — | Só popup. Timeout de carregamento do iframe. Padrão 30000. Passe 0 para desativar |
locale | string | — | Tag BCP-47 encaminhada como ?locale= para a página de checkout (en, ja, zh-CN, zh-TW) |
hideSummary | boolean | — | Esconde a coluna de resumo do pedido. Padrão false |
hideHeader | boolean | — | Esconde o header InfraIO e o botão embutido de wallet-connect. Padrão false. Combine com walletAddress para white-label completo |
walletAddress | string | — | Pré-conecta uma carteira do comprador. Requer onSignRequest |
walletChainId | number | — | EVM chain ID para a carteira pré-conectada |
onReady | () => void | — | Dispara uma vez que o iframe está interativo. Só popup/embed |
onSignRequest | (req: { method: string; params: unknown[] }) => Promise<string> | quando walletAddress está set | O SDK faz proxy das RPCs de carteira para o seu handler; retorne o hex assinado |
onSuccess | ({ sessionId }) => void | — | Dispara em pagamento bem-sucedido. Não é oficial — o webhook é |
onCancel | () => void | — | Dispara quando o comprador fecha o popup/embed sem pagar |
onError | (err: InfraIoError) => void | — | Dispara em falha de carregamento do iframe (modos popup + embed). Argumentos inválidos são lançados de forma síncrona, não entregues aqui. O modo redirect não tem superfície de erro em runtime — a falha é observada na página redirecionada. |
onSuccess não é oficial. Pode disparar mesmo quando o
webhook depois determina que o pagamento falhou (reorgs de
testnet, timing do lado do comprador). Use só para UX (mostrar
“Obrigado!”, redirecionar). Sempre confirme via webhook antes de
cumprir a entrega.
sdk.close()
Descarta programaticamente um popup ou embed aberto. No-op para o modo redirect.
sdk.checkout({ sessionId, mode: "popup", /* … */ });
// depois, por exemplo, quando o usuário navega para longe
sdk.close();sdk.openRefundRequest({ … })
Abre o formulário hospedado de pedido de reembolso para um
token de uso único que o seu backend criou via
POST /b2b/v1/merchants/{merchant_id}/refund-requests. O comprador
preenche o endereço de destino do reembolso + motivo + (opcional)
metadata na nossa página; a sua página só cuida do ciclo de
abertura/fechamento. Retorna uma função close() — chame para
descartar programaticamente o popup ou destacar o iframe de embed.
No modo redirect a função retornada é no-op.
O formulário vive em
https://checkout.infraio.xyz/refund-request/:token. Este método
só envelopa essa URL num popup / redirect / embed para que o
comprador nunca saia do seu domínio (em popup / embed) ou volte
para ele automaticamente (em redirect). O endpoint que o seu
backend chama para criar o token é
POST /b2b/v1/merchants/{merchant_id}/refund-requests — assinado
com HMAC pela sua chave secreta, mesma auth do resto da
superfície B2B. Veja
Conceitos → Reembolsos.
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere");
// Cria o token no servidor e entrega para o SDK no 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 }) => {
// Comprador submeteu o formulário.
// linkToken → página de status /r/:linkToken (compartilhe com o comprador).
// refundId → use com a API B2B para aprovar / rejeitar.
window.location.href = `/r/${linkToken}`;
},
onCancel: () => { /* comprador fechou sem enviar */ },
});
// Descarte programaticamente o popup depois, se precisar:
// close();| Campo | Tipo | Obrigatório | Notas |
|---|---|---|---|
token | string | ✓ | O token rfqt_… retornado por POST /b2b/v1/merchants/{merchant_id}/refund-requests |
mode | "popup" | "redirect" | "embed" | — | Padrão "popup". Mesma semântica de superfície do sdk.checkout() — veja Notas sobre os modos |
container | string | HTMLElement | só embed | Seletor CSS ou elemento do DOM onde o iframe é montado |
locale | string | — | Tag BCP-47 encaminhada como ?locale= (en, ja, zh-CN, zh-TW) |
hideHeader | boolean | — | Esconde o header InfraIO dentro do iframe. Em popup/embed o SDK desenha o próprio chrome de modal, então o header da página costuma ser ruído. Padrão false |
hideSummary | boolean | — | Esconde a coluna de Resumo do Pedido, mostrando só o formulário de reembolso. Padrão false |
walletAddress | string | — | Pré-preenche o campo de carteira de destino (?wallet_address=). Deixa um lojista que já conhece a carteira do comprador pular a re-digitação manual |
onSuccess | (data: { linkToken: string; refundId: string }) => void | — | Dispara depois que o comprador submete o formulário. linkToken → página de status /r/:linkToken para compartilhar com o comprador. refundId → use com a API B2B para aprovar / rejeitar |
onCancel | () => void | — | Dispara quando o comprador fecha o popup/embed sem submeter |
onError | (err: InfraIoError) => void | — | Dispara em falha de carregamento do iframe ou args inválidos. Expiração de token / cancelamento é tratado pela página hospedada, não via onError |
Estados de token expostos via onError
Se o comprador abre um token velho, a própria página cuida do
display (renderiza um prompt “Expirado — peça link novo”, etc.), e
o SDK não dispara onError para esses casos — o comprador
está dentro do fluxo do formulário e o seu código não precisa
reagir. onError só dispara para coisas em que o seu código pode
agir (argumentos ruins, falha de rede ao carregar o iframe).
openRefundRequest registra a intenção de reembolso — ele não
move fundos. Depois de onSuccess, a linha de reembolso está
PENDING (ou APPROVED se a sua config de lojista faz
auto-aprovação de reembolsos de cliente). Você ainda precisa
assinar e transmitir a transferência on-chain da carteira do seu
lojista e depois postar o tx hash em
POST /b2b/v1/refunds/:id/submit-tx. Veja
Conceitos → Reembolsos para o ciclo de
vida completo.
Classe de erro
import { InfraIoError } from "@lartech/infraio-checkout-js";
sdk.checkout({
sessionId,
onError: (err: InfraIoError) => {
switch (err.code) {
case "invalid_request_error": /* sessionId / args ruins */ break;
case "iframe_load_error": /* iframe falhou em carregar */ break;
case "iframe_timeout_error": /* excedeu timeoutMs */ break;
case "already_open_error": /* outro checkout já está aberto */ break;
case "network_error": /* problema de rede transiente falando com a origem do checkout */ break;
case "api_error": /* backend retornou não-2xx para uma chamada emitida pelo SDK */ break;
}
},
});sdk.openRefundRequest() lança somente invalid_request_error
(token / args ausentes ou inválidos), de forma síncrona.
iframe_load_error (o iframe de pedido de reembolso falhou em
carregar) é entregue de forma assíncrona via onError, não
lançado. Ele não emite iframe_timeout_error nem
already_open_error — o popup de pedido de reembolso não tem
load-timeout e permite múltiplos popups concorrentes.
Notas sobre os modos
Popup
- Overlay centralizado com um backdrop escuro semi-transparente
z-index: 2147483647(max int32) — fica acima de tudo- Scroll do body é travado enquanto aberto; restaurado no fechamento
- Botão de fechar pega o foco inicial; Tab é trapeado no popup
- Fechado por: botão de fechar, Escape, clique fora,
sdk.close(). Todos eles chamamonCancel - A página de checkout pode pedir resize via
postMessage— o SDK limita dentro dos limites dewidth/height
Redirect
- Navegação completa via
window.location.href - Anexa automaticamente
?return_url=<página-atual>para que o comprador volte ao lugar de onde veio. Se a suasuccess_url/cancel_urlna sessão já cobrem isso, a viagem de ida e volta ignorareturn_url
Embed
- iframe com
allow="payment; clipboard-write"(diretivas HTML5 Feature Policy — não o atributosandbox). O iframe é servido da origem do checkout, então popups de carteira e escritas no clipboard do lado do comprador funcionam sem opt-in adicional. - Largura do container é 100%; altura faz auto-resize via
postMessage
INFRAIO_RESIZE, limitada a[200, 2000]px - Sem isolamento CSS além da fronteira do iframe — os estilos da página pai não vazam para dentro
- Sempre conecte
onReadypara você poder esconder o seu próprio estado de carregamento quando o checkout fica interativo
TypeScript
Todos os tipos vêm embutidos. Exports mais úteis:
import type {
CheckoutOptions,
RefundRequestOptions,
LoadOptions,
InfraIoInstance,
InfraIoErrorCode,
} from "@lartech/infraio-checkout-js";
import { loadInfraIo, InfraIoError, VERSION } from "@lartech/infraio-checkout-js";VERSION é a string de versão do próprio SDK — útil em bug
reports.
Próximos passos
- Wrappers para React / Vue — planejados para a iteração
pós-lançamento, uma vez que a superfície JS vanilla estabilize
entre os lojistas-piloto. O SDK vanilla funciona bem dentro do
React hoje; os wrappers só vão remover o
useRefmanual + o plumbing de ciclo de vida. - Resumo de sessão entre abas — abre o checkout na aba A, termina na aba B. Útil quando um comprador segue um magic-link no meio do fluxo. Rastreado para o próximo minor release.
- Theming via CSS variables — expor um pequeno conjunto de design tokens (raio, cor de acento) no iframe para que lojistas consigam combinar a marca sem forkar a página.
- Helpers do lado do servidor — um pacote minúsculo
@lartech/infraio-serverexpondoverifyWebhook()+signedRequest()para que código de backend não precise copiar o ritual HMAC. Até ele chegar, a página de verificação de assinatura lista implementações drop-in em TypeScript, Go, Python e Ruby.