Documentation Index
Fetch the complete documentation index at: https://developer.pagou.ai/llms.txt
Use this file to discover all available pages before exploring further.
Use esta página quando estiver saindo de uma integração de demonstração para um checkout seguro para produção.
Fluxo seguro para produção
- Desabilite envios duplicados no navegador.
- Chame
elements.submit(...) apenas uma vez por tentativa de checkout.
- Deixe o back-end criar a transaction.
- Trate
next_action quando 3D Secure for necessário.
- Faça fulfillment apenas a partir de webhook ou reconciliação.
Padrão de submit no front-end
let isSubmitting = false;
let lastTokenData = null;
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (isSubmitting) return;
isSubmitting = true;
const result = await elements.submit({
createTransaction: async (tokenData) => {
lastTokenData = tokenData;
const response = await fetch("/api/pay", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: tokenData.token,
amount: 2490,
orderId: "order_2001",
}),
});
const payload = await response.json();
return payload.data ?? payload;
},
});
isSubmitting = false;
if (result.status === "error") {
messageEl.textContent = result.error ?? "Pagamento falhou.";
return;
}
if (lastTokenData) {
cardSummaryEl.textContent = `${lastTokenData.brand} final ${lastTokenData.last4}`;
}
});
elements.submit(...) é o gatilho de tokenização. Ele cria uma sessão de Element se necessário, solicita a tokenização ao campo hospedado e chama o callback createTransaction com o payload do token.
Payload do token
O callback createTransaction recebe metadados não sensíveis do cartão junto com o token:
{
"token": "pgct_token_from_browser",
"brand": "visa",
"last4": "4242",
"exp_month": "12",
"exp_year": "2030"
}
Envie tokenData.token ao seu back-end para criar a transação. Use brand, last4, exp_month e exp_year apenas para UI provisória do checkout ou bookkeeping do seu próprio back-end; o estado final do pagamento continua vindo da resposta da transação, webhook ou reconciliação.
Exemplo de requisição do back-end
{
"external_ref": "order_2001",
"amount": 2490,
"currency": "BRL",
"method": "credit_card",
"token": "pgct_token_from_browser",
"installments": 1
}
Exemplo de resposta do back-end
{
"success": true,
"requestId": "req_4003",
"data": {
"id": "tr_2001",
"status": "three_ds_required",
"next_action": {
"type": "three_ds_challenge",
"challenge_session_id": "3ds_1001",
"client_secret": "sec_1001",
"expires_at": "2026-03-16T14:20:00.000Z"
}
}
}
Erro comum
{
"type": "https://api.pagou.ai/problems/validation-error",
"title": "Validation Error",
"status": 422,
"detail": "The request contains invalid data.",
"errors": [
{
"field": "token",
"message": "Token is required for credit card payments",
"code": "invalid_type"
}
]
}
Como corrigir: não crie a transaction antes de o navegador ter um token do Payment Element. Se um fluxo de challenge for interrompido, reconcilie a transaction antes de permitir nova tentativa.
Tratamento de estado inválido
Mantenha o botão de submit desabilitado até que o campo de cartão reporte um estado válido:
let cardIsValid = false;
card.on("change", ({ valid, brand, errors }) => {
cardIsValid = valid;
submitButton.disabled = !cardIsValid || isSubmitting;
brandEl.textContent = brand ?? "";
errorEl.textContent = Object.values(errors ?? {})[0] ?? "";
});
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (!cardIsValid || isSubmitting) return;
// Chame elements.submit(...) aqui.
});
Se elements.submit(...) retornar { "status": "error" }, não chame seu back-end novamente com um token ausente ou antigo. Mostre o erro retornado, deixe o comprador corrigir os dados do cartão e execute uma nova tentativa de checkout.
Regra de estado final
Uma mensagem de sucesso no navegador não basta para fazer fulfillment do pedido. O fulfillment final pertence ao estado do pagamento confirmado por webhook ou reconciliação.