> ## Documentation Index
> Fetch the complete documentation index at: https://docs.malga.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Criando uma transação

Com a configuração pronta, o fluxo de uma transação utilizando 3D Secure 2 na Malga envolve várias etapas. Abaixo descrevemos cada passo com explicações e exemplos práticos:

### Passo 1: Setup da Sessão 3DS2

Antes de criar uma cobrança (transação) com 3DS2, é necessário iniciar uma sessão de autenticação. Essa etapa de **setup** prepara o provedor de autenticação 3DS e retorna parâmetros que serão usados nas próximas etapas.

Você deve chamar o endpoint `/v1/charges/3ds/setup` informando a fonte do cartão. Essa fonte pode ser um cartão tokenizado (`sourceType: "token"`) ou um cartão previamente cadastrado (`sourceType: "card"`), junto com o identificador correspondente (`tokenId` ou `cardId`).

**Exemplo de requisição (Setup 3DS2):**

<Tabs>
  <Tab title="Exemplo com tokenId">
    ```bash theme={null}
    curl --request POST 'https://api.malga.io/v1/charges/3ds/setup' \
    --header 'x-api-key: <SEU_API_KEY>' \
    --header 'x-client-id: <SEU_CLIENT_ID>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "sourceType": "token",
        "tokenId": "123e4567-e89b-12d3-a456-426614174000"
    }'
    ```
  </Tab>

  <Tab title="Exemplo com cardId">
    ```bash theme={null}
    curl --request POST 'https://api.malga.io/v1/charges/3ds/setup' \
    --header 'x-api-key: <SEU_API_KEY>' \
    --header 'x-client-id: <SEU_CLIENT_ID>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "sourceType": "card",
        "cardId": "123e4567-e89b-12d3-a456-426614174000"
    }'
    ```
  </Tab>
</Tabs>

No primeiro exemplo acima, foi utilizado um cartão tokenizado (substitua "tokenId" por um ID de token de cartão válido obtido via tokenização da Malga). Se você tivesse um `cardId`, poderia usá-lo alterando `sourceType` para `card`.

**Resposta do Setup:** Ao chamar o setup, a API retorna um objeto contendo informações essenciais para prosseguir. Um exemplo simplificado de resposta JSON seria:

```json theme={null}
{
  "id": "11111111-2222-3333-4444-555555555555",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....", 
  "collectUrl": "https://centinel.api.cardecommerce.com/V1/Cruise/Collect",
  "providerType": "CYBERSOURCE",
  "error": null
}
```

Os campos importantes desse retorno são:

* `id` – Identificador único da sessão 3DS2 criada. Este **Setup ID** será usado posteriormente ao criar a cobrança 3DS2.
* `token` – Um token JWT fornecido pelo provedor de autenticação 3DS. Este token deverá ser usado na próxima etapa de coleta de dados no navegador do cliente.
* `collectUrl` – URL para a qual os dados do dispositivo do cliente deverão ser enviados. Também será usada na etapa de **coleta de dados** no front-end.
* `providerType` – Indica qual provedor de 3DS2 está sendo utilizado (ex: CYBERSOURCE, etc).
* `error` – Em caso de falha na criação da sessão, este campo trará detalhes do erro; caso contrário virá como null.

Guarde o valor de `id` retornado (Setup ID), pois ele será necessário no passo de criação da cobrança. Em seguida, prossiga imediatamente para a etapa de coleta de dados do dispositivo no navegador.

### Passo 2: Coleta de Dados do Dispositivo (Data Collection)

Com o `token` e o `collectUrl` retornados no setup, é preciso coletar informações do dispositivo/navegador do comprador. Essa coleta é feita no front-end do seu checkout, normalmente via um formulário invisível e um iframe, e serve para o provedor 3DS reunir dados de contexto para a autenticação.

Para implementar essa etapa, inclua no HTML do seu checkout um bloco de código semelhante ao abaixo:

```html theme={null}
<!-- Elementos ocultos para coleta de dados 3DS2 -->
<div style="display: none;">
  <iframe id="collection_iframe" name="collectionIframe" height="1" width="1"></iframe>
  <form id="collection_form" method="POST" target="collectionIframe">
    <input id="collection_input" type="hidden" name="JWT" value="" />
  </form>
</div>
<script>
  // Valores obtidos na resposta do setup:
  const collectUrl = "<URL_RETORNADA_NO_SETUP>";   // ex: https://centinel.api.../Collect
  const token3DS = "<TOKEN_RETORNADO_NO_SETUP>";   // JWT retornado no setup
  
  // Configura o formulário oculto com os dados de coleta:
  const form = document.getElementById('collection_form');
  const input = document.getElementById('collection_input');
  form.action = collectUrl;
  input.value = token3DS;
  form.submit();

  // Listener para detectar conclusão da coleta
  window.addEventListener("message", function(event) {
    const expectedOrigin = new URL(collectUrl).origin;
    if (event.origin === expectedOrigin) {
      console.log("Coleta de dados 3DS2 finalizada:", event.data);
      // Você pode opcionalmente enviar um evento ou atualizar o estado do checkout aqui
    }
  });
</script>
```

