Pré-requisito: este guia assume que você já carregou o
legacy-pay.js e inicializou o client. Se ainda não fez isso, veja Tokenização de Cartões.client.prepareCardPayment(). Você só precisa carregar o legacy-pay.js — nenhum SDK externo de banco ou adquirente é necessário, você não vê desafios no seu código, não monta payloads diferentes para bancos diferentes. Quando o prepareCardPayment() retorna com sucesso, o prepared.payinCard já contém os dados de autenticação prontos para o /payin.
Verificar se 3DS está ativo
Cada loja é configurada com seu próprio perfil de risco. Consulte:enabled: false, o prepareCardPayment() não dispara desafios — o token é gerado direto.
Como funciona para quem integra
prepareCardPayment(), o SDK pode abrir um modal/iframe com o desafio do banco. Ele aparece sobre a sua página e fecha sozinho quando o comprador confirma. Você não precisa fazer nada — só esperar a Promise resolver.
Falhas mais comuns
| Causa | Solução |
|---|---|
| Comprador não consegue confirmar o desafio (timeout, código errado, app fechado). | Mostre erro amigável e ofereça outro cartão. |
| Cartão não suportado pelo emissor para 3DS. | Idem — peça outro cartão. |
| Navegador sem suporte (popups bloqueados, modo anônimo restritivo). | Oriente o comprador a permitir popups ou trocar de navegador. |
LegacyPayError com err.code === "THREEDS_FAILED". Você não precisa diferenciar a sub-causa — a UX em todos os casos é a mesma: pedir outro cartão.
Quando o desafio acontece “depois” (pós-ordem)
Em alguns perfis de loja, o desafio 3DS é decidido após o/payin ser criado (a análise antifraude pode pedir o desafio só para casos suspeitos). Nessa situação, a resposta de /payin virá com "threeDSecurePending": true, "status": "PENDING_3DS" e os campos planos threeDSecureSession, threeDSecureTransactionId e threeDSecureSdkUrl com os dados do desafio.
O SDK lida com isso automaticamente quando você usa client.processCardPayment() — ele detecta o threeDSecurePending, roda o desafio via handlePendingThreeDS() e retoma o fluxo. Se você está montando o /payin manualmente, use client.handlePendingThreeDS(payinResponse, { card, customer, amount, installments }) para completar o desafio.
Na maioria dos casos o 3DS é pré-ordem: a autenticação acontece durante o
prepareCardPayment() e os dados já vão no /payin. O fluxo pós-ordem acima vale para perfis que exigem desafio assíncrono. O SDK é agnóstico — você não precisa saber qual modo a loja usa.Resumindo
- Não importe nenhum SDK externo — só
legacy-pay.js. - Não monte payloads de 3DS — o SDK monta tudo internamente.
- Use
client.prepareCardPayment()para tokenizar o cartão e executar o 3DS automaticamente. - Trate
LegacyPayError.code === "THREEDS_FAILED"com uma mensagem amigável. - Use
client.processCardPayment()se você quer um único método que cuida do/payin+ desafio pós-ordem. - Confirme a venda via webhook ou
GET /payin/{id}— o sucesso do SDK indica só autenticação 3DS, nunca aprovação da venda.