Sopague · Exemplo educacional

Implemente um pagamento 3DS, do cartão ao resultado final

Esta página mostra a jornada completa e separa claramente o código do navegador das chamadas que devem permanecer no seu backend.

🔐

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.

Seu backend Obtém a chave pública Usa o Bearer token apenas no servidor.
Navegador Prepara os dados Criptografa o cartão e coleta o contexto do dispositivo.
Seu backend Cria o pagamento Envia a requisição para /v1/payments/3ds.
Navegador Mostra o challenge Somente quando solicitado pelo banco emissor.
Seu backend Valida e conclui Confirma o resultado e devolve o status ao checkout.
1

Preparar a biblioteca

Receba a chave pública do seu backend e inicialize o contexto de segurança.

Navegador
Seu backend busca a chave; o navegador apenas a utiliza.

Em produção, crie um endpoint próprio, por exemplo GET /api/checkout/public-key, que repasse somente a chave pública.

Aceita PEM completo ou o conteúdo Base64 devolvido pela API.
Gere um UUID diferente para cada tentativa de checkout.
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);
2

Proteger o cartão e coletar o dispositivo

A criptografia acontece somente quando o comprador confirma a compra.

Navegador
O token criptografado expira.

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.

Use o código ISO de duas letras, como BR para Brasil.
Normalmente o backend identifica o IP da requisição; não confie apenas em um valor informado pelo navegador.
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
};
3

Criar o pagamento

O navegador envia o checkout preparado ao seu servidor.

Seu backend
Esta página não chama a API Sopague diretamente.

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());
});
4

Interpretar a resposta

O banco pode autenticar silenciosamente ou exigir a confirmação do comprador.

Sopague / emissor
A página identifica automaticamente o próximo passo.

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.

Use esta área para registrar e inspecionar a resposta real. Nunca cole credenciais.
5

Executar o challenge

A biblioteca apresenta o ambiente seguro do banco emissor.

Navegador
Não fixe a ACS URL no código.

Os dados do challenge e acsUrl pertencem a uma única tentativa e devem vir da resposta de criação do pagamento.

Preenchido automaticamente com pareq, creq ou threeDs.paymentToken.
Preenchida automaticamente com 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.
6

Validar e concluir

Envie os dados da autenticação ao backend para concluir o pagamento.

Seu backend
O challenge concluído ainda não realiza 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"
}
Ao concluir, a página verifica se o JSON é válido e se returnCode é "0".
✅

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.

✓ Bearer token existe somente no backend
✓ Cartão é criptografado apenas ao pagar
✓ Dados reais do navegador são enviados
✓ ACS URL nunca é fixa
✓ Fluxos silent e challenge são tratados
✓ Resultado final vem da validação do backend