Inyo

Integração via Iframe

Guia passo a passo para integrar a Hosted Payment Page ao seu site por meio do iframe.

Resumo do fluxo: seu backend cria uma sessão segura (autenticada via OAuth 2.0) → recebe um sessionToken → seu frontend carrega o SDK e monta o iframe com esse token → o cliente paga → você recebe o resultado via callback ou redirect → seu backend confirma a transação.


Pré-requisitos

Antes de começar, você precisa das credenciais fornecidas pela Inyo:

CredencialDescrição
OAUTH_CLIENT_IDIdentificador do seu tenant (cliente).
OAUTH_CLIENT_SECRETSegredo usado para autenticar a criação de sessões.
URL do backendEndpoint da API de sessões (referido abaixo como https://{HPP_API}).
URL do frontendOrigem da página hospedada que roda dentro do iframe (referida abaixo como https://{HPP_HOST}).

O OAUTH_CLIENT_SECRET nunca deve aparecer no frontend. Toda a criação de sessões acontece no seu servidor.


Etapa 1 — Crie uma sessão de pagamento (no seu backend)

Antes de exibir o iframe, seu servidor cria uma sessão. Esta chamada é protegida por OAuth 2.0 Client Credentials (HTTP Basic Auth).

Endpoint: POST /api/sessions/create

Autenticação: header Authorization: Basic base64(clientId:clientSecret)

Parâmetros do corpo da requisição

ParâmetroTipoObrigatórioDescrição
amountNumberSimValor da transação (ex.: 50.00). Use 0 para card_validation.
currencyStringSimCódigo da moeda (atualmente apenas USD).
transactionTypeStringSimpayment, card_validation ou account_validation.
parentOriginStringSimOrigem HTTPS da página que hospeda o iframe (ex.: https://your-site.com).
captureBooleanNãotrue captura imediatamente; false apenas autoriza (padrão).
tokenTypeStringNãoone_time (padrão) ou recurring.
customCssStringNãoURL de um arquivo CSS hospedado para personalizar a aparência.
billingPreferenceStringNãoVisibilidade dos campos de cobrança: editable (padrão), read_only ou hidden.
billingDetailsObjectNãoPré-preenche os dados de cobrança (nome, e-mail, endereço, etc.).
threeDSDataObjectNãoConfiguração do 3D Secure: { "enable": true, "successUrl": "...", "failUrl": "..." }.
metadataObjectNãoDados livres de rastreamento (ex.: orderId, customerId, uiOrder).

Exemplo (Node.js)

const clientId = process.env.OAUTH_CLIENT_ID;
const clientSecret = process.env.OAUTH_CLIENT_SECRET;
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');

const response = await fetch('https://{HPP_API}/api/sessions/create', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 50.00,
    currency: 'USD',
    transactionType: 'payment',
    parentOrigin: 'https://your-site.com',
    billingPreference: 'editable',
    threeDSData: { enable: true },
    metadata: { orderId: 'ORD-789' }
  })
});

const session = await response.json();
// Retorne SOMENTE o sessionToken ao seu frontend.

Resposta

{
  "sessionToken": "eyJ...",
  "sessionId": "sess_uuid",
  "expiresAt": "2026-06-16T12:15:00Z",
  "tenant": {
    "name": "Your Company",
    "logoUrl": "https://...",
    "supportEmail": "support@...",
    "primaryColor": "#3b82f6",
    "paymentMethods": ["card", "ach"]
  }
}

O sessionToken expira em 15 minutos por padrão. Crie a sessão apenas quando o cliente estiver pronto para pagar.


Etapa 2 — Carregue o SDK no seu frontend

Inclua o script do SDK na página onde o checkout será exibido e adicione um contêiner (uma <div>) onde o iframe será montado.

<!-- Contêiner onde o iframe será inserido -->
<div id="checkout-container"></div>

<!-- SDK de checkout -->
<script src="https://{HPP_HOST}/iframe.min.js"></script>

Etapa 3 — Inicialize e monte o iframe

Use o sessionToken obtido na Etapa 1 para inicializar o SDK e montar o iframe no contêiner.

<script>
  InyoCheckout.init({
    sessionToken: 'SESSION_TOKEN_FROM_BACKEND',

    // Chamado quando o pagamento é aprovado/autorizado
    onSuccess: (data) => {
      console.log('Payment approved!', data.transaction);
      // data.transaction = { status, paymentId, cardToken, billingInfo }
      // IMPORTANTE: confirme no seu backend antes de concluir o pedido (Etapa 5).
    },

    // Chamado quando o pagamento é recusado ou ocorre um erro
    onError: (error) => {
      console.error('Payment failed:', error);
    }
  });

  InyoCheckout.mount('#checkout-container');
</script>

Opções aceitas por init

OpçãoDescrição
sessionTokenObrigatório. Token retornado na Etapa 1.
onSuccess(data)Callback de sucesso. Recebe { transaction }.
onError(error)Callback de erro/recusa.
storeLaterUsetrue para exibir a opção "salvar cartão para uso futuro".
threeDSDataConfiguração do 3D Secure (espelha o que foi enviado na sessão).

O sessionToken não vai na URL do iframe — o SDK o envia internamente via postMessage (INIT_SESSION) após o iframe carregar. O iframe também é carregado em modo sandbox por segurança.


