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

# Roteamento inteligente

> Escolha automaticamente o melhor provedor com base em taxas e disponibilidade

## O que é roteamento inteligente?

O roteamento inteligente permite que o **pagamentos.dev** escolha automaticamente o provedor mais adequado para cada operação, em vez de sempre usar o mesmo. Isso é especialmente útil quando você integra **múltiplos provedores** e quer otimar custos ou garantir alta disponibilidade.

Há duas estratégias de roteamento disponíveis:

* **`melhorTaxa()`** — escolhe o provedor que oferece o menor custo de taxa para o valor e método de pagamento da transação.
* **`disponibilidade()`** — tenta os provedores em uma ordem de prioridade definida por você, fazendo fallback automaticamente se o primeiro falhar.

## Requisitos

Para usar roteamento, você precisa de **pelo menos 2 provedores** configurados. Além disso, **todos os provedores devem ter uma taxa configurada**.

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Pagamentos, melhorTaxa, abacatepay, mercadopago } from 'pagamentos'

const pg = new Pagamentos({
  router: melhorTaxa(),
  providers: [
    abacatepay({
      apiKey: '...',
      taxa: { type: 'flat', value: 80 } // R$ 0,80 em centavos
    }),
    mercadopago({
      accessToken: '...',
      taxa: { type: 'percentage', value: (v) => v * 0.01 } // 1%
    })
  ]
})
```

<Warning>
  Se algum provedor não tiver `taxa` configurada, o SDK lançará um erro no momento da inicialização.
</Warning>

## Router `melhorTaxa()`

O router `melhorTaxa()` compara o **custo líquido** (`valor - taxa`) de cada provedor e escolhe o que oferece o melhor valor. A taxa nunca é descontada do valor enviado ao provedor — ela serve apenas para comparação interna de custo.

### Exemplo prático

Imagine que você tem:

* **AbacatePay** cobra uma taxa fixa de R\$ 0,80 (`80` centavos)
* **MercadoPago** cobra 1% sobre o valor da transação

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Pagamentos, melhorTaxa, abacatepay, mercadopago } from 'pagamentos'

const pg = new Pagamentos({
  router: melhorTaxa(),
  providers: [
    abacatepay({
      apiKey: '...',
      taxa: { type: 'flat', value: 80 }
    }),
    mercadopago({
      accessToken: '...',
      taxa: { type: 'percentage', value: (originalValue) => originalValue * 0.01 }
    })
  ]
})

// Para R$ 50,00 (5000 centavos):
// AbacatePay: 5000 - 80 = 4920
// MercadoPago: 5000 - 50 = 4950
// -> Escolhe MercadoPago
await pg.cobrancas.create({ idempotencyKey: crypto.randomUUID(), valor: 5000, metodoPagamento: 'pix' })

// Para R$ 100,00 (10000 centavos):
// AbacatePay: 10000 - 80 = 9920
// MercadoPago: 10000 - 100 = 9900
// -> Escolhe AbacatePay
await pg.cobrancas.create({ idempotencyKey: crypto.randomUUID(), valor: 10_000, metodoPagamento: 'pix' })
```

### Tipos de taxa

Você pode definir a taxa de três formas:

| Tipo         | Descrição                                           | Exemplo                                                  |
| ------------ | --------------------------------------------------- | -------------------------------------------------------- |
| `flat`       | Valor fixo em **centavos**                          | `{ type: 'flat', value: 80 }` = R\$ 0,80                 |
| `percentage` | Função que recebe o valor original e retorna a taxa | `{ type: 'percentage', value: (v) => v * 0.01 }` = 1%    |
| `async`      | Valor ou função assíncrona                          | `{ type: 'flat', value: async () => getFromDatabase() }` |

### Taxa por método de pagamento

Você também pode definir taxas diferentes por método de pagamento usando um **array**:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
woovi({
  appId: '...',
  mode: 'production',
  taxa: [
    { type: 'flat', metodosPagamento: ['pix'], value: 10 },
    { type: 'flat', metodosPagamento: ['boleto'], value: 100 }
  ]
})
```

<Warning>
  Se você usar `metodosPagamento` em uma taxa, **todos os métodos de pagamento** usados pela sua aplicação devem estar cobertos por pelo menos uma taxa do provedor. Caso contrário, o SDK lançará um erro informando qual método não está coberto.
</Warning>

## Router `disponibilidade()`

O router `disponibilidade()` define uma **ordem de prioridade** entre os provedores. Ele sempre tenta o primeiro da lista; se a operação falhar por **timeout** ou erro **5xx** (após os retries configurados), ele passa automaticamente para o próximo provedor da ordem.

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import { Pagamentos, disponibilidade, abacatepay, mercadopago, woovi } from 'pagamentos'

const pg = new Pagamentos({
  router: disponibilidade({ ordem: ['woovi', 'abacatepay', 'mercadopago'] }),
  providers: [
    woovi({ appId: '...', mode: 'production', taxa: { type: 'flat', value: 10 } }),
    abacatepay({ apiKey: '...', taxa: { type: 'flat', value: 80 } }),
    mercadopago({ accessToken: '...', taxa: { type: 'percentage', value: (v) => v * 0.01 } })
  ]
})
```

