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:
| Credencial | Descrição |
|---|---|
OAUTH_CLIENT_ID | Identificador do seu tenant (cliente). |
OAUTH_CLIENT_SECRET | Segredo usado para autenticar a criação de sessões. |
| URL do backend | Endpoint da API de sessões (referido abaixo como https://{HPP_API}). |
| URL do frontend | Origem da página hospedada que roda dentro do iframe (referida abaixo como https://{HPP_HOST}). |
O
OAUTH_CLIENT_SECRETnunca 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âmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
amount | Number | Sim | Valor da transação (ex.: 50.00). Use 0 para card_validation. |
currency | String | Sim | Código da moeda (atualmente apenas USD). |
transactionType | String | Sim | payment, card_validation ou account_validation. |
parentOrigin | String | Sim | Origem HTTPS da página que hospeda o iframe (ex.: https://your-site.com). |
capture | Boolean | Não | true captura imediatamente; false apenas autoriza (padrão). |
tokenType | String | Não | one_time (padrão) ou recurring. |
customCss | String | Não | URL de um arquivo CSS hospedado para personalizar a aparência. |
billingPreference | String | Não | Visibilidade dos campos de cobrança: editable (padrão), read_only ou hidden. |
billingDetails | Object | Não | Pré-preenche os dados de cobrança (nome, e-mail, endereço, etc.). |
threeDSData | Object | Não | Configuração do 3D Secure: { "enable": true, "successUrl": "...", "failUrl": "..." }. |
metadata | Object | Não | Dados 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
sessionTokenexpira 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ção | Descrição |
|---|---|
sessionToken | Obrigatório. Token retornado na Etapa 1. |
onSuccess(data) | Callback de sucesso. Recebe { transaction }. |
onError(error) | Callback de erro/recusa. |
storeLaterUse | true para exibir a opção "salvar cartão para uso futuro". |
threeDSData | Configuração do 3D Secure (espelha o que foi enviado na sessão). |
O
sessionTokennão vai na URL do iframe — o SDK o envia internamente viapostMessage(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
| Status | Significado |
|---|---|
AUTHORIZED | Autorizado (ainda não capturado). |
APPROVED / CAPTURED | Pagamento concluído. |
DECLINED | Cartão recusado. |
CHALLENGE | Requer verificação 3D Secure (tratada automaticamente pelo iframe). |
PENDING | Pagamento 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 combillingDetails. - 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ção | type da mensagem | Payload |
|---|---|---|
| Parent → iframe | INIT_SESSION | { sessionToken } |
| iframe → Parent | RESIZE_IFRAME | { height } |
| iframe → Parent | PAYMENT_SUCCESS | { transaction } → dispara onSuccess |
| iframe → Parent | PAYMENT_ERROR | { error } → dispara onError |
Checklist de integração
- [ ] Credenciais OAuth (
clientId/clientSecret) mantidas apenas no backend. - [ ] Sessão criada via
POST /api/sessions/createno servidor. - [ ]
parentOrigindefinido corretamente (HTTPS em produção). - [ ] SDK (
iframe.min.js) carregado e iframe montado com osessionToken. - [ ]
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>
