# Fluxo de pagamento — Casos extremos

Nem todo pagamento segue o [caminho feliz](/pt/docs/payment-flows/std-flow). Esta página cobre resultados não padrão — pagamento insuficiente, pagamento em excesso, expiração, transações on-chain falhas e reembolsos — incluindo o que a Fluxis faz internamente, quais webhooks você recebe e como tratar cada cenário na sua integração.

## Visão geral

```mermaid
flowchart TD
    PR[Payment Request] --> Exp{Expired before payment?}
    Exp -->|Yes| E[expired]
    Exp -->|No| Pay{Customer pays}
    Pay --> Proc[processing]
    Proc --> Final{After finality}
    Final -->|Amount matches| Comp[completed → confirmed]
    Final -->|Too little| Under[underpaid]
    Final -->|Too much| Over[overpaid → confirmed]
    Final -->|Tx failed on-chain| Fail[stuck in processing]
```

| Scenario | Final status | Internal transaction | Webhook sent |
| -------- | ------------ | -------------------- | ------------ |
| Exact payment | `completed` → `confirmed` | Yes | `processing`, `completed` |
| Underpayment | `underpaid` | **No** | `processing`, `underpaid` |
| Overpayment | `overpaid` → `confirmed` | Yes (full received amount) | `processing`, `overpaid` |
| No payment in time | `expired` | No | No |
| On-chain tx reverts / fails | `processing` (stuck) | No | `processing` only |

## Matriz de entrega de webhooks

A Fluxis envia webhooks em nível de conta apenas para estas mudanças de status de solicitação de pagamento:

| Status | Webhook delivered | Typical trigger |
| ------ | ----------------- | --------------- |
| `processing` | Yes | Cron detectou transferência on-chain (salto 1) |
| `completed` | Yes | Confirmado após finalidade; valor corresponde (salto 2) |
| `underpaid` | Yes | Confirmado após finalidade; valor muito baixo (salto 2) |
| `overpaid` | Yes | Confirmado após finalidade; valor muito alto (salto 2) |
| `confirmed` | **No** | Transação interna de ledger criada (salto 3) |
| `expired` | **No** | Cron de expiração marca solicitação como expirada |
| `failed` | **No** | Não definido atualmente pelo worker |
| `pending` / `created` | **No** | Criação inicial — consulte ou use seu próprio estado de UI |

::::info
**Consulte status sem webhooks**

Use `GET /v1/pos/{posID}/payment-request/{paymentRequestID}` para detectar status `expired` e `confirmed`. Registre webhooks em `POST /v1/account/{accountID}/webhook` — consulte [Webhooks](/pt/docs/developers/webhooks).
::::

---

## Underpaid

Um pagamento **underpaid** ocorre quando o cliente envia menos que o valor esperado e a transação on-chain é confirmada após a finalidade.

### O que a Fluxis faz

```mermaid
sequenceDiagram
    participant W as Transaction Worker
    participant DB as Database
    participant WH as Webhook

    W->>W: Compare received vs expected
    Note over W: received < expected
    W->>DB: status → underpaid
    W->>WH: Webhook (underpaid)
    W->>W: Release vault
    Note over W: Hop 3 skipped — no internal transaction
```

1. O salto 2 compara `ReceivedAmount` (da detecção do cron) com `ExpectedAmount`
2. Status é definido como **`underpaid`**
3. Um webhook é enviado com status `underpaid`
4. O vault é liberado e removido do cache Redis
5. **Salto 3 é ignorado** — nenhum registro interno de `Transaction` é criado, status **não** atinge `confirmed`

::::warning
**Sem transação de ledger para underpaid**