Neste exemplo:

1. Sempre tenta a **Woovi** primeiro.
2. Se a Woovi não responder dentro do timeout ou retornar 5xx, tenta a **AbacatePay**.
3. Se a AbacatePay também falhar, tenta o **MercadoPago**.
4. Se todos falharem, lança um erro agregado.

## Configurações globais

Você pode configurar o **timeout** e o número de **retries** diretamente na instância `Pagamentos`:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
const pg = new Pagamentos({
  router: melhorTaxa(),
  timeout: 15_000,      // 15 segundos (padrão)
  retryCount: 1,        // 1 tentativa por provedor (padrão)
  providers: [/* ... */]
})
```

| Opção        | Padrão   | Descrição                                                              |
| ------------ | -------- | ---------------------------------------------------------------------- |
| `timeout`    | `15_000` | Tempo máximo de espera por uma resposta do provedor, em milissegundos. |
| `retryCount` | `1`      | Número de tentativas por provedor antes de considerar que ele falhou.  |

## Override manual do provedor

Mesmo com um router configurado, você pode **forçar um provedor específico** passando `{ provider: 'nome' }` como último argumento da operação:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// Normalmente o router escolheria automaticamente
await pg.cobrancas.create({ idempotencyKey: crypto.randomUUID(), valor: 5000, metodoPagamento: 'pix' })

// Forçando um provedor específico
await pg.cobrancas.create(
  { idempotencyKey: crypto.randomUUID(), valor: 5000, metodoPagamento: 'pix' },
  { provider: 'abacatepay' }
)
```

Isso é útil para:

* Testes e debugging
* Casos especiais onde você sabe qual provedor usar
* Migrar clientes gradualmente entre provedores

## Exemplo completo

Aqui está um exemplo completo combinando roteamento por taxa com múltiplos provedores e configurações personalizadas:

```ts theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import {
  Pagamentos,
  melhorTaxa,
  abacatepay,
  mercadopago,
  woovi,
  onCobrancaCreated
} from 'pagamentos'

const pg = new Pagamentos({
  router: melhorTaxa(),
  timeout: 10_000,     // 10 segundos de timeout
  retryCount: 2,       // 2 tentativas por provedor
  providers: [
    abacatepay({
      apiKey: process.env.ABACATEPAY_API_KEY!,
      taxa: { type: 'flat', value: 80 }
    }),
    mercadopago({
      accessToken: process.env.MERCADOPAGO_ACCESS_TOKEN!,
      taxa: { type: 'percentage', value: (v) => v * 0.01 }
    }),
    woovi({
      appId: process.env.WOOVI_APP_ID!,
      mode: 'production',
      taxa: [
        { type: 'flat', metodosPagamento: ['pix'], value: 15 },
        { type: 'flat', metodosPagamento: ['boleto'], value: 120 }
      ]
    })
  ],
  hooks: [
    onCobrancaCreated(async (evt) => {
      console.log(`Cobrança criada no provedor: ${evt.provider}`)
      console.log(`ID: ${evt.output.id}, Valor: ${evt.output.valor}`)
    })
  ]
})

// O SDK escolhe automaticamente o provedor mais barato
const cobranca = await pg.cobrancas.create({
  idempotencyKey: crypto.randomUUID(),
  valor: 7500, // R$ 75,00
  metodoPagamento: 'pix',
  cliente: {
    nome: 'Maria Souza',
    documento: '987.654.321-00'
  }
})
```

## Dicas e boas práticas

* **Taxas em centavos**: o tipo `flat` sempre usa centavos. `80` = R$ 0,80, `1000` = R$ 10,00.
* **Taxa é apenas para comparação**: o valor enviado ao provedor é o valor original da cobrança. A taxa não é descontada automaticamente.
* **Cobertura completa de métodos**: quando usar `metodosPagamento` em taxas, certifique-se de que todos os métodos que sua aplicação usa estejam cobertos.
* **Combine com hooks**: use lifecycle hooks para registrar qual provedor foi escolhido em cada transação. Isso ajuda na análise e reconciliação.
* **Monitore falhas**: ao usar `disponibilidade()`, monitore logs de fallback para identificar provedores com instabilidade.
* **Teste antes de ativar**: teste o comportamento do router com valores diferentes para entender quando cada provedor será escolhido.

## Quando usar cada router?

| Cenário                                    | Router recomendado  |
| ------------------------------------------ | ------------------- |
| Quer minimizar custos de taxa              | `melhorTaxa()`      |
| Tem provedores com SLA diferentes          | `disponibilidade()` |
| Quer priorizar um provedor mas ter backup  | `disponibilidade()` |
| Taxas variam muito por valor de transação  | `melhorTaxa()`      |
| Precisa de alta disponibilidade (failover) | `disponibilidade()` |
