Metadata-Version: 2.4
Name: abacapython
Version: 0.1.0
Summary: SDK Python não-oficial para AbacatePay (PIX, Checkout, Assinaturas, Webhooks) — projeto educacional. Já existe um SDK oficial; use o oficial em produção.
Project-URL: Homepage, https://github.com/nicollasrezende/abacapython
Project-URL: Documentation, https://nicollasrezende.github.io/abacapython/
Project-URL: Repository, https://github.com/nicollasrezende/abacapython
Project-URL: Issues, https://github.com/nicollasrezende/abacapython/issues
Project-URL: Changelog, https://github.com/nicollasrezende/abacapython/blob/main/CHANGELOG.md
Project-URL: AbacatePay (gateway oficial), https://abacatepay.com
Project-URL: AbacatePay API Docs, https://docs.abacatepay.com
Author-email: Nicollas Rezende <nicollas.pereira@seatecnologia.com.br>
License: MIT License
        
        Copyright (c) 2026 Nicollas Rezende
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: abacapython,abacatepay,brazil,checkout,fintech,gateway,payments,pix,subscriptions
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.6
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.26; extra == 'docs'
Requires-Dist: pymdown-extensions>=10.9; extra == 'docs'
Description-Content-Type: text/markdown

<div align="center">

# 🥑 abacapython

