# Autenticação do dono do cartão (3DS)

O 3DS é a confirmação, feita pelo banco que emitiu o cartão, de que quem está pagando é mesmo o dono dele. É o mesmo mecanismo que, em algumas compras, abre uma janela pedindo senha ou código.

Serve para reduzir fraude e contestação de compra. Quando a autenticação acontece, a responsabilidade por uma compra contestada passa a ser do banco, não sua.

O pacote é o `@validapay/3ds` e roda no navegador do comprador, junto com o [SDK de tokenização](/sdks/tokenizacao.md).

## Quando chamar

Sempre no clique de pagar, **antes** de gerar o `cardToken`:

1. O comprador preenche o cartão e os dados pessoais.
2. Você chama `authenticate(...)`.
3. O banco aprova direto ou abre a janela para o comprador confirmar.
4. Com o resultado em mãos, você gera o `cardToken` com o [SDK de tokenização](/sdks/tokenizacao.md) e segue com a chamada para a API de cobrança.

## 1. Instalar

```bash
npm install @validapay/tokenize @validapay/3ds
```

## 2. Autenticar

Chame o `authenticate(...)` antes de gerar o `cardToken`, conforme exemplificado abaixo:

```javascript
import { authenticate } from '@validapay/3ds';

const authentication = await authenticate({
  publicId: 'SEU_ID_PUBLICO',
  amount: 149.9,
  card: {
    number: '5230552482605921',
    holderName: 'LUKE SKYWALKER',
    cvv: '100',
    expiration: '12/2030',
  },
  customer: {
    name: 'Luke Skywalker',
    document: '86564950039',
    email: 'luke@teste.com',
    phone: '11999998888',
    address: {
      zipCode: '01310100',
      street: 'Av. Paulista',
      number: '1000',
      neighborhood: 'Bela Vista',
      city: 'São Paulo',
      state: 'SP',
    },
  },
  statementDescriptor: 'Minha Loja',
});
```

Resposta:

```json
{
  "authenticationId": "9WDHbW3Mipl6pFQ2LnM2",
  "cardId": "card_p7s6je7w90uomjkgn1siy2xkw"
}
```

## Parâmetros

| Parâmetro | Obrigatório | Descrição |
|---|---|---|
| `publicId` | Sim | Identificador público da conta, no painel em Gerenciamento > Minha Conta > Id Público |
| `amount` | Sim | Valor **exato** que será cobrado, em reais, já com juros e descontos |
| `card` | Sim | Mesmos dados que o comprador digitou: `number`, `holderName`, `cvv` e `expiration` (MM/YYYY) |
| `customer` | Sim | Nome, documento, e-mail, **telefone** e **endereço completo** |
| `statementDescriptor` | Não | Nome que aparece na janela do banco. Até 30 caracteres |

O telefone e o endereço são exigidos pelo banco. Sem eles a autenticação nem começa.

## 3. Gerar o cardToken

Para gerar uma cobrança é necessário antes tokenizar o cartão chamando o método `tokenize()` do SDK `@validapay/tokenize`. Este método recebe os inputs: `publicId`, `card`, `customer`. O `cardToken` e o `deviceId` que a cobrança exige saem desse SDK — o passo a passo está em [Tokenização de cartão](/sdks/tokenizacao.md). A chamada deve ser feita conforme exemplificado abaixo:

```javascript
import { tokenize } from '@validapay/tokenize/browser';

const { cardToken } = await tokenize({
  publicId: 'SEU_ID_PUBLICO',
  card: {
    number: '5230552482605921',
    holderName: 'LUKE SKYWALKER',
    cvv: '100',
    expiration: '12/2030',
  },
  customer: {
    name: 'Luke Skywalker',
    document: '86564950039',
    email: 'luke@teste.com',
  },
  authentication,
});
```

Resposta:

```json
{
  "cardToken": "ctk_9f8s7d6f5g4h3j2k1l0",
  "cardTokenExpiresAt": "2026-09-17T16:37:00.720Z",
  "cardBrand": "MASTERCARD",
  "cardLastFour": "5921"
}
```

## 4. Cobrar pelo seu servidor

Com o `cardToken`, `deviceId` e o objeto de autenticação retornado pelo 3DS, envie-os ao seu servidor e gere a cobrança em [Checkout Transparente → Gerar cobrança Cartão 3DS](/referencia/post-gerar-cobranca-cartao-3ds.md).

## O que o comprador vê

- **Sem atrito:** o banco reconhece o comprador e aprova sozinho. Ele não vê nada.
- **Com desafio:** abre uma janela do banco pedindo senha ou código. Só depois disso a promessa é resolvida.

Desabilite o botão de pagar enquanto a autenticação estiver em andamento, e não feche a janela pelo seu código.

## Testando em sandbox

Use o `publicId` da conta de sandbox e passe `environment: 'sandbox'`. Por padrão a autenticação passa sem atrito; para ver a janela do desafio, peça com `challenge: true`:

```javascript
const authentication = await authenticate({
  publicId: 'SEU_ID_PUBLICO',
  environment: 'sandbox',
  challenge: true,
  amount: 149.9,
  card,
  customer,
});
```

Em sandbox a autenticação acontece de verdade, com as mesmas validações e os mesmos erros, mas a cobrança é simulada: serve para testar o fluxo na sua página, não a transferência de responsabilidade por contestação, que só existe em produção.

## Erros

| Código | O que aconteceu | O que fazer |
|---|---|---|
| `THREE_DS_MISSING_DATA` | Faltou telefone ou algum campo do endereço | Peça o dado que falta e chame de novo. O erro traz a lista em `details.missing` |
| `THREE_DS_FAILED` | O banco não autenticou o cartão | Não cobre. Peça outro cartão ao comprador |
| `THREE_DS_TIMEOUT` | O comprador não concluiu em 3 minutos | Ofereça tentar de novo |
| `THREE_DS_UNAVAILABLE` | O serviço de autenticação não carregou na página | Tente de novo; persistindo, siga sem 3DS |
| `INVALID_AMOUNT` | O `amount` não foi enviado, é zero ou negativo | Envie o valor exato que será cobrado, em reais, maior que zero |
| `INVALID_ENVIRONMENT` | O `environment` informado não existe | Use `production`, `sandbox` ou `development` |

Se o comprador errar a senha no desafio, a recusa aparece na resposta da cobrança, não aqui.

## Próximos passos

- [Tokenização de cartão, do início ao fim](/sdks/tokenizacao.md)
- [Cobrança com cartão (sem 3DS)](/referencia/post-gerar-cobranca-cartao.md)
- [Cobrança com cartão 3DS](/referencia/post-gerar-cobranca-cartao-3ds.md)