No código acima, substitua `collectUrl` e `token3DS` pelos valores reais obtidos no **Passo 1**. Ao executar esse script, o formulário é enviado em background (iframe oculto) para a URL de coleta do provedor 3DS, junto com o token JWT. O provedor então coleta atributos do navegador (como informações de dispositivo, IP, etc.) automaticamente. Um event listener é adicionado para ouvir a mensagem de retorno indicando que a coleta terminou (o provedor geralmente envia um evento de mensagem para a janela original ao concluir a coleta).

Essa etapa é fundamental para a autenticação 3DS: ela fornece ao emissor do cartão os dados contextuais do dispositivo do cliente, auxiliando na decisão de aprovar diretamente (autenticação frictionless) ou exigir um desafio.

### Passo 3: Criação da Cobrança (Transação com 3DS2)

Com a sessão criada (Setup ID) e a coleta de dados realizada, você pode prosseguir para criar a cobrança (transação de pagamento). A requisição de cobrança é feita no endpoint padrão `/v1/charges`, porém deve conter um objeto adicional `threeDSecure2` com os campos necessários.

Na cobrança 3DS2, o provedor de pagamento tentará autenticar o portador do cartão junto ao banco emissor. Dependendo do resultado, o pagamento poderá ser autenticado de forma silenciosa (frictionless) ou o emissor pode solicitar um **desafio adicional** ao cliente (challenge).

Montar a requisição corretamente é crucial. Segue um exemplo de **requisição cURL** para criar uma cobrança com 3DS2:

```bash theme={null}
curl --request POST 'https://api.malga.io/v1/charges' \
  --header 'x-api-key: <SEU_API_KEY>' \
  --header 'x-client-id: <SEU_CLIENT_ID>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "merchantId": "<MERCHANT_ID>",
    "amount": 5790,
    "currency": "BRL",
    "capture": true,
    "statementDescriptor": "Compra 3DS2 - Pedido 12345",
    "paymentSource": {
      "sourceType": "token",
      "tokenId": "123e4567-e89b-12d3-a456-426614174000"
    },
    "paymentMethod": {
      "paymentType": "credit",
      "installments": 1
    },
    "paymentFlow": {
      "metadata": {
        "exemplo": "algum valor"
      }
    },
    "threeDSecure2": {
      "requiresLiabilityShift": true,
      "setupId": "<ID_RETORNADO_NO_SETUP>",
      "redirectURL": "https://www.sualoja.com.br/checkout",
      "requestorURL": "https://www.sualoja.com.br",
      "billingAddress": {
        "city": "São Paulo",
        "country": "BR",
        "street": "Avenida Exemplo",
        "streetNumber": "100",
        "zipCode": "01010010",
        "state": "SP"
      },
      "browser": {
        "ip": "203.0.113.45",
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
        "acceptHeader": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "language": "pt-BR",
        "colorDepth": 24,
        "screenHeight": 1080,
        "screenWidth": 1920,
        "timeZoneOffset": "180",
        "javaEnabled": false,
        "javaScriptEnabled": true
      },
      "cardHolder": {
        "email": "cliente@example.com",
        "mobilePhone": "5511999999999"
      }
    }
  }'
```

**Vamos explicar os principais campos usados acima dentro de threeDSecure2:**

<ParamField body="requiresLiabilityShift" type="boolean">
  Indica se você <b>exige o liability shift</b>. Se <code>true</code>, a transação só prosseguirá se houver mudança de responsabilidade para o emissor.
</ParamField>

<ParamField body="setupId" type="string" required>
  O ID da sessão de setup obtido no <b>Passo 1</b>. <b>Obrigatório</b>; vincula a transação atual com os dados coletados anteriormente. <b>Importante:</b> Este ID é válido apenas para <b>uma única tentativa de cobrança</b>. Se a transação falhar, você não pode reutilizar o mesmo <code>setupId</code> para retentar — será necessário criar um novo setup e reiniciar todo o fluxo 3DS.
</ParamField>

<ParamField body="redirectURL" type="string">
  A URL para a qual o cliente será <b>redirecionado de volta</b> após completar a autenticação 3DS (no caso de desafio). Normalmente é uma página do seu site (por exemplo, a página de confirmação de pedido ou de checkout) que irá processar a resposta. O provedor/autenticador usará esta URL para retornar o controle ao seu sistema após o desafio.