Etapa 4 — Receba o resultado do pagamento

Você pode tratar o resultado de duas formas (use uma ou ambas).

Opção A — Callbacks JavaScript

O SDK dispara onSuccess ou onError automaticamente. O objeto data.transaction contém:

{
  status: 'APPROVED' | 'AUTHORIZED' | 'DECLINED' | 'CHALLENGE' | 'PENDING',
  paymentId: 'pay_12345',
  cardToken: { token: '...', schemeId: 'VISA', lastFourDigits: '4242' },
  billingInfo: { /* endereço de cobrança preenchido */ }
}

Exemplo:

onSuccess: (data) => {
  const { status, paymentId } = data.transaction;
  if (status === 'APPROVED' || status === 'AUTHORIZED') {
    window.location.href = `/confirmation?pid=${paymentId}`;
  }
}

Opção B — Redirect (server-side)

Se você forneceu successUrl / failUrl ao criar a sessão (dentro de threeDSData ou na configuração da sessão), o iframe redireciona a página inteira ao final, anexando os parâmetros:

https://your-site.com/success?sessionId=sess_123&paymentId=pay_456

Status possíveis

StatusSignificado
AUTHORIZEDAutorizado (ainda não capturado).
APPROVED / CAPTUREDPagamento concluído.
DECLINEDCartão recusado.
CHALLENGERequer verificação 3D Secure (tratada automaticamente pelo iframe).
PENDINGPagamento assíncrono (ex.: ACH) aguardando confirmação.

Etapa 5 — Confirme a transação no seu backend (obrigatório)

Nunca conclua o pedido com base apenas no callback do frontend. Sempre confirme o status a partir do seu servidor.

Opção 1 — Consulte o status da sessão

GET /api/sessions/:sessionId Header: x-session-token: <sessionToken>

const res = await fetch(`https://{HPP_API}/api/sessions/${sessionId}`, {
  headers: { 'x-session-token': sessionToken }
});
const session = await res.json();

if (session.status === 'completed') {
  // Conclua o pedido com segurança.
}

Opção 2 — Verifique junto ao gateway pelo paymentId

POST /api/verify-transaction Header: x-session-token: <sessionToken> Body: { "paymentId": "pay_123" }


Personalização visual

A aparência do checkout é totalmente personalizável:

  • CSS personalizado: envie um customCss (URL de uma folha de estilos hospedada) ao criar a sessão para sobrescrever os estilos padrão.
  • Cor da marca: definida no registro do tenant (primaryColor), aplicada a botões e destaques.
  • Campos de cobrança: controle a visibilidade com billingPreference (editable, read_only, hidden) e pré-preencha com billingDetails.
  • Ordem das seções: controle a ordem das seções de cobrança e pagamento via metadata.uiOrder (ex.: ["billing", "payment"]).

Comportamento automático do iframe

  • Redimensionamento: o iframe ajusta a própria altura conforme o conteúdo muda (via mensagem RESIZE_IFRAME). Não defina uma altura fixa.
  • 3D Secure: quando necessário, o iframe trata o redirect ao banco e a verificação ACS automaticamente, validando o resultado no backend antes de disparar onSuccess / onError. Veja Handling 3D secure para o comportamento subjacente do gateway.

Protocolo postMessage (referência)

O SDK e o iframe se comunicam por window.postMessage. Normalmente você não trata essas mensagens diretamente — o SDK as traduz para os callbacks do init — mas elas estão documentadas aqui para depuração.

Direçãotype da mensagemPayload
Parent → iframeINIT_SESSION{ sessionToken }
iframe → ParentRESIZE_IFRAME{ height }
iframe → ParentPAYMENT_SUCCESS{ transaction } → dispara onSuccess
iframe → ParentPAYMENT_ERROR{ error } → dispara onError

Checklist de integração

  • [ ] Credenciais OAuth (clientId / clientSecret) mantidas apenas no backend.
  • [ ] Sessão criada via POST /api/sessions/create no servidor.
  • [ ] parentOrigin definido corretamente (HTTPS em produção).
  • [ ] SDK (iframe.min.js) carregado e iframe montado com o sessionToken.
  • [ ] onSuccess / onError (ou redirects) tratados no frontend.
  • [ ] Transação confirmada no backend antes de concluir o pedido.

Exemplo completo (condensado)

Backend (cria a sessão):

const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
const r = await fetch('https://{HPP_API}/api/sessions/create', {
  method: 'POST',
  headers: { 'Authorization': `Basic ${credentials}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    amount: 29.99,
    currency: 'USD',
    transactionType: 'payment',
    parentOrigin: 'https://your-site.com',
    metadata: { orderId: 'ORD-123' }
  })
});
const { sessionToken } = await r.json();
// envie o sessionToken ao frontend

Frontend (monta o iframe):

<div id="checkout"></div>
<script src="https://{HPP_HOST}/iframe.min.js"></script>
<script>
  InyoCheckout.init({
    sessionToken: sessionTokenFromBackend,
    onSuccess: async (data) => {
      await fetch('/api/confirm-payment', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ paymentId: data.transaction.paymentId })
      });
    },
    onError: (err) => alert('Payment not completed.')
  });
  InyoCheckout.mount('#checkout');
</script>