# Dinheiro e precisão (/docs/pix-processamento/best-practices/money)



<QuickLinks>
  <QuickLink href="/docs/pix-processamento/endpoints/pix-operations/post_pix" title="POST /pix" />

  <QuickLink href="/docs/pix-processamento/endpoints/withdrawals/post_withdraw" title="POST /withdraw" />

  <QuickLink href="/docs/pix-processamento/glossary" title="Glossário" />
</QuickLinks>

A PayZu Pix API usa **reais com casas decimais**. Atenção: muitos PSPs trabalham em centavos, então se você está migrando ou comparando integrações, o ponto decimal aqui não é opcional.

```json
{ "amount": 99.90 }
```

## Precisão decimal em código [#precisão-decimal-em-código]

Em JavaScript, `0.1 + 0.2 !== 0.3`. Em Python `Decimal` é seguro mas `float` não. Em SQL, `FLOAT` perde precisão.

| Linguagem        | Use                                               |
| ---------------- | ------------------------------------------------- |
| **JavaScript**   | Inteiro em centavos, ou biblioteca `decimal.js`.  |
| **Python**       | `decimal.Decimal` ao calcular, `float` só na API. |
| **Go**           | `shopspring/decimal` ou inteiro em centavos.      |
| **Java**         | `BigDecimal`, nunca `double`.                     |
| **PHP**          | `bcmath`, ou inteiro em centavos.                 |
| **SQL/Postgres** | `NUMERIC(15,2)`, nunca `FLOAT` ou `REAL`.         |

### Padrão recomendado: centavos internamente [#padrão-recomendado-centavos-internamente]

Armazene como inteiro em centavos no seu DB e converta apenas na borda da API:

<Tabs items="['Node.js', 'Python']">
  <Tab value="Node.js">
    ```ts
    function centsToReais(cents: number): number {
      return cents / 100;
    }

    function reaisToCents(reais: number): number {
      return Math.round(reais * 100);
    }

    await createPixCharge({
      amount: centsToReais(order.totalCents),
      clientReference: `order-${order.id}`,
    });

    const callbackAmountCents = reaisToCents(callback.amount);
    if (callbackAmountCents !== order.totalCents) {
      throw new Error('Valor divergente entre callback e pedido');
    }
    ```
  </Tab>

  <Tab value="Python">
    ```python
    from decimal import Decimal

    def cents_to_reais(cents: int) -> Decimal:
        return Decimal(cents) / Decimal(100)

    def reais_to_cents(reais: float | Decimal) -> int:
        return int((Decimal(str(reais)) * Decimal(100)).quantize(Decimal('1')))

    create_pix_charge({
        'amount': float(cents_to_reais(order.total_cents)),
        'clientReference': f'order-{order.id}',
    })
    ```
  </Tab>
</Tabs>

## Limites mínimos por operação [#limites-mínimos-por-operação]

A PayZu valida no servidor. Pedido abaixo do mínimo retorna `400 Bad Request`.

| Operação                                                                                                 | `amount` mínimo |
| -------------------------------------------------------------------------------------------------------- | --------------- |
| [`POST /pix`](/docs/pix-processamento/endpoints/pix-operations/post_pix) (cobrança)                      | **R$ 1,00**     |
| [`POST /withdraw`](/docs/pix-processamento/endpoints/withdrawals/post_withdraw) (saque por chave)        | **R$ 0,01**     |
| [`POST /withdraw/qrcode`](/docs/pix-processamento/endpoints/withdrawals/post_withdraw_qrcode) (pagar QR) | **R$ 0,10**     |
| [`POST /internal-transfer`](/docs/pix-processamento/endpoints/internal-transfer/post_internal_transfer)  | **R$ 0,01**     |

## Tarifa [#tarifa]

A tarifa cobrada na PayZu chega no callback no campo `serviceFeeCharged` (em reais).

```json
{
  "amount": 99.90,
  "serviceFeeCharged": 0.99,
  "status": "COMPLETED"
}
```

Para conciliação financeira, considere:

| Valor               | Significado                                                                               |
| ------------------- | ----------------------------------------------------------------------------------------- |
| `amount`            | O que o cliente pagou ou você sacou.                                                      |
| `serviceFeeCharged` | Tarifa PayZu sobre a operação.                                                            |
| Líquido             | `amount - serviceFeeCharged` (recebimento) ou `amount + serviceFeeCharged` (saída total). |

## Validar valor recebido no callback [#validar-valor-recebido-no-callback]

Sempre confira que o callback bate com o pedido. Cliente pode pagar valor diferente (Pix permite QR sem valor fixo em alguns casos).

```ts
async function handleDepositCallback(tx: PayzuCallback, order: Order) {
  const callbackCents = reaisToCents(tx.amount);
  if (callbackCents !== order.totalCents) {
    log.warn('Valor divergente', {
      pedido: order.totalCents,
      recebido: callbackCents,
    });
    await flagForReview(order, tx);
    return;
  }
  await markOrderPaid(order, tx);
}
```

## Armadilhas comuns [#armadilhas-comuns]

| Armadilha                                         | Sintoma                                    |
| ------------------------------------------------- | ------------------------------------------ |
| Enviar `amount: 9990` achando que é centavos      | Cobra R$ 9.990,00 do cliente               |
| Armazenar `amount` como `FLOAT` no Postgres       | Perda de centavos em soma de muitas linhas |
| Somar `Decimal` com `float` em Python             | Erro de tipo ou precisão perdida           |
| Confiar em `parseFloat(tx.amount)` sem arredondar | `99.90` vira `99.9000000000001`            |
| Não verificar valor recebido vs valor esperado    | Pagamento parcial passa como concluído     |