**SDK Python não-oficial para o gateway de pagamentos [AbacatePay](https://abacatepay.com)**

[![PyPI](https://img.shields.io/pypi/v/abacapython.svg)](https://pypi.org/project/abacapython/)
[![Python](https://img.shields.io/pypi/pyversions/abacapython.svg)](https://pypi.org/project/abacapython/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![CI](https://github.com/nicollasrezende/abacapython/actions/workflows/ci.yml/badge.svg)](https://github.com/nicollasrezende/abacapython/actions/workflows/ci.yml)
[![Code style: ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)

</div>

> 📚 **Projeto feito para fins de estudo.**
> Sim, já existe um SDK Python oficial/anterior da AbacatePay — descobrimos depois 😅
> Esta biblioteca foi construída como exercício de engenharia: explorar design de SDK, sync+async com `httpx`, validação com Pydantic v2, verificação de webhook, packaging moderno, CI/CD com OIDC Trusted Publishing, MkDocs, etc. Se servir de referência para alguém estudando os mesmos temas, ótimo.
>
> ⚠️ **Biblioteca não-oficial, mantida pela comunidade, sem fins comerciais.**
> Todos os créditos da plataforma de pagamentos, dos produtos e da API REST são da [AbacatePay](https://abacatepay.com). Documentação oficial da API: https://docs.abacatepay.com.

---

## ✨ Features

- 🐍 **Python 3.10+** com type hints completos (compatível com `mypy --strict`)
- ⚡ **Sync e async** na mesma interface (`AbacaPay` e `AsyncAbacaPay`, ambos sobre `httpx`)
- 🧱 **Modelos Pydantic v2** com validação, alias automático (camelCase ↔ snake_case) e tolerância a campos novos
- 🛡️ **Hierarquia de erros tipada** por status HTTP (`AuthenticationError`, `NotFoundError`, `RateLimitError`, …)
- 🔁 **Retries com backoff exponencial + jitter** em `429` e `5xx`
- 🔐 **Verificação de webhook** (HMAC-SHA256, comparação constant-time)
- 📦 **Cobre 100% dos endpoints documentados**: Checkouts, Payment Links, Customers, Checkout Transparente (PIX), Products, Coupons, Webhooks, Subscriptions, Payouts, PIX Transfers, Store e TrustMRR
- 🧪 **Testado** com `pytest` + `respx`

## 📦 Instalação

```bash
pip install abacapython
```

Ou com `uv`:

```bash
uv add abacapython
```

## 🚀 Quickstart

### Síncrono

```python
from abacapython import AbacaPay

client = AbacaPay(api_key="abc_dev_...")  # ou via env: ABACATEPAY_API_KEY

# 1. Crie um produto
produto = client.products.create({
    "external_id": "plano-mensal",
    "name": "Plano Mensal",
    "price": 9990,           # R$ 99,90 em centavos
    "currency": "BRL",
})

# 2. Crie um checkout hospedado
checkout = client.checkouts.create({
    "items": [{"id": produto.id, "quantity": 1}],
    "methods": ["PIX", "CARD"],
    "completion_url": "https://meusite.com/obrigado",
})

print(checkout.url)  # redirecione o cliente para esta URL
```

### Assíncrono

```python
import asyncio
from abacapython import AsyncAbacaPay

async def main() -> None:
    async with AsyncAbacaPay(api_key="abc_dev_...") as client:
        loja = await client.store.get()
        print(loja.name)

asyncio.run(main())
```

### PIX Checkout Transparente (QR Code no seu site)

```python
pix = client.pix_qrcodes.create({
    "amount": 4990,                    # R$ 49,90
    "description": "Pedido #1234",
    "expires_in": 3600,                # 1 hora
    "customer": {"email": "alice@example.com", "tax_id": "12345678900"},
})

# Mostre estes para o cliente:
print(pix.br_code)         # "copia-e-cola"
print(pix.br_code_base64)  # imagem PNG do QR Code

# Mais tarde:
status = client.pix_qrcodes.check(id=pix.id)
if status.status == "PAID":
    ...
```

### Assinaturas (recorrência)

```python
from abacapython import CreateProductParams, ProductCycle

plano = client.products.create(CreateProductParams(
    external_id="premium",
    name="Premium Mensal",
    price=4990,
    currency="BRL",
    cycle=ProductCycle.MONTHLY,        # produto recorrente
))

sub = client.subscriptions.create({
    "items": [{"id": plano.id, "quantity": 1}],
    "completion_url": "https://meusite.com/bem-vindo",
})

print(sub.url)
```

### Webhooks

```python
import os
from flask import Flask, request, abort
from abacapython import webhooks

app = Flask(__name__)
SECRET = os.environ["ABACATEPAY_WEBHOOK_SECRET"]

@app.post("/abacatepay/webhook")
def receive():
    signature = webhooks.extract_signature(request.headers)
    try:
        event = webhooks.parse_event(request.data, signature, SECRET)
    except webhooks.WebhookSignatureError:
        abort(401)

    if event.event == "checkout.completed":
        # Marque pedido como pago...
        pass
    elif event.event == "transparent.completed":
        # PIX confirmado...
        pass
    return "", 204
```

### Tratamento de erros

```python
from abacapython.exceptions import (
    AuthenticationError, NotFoundError, RateLimitError, APIResponseError,
)

try:
    client.customers.get(id="cust_inexistente")
except NotFoundError:
    ...
except AuthenticationError:
    ...
except RateLimitError:
    ...
except APIResponseError as exc:
    # Fallback genérico
    print(exc.status_code, exc.message)
```

## ⚙️ Configuração

| Parâmetro          | Default                                | Descrição                                                                    |
| ------------------ | -------------------------------------- | ---------------------------------------------------------------------------- |
| `api_key`          | `os.environ["ABACATEPAY_API_KEY"]`     | Bearer Token da AbacatePay.                                                  |
| `base_url`         | `https://api.abacatepay.com/v2`        | Pode ser sobrescrito por `ABACATEPAY_BASE_URL`.                              |
| `timeout`          | `30.0`                                 | Timeout (s) para cada requisição.                                            |
| `max_retries`      | `2`                                    | Tentativas extras para `429`, `5xx`, timeouts e erros de conexão.            |
| `backoff_factor`   | `0.5`                                  | Fator base do backoff exponencial entre retries.                             |
| `backoff_max`      | `8.0`                                  | Limite (s) para qualquer espera entre retries.                               |
| `http_client`      | `None`                                 | Instância customizada de `httpx.Client` / `httpx.AsyncClient`.               |

## 🗺️ Mapa de endpoints

| Recurso na API           | Acesso no SDK                |
| ------------------------ | ---------------------------- |
| `/customers/*`           | `client.customers`           |
| `/products/*`            | `client.products`            |
| `/checkouts/*`           | `client.checkouts`           |
| `/payment-links/*`       | `client.payment_links`       |
| `/transparents/*` (PIX)  | `client.pix_qrcodes`         |
| `/coupons/*`             | `client.coupons`             |
| `/webhooks/*`            | `client.webhooks`            |
| `/subscriptions/*`       | `client.subscriptions`       |
| `/payouts/*`             | `client.payouts`             |
| `/pix/*` (transferência) | `client.pix_transfers`       |
| `/store/*`               | `client.store`               |
| `/trustMRR/*` (público)  | `client.trust_mrr`           |

## 🛣️ Compatibilidade

| Python | Status     |
| ------ | ---------- |
| 3.10   | ✅ testado |
| 3.11   | ✅ testado |
| 3.12   | ✅ testado |
| 3.13   | ✅ testado |

## 🤝 Como contribuir

Pull Requests são muito bem-vindos! Veja [CONTRIBUTING.md](CONTRIBUTING.md) para detalhes.

Em resumo:

```bash
git clone https://github.com/nicollasrezende/abacapython
cd abacapython
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,docs]"
ruff check . && ruff format --check .
mypy
pytest
```

## 📜 Licença

[MIT](LICENSE). Faça bom proveito.

## 📖 Por que existe (TL;DR sincero)

Eu queria praticar:

- Design de SDK no estilo Stripe/Twilio (resources, modelos tipados, sync+async)
- `httpx` com retries + backoff exponencial + jitter
- Pydantic v2 com alias (`camelCase` ↔ `snake_case`) e validações declarativas
- Verificação HMAC de webhook com comparação constant-time
- Packaging moderno (`hatchling`, `pyproject.toml`, `py.typed`)
- CI/CD com matrix multi-Python e PyPI via **OIDC Trusted Publishing** (sem token no repo)
- MkDocs Material com `mkdocstrings` gerando referência da API
- Workflow open-source: CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, issue/PR templates

A `abacapython` foi o pretexto para fazer tudo isso. **Já existe um SDK oficial da AbacatePay para Python**, então não use esta lib em produção — use a deles. Se este código te ajudou a aprender algum dos tópicos acima, missão cumprida 🥑

## 🙏 Créditos

- **[AbacatePay](https://abacatepay.com)** — gateway de pagamentos, API e produto. Esta biblioteca apenas consome a API REST pública deles, documentada em https://docs.abacatepay.com.
- Comunidade Python brasileira por inspirar projetos open-source de qualidade.

---

<sub>Esta biblioteca **não é afiliada à AbacatePay**. AbacatePay é marca registrada de seus respectivos titulares.</sub>
