Regra mais importante
Seu token de autenticação da API nunca deve aparecer neste HTML. O navegador protege o cartão e apresenta o challenge; o seu servidor autentica e chama a API Sopague.
Quem faz o quê?
Antes de testar, entenda como os dados percorrem a integração.
/v1/payments/3ds.
Preparar a biblioteca
Receba a chave pública do seu backend e inicialize o contexto de segurança.
Em produção, crie um endpoint próprio, por exemplo GET /api/checkout/public-key, que repasse somente a chave pública.
Ver o código desta etapa
// Backend: sua API obtém a chave usando o Bearer token da Sopague
const response = await fetch(`${SOPAGUE_URL}/v1/cards/public-key`, {
headers: { Authorization: `Bearer ${accessToken}` }
});
const { key } = await response.json();
// Frontend: recebe somente a chave pública
const { key } = await fetch('/api/checkout/public-key').then(r => r.json());
Sopague.setEncryptPublicKey(toPem(key));
const antiFraudId = crypto.randomUUID();
const codeAntiFraud = Sopague.initAntiFraud(antiFraudId);
Proteger o cartão e coletar o dispositivo
A criptografia acontece somente quando o comprador confirma a compra.
Não gere o token ao abrir a página e não o armazene. Gere imediatamente antes de criar o pagamento.
Dados do cliente
Preencha com os dados reais do comprador. O exemplo não contém informações pessoais pré-cadastradas.
Ver o código desta etapa
const encryptedCard = await Sopague.encryptCard(cardNumber);
const deviceInfo = {
httpAcceptBrowserValue: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
httpAcceptContent: '*/*',
httpBrowserLanguage: navigator.language,
httpBrowserJavaEnabled: navigator.javaEnabled(),
httpBrowserJavaScriptEnabled: true,
httpBrowserColorDepth: String(screen.colorDepth),
httpBrowserScreenHeight: String(screen.height),
httpBrowserScreenWidth: String(screen.width),
httpBrowserTimeDifference: String(-new Date().getTimezoneOffset()),
userAgentBrowserValue: navigator.userAgent,
ipAddress: customerIpAddress
};
Criar o pagamento
O navegador envia o checkout preparado ao seu servidor.
Copie o payload abaixo para visualizar o contrato entre o frontend e o seu backend. O servidor acrescentará credenciais e substituirá os campos confiáveis, como IP, URL 3DS e tipo de produto.
Prepare as etapas anteriores para gerar o payload.
Ver o código do endpoint do cliente
// Exemplo conceitual. Mantenha credenciais, IP e regras de negócio no servidor.
app.post('/api/checkout/payments', async (req, res) => {
const gatewayPayload = montarPagamento3DS(req.body);
const response = await fetch(`${SOPAGUE_URL}/v1/payments/3ds`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(gatewayPayload)
});
res.status(response.status).json(await response.json());
});
Interpretar a resposta
O banco pode autenticar silenciosamente ou exigir a confirmação do comprador.
Quando o retorno exigir challenge, a biblioteca recebe o primeiro campo disponível entre pareq, creq e threeDs.paymentToken, além de threeDs.acsUrl. O backend valida o resultado usando authenticationTransactionId e paymentToken da resposta de criação.
Executar o challenge
A biblioteca apresenta o ambiente seguro do banco emissor.
Os dados do challenge e acsUrl pertencem a uma única tentativa e devem vir da resposta de criação do pagamento.
pareq, creq ou threeDs.paymentToken.
threeDs.acsUrl.
Ver uma integração mais simples com Promise
function executarChallenge({ creq, acsUrl }) {
return new Promise((resolve, reject) => {
try {
Sopague.start3DSChallenge(creq, acsUrl, resolve);
} catch (error) {
reject(error);
}
});
}
const challengeResult = await executarChallenge({ creq, acsUrl });
// Agora envie o resultado ao seu backend para validação.
Validar e concluir
Envie os dados da autenticação ao backend para concluir o pagamento.
Envie ao seu backend os dados exibidos abaixo. Ele deve chamar POST /v1/payments/3ds/validate-v2 com authenticationTransactionId e paymentToken da resposta de criação. Depois, cole aqui o JSON retornado por essa validação. O pagamento só será considerado realizado quando returnCode for "0".
Conclua o challenge para preparar os dados de validação.
Exemplo de resposta de pagamento aprovado
{
"returnCode": "0",
"description": "SUCESSO",
"paymentId": "864794851310011023208647948513102709202619",
"authorizationCode": "908362",
"orderNumber": "86479485131001102320",
"amount": 123,
"releaseAt": "2026-09-27T19:04:00"
}
Jornada concluída
Você percorreu as responsabilidades do frontend e do backend. Use a checklist abaixo antes de levar a integração para produção.