---
updatedAt: 2026-09-30T18:04:13.000Z
agentTools:
  projectIndex: https://docs.pagar.me/llms.txt
---

# Manual de Integração 3DS

Um guia completo para integrar o protocolo de segurança que protege suas vendas online, aumenta a aprovação e elimina chargebacks por fraude.

# Manual de Integração 3DS

## Índice

1. [Visão Geral](#visão-geral)
2. [O que é 3DS?](#o-que-é-3ds)
3. [Como Funciona o 3DS](#como-funciona-o-3ds)
4. [Começando: Configuração Inicial](#começando-configuração-inicial)
5. [Guia de Integração Passo a Passo](#guia-de-integração-passo-a-passo)
6. [Validação de Liability Shift na Criação de Pedidos sem Antifraude Ativo](#validação-de-liability-shift-na-criação-de-pedidos-sem-antifraude-ativo)
7. [Objeto Order](#objeto-order)
8. [Ambientes de Teste](#ambientes-de-teste)
9. [Tratamento de Erros](#tratamento-de-erros)
10. [Solução de Problemas](#solução-de-problemas)

***

## Visão Geral

### Para que serve esta documentação?

Esta documentação é seu guia completo para integrar a autenticação 3DS da Stone usando nossa biblioteca `3ds-nx-js`. Se você é um desenvolvedor que precisa implementar 3DS em sua aplicação, você está no lugar certo.

### O que você vai aprender?

* **Conceitos fundamentais** do 3DS de forma simples e clara
* **Implementação prática** com exemplos de código prontos para usar
* **Como testar** sua integração com cartões de teste específicos
* **Tratamento de cenários** tanto de fluxo simples quanto de desafio
* **Boas práticas** para uma implementação segura

***

## O que é 3DS?

O 3D Secure (3DS) é um protocolo de segurança que adiciona uma camada extra de autenticação para transações com cartão de crédito e débito online. Pense nele como uma "segunda verificação" que confirma se é realmente o portador do cartão quem está fazendo a compra.

### Por que usar 3DS?

✅ **Proteção contra fraudes**: Reduz significativamente transações fraudulentas

✅ **Liability Shift**: A responsabilidade por chargebacks de fraude passa para o emissor do cartão

✅ **Aprovação aumentada**: Emissores tendem a aprovar mais transações autenticadas

***

## Como Funciona o 3DS

O processo de autenticação 3DS pode seguir dois caminhos principais:

### 🚀 Fluxo Frictionless (Sem Atrito)

![](https://files.readme.io/2a950e6a9be10d2a06a5e42b8aff35daacf11a15e993bc6d6989ba61cd94cf05-image.png)

**O que acontece**: O emissor aprova a transação automaticamente baseado no perfil de risco, sem interação do usuário.

### 🔐 Fluxo Challenge (Com Desafio)

![](https://files.readme.io/b24185326ea87b025150f23334e45374bc3e8173b7fc247fe6ec068a62451e71-image.png)

**O que acontece**: O emissor solicita que o cliente confirme sua identidade através de SMS, app do banco, ou outro método.

***

## Começando: Configuração Inicial

### Pré-requisitos

* Secret Key da Stone (todos os clientes Stone possuem)
* Conhecimento básico em JavaScript
* Ambiente backend capaz de fazer requisições HTTPS

### 1. Incluir a biblioteca no HTML

#### URLs das bibliotecas por ambiente

| Ambiente | URL da Biblioteca                                    |
| -------- | ---------------------------------------------------- |
| Sandbox  | `https://3ds-nx-js.stone.com.br/test/v2/3ds2.min.js` |
| Produção | `https://3ds-nx-js.stone.com.br/live/v2/3ds2.min.js` |

Exemplo de como incluir a biblioteca no seu HTML:

```html
<!-- Para o ambiente de sandbox: -->
<script src="https://3ds-nx-js.stone.com.br/test/v2/3ds2.min.js"></script>

<!-- Para o ambiente de produção: -->
<script src="https://3ds-nx-js.stone.com.br/live/v2/3ds2.min.js"></script>
```

### 2. Estrutura básica do HTML

A biblioteca requer alguns containers no HTML da sua aplicação para funcionar corretamente. Dentro deles ocorrerá o processo de 3DS Method e Challenge. Recomendamos que sejam elementos do tipo `<div>` para facilitar a manipulação. Dentro desses elementos a biblioteca irá inserir os iframes e forms necessários para o processo de autenticação. Portanto, sua aplicação não deve interferir na estrutura interna desses containers.

Um exemplo de como preparar os containers onde o 3DS vai operar:

```html
<div id="myApplication">
  <!-- Container invisível para o 3DS Method -->
  <div id="tdsMethodContainer" style="display: none;"></div>
  
  <!-- Container para o Challenge -->
  <div id="challengeContainer"></div>
  
  <!-- Botão para iniciar o processo de autenticação 3DS que será utilizado nos exemplos a seguir -->
  <button id="submitButton">Finalizar Compra</button>
</div>
```

### 3. Geração do token 3DS

**⚠️ IMPORTANTE**: O token 3DS deve **sempre** ser gerado no seu backend por questões de segurança, dado que para gerá-lo é necessário utilizar a secret key da Stone, que deverá ser mantida em segredo e nunca exposta no frontend.

#### URLs base dos ambientes

| Ambiente | URL Base                          |
| -------- | --------------------------------- |
| Sandbox  | `https://3ds-sdx.stone.com.br/v2` |
| Produção | `https://3ds.stone.com.br/v2`     |

#### Como gerar o token 3DS no backend

Recomendamos criar um endpoint seguro em seu backend que seja responsável pela geração do token. Dessa forma sua aplicação pode obter o token de forma segura e evitar expor a secret key no frontend.

O token 3DS é obtido fazendo uma requisição para nosso endpoint `GET /tds-token` utilizando [Basic Access Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) com a secret key encodada em Base64 da seguinte forma:

```
Authorization: Basic <base64(secret_key:)>
```

Veja o exemplo abaixo da implementação de uma função em Node.js responsável por gerar o token 3DS:

```javascript
// Exemplo em Node.js com a biblioteca axios
const axios = require('axios');

async function generateTDSToken(api, secretKey) {
  try {
    const response = await axios.get(`${api}/tds-token`, {
      headers: {
        'Authorization': 'Basic ' + Buffer.from(`${secretKey}:`).toString('base64'),
      },
    });
    
    return response.data.tds_token;
  } catch (error) {
    throw new Error(`Failed to generate token: ${error.response?.data?.message || error.message}`);
  }
}
```

O código acima faz uma requisição GET para o endpoint `/tds-token`, passando a secret key codificada em Base64 no cabeçalho de autorização. A resposta conterá o token 3DS necessário para iniciar o processo de autenticação.

E para que seu frontend possa obter esse token, você pode criar um endpoint em seu backend que retorne o token gerado:

```javascript
// Exemplo em Node.js com a biblioteca Express.js

const TDS_API_URLS = {
  sandbox: 'https://3ds-sdx.stone.com.br/v2',
  production: 'https://3ds.stone.com.br/v2'
};

app.get('/tds-token', async (req, res) => {
  try {
    const environment = process.env.NODE_ENV === 'production' ? 'production' : 'sandbox';
    const api = TDS_API_URLS[environment];
    
    if (!api) {
      throw new Error(`Invalid environment: ${environment}`);
    }
    
    const token = await generateTDSToken(api, process.env.STONE_SECRET_KEY);
    res.json({ token });
  } catch (error) {
    console.error('Error generating 3DS token:', error.message);
    res.status(500).json({ error: 'Failed to generate token' });
  }
});
```

O código acima cria um endpoint `/generate-3ds-token` que, ao ser chamado, gera e retorna o token 3DS. O ambiente (sandbox ou produção) é determinado pela variável de ambiente `NODE_ENV`. O token é gerado utilizando a função `generateTDSToken` do exemplo anterior e a secret key da Stone que está sendo obtida da variável de ambiente `STONE_SECRET_KEY`.

***

## Guia de Integração Passo a Passo

### Passo 1: Obter o token 3DS no frontend

O seu frontend deve solicitar ao seu backend o token 3DS antes de iniciar o processo de autenticação 3DS. Recomendamos que o token seja obtido sempre antes de cada transação, para garantir que você esteja usando o token mais recente e válido, evitando problemas de expiração.

Abaixo está um exemplo de uma função em JavaScript que faz uma requisição para o endpoint `POST /generate-3ds-token` definido nos exemplos anteriores:

```javascript
async function getToken() {
  const response = await fetch('/generate-3ds-token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    }
  });
  
  const data = await response.json();
  return data.token;
}
```

### Passo 2: Preparar os dados do pedido

A biblioteca espera receber um objeto com os dados do pedido (order) que será processado. Esses dados são similares aos dados que você enviaria para criar um pedido na Stone, mas com algumas diferenças, consulte a seção [Objeto Order](#objeto-order) para mais detalhes.

Para o ambiente de teste, é possível utilizar uma série de cartões de teste que simulam diferentes cenários de autenticação 3DS. Basta informar o número do cartão no campo `number` do objeto `card` dentro do pedido. Para uma lista completa de cartões de teste, consulte a seção [Cartões de Teste Específicos para 3DS](#cartões-de-teste-específicos-para-3ds).

Exemplo da estrutura de dados do pedido:

```javascript
const orderData = {
  "payments": [
    {
      "payment_method": "credit_card",
      "credit_card": {
        "card": {
          "number": "3000100811112072", // Cartão de teste que gera challenge manual
          "holder_name": "JOAO SILVA",
          "exp_month": 12,
          "exp_year": 2028,
          "billing_address": {
            "country": "BR",
            "state": "SP",
            "city": "São Paulo",
            "zip_code": "01234567",
            "line_1": "123, Rua das Flores, Centro",
            "line_2": "Apartamento 45"
          }
        },
      },
      "amount": 20000
    }
  ],
  "customer": {
    "name": "João Silva",
    "email": "joao.silva@email.com",
    "code": "CUST-001",
    "document": "12345678901",
    "phones": {
      "home_phone": {
        "country_code": "55",
        "area_code": "11",
        "number": "987654321"
      },
      "mobile_phone": {
        "country_code": "55",
        "area_code": "11",
        "number": "123456789"
      }
    }
  },
  "items": [
    {
      "description": "Smartphone Samsung Galaxy",
      "code": "ITEM-001"
    },
    {
      "description": "Capa Protetora",
      "code": "ITEM-002"
    }
  ],
  "shipping": {
    "recipient_name": "João Silva",
    "address": {
      "country": "BR",
      "state": "SP",
      "city": "São Paulo",
      "zip_code": "01234567",
      "line_1": "123, Rua das Flores, Centro",
      "line_2": "Apartamento 45"
    }
  },
	"requestor_url": "https://suaempresa.com.br"
};
```

### Passo 3: Iniciando o processo de autenticação 3DS

Assim que o cliente finalizar o preenchimento dos dados necessários para o pedido, você pode iniciar o processo de autenticação 3DS. A biblioteca `3ds-nx-js` fornece uma função chamada `TDS.init` que gerencia todo o fluxo de autenticação com apenas uma chamada. Para isso você deve passar o token 3DS, os containers onde o 3DS Method e o Challenge serão exibidos, e os dados do pedido.

Abaixo está um exemplo de como implementar essa chamada:

```javascript
async function process3DS() {
  // Desabilita o botão para evitar duplo clique
  document.getElementById('submitButton').disabled = true;
  
  try {
    // 1. Obter o token do backend
    const token = await getToken();
    
    // 2. Referências dos containers
    const tdsMethodContainer = document.getElementById('tdsMethodContainer');
    const challengeContainer = document.getElementById('challengeContainer');
    
    // 3. Executar o fluxo 3DS
    const response = await window.TDS.init({
      token: token,
      tds_method_container_element: tdsMethodContainer,
      challenge_container_element: challengeContainer,
      use_default_challenge_iframe_style: true, // Usar estilo padrão
      challenge_window_size: '03' // Tamanho médio da janela
    }, orderData);
    
    // 4. Processar resposta
    console.log('3DS Response:', response);
    alert('Transação processada com sucesso!');
    
  } catch (error) {
    console.error('Erro no 3DS:', error);
    alert('Erro ao processar pagamento: ' + error.message);
  } finally {
    // Reabilitar o botão
    document.getElementById('submitButton').disabled = false;
  }
}

// Vincular ao botão
document.getElementById('submitButton').addEventListener('click', process3DS);
```

### Passo 4: CSS para o challenge

O challenge será renderizado em um iframe dentro do container informado em `challenge_container_element`. Se você definir `use_default_challenge_iframe_style: true` na chamada da função TDS.init, a biblioteca aplicará um estilo padrão ao iframe do challenge, que pode funcionar bem para alguns casos, mas pode não ser o ideal para todos os layouts. Por esse motivo, recomendamos que você personalize o estilo do iframe para melhor se adequar ao design da sua aplicação.

Para fazer isso, você deve definir `use_default_challenge_iframe_style: false` e aplicar seu próprio CSS ao iframe do challenge. Sempre que houver uma challenge para ser exibida, a biblioteca irá inserir um iframe dentro do container `challenge_container_element`. Você pode personalizar o estilo desse iframe para que ele se encaixe melhor no design da sua aplicação.

Veja um exemplo de como fazer isso:

```css
/* Estilo personalizado para o challenge iframe */
#challengeContainer iframe {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 60%;
  max-width: 500px;
  height: 600px;
  border: 2px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  background: white;
  z-index: 9999;
}
```

### Passo 5: Definindo o `challenge_window_size`

O parâmetro `challenge_window_size` define o tamanho da janela do challenge e impacta diretamente na experiência do usuário. Por esse motivo é importante escolher um tamanho adequado para o seu público-alvo.

Recomendamos que você escolha o tamanho de janela baseado no dispositivo que o seu cliente estiver utilizando no momento da autenticação. Abaixo estão os tamanhos recomendados:

| Código | Dimensões  | Recomendado para       |
| ------ | ---------- | ---------------------- |
| '01'   | 250x400px  | Mobile portrait        |
| '02'   | 390x400px  | Mobile landscape       |
| '03'   | 500x600px  | Desktop (padrão)       |
| '04'   | 600x400px  | Desktop wide           |
| '05'   | Fullscreen | Máxima compatibilidade |

### Passo 6: Finalizando o pedido

Após o processo de autenticação 3DS, a função `TDS.init` retornará um array de objetos, um para cada cartão autenticado com o seguinte formato:

```
[
  {
    tds_server_trans_id: "<UUID>",
    trans_status: "<Y|A|N|C|U|R|I>",
    authenticated_card: "<card number>",
    challenge_canceled: <true|false>,
  }
]
```

| Nome do campo         | Descrição                                        | Tipo    |
| --------------------- | ------------------------------------------------ | ------- |
| `tds_server_trans_id` | ID da transação autenticada                      | string  |
| `trans_status`        | Status da transação 3DS                          | string  |
| `authenticated_card`  | Número do cartão autenticado (mascarado)         | string  |
| `challenge_canceled`  | Indica se o challenge foi cancelado pelo usuário | boolean |

| Status (`trans_status`) | Descrição                        | Responsabilidade em caso de fraude                  |
| ----------------------- | -------------------------------- | --------------------------------------------------- |
| Y                       | Transação autenticada            | Emissor                                             |
| A                       | Tentativa de autenticação        | Lojista ou Emissor (depende da resposta do emissor) |
| N                       | Transação não autenticada        | Lojista                                             |
| C                       | Solicitação de desafio           | Lojista ou Emissor (depende da resposta do emissor) |
| U                       | Autenticação indisponível        | Lojista                                             |
| R                       | Autenticação negada pelo emissor | Lojista                                             |
| I                       | Apenas informação                | Lojista                                             |

Vale destacar que as transações que possuem **Liability Shift&#x20;**&#x73;ão as transações com retorno "Y", e eventualmente os status "A" e "C", a depender da resposta do emissor.<br />Essas são as transações que quando autenticadas pelo emissor do cartão de crédito, ele se responsabiliza por eventuais chargebacks por fraude.

Após receber a resposta, se desejar [criar o pedido (order)](https://docs.pagar.me/reference/criar-pedido-2), utilize o `tdsServerTransID` retornado. No contrato de criação de pedidos, o campo correspondente ao `tdsServerTransID` é o `transaction_id`, mais detalhes na <Anchor target="_blank" href="https://docs.pagar.me/reference/cart%C3%A3o-de-cr%C3%A9dito-1#transa%C3%A7%C3%B5es-autenticadas-com-3ds">seção Transações Autenticadas dessa documentação</Anchor>.

***

## Validação de Liability Shift na Criação de Pedidos sem Antifraude Ativo

Caso o módulo de Antifraude **não esteja ativo** e o cliente deseje criar pedidos apenas para transações com liability shift aprovado via 3DS, a lógica de validação deverá ser implementada na própria aplicação do cliente.

A aplicação deve verificar o status retornado no processo de autenticação 3DS e prosseguir com a criação do pedido exclusivamente quando o status retornado for Y.

Essa validação deve ocorrer **antes** da chamada de criação do pedido, garantindo que apenas transações autenticadas com liability shift aprovado sejam processadas no sistema.

***

## Objeto Order

O objeto Order representa os dados do pedido que será processado no fluxo de autenticação 3DS. Abaixo estão as especificações detalhadas de cada campo e tipo necessário.

<Callout icon="ℹ️" theme="info">
  ### Atualmente **não** aceitamos campos para transações tokenizadas, como token ou card_id.
</Callout>

### Order

| Nome do campo   | Tipo                   | Obrigatório? | Valor padrão                |
| --------------- | ---------------------- | ------------ | :-------------------------- |
| `customer`      | [Customer](#customer)  | Sim          | -                           |
| `items`         | [Item](#item)\[]       | Não          | -                           |
| `shipping`      | [Shipping](#shipping)  | Não          | -                           |
| `payments`      | [Payment](#payment)\[] | Sim          | -                           |
| `requestor_url` | string                 | Não          | Endereço atual do navegador |

Obs.: O campo `requestor_url` é utilizado para identificar a aplicação que está solicitando a autenticação 3DS. Caso não seja fornecido, o valor padrão será o endereço atual do navegador onde a biblioteca está sendo executada. Recomendamos que você informe esse campo explicitamente para garantir maior segurança e rastreabilidade das transações. Esse endereço também não pode ser um endereço local ou interno, como "localhost", pois esses endereços são considerados inválidos.

### Customer

| Nome do campo | Tipo              | Obrigatório? |
| ------------- | ----------------- | ------------ |
| `name`        | string            | Não          |
| `email`       | string            | Sim          |
| `code`        | string            | Não          |
| `document`    | string            | Não          |
| `phones`      | [Phones](#phones) | Não          |

### Phones

| Nome do campo  | Tipo            | Obrigatório? |
| -------------- | --------------- | ------------ |
| `home_phone`   | [Phone](#phone) | Não          |
| `mobile_phone` | [Phone](#phone) | Não          |

### Phone

| Nome do campo  | Tipo   | Obrigatório? |
| -------------- | ------ | ------------ |
| `country_code` | string | Sim          |
| `area_code`    | string | Sim          |
| `number`       | string | Sim          |

### Item

| Nome do campo | Tipo   | Obrigatório? |
| ------------- | ------ | ------------ |
| `description` | string | Sim          |
| `code`        | string | Sim          |

### Shipping

| Nome do campo         | Tipo                | Obrigatório?                                            |
| --------------------- | ------------------- | ------------------------------------------------------- |
| `recipient_name`      | string              | Sim                                                     |
| `electronic_delivery` | boolean             | Não                                                     |
| `address`             | [Address](#address) | É obrigatório apenas se `electronic_delivery` for false |

### Payment

| Nome do campo    | Tipo                      | Obrigatório? | Observações                                                      |
| ---------------- | ------------------------- | ------------ | :--------------------------------------------------------------- |
| `payment_method` | string                    | Não          | -                                                                |
| `credit_card`    | [CreditCard](#creditcard) | Sim          | -                                                                |
| `amount`         | number                    | Sim          | Obrigatório ser um valor inteiro (Valor da cobrança em centavos) |
| `purpose`        | string                    | Não          |                                                                  |
| `recurrence`     | [Recurrence](#recurrence) | Não          |                                                                  |

### CreditCard

| Nome do campo | Tipo          | Obrigatório? |
| ------------- | ------------- | ------------ |
| `card`        | [Card](#card) | Sim          |

### Recurrence

| Nome do campo    | Tipo   | Obrigatório? |
| ---------------- | ------ | ------------ |
| `deadline`       | string | Sim          |
| `frequency_days` | number | Sim          |

### Card

| Nome do campo     | Tipo                | Obrigatório? |
| ----------------- | ------------------- | ------------ |
| `number`          | string              | Sim          |
| `holder_name`     | string              | Sim          |
| `exp_month`       | number              | Sim          |
| `exp_year`        | number              | Sim          |
| `billing_address` | [Address](#address) | Sim          |

### Address

| Nome do campo | Tipo   | Obrigatório? | Formato                                                                                                           |
| ------------- | ------ | ------------ | ----------------------------------------------------------------------------------------------------------------- |
| `country`     | string | Sim          | Código do país no formato [ISO 3166-1 alpha-2](https://www.iso.org/iso-3166-country-codes.html) (ex.: BR, US, FR) |
| `state`       | string | Sim          | -                                                                                                                 |
| `city`        | string | Sim          | -                                                                                                                 |
| `zip_code`    | string | Sim          | -                                                                                                                 |
| `line_1`      | string | Sim          | `number, street, district`                                                                                        |
| `line_2`      | string | Sim          | -                                                                                                                 |

## Ambientes de Teste

### Cartões de Teste Específicos para 3DS

Use estes cartões em ambiente sandbox para testar diferentes cenários:

#### Cartões 3DS 2.2

| Número do Cartão   | Versão 3DS | Comportamento                 | Descrição                                                   |
| :----------------- | :--------- | :---------------------------- | :---------------------------------------------------------- |
| `4000100511112003` | 2.2        | Frictionless Success          | Aprovado automaticamente sem challenge                      |
| `5000100411112203` | 2.2        | 3DS Method Timeout            | Testa timeout do 3DS Method                                 |
| `6000100611112103` | 2.2        | Frictionless sem 3DS Method   | Aprovado sem executar 3DS Method                            |
| `3000100811112072` | 2.2        | Manual Challenge              | Exibe challenge manual para o usuário                       |
| `7000100911112070` | 2.2        | Auto Challenge Success        | Challenge automático - aprovado                             |
| `3000101011112071` | 2.2        | Auto Challenge Fail           | Challenge automático - negado                               |
| `9000100111111111` | 2.2        | Cartão não preparado para 3DS | Simula um cartão ou BIN não elegível para autenticação 3DS. |

### Exemplo de Teste Completo

```javascript
// Função para testar diferentes cenários
async function testScenario(cardNumber, description) {
  console.log(`🧪 Testando: ${description}`);
  
  const testOrder = {
    ...orderData,
    payments: [{
      ...orderData.payments[0],
      credit_card: {
        ...orderData.payments[0].credit_card,
        card: {
          ...orderData.payments[0].credit_card.card,
          number: cardNumber // Sobrescrever com cartão de teste
        }
      }
    }]
  };
  
  try {
    const token = await getToken();
    const response = await window.TDS.init({
      token,
      tds_method_container_element: document.getElementById('tdsMethodContainer'),
      challenge_container_element: document.getElementById('challengeContainer')
    }, testOrder);
    
    console.log(`✅ ${description} - Resultado:`, response);
  } catch (error) {
    console.log(`❌ ${description} - Erro:`, error.message);
  }
}
```

```javascript
// Executar testes
async function runAllTests3DS22() {
  // Testes 3DS 2.2
  await testScenario('4000100511112003', 'Frictionless Success (3DS 2.2)');
  await testScenario('3000100811112072', 'Manual Challenge (3DS 2.2)');
  await testScenario('7000100911112070', 'Auto Challenge Success (3DS 2.2)');
}
```

***

## Tratamento de Erros

### Estrutura de Erro da API

Quando ocorre um erro durante o processo de autenticação 3DS, a API retorna uma estrutura padronizada que facilita o diagnóstico e tratamento do problema. A biblioteca `3ds-nx-js` encapsula esses erros em objetos `TDSError` que você pode capturar e analisar.

#### Estrutura do Erro

```typescript
{
  "error": {
    "code": "VALIDATION_ERROR",              // Código do erro (machine-readable)
    "message": "Invalid request payload",     // Mensagem descritiva (human-readable)
    "details": {                              // Detalhes específicos do erro (opcional)
      "card_number": {
        "rule": "required",
        "error": "'card_number' is required"
      }
    },
    "request_id": "a8a03e4f-...",            // ID da requisição para rastreamento
    "authentication_id": "f5cab16a-...",     // ID da autenticação (opcional)
    "documentation_url": "https://docs.pagar.me/docs/manual-integracao-3ds"
  },
  "status": 422  // HTTP status code
}
```

### Códigos de Erro

Abaixo estão os principais códigos de erro retornados pela API 3DS, suas descrições e como resolver cada um deles:

#### Erros de Autenticação

| Código              | Descrição                                       | HTTP Status | Solução                                                                                           |
| ------------------- | ----------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------- |
| `UNAUTHORIZED`      | Cartão não autorizado para realizar a transação | 422         | O cartão foi bloqueado ou não está elegível para 3DS. Solicite outro meio de pagamento ao cliente |
| `BIN_FRAUD_SUSPECT` | BIN do cartão está sob suspeita de fraude       | 422         | O BIN foi identificado como suspeito. Solicite outro cartão ao cliente                            |

#### Erros de Configuração do Cartão

| Código                     | Descrição                                                                                    | HTTP Status | Solução                                      |
| -------------------------- | -------------------------------------------------------------------------------------------- | ----------- | -------------------------------------------- |
| `SCHEME_NOT_SUPPORTED`     | Bandeira do cartão não é suportada.                                                          | 422         | Solicite outro cartão com bandeira suportada |
| `INVALID_PROTOCOL_VERSION` | Versão do protocolo 3DS não é compatível. O cartão não suporta as versões de 3DS disponíveis | 422         | Solicite outro cartão com versão compatível  |

#### Erros do Servidor 3DS

| Código               | Descrição                        | HTTP Status | Solução                                                                                        |
| -------------------- | -------------------------------- | ----------- | ---------------------------------------------------------------------------------------------- |
| `TDS_RESPONSE_ERROR` | Erro na resposta do servidor 3DS | 422         | Problema na comunicação com o servidor 3DS. Tente novamente, e se persistir, contate o suporte |

#### Erros Gerais

| Código                  | Descrição                            | HTTP Status | Solução                                         |
| ----------------------- | ------------------------------------ | ----------- | ----------------------------------------------- |
| `BAD_GATEWAY`           | Erro no gateway                      | 502         | Problema temporário. Tente novamente            |
| `SERVICE_UNAVAILABLE`   | Serviço indisponível temporariamente | 503         | Aguarde alguns instantes e tente novamente      |
| `INTERNAL_SERVER_ERROR` | Erro interno do servidor             | 500         | Erro inesperado. Contate o suporte se persistir |

### Acessando Informações do Erro

A biblioteca `3ds-nx-js` fornece uma classe `TDSError` com métodos convenientes para acessar as informações do erro:

```javascript
try {
  const response = await window.TDS.init({
    token,
    tds_method_container_element: tdsMethodContainer,
    challenge_container_element: challengeContainer
  }, orderData);
  
  console.log('Autenticação bem-sucedida:', response);
  
} catch (error) {
  if (error instanceof window.TDS.TDSError) {
    // Informações principais
    console.error('Erro 3DS:', {
      message: error.message,                          // Mensagem descritiva
      code: error.getCode(),                          // Código do erro
      status: error.getStatus(),                      // HTTP status code
      
      // Informações de rastreamento
      requestID: error.getRequestID(),                // ID da requisição
      authenticationID: error.getAuthenticationID(),  // ID da autenticação
      
      // Detalhes adicionais
      details: error.getDetails(),                    // Detalhes específicos do erro
      documentationURL: error.getDocumentationURL()   // Link para documentação
    });
    
    // Tratamento específico por código de erro
    switch (error.getCode()) {
      case 'UNAUTHORIZED':
      case 'BIN_FRAUD_SUSPECT':
        console.error('Cartão não autorizado:', error.message);
        // Solicitar outro meio de pagamento
        alert('Este cartão não pode ser utilizado. Por favor, utilize outro cartão.');
        break;
        
      case 'SCHEME_NOT_SUPPORTED':
        console.error('Bandeira não suportada:', error.message);
        // Informar bandeiras aceitas
        alert('Esta bandeira de cartão não é suportada. Aceitamos Mastercard, Visa e Amex.');
        break;
        
      case 'INTERNAL_SERVER_ERROR':
      case 'SERVICE_UNAVAILABLE':
        console.error('Erro temporário:', error.message);
        // Sugerir tentar novamente
        alert('Erro temporário. Por favor, tente novamente em alguns instantes.');
        break;
        
      default:
        console.error('Erro não tratado:', error.message);
        alert('Ocorreu um erro inesperado. Por favor, contate o suporte.');
    }
  } else {
    // Erro não relacionado ao 3DS
    console.error('Erro inesperado:', error);
  }
}
```

### Erros Comuns e Soluções

#### 1. "Invalid JWT for 3DS"

```javascript
// ❌ Erro comum
catch (error) {
  if (error.message.includes('Invalid JWT')) {
    console.error('Token inválido ou expirado');
    // Gerar um novo token
    const newToken = await getToken();
    // Tentar novamente
  }
}
```

**Solução**: Verifique se o token está sendo gerado corretamente e se não expirou (20 segundos de validade).

#### 2. "config.token is required"

```javascript
// ✅ Validação correta
if (!token || typeof token !== 'string') {
  throw new Error('Token é obrigatório e deve ser uma string');
}
```

#### 3. "HTMLElement not found"

```javascript
// ✅ Verificação dos containers
const tdsMethodContainer = document.getElementById('tdsMethodContainer');
const challengeContainer = document.getElementById('challengeContainer');

if (!tdsMethodContainer || !challengeContainer) {
  throw new Error('Containers do 3DS não encontrados no DOM');
}
```

### Exemplo de Tratamento Robusto

```javascript
async function robustProcess3DS() {
  const maxRetries = 3;
  let attempt = 0;
  
  while (attempt < maxRetries) {
    try {
      const token = await getToken();
      
      const response = await window.TDS.init({
        token,
        tds_method_container_element: document.getElementById('tdsMethodContainer'),
        challenge_container_element: document.getElementById('challengeContainer'),
        use_default_challenge_iframe_style: true,
        challenge_window_size: '03'
      }, orderData);
      
      return response; // Sucesso
      
    } catch (error) {
      attempt++;
      console.warn(`Tentativa ${attempt} falhou:`, error.message);
      
      if (attempt >= maxRetries) {
        throw new Error(`Falha após ${maxRetries} tentativas: ${error.message}`);
      }
      
      // Aguardar antes de tentar novamente
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
}
```

***

## Solução de Problemas

### Cenário 1: Challenge não aparece

**Sintomas**: O processo parece executar mas nenhum challenge é exibido.

**Possíveis causas**:

* Container `challengeContainer` não existe ou está oculto
* CSS está impedindo a exibição
* Cartão de teste não requer challenge

**Solução**:

```javascript
// Debug do container
const container = document.getElementById('challengeContainer');
console.log('Container exists:', !!container);
console.log('Container visible:', container && container.offsetHeight > 0);

// Testar com cartão que força challenge
const testCard = '3000100811111072'; // Manual challenge
```

### Cenário 2: Timeout frequente

**Sintomas**: Erro "Token expirado" ou timeout.

**Possíveis causas**:

* Operações lentas no backend
* Problemas de conectividade
* Token gerado muito cedo

**Solução**:

```javascript
// Gerar token just-in-time
async function justInTimeProcess() {
  // Preparar tudo primeiro
  const orderReady = validateOrder(orderData);
  const containersReady = validateContainers();
  
  if (orderReady && containersReady) {
    // Só então gerar o token
    const token = await getToken();
    return window.TDS.init(/* ... */);
  }
}
```

### Cenário 3: Erro de CORS

**Sintomas**: Erro de Cross-Origin Request.

**Solução**:

```javascript
// Backend deve incluir headers CORS
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://seudominio.com');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});
```