# Cartão com a Vortex

> Regras e comportamento do checkout quando a venda passa pela Vortex (acquirer vortex): sem verificação do banco, tudo dentro do elemento, navegador de app, pagamento em análise, códigos de erro e webhook.

Fonte: https://app.thronecorporate.com/docs/cartao/vortex

## O que é igual às outras adquirentes

A integração é a mesma do [guia de cartão](/docs/cartao): `POST /elements/checkout` na moeda do comprador, Throne Elements na página, webhook `transaction.paid`. Campos, respostas, erros, moedas e formato do webhook não mudam. Esta página cobre só o que é próprio da Vortex.

**Para usar a Vortex**, mande `"acquirer": "vortex"` na criação do checkout. Se a Vortex for a padrão da sua conta, o campo é opcional. A Vortex é habilitada pelo suporte, conta a conta. Veja [Escolher a adquirente](/docs/cartao/escolher).

**Nome e e-mail do comprador são obrigatórios na criação.** Mande `customer.name` (até 120 caracteres) e `customer.email` (e-mail válido, até 180). Sem eles, ou fora desses tamanhos, a chamada volta `422 customer_required_for_vortex` e nada é criado. O elemento nunca pergunta nome nem e-mail ao comprador: colete os dois na sua página antes de chamar a API. A regra vale sempre que a venda fica com a Vortex, inclusive sem o campo `acquirer`, quando ela é a padrão da conta. Nas outras adquirentes, `customer` continua opcional. O exemplo abaixo já manda os dois campos.

```bash
curl -X POST https://app.thronecorporate.com/api/v1/elements/checkout \
  --max-time 60 \
  -H "Authorization: Bearer $THRONE_PK:$THRONE_SK" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "amount_cents": 4990, "currency": "eur", "acquirer": "vortex", "customer": { "name": "Lena Fischer", "email": "lena@example.de" } }'
```

A resposta `201` traz `"acquirer": "vortex"`, e a venda fica na Vortex até o fim: pagamento, estorno e contestação.

**A aprovação nem sempre é imediata.** O banco do comprador autoriza na hora, mas a venda ainda passa por uma análise de risco antes de virar paga. Quando isso acontece, o elemento mostra o pagamento em análise, a venda fica `pending` e o `transaction.paid` chega quando a análise libera, em geral em segundos. Uma reprovação na análise fecha a venda como recusada e conta como tentativa. Não trate `pending` como falha: espere o webhook.

**A moeda funciona exatamente como nas outras adquirentes.** Você manda o valor na moeda do comprador (por exemplo, `"currency": "eur"`) e ele paga nessa moeda. A cotação que credita o seu saldo é fixada na criação, e o webhook traz `currency`, `native_amount_cents` e `fx_rate` no mesmo formato. Detalhes em [Moedas e limites](/docs/cartao/moeda).

Existe também a [integração direta por API](/docs/cartao/vortex-direto), sem o Throne Elements, para quem já tem checkout próprio. Ela é liberada caso a caso; sem a liberação, a Vortex habilitada na conta dá acesso ao checkout comum desta página.

**A Vortex faz cobrança recorrente**, nos sete ciclos de `weekly` a `yearly`: mande `recurrence` na criação do checkout e as cobranças seguintes saem sozinhas, no mesmo cartão. Veja [Recorrência na Vortex](#recorrencia), mais abaixo, e o [guia de Recorrência](/docs/cartao/recorrencias).

**A Vortex faz upsell em um clique na integração direta**, e só nela: o
[`POST /api/v1/vortex/upsell`](/docs/cartao/vortex-direto#upsell-em-um-clique)
cobra um segundo produto no mesmo cartão de uma venda paga, sem pedir o cartão
de novo. No checkout do Throne, este, o `one_click_from` com
`"acquirer": "vortex"` ainda volta `one_click: false`, sem erro: a página
hospedada desta adquirente não sabe cobrar o cartão guardado.

A Vortex não atende o [Checkout Brasil](/docs/cartao/brasil): o
`POST /elements/checkout/br` volta `422 acquirer_not_enabled`.

## Resumo

| Item | Na Vortex |
|---|---|
| Verificação do banco | Não tem. O banco autoriza ou recusa na hora, e o resultado aparece dentro do próprio elemento |
| Pagamento em análise | Pode acontecer: autorizada pelo banco, a venda ainda passa por uma análise de risco. Nesse intervalo ela fica `pending`, e o `transaction.paid` chega quando a análise libera |
| Navegador de app (Instagram, Facebook, Google, TikTok) | Tudo dentro do elemento; os eventos chegam normalmente |
| Eventos na sua página | Em todos os caminhos: computador, celular e navegador de app |
| Valor máximo por venda | Varia com a moeda e com a cotação do dia. Veja [Limites](#limites) |
| Tentativas por checkout | 5, contadas no servidor. Recarregar a página não devolve tentativas |
| Validade do checkout | 24 horas |
| Fechamento por recusa | Na 5ª recusa, ou 10 minutos depois de uma recusa sem nova tentativa (`failed`) |
| Parcelas | À vista |
| Recorrência | Sim, nos sete ciclos de `weekly` a `yearly`. A assinatura só começa a valer quando a primeira cobrança aprova. Veja [Recorrência](#recorrencia) |
| Upsell em um clique | Não |
| Dados do comprador | `customer.name` e `customer.email` obrigatórios na criação. O elemento não os pergunta |
| Idioma do checkout | Pelo país do comprador; Brasil e Portugal veem em inglês. `?nl=` no `checkout_url` mostra outro idioma, para teste |
| Idioma da mensagem de recusa | O mesmo do checkout, pelo país do comprador (ou pelo `?nl=`), na tela e em `e.detail.message`. Não é preciso enviar `Accept-Language` na criação |
| Códigos em `throne-elements:error` | `declined`, `attempts_exhausted`, `token`, `network`, `timeout`, `expired`, `ended` |

## Limites

| Limite | Na Vortex |
|---|---|
| Mínimo por venda | Varia com a moeda e com a cotação do dia, ou o mínimo próprio da Vortex, se houver |
| Máximo por venda | Depende da adquirente e varia com a moeda e com a cotação do dia. Consulte `GET /elements/acquirers?currency=` (campo `limits.max_amount_cents`) |
| Acima do máximo | `422 invalid_amount` com `max_amount_cents` na sua moeda e `alternatives`. Nada é criado |
| Capacidade de criação | Em pico ou instabilidade, `503 temporarily_unavailable` com `Retry-After` |

## Como o comprador paga

### Em qualquer aparelho

1. Preenche número, validade, CVV e nome impresso no cartão.
2. Clica em pagar.
3. O resultado sai em poucos segundos, dentro do próprio elemento. Não há etapa do banco nem janela nova.
4. Aprovado: o elemento mostra a confirmação e dispara `throne-elements:paid`.
5. Recusado: o elemento mostra o motivo, quantas tentativas restam e um botão para tentar de novo. A venda continua `pending`.

### Em navegador de app

Instagram, Facebook, o app do Google, TikTok e outros apps abrem links num navegador próprio, que não abre uma segunda janela. Na Vortex isso não faz diferença: o pagamento acontece todo dentro do elemento, o comprador termina na sua página e `throne-elements:paid` chega como no computador. Mesmo assim, libere o pedido pelo webhook ou pelo `GET`, nunca só pelo evento da página.

### O que o comprador vê

- **O endereço.** Nada muda: o comprador fica na sua página do começo ao fim.
- **Nenhuma confirmação do banco.** Não há código por mensagem, aplicativo do banco nem pergunta de segurança: o cartão é autorizado na hora. Um aviso ao lado do botão de pagar é opcional.
- **A fatura.** Na fatura do cartão, a compra aparece sem o nome da sua loja.

Textos sugeridos, se quiser avisar:

```text Inglês
Secure payment. You will see the result right here, on this page.
```

```text Alemão
Sichere Zahlung. Das Ergebnis erscheint direkt hier auf dieser Seite.
```

```text Espanhol
Pago seguro. Verás el resultado aquí mismo, en esta página.
```

## Requisitos da página

- **Não fixe a altura do container** e não esconda o `overflow`: as telas de resultado e de análise mudam a altura do elemento.
- Sem `sandbox` em volta do elemento. Se não der para tirar, use a lista mínima de [Throne Elements](/docs/cartao/elements#boas-praticas).
- **O clique no botão de pagar precisa ser do comprador.** Não dispare o pagamento por código.
- Se o seu site usa Content-Security-Policy, libere `https://app.thronecorporate.com` em `script-src` e em `img-src`, e em `frame-src` libere esse domínio e o domínio do `checkout_url`, como em [Throne Elements](/docs/cartao/elements#boas-praticas).

## Pagamento em análise

Às vezes o pagamento entra em análise antifraude. O comprador vê "Pagamento em análise", sem formulário, e a venda fica `pending` até a decisão:

- aprovado, vira `paid` e o webhook `transaction.paid` é enviado;
- reprovado, conta como uma recusa: a tentativa é gasta, o elemento mostra o motivo e, com tentativas sobrando, o comprador pode tentar de novo. A venda continua `pending`; na 5ª recusa o checkout fecha como `failed`.

Se a decisão demorar, o elemento avisa que a confirmação pode levar alguns minutos e envia `timeout` em `throne-elements:error`. Isso não é recusa. Não libere o pedido enquanto não chegar `transaction.paid`, e não cancele o pedido só pelo `timeout`.

## Erros e o que fazer

Na criação do checkout:

| Situação | Resposta | O que fazer |
|---|---|---|
| Valor acima do máximo da Vortex | `422 invalid_amount`, com `max_amount_cents` e `alternatives` | Não repita. Crie com o `acquirer` de uma das `alternatives` ou divida o pedido |
| Valor abaixo do mínimo | `422 invalid_amount`, com `min_amount_cents` | Aumente o valor |
| Sem `customer.name` ou `customer.email`, e-mail inválido ou fora dos tamanhos (nome até 120 caracteres, e-mail até 180) | `422 customer_required_for_vortex` | Mande os dois campos na criação, dentro dos tamanhos. Nada é criado |
| Vortex não habilitada na conta | `422 acquirer_not_enabled`, com as habilitadas no `message` | Use uma das habilitadas, ou fale com o suporte para habilitar a Vortex |
| Vortex em pausa, instável ou sem capacidade | `503 temporarily_unavailable`, com `Retry-After` e `"retryable": true` | Espere o `Retry-After` e repita com uma `Idempotency-Key` nova, ou use outra adquirente habilitada |
| Criação recusada | `502 checkout_failed`, com `"retryable": false` | Não repita igual. Se continuar, fale com o suporte |
| Falha passageira de conexão | `502 checkout_failed`, com `"retryable": true` | Repita com uma `Idempotency-Key` nova |
| Sem resposta (timeout do seu lado) | Nenhuma | Repita com a **mesma** `Idempotency-Key` ([regra](/docs/comecar#como-repetir-uma-chamada-com-seguranca)) |

Na página, em `throne-elements:error` (`e.detail.code`):

| `code` | O que aconteceu | O que fazer |
|---|---|---|
| `declined` | O banco não autorizou | O comprador pode tentar de novo ou usar outro cartão. Vale sugerir que ele libere compras online e internacionais no app do banco |
| `attempts_exhausted` | O checkout fechou: acabaram as 5 tentativas | Ofereça outro meio de pagamento ou um checkout novo |
| `token` | Os dados do cartão não passaram na validação, antes da cobrança | O comprador confere os dados e tenta de novo. Nenhuma tentativa é gasta |
| `network` | Falha de conexão, ou o formulário não carregou | O comprador pode tentar de novo em alguns instantes |
| `timeout` | A análise antifraude está demorando e o pagamento segue em análise | Espere o webhook ou consulte `GET /transactions/{id}`. Não é recusa; não crie outro checkout por isso |
| `expired`, `ended` | O checkout passou da validade ou foi encerrado | Crie um checkout novo |

A tabela completa dos códigos, nas seis adquirentes, está em [Throne Elements](/docs/cartao/elements#codigos-de-erro). Duas tentativas ao mesmo tempo no mesmo checkout (duas abas ou duplo clique) não geram cobrança dupla: a segunda recebe "Já existe um pagamento em andamento. Aguarde." e o elemento acompanha o pagamento que já está em andamento.

### Tratar os eventos na página

Na Vortex, um código pede tratamento próprio: `timeout` é espera, não recusa.

```js
window.addEventListener('throne-elements:paid', (e) => {
  // e.detail.transaction_id: mostre o "obrigado". A liberação do pedido vem pelo webhook.
});

window.addEventListener('throne-elements:error', (e) => {
  switch (e.detail.code) {
    case 'timeout':
      // o pagamento segue em análise: mostre "estamos confirmando" e espere o webhook
      break;
    case 'attempts_exhausted':
    case 'expired':
    case 'ended':
      // este checkout acabou: ofereça outro meio ou crie um checkout novo
      break;
    default:
      // declined, token, network: o próprio elemento já oferece a nova tentativa
      break;
  }
});
```

## Quando chega o webhook

O resultado sai na hora e o webhook `transaction.paid` costuma sair logo depois da aprovação. Numa venda que entra em análise, ele sai quando a análise aprova. Se a confirmação da Vortex se perder no caminho, a conferência automática do Throne a recupera alguns minutos depois. Não cancele o pedido por falta de webhook antes da validade de 24 horas; na dúvida, consulte `GET /transactions/{id}`.

O webhook é o mesmo das outras adquirentes: `currency` e `native_amount_cents` com a venda na moeda do comprador, `amount_cents` com o valor creditado no seu saldo e `fx_rate` com a cotação fixada na criação. Veja [Webhooks](/docs/webhooks#quando-o-webhook-chega).

## Recorrência

A Vortex faz cobrança recorrente nos sete ciclos do Throne, com a integração do [guia de Recorrência](/docs/cartao/recorrencias): o mesmo `POST /elements/checkout`, com o campo `recurrence`.


- **Estorno**: não é feito pela API; fale com o suporte. O estorno total deixa a venda `refunded`. O parcial mantém `paid`, com os valores reduzidos.
- **Contestação**: o Throne debita da sua carteira o valor líquido da venda, e ela vira `chargeback`. Se a contestação for revertida a seu favor, ela volta para `paid`.
- Nenhum desses eventos gera webhook. Acompanhe pelo `GET /transactions/{id}`.

## Testar

Use um cartão de verdade com valor baixo. Para ver como o comprador de outro país enxerga o checkout, abra o `checkout_url` da resposta com `?nl=` e o código do idioma (por exemplo, `?nl=de` para alemão): o formulário, os números e as telas do elemento saem nesse idioma. Teste também dentro do navegador do Instagram ou do Facebook, no celular: na Vortex o resultado aparece na sua página e o evento chega. Os erros que dá para provocar sem custo e o roteiro completo estão em [Como testar](/docs/testar).

## Checklist

- [ ] Checkout criado no servidor, com `"acquirer": "vortex"` (ou a Vortex como padrão da conta), `Idempotency-Key` nova por venda e timeout de 60 segundos.
- [ ] `customer.name` e `customer.email` (e-mail válido) enviados na criação, coletados na sua página antes de chamar a API.
- [ ] Moeda do comprador em `currency`, sem ajustar o valor no seu site.
- [ ] Máximo da Vortex conferido na moeda do seu público, com plano para `422 invalid_amount` (outra adquirente ou pedido dividido).
- [ ] Container sem altura fixa e sem `sandbox` em volta do elemento (ou com a lista mínima).
- [ ] Tratamento de `e.detail.code` em `throne-elements:error`, com `timeout` tratado como espera.
- [ ] Pedido liberado só com `transaction.paid` (assinatura validada) ou com o `GET`.
- [ ] Novo checkout para cada nova tentativa de compra depois de `failed` ou `expired`.