</ParamField>

<ParamField body="requestorURL" type="string">
  URL do domínio do <b>lojista (merchant)</b>, geralmente o endereço do seu site. Esse valor pode ser usado internamente pelo provedor 3DS2 durante a autenticação para verificar a origem da requisição.
</ParamField>

<ParamField body="billingAddress" type="object">
  Endereço de cobrança do portador do cartão. Campos como cidade, país, CEP, etc. (<b>Dados importantes para análise de risco e autenticação</b>).
</ParamField>

<ParamField body="browser" type="object" required>
  Objeto contendo <b>informações do navegador</b> do comprador, coletadas preferencialmente do próprio navegador do cliente. Inclua exatamente os dados requeridos:

  <ul>
    <li><code>ip</code>: IP do cliente.</li>
    <li><code>userAgent</code>: String do agente de usuário do navegador.</li>
    <li><code>acceptHeader</code>: Conteúdo do header HTTP "Accept" enviado pelo browser.</li>
    <li><code>language</code>: Idioma preferido do navegador (por exemplo, "pt-BR").</li>
    <li><code>colorDepth</code>, <code>screenHeight</code>, <code>screenWidth</code>: Profundidade de cor e resolução de tela do dispositivo.</li>
    <li><code>timeZoneOffset</code>: Fuso horário do usuário em minutos (ex.: Brasil = "180" minutos atrasados em relação a UTC).</li>
    <li><code>javaEnabled</code>: Se Java (Applet) está habilitado no browser (geralmente <code>false</code> hoje em dia).</li>
    <li><code>javaScriptEnabled</code>: Se o navegador tem JavaScript habilitado (<code>true</code> na maioria dos casos).</li>
  </ul>
</ParamField>

<ParamField body="cardHolder" type="object">
  Informações do portador do cartão, como email e telefone celular. Esses dados podem ser utilizados pelo emissor durante a autenticação (por exemplo, enviar um OTP via SMS).
</ParamField>

<Note>
  <b>Observação:</b> No exemplo acima, usamos valores simulados (como IP e userAgent abreviado). Em um cenário real, você deve capturar esses dados do navegador do cliente no front-end e passá-los corretamente na requisição. A Malga não coleta esses dados automaticamente, portanto sua aplicação cliente deve fornecê-los (por exemplo, usando <code>window\.navigator</code> para obter <code>userAgent</code>, <code>screen.width</code> etc., e APIs do browser para IP se disponível, ou obtendo IP do lado servidor).
</Note>

**Resposta da Cobrança:**

Ao criar a cobrança com 3DS2, a resposta da API incluirá, além dos dados da transação, um objeto `threeDSecure2.authData` com informações sobre a autenticação. Em particular, duas situações podem ocorrer:

* **Transação Autorizada de imediato (Frictionless):** O campo status da transação vem como `authorized` ou `pre_authorized` indicando que o banco emissor não exigiu desafio.

```json theme={null}
{
    ...
    "threeDSecure2": {
        "authData": {
            "action": "REDIRECT",
            "networkTransactionId": "7518984890596838804807",
            "providerType": "CYBERSOURCE",
            "response": null,
            "responseType": "AUTHORIZATION"
        },
        "authenticated": true
    }
}
```

* **Transação Pendente (Desafio necessário):** O campo status da transação virá como `pending`, indicando que o emissor solicitou um desafio (challenge) de autenticação. Nesse caso, o objeto `threeDSecure2.authData.response` trará os campos `stepUrl` e `token` que serão usados para iniciar o desafio. A transação ficará pendente até a conclusão do desafio pelo cliente.

```json theme={null}
{
  ...
  "threeDSecure2": {
        "authData": {
            "action": "REDIRECT",
            "networkTransactionId": "7518912480166601504805",
            "providerType": "CYBERSOURCE",
            "response": {
                "pareq": "...",
                "stepUrl": "https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp",
                "token": "..."
            },
            "responseType": "AUTHENTICATION"
        },
        "authenticated": null
  }
}
```

No caso `pending`, prossiga para o **Passo 4** abaixo para realizar o desafio de autenticação. Se a transação foi autorizada sem desafio, você pode pular o próximo passo e apenas informar o cliente do resultado (ou confirmar pagamento, etc.).

<Note>
  <b>Importante sobre retentativas:</b> Se a transação falhar por qualquer motivo (timeout, erro de tokenização, erro de autenticação, etc.), <b>não é permitido reutilizar o mesmo <code>setupId</code></b> para tentar novamente. Para retentar uma transação 3DS2 que falhou, você deve:

  <ol>
    <li>Criar um novo setup chamando <code>POST /v1/charges/3ds/setup</code> novamente</li>
    <li>Realizar uma nova coleta de dados do dispositivo (Passo 2)</li>
    <li>Criar uma nova cobrança com o novo <code>setupId</code> obtido (Passo 3)</li>
  </ol>

  Cada <code>setupId</code> é válido apenas para uma única tentativa de cobrança e não pode ser reutilizado em retentativas.
