Metadata-Version: 2.4
Name: paylet
Version: 0.1.0
Summary: SDK Paylet FR — passerelle de micro-paiement M2M (x402 / HTTP 402).
Author: Paylet FR
License: MIT
Keywords: x402,402,payment,m2m,micropayment,paylet
Classifier: Development Status :: 3 - Alpha
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.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"

# Paylet FR — SDK Python

SDK Python de la passerelle Paylet FR, passerelle de micro-paiement
Machine-to-Machine (M2M) compatible x402 / HTTP 402 Payment Required.

Le SDK enveloppe la gateway Paylet et orchestre le flux de paiement à la
volée : un agent appelle une ressource payante, reçoit un challenge 402, le
règle, puis rejoue la requête avec la preuve de paiement.

- Aucune dépendance runtime (bibliothèque standard uniquement).
- Montants exacts en micro-crédits (entiers), zéro flottant.
- Idempotence automatique (`Idempotency-Key`), retries avec backoff.
- Helpers de signature HMAC-SHA256 côté vendeur.

## Installation

```bash
pip install ./sdk-python
# ou, en développement :
pip install -e ./sdk-python
```

## Démarrage rapide

```python
from paylet import Paylet, Money

client = Paylet("ak_live_<votre-cle>")  # clé M2M, header X-API-Key

# Solde du compte
solde = client.get_balance()
print(solde.available)                 # -> 3.42 EUR
print(solde.available.minor)           # -> 3420000 micro-crédits

# Accès à une ressource payante : le 402 est géré automatiquement
data = client.fetch_paid("GET", "https://vendor.example.com/data/42")
print(data)
```

Le flux `fetch_paid` exécute la séquence x402 complète : appel sans preuve
-> 402 `payment_required` -> règlement (`POST /v1/payments`) -> rejeu avec
l'en-tête `X-Payment` -> livraison de la ressource.

## Fonctions exposées

### Classe `Paylet` (client gateway + flux x402)

| Méthode                | Endpoint                    | Description                                      |
|------------------------|-----------------------------|--------------------------------------------------|
| `get_balance()`        | GET /v1/balance             | solde courant, réservé, disponible               |
| `get_ledger(**f)`      | GET /v1/ledger              | écritures du grand livre (pagination curseur)    |
| `list_transactions(**f)` | GET /v1/transactions      | liste des transactions                           |
| `get_transaction(id)`  | GET /v1/transactions/{id}   | une transaction                                  |
| `get_payment(id)`      | GET /v1/payments/{id}       | un paiement                                      |
| `get_payment_receipt(id)` | GET /v1/payments/{id}/receipt | récupère un reçu signé perdu                  |
| `settle(challenge, ...)` | POST /v1/payments          | règle un challenge 402, renvoie un `Payment`     |
| `fetch_paid(method, url, ...)` | — (vendeur tiers)     | flux x402 de bout en bout                        |

### Type `Money` (montants exacts, zéro flottant)

- `Money.from_minor(1500000)` : depuis un entier de micro-crédits.
- `Money.from_eur("1.50")` : depuis un prix en euros (chaîne ou `Decimal`).
- `.minor` : l'entier de micro-crédits.
- `.to_eur_str()` : la valeur en euros sous forme de chaîne.

`1 EUR = 1 000 000 micro-crédits`. Aucune conversion silencieuse : passer un
flottant à `Money` lève `TypeError`.

### Exceptions (`paylet.errors`)

Hiérarchie typée par code d'erreur (contrat section 4.4) :
`InsufficientFundsError`, `ChallengeExpiredError`, `ChallengeInvalidError`,
`IdempotencyConflictError`, `AuthenticationError`, `RateLimitedError`,
`NotFoundError`, etc. Toutes héritent de `PayletError` (attributs
`code`, `message`, `status_code`, `details`).

### Signature et vendeur (`paylet.signing`, `paylet.vendor`)

- `sign_payload` / `verify_payload` : primitives HMAC-SHA256.
- `compute_payload_hash(body)` : empreinte `sha256:<hex>` du corps payant.
- `create_challenge` / `verify_challenge` : challenge x402 côté vendeur.
- `verify_receipt` : vérification locale d'un reçu (ressource, montant,
  bénéficiaire), sans appel réseau.
- `Vendor` : regroupe ces opérations sous un objet.

## Exemples runnables

```bash
python exemples/demo_locale.py   # démo de bout en bout, 100 % locale
python exemples/basic.py         # usage minimal (clé + gateway réelles)
```

## Tests

```bash
python -m unittest discover -t . -s tests -v
```

## Note d'interopérabilité

Le format exact du champ de signature des objets signés (challenge et reçu) —
champ `sig` ajouté au JSON canonique, le tout encodé en base64url — n'est pas
figé par ARCHITECTURE.md (qui ne précise que « HMAC-SHA256 + base64url »). Ce
SDK fixe donc une convention, identique en Python et en TypeScript, à valider
par l'architecte pour garantir l'interopérabilité avec la gateway.