Como o salto 3 executa apenas para status `completed` e `overpaid`, pagamentos underpaid permanecem fora do pipeline padrão de liquidação. Coordene a resolução com o suporte Fluxis ou inicie um [reembolso](#refunds-api) se devolver fundos ao cliente.
::::

### Tratamento do comerciante

| Action | Recommendation |
| ------ | -------------- |
| **Do not fulfill** the order automatically | Trate `underpaid` como pagamento parcial que exige revisão manual |
| **Contact the customer** | Solicite o saldo restante ou acorde cumprimento parcial |
| **Create a new payment request** | Para a diferença pendente, se o cliente concordar em pagar mais |
| **Request a refund** | Use a [Refunds API](#refunds-api) para devolver o valor parcial à wallet do cliente |

Status elegíveis para reembolso incluem `underpaid`. Consulte [Refunds API](#refunds-api) abaixo.

---

## Overpaid

Um pagamento **overpaid** ocorre quando o cliente envia mais que o valor esperado.

### O que a Fluxis faz

```mermaid
sequenceDiagram
    participant W as Transaction Worker
    participant DB as Database
    participant WH as Webhook

    W->>W: Compare received vs expected
    Note over W: received > expected
    W->>DB: status → overpaid, save full received amount
    W->>WH: Webhook (overpaid)
    W->>W: Hop 3 — create internal transaction
    W->>DB: status → confirmed
```

1. O salto 2 define status como **`overpaid`** e registra o valor recebido integral
2. Um webhook é enviado com status `overpaid`
3. O salto 3 cria uma **Transaction** interna pelo valor recebido integral
4. Status transiciona para **`confirmed`** (sem webhook adicional)

### Tratamento do comerciante

| Action | Recommendation |
| ------ | -------------- |
| **Fulfill the order** for the requested amount | O cliente pagou pelo menos o preço esperado |
| **Refund the excess** | Use `POST /v1/refunds/payment-request/{paymentRequestID}` com `amount` explícito para a porção overpaid |
| **Contact support** | Para casos complexos onde reembolso automático é insuficiente |

Quando `amount` é omitido em solicitação de reembolso para pagamento overpaid, a Fluxis reembolsa por padrão a **porção overpaid** (recebido menos esperado).

---

## Expired

Uma solicitação de pagamento **expira** quando nenhum pagamento on-chain é detectado antes do timestamp de expiração.

### Temporização

| Setting | Value | Scope |
| ------- | ----- | ----- |
| Payment request expiration | **8 minutos** | Desde atribuição de vault (status `created`) |
| Payment intention expiration | **5 minutos** | Apenas fluxo PoS caixa, antes de criar PR |
| Expiration check interval | Every **30 seconds** | Job cron em segundo plano |

### O que a Fluxis faz

```mermaid
stateDiagram-v2
    created --> expired: expiration < now (cron)
    expired --> [*]
```

1. O cron de expiração encontra solicitações com `status = created` e `expiration < now`
2. Atualiza status para **`expired`**
3. **Nenhum webhook** é enviado por expiração
4. O vault **não é liberado imediatamente** — é reciclado quando o pool de vaults o reatribui (lógica de sobrescrita de vault expirado)

::::note
**Período de graça para pagamentos tardios**

Transações transmitidas logo antes da expiração ainda podem ser detectadas se o endereço vault permanecer no cache Redis (TTL = expiração + 60 segundos). Não assuma que `expired` significa que o cliente não pode pagar — verifique webhooks `processing` tardios ou consulte o endpoint de status.
::::

### Tratamento do comerciante

| Action | Recommendation |
| ------ | -------------- |
| **Show expiration in UI** | Exiba contagem regressiva baseada no campo `expiration` da resposta de criação |
| **Create a new payment request** | Recuperação padrão — cada solicitação é de uso único |
| **Poll for late payments** | Se o cliente afirma ter pago, verifique status antes de criar solicitação duplicada |

Consulte [Payment Requests — Timing](/pt/docs/key-concepts/payment-request#timing-and-expiration) para detalhes.

---

## Transação falha presa em processing

Quando uma transação on-chain **falha ou reverte** após ser detectada, o worker registra a falha mas **não** atualiza o status da solicitação de pagamento.

### O que a Fluxis faz

No salto 2 (`transaction_check_update_payment_request`), quando `GetTransaction` retorna status **failed**:

1. O worker registra `"Blockchain Transaction Failed"`
2. Retorna sem atualizar a solicitação de pagamento
3. A solicitação de pagamento **permanece em `processing`** indefinidamente
4. Nenhum webhook adicional é enviado além da notificação inicial `processing`

```mermaid
flowchart LR
    A[processing] --> B{GetTransaction status}
    B -->|confirmed| C[completed / underpaid / overpaid]
    B -->|pending| D[Re-enqueue with finality delay]
    B -->|failed| E[Log only — stays processing]
```

::::warning
**Comportamento conhecido**

Este é o comportamento atual da plataforma. Se uma solicitação está presa em `processing` e a transação on-chain falhou, entre em contato com [support@fluxis.us](mailto:support@fluxis.us) para resolução manual. Consulte `GET /v1/pos/{posID}/payment-request/{paymentRequestID}` e verifique o hash da transação em um block explorer.
::::

### Tratamento do comerciante

| Action | Recommendation |
| ------ | -------------- |
| **Verify on-chain** | Busque o hash da transação (se disponível) em um block explorer |
| **Do not fulfill** | Status `processing` preso não garante pagamento |
| **Contact support** | Forneça o ID da solicitação de pagamento e hash da transação |
| **Create a new payment request** | Se a transação original falhou definitivamente |

---

## Refunds API

A Fluxis fornece uma Refunds API para iniciar reembolsos de solicitações de pagamento elegíveis. Reembolsos são criados no nível da API e disparam notificação webhook — **a execução on-chain do reembolso ainda não está automatizada**.

### Status elegíveis

Reembolsos podem ser criados quando a solicitação de pagamento está em um de:

- `completed`
- `confirmed`
- `overpaid`
- `underpaid`

### Criar um reembolso

```
POST /v1/refunds/payment-request/{paymentRequestID}
Authorization: Bearer <token>
x-fluxis-api-key: <api_key_id>
```

```json
{
  "refund_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "amount": "5.00",
  "reason": "Customer overpaid — returning excess"
}
```

| Field | Required | Description |
| ----- | -------- | ----------- |
| `refund_to_address` | Yes | Endereço wallet do cliente para receber o reembolso |
| `amount` | No | Valor a reembolsar. Se omitido: valor integral para `completed`/`confirmed`, porção overpaid para `overpaid` |
| `reason` | No | Motivo em texto livre para auditoria |

Exemplo de resposta:

```json
{
  "status": "success",
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "refund_to_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "amount": "5.00",
    "status": "processing"
  }
}
```

### Verificar status do reembolso

```
GET /v1/refunds/{refundID}
```

### Webhook de reembolso

Ao criar um reembolso, a Fluxis envia webhook com `notification_type: refund_status_update`:

```json
{
  "data": {
    "notification_type": "refund_status_update",
    "refund_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "payment_request_id": "aa5d6c80-0b0b-4a2a-bbc8-14a41e6245bf",
    "status": "processing",
    "amount": "5.00"
  }
}
```

::::warning
**Execução on-chain pendente**

A Refunds API cria registro `processing` e envia webhook. O processamento on-chain do reembolso está planejado, mas ainda não automatizado. Trate registros de reembolso como intenção até `refund_transaction_hash` ser preenchido em `GET /v1/refunds/{refundID}`.
::::

### Cenários comuns de reembolso

| Scenario | Suggested approach |
| -------- | ------------------ |
| **Overpaid** | Omita `amount` para reembolsar o excesso, ou especifique a porção overpaid exata |
| **Underpaid — return partial payment** | Especifique `amount` igual ao valor recebido (parcial) |
| **Completed — full refund** | Omita `amount` para reembolsar o pagamento integral |
| **Customer provided wrong address** | Entre em contato com suporte se o endereço de reembolso precisar correção após envio |

---

## Checklist de integração para casos extremos

Use este checklist ao construir integrações de produção:

```mermaid
flowchart TD
    A[Receive webhook] --> B{Verify HMAC signature}
    B -->|Invalid| X[Reject — 401]
    B -->|Valid| C{status?}
    C -->|processing| D[Show confirming UI — do not fulfill]
    C -->|completed| E[Fulfill order]
    C -->|underpaid| F[Manual review / refund / new PR]
    C -->|overpaid| G[Fulfill order / refund excess]
    H[Poll GET payment-request] --> I{status?}
    I -->|expired| J[Offer new payment request]
    I -->|processing + tx failed on-chain| K[Contact support]
```

1. **Trate os quatro status webhook** — `processing`, `completed`, `underpaid`, `overpaid`
2. **Nunca cumpra em `processing`** — aguarde um resultado terminal de valor
3. **Consulte `expired` e `confirmed`** — estes não disparam webhooks
4. **Exiba contagem regressiva de 8 minutos** — reduza tickets de suporte por expiração
5. **Verifique assinaturas webhook** — consulte [Webhook Signature Verification](/pt/docs/developers/webhook-signature-verification)
6. **Use a Refunds API** para resolução overpaid/underpaid quando apropriado
7. **Monitore `processing` preso** — verifique block explorer se status não progride

## Documentação relacionada

- [Payment Flow — Happy Path](/pt/docs/payment-flows/std-flow) — Fluxo padrão criar → detectar → confirmar
- [Payment Requests](/pt/docs/key-concepts/payment-request) — Definições de status e exemplos de API
- [Creating Payment Requests](/pt/docs/merchant-integration/create-payreq) — Guia de integração
- [Webhooks](/pt/docs/developers/webhooks) — Registro e formato de payload
- [Webhook Signature Verification](/pt/docs/developers/webhook-signature-verification) — Verificação HMAC e fluxo de teste
- [FAQ — Payment Monitoring](/pt/docs/faq#payment-monitoring) — Perguntas frequentes
- [API Reference — Refunds](/api/refunds) — Documentação interativa de endpoints