</Note>

### Passo 4: Desafio de Autenticação (Challenge 3DS2)

Quando o banco emissor exige uma validação adicional, é preciso apresentar ao cliente o desafio 3DS - normalmente uma tela onde ele deve, por exemplo, inserir um código SMS, senha ou outro fator de autenticação. A Malga simplifica esse processo fornecendo a URL e o token necessários para abrir a interface do banco emissor em um **iframe** dentro do seu site (ou via redirecionamento).

Assim como na coleta de dados, a implementação do desafio é feita no front-end, inserindo um formulário que será automaticamente enviado para o `stepUrl` do desafio, contendo o token de autorização. Esses valores foram retornados na resposta da cobrança (Passo 3) dentro de `threeDSecure2.authData.response.stepUrl` e `...response.token`.

Você pode implementar de forma similar à abaixo no seu HTML (por exemplo, abrindo um modal ou sobreposição com um iframe para o desafio):

```html theme={null}
<!-- Elementos para o desafio 3DS2 (exibidos ao usuário) -->
<div id="desafio_3ds" style="display: none;">
  <!-- Formulário que será submetido ao banco emissor -->
  <form id="step_form" method="POST" target="stepUpIframe">
    <input id="step_input_jwt" type="hidden" name="JWT" value="" />
  </form>
  <!-- Iframe para exibir o conteúdo do desafio do emissor -->
  <iframe id="stepUpIframe" name="stepUpIframe" style="border:none; width:400px; height:800px;"></iframe>
</div>
<script>
  // Valores obtidos da resposta da cobrança 3DS (authData):
  const stepUrl = "<URL_RETORNADA_NO_AUTHDATA>";   // e.g., https://acs.cardissuer.com/step-auth
  const stepToken = "<TOKEN_RETORNADO_NO_AUTHDATA>"; // JWT do authData para desafio

  // Submete o formulário de desafio:
  const formStep = document.getElementById('step_form');
  const inputJwt = document.getElementById('step_input_jwt');
  formStep.action = stepUrl;
  inputJwt.value = stepToken;
  formStep.submit();
  
  // Exibe o iframe/modal de desafio para o usuário
  document.getElementById('desafio_3ds').style.display = 'block';
</script>
```

No código acima, `stepUrl` (`threeDSecure2.authData.response.stepUrl`) e `stepToken` (`threeDSecure2.authData.response.token`) devem ser preenchidos com os valores retornados na resposta da criação da cobrança pendente (obtidos no **Passo 3**). Ao executar `formStep.submit()`, o navegador irá **redirecionar o iframe** para o endereço do desafio do emissor, efetivamente carregando a página de autenticação do banco dentro do iframe. O cliente então interage com essa página (por exemplo, digitando a senha do cartão ou um código enviado por SMS).

Durante o desafio, o navegador do cliente está se comunicando diretamente com o **banco emissor** (via provedor 3DS). Uma vez concluído (sucesso, falha ou expirado), o fluxo de 3DS2 providenciará um redirecionamento de volta para a URL que você configurou em `redirectURL` no Passo 3.

### Passo 5: Verificando o Resultado Final

Após o cliente completar (ou tentar) o desafio e retornar para o seu site (URL de retorno configurada), é necessário verificar o status final da transação para saber se o pagamento foi **autorizado** ou **negado** pelo emissor. A Malga permite consultar a transação a qualquer momento via API, então você deve fazer uma requisição **GET** para o endpoint `/v1/charges/{chargeId}` usando o ID da cobrança criada no Passo 3.

Por exemplo, suponha que o ID da cobrança retornado no Passo 3 foi `6607c9b8-f6a3-48e2-9918-518d41d2fa60`. Você pode consultá-la assim:

```bash theme={null}
curl --request GET 'https://api.malga.io/v1/charges/6607c9b8-f6a3-48e2-9918-518d41d2fa60' \
  --header 'x-api-key: <SEU_API_KEY>' \
  --header 'x-client-id: <SEU_CLIENT_ID>' \
  --header 'Accept: application/json'
```

A resposta trará todos os detalhes da cobrança, incluindo o campo `status` atualizado (que após o desafio provavelmente estará como `authorized` se o cliente autenticou com sucesso e o pagamento foi aprovado, ou outro status final como `declined` em caso de falha). Você também poderá ver dentro de `threeDSecure2` detalhes como `authenticated: true/false`, `liabilityShift: true/false`, etc., indicando o resultado da autenticação 3DS2.
