paylet 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- paylet-0.1.0/PKG-INFO +127 -0
- paylet-0.1.0/README.md +105 -0
- paylet-0.1.0/paylet/__init__.py +100 -0
- paylet-0.1.0/paylet/client.py +540 -0
- paylet-0.1.0/paylet/errors.py +146 -0
- paylet-0.1.0/paylet/money.py +164 -0
- paylet-0.1.0/paylet/py.typed +0 -0
- paylet-0.1.0/paylet/signing.py +105 -0
- paylet-0.1.0/paylet/vendor.py +233 -0
- paylet-0.1.0/paylet.egg-info/PKG-INFO +127 -0
- paylet-0.1.0/paylet.egg-info/SOURCES.txt +18 -0
- paylet-0.1.0/paylet.egg-info/dependency_links.txt +1 -0
- paylet-0.1.0/paylet.egg-info/requires.txt +3 -0
- paylet-0.1.0/paylet.egg-info/top_level.txt +1 -0
- paylet-0.1.0/pyproject.toml +41 -0
- paylet-0.1.0/setup.cfg +4 -0
- paylet-0.1.0/tests/test_client.py +267 -0
- paylet-0.1.0/tests/test_money.py +97 -0
- paylet-0.1.0/tests/test_signing.py +94 -0
- paylet-0.1.0/tests/test_vendor.py +217 -0
paylet-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: paylet
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: SDK Paylet FR — passerelle de micro-paiement M2M (x402 / HTTP 402).
|
|
5
|
+
Author: Paylet FR
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: x402,402,payment,m2m,micropayment,paylet
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
22
|
+
|
|
23
|
+
# Paylet FR — SDK Python
|
|
24
|
+
|
|
25
|
+
SDK Python de la passerelle Paylet FR, passerelle de micro-paiement
|
|
26
|
+
Machine-to-Machine (M2M) compatible x402 / HTTP 402 Payment Required.
|
|
27
|
+
|
|
28
|
+
Le SDK enveloppe la gateway Paylet et orchestre le flux de paiement à la
|
|
29
|
+
volée : un agent appelle une ressource payante, reçoit un challenge 402, le
|
|
30
|
+
règle, puis rejoue la requête avec la preuve de paiement.
|
|
31
|
+
|
|
32
|
+
- Aucune dépendance runtime (bibliothèque standard uniquement).
|
|
33
|
+
- Montants exacts en micro-crédits (entiers), zéro flottant.
|
|
34
|
+
- Idempotence automatique (`Idempotency-Key`), retries avec backoff.
|
|
35
|
+
- Helpers de signature HMAC-SHA256 côté vendeur.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install ./sdk-python
|
|
41
|
+
# ou, en développement :
|
|
42
|
+
pip install -e ./sdk-python
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Démarrage rapide
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from paylet import Paylet, Money
|
|
49
|
+
|
|
50
|
+
client = Paylet("ak_live_<votre-cle>") # clé M2M, header X-API-Key
|
|
51
|
+
|
|
52
|
+
# Solde du compte
|
|
53
|
+
solde = client.get_balance()
|
|
54
|
+
print(solde.available) # -> 3.42 EUR
|
|
55
|
+
print(solde.available.minor) # -> 3420000 micro-crédits
|
|
56
|
+
|
|
57
|
+
# Accès à une ressource payante : le 402 est géré automatiquement
|
|
58
|
+
data = client.fetch_paid("GET", "https://vendor.example.com/data/42")
|
|
59
|
+
print(data)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Le flux `fetch_paid` exécute la séquence x402 complète : appel sans preuve
|
|
63
|
+
-> 402 `payment_required` -> règlement (`POST /v1/payments`) -> rejeu avec
|
|
64
|
+
l'en-tête `X-Payment` -> livraison de la ressource.
|
|
65
|
+
|
|
66
|
+
## Fonctions exposées
|
|
67
|
+
|
|
68
|
+
### Classe `Paylet` (client gateway + flux x402)
|
|
69
|
+
|
|
70
|
+
| Méthode | Endpoint | Description |
|
|
71
|
+
|------------------------|-----------------------------|--------------------------------------------------|
|
|
72
|
+
| `get_balance()` | GET /v1/balance | solde courant, réservé, disponible |
|
|
73
|
+
| `get_ledger(**f)` | GET /v1/ledger | écritures du grand livre (pagination curseur) |
|
|
74
|
+
| `list_transactions(**f)` | GET /v1/transactions | liste des transactions |
|
|
75
|
+
| `get_transaction(id)` | GET /v1/transactions/{id} | une transaction |
|
|
76
|
+
| `get_payment(id)` | GET /v1/payments/{id} | un paiement |
|
|
77
|
+
| `get_payment_receipt(id)` | GET /v1/payments/{id}/receipt | récupère un reçu signé perdu |
|
|
78
|
+
| `settle(challenge, ...)` | POST /v1/payments | règle un challenge 402, renvoie un `Payment` |
|
|
79
|
+
| `fetch_paid(method, url, ...)` | — (vendeur tiers) | flux x402 de bout en bout |
|
|
80
|
+
|
|
81
|
+
### Type `Money` (montants exacts, zéro flottant)
|
|
82
|
+
|
|
83
|
+
- `Money.from_minor(1500000)` : depuis un entier de micro-crédits.
|
|
84
|
+
- `Money.from_eur("1.50")` : depuis un prix en euros (chaîne ou `Decimal`).
|
|
85
|
+
- `.minor` : l'entier de micro-crédits.
|
|
86
|
+
- `.to_eur_str()` : la valeur en euros sous forme de chaîne.
|
|
87
|
+
|
|
88
|
+
`1 EUR = 1 000 000 micro-crédits`. Aucune conversion silencieuse : passer un
|
|
89
|
+
flottant à `Money` lève `TypeError`.
|
|
90
|
+
|
|
91
|
+
### Exceptions (`paylet.errors`)
|
|
92
|
+
|
|
93
|
+
Hiérarchie typée par code d'erreur (contrat section 4.4) :
|
|
94
|
+
`InsufficientFundsError`, `ChallengeExpiredError`, `ChallengeInvalidError`,
|
|
95
|
+
`IdempotencyConflictError`, `AuthenticationError`, `RateLimitedError`,
|
|
96
|
+
`NotFoundError`, etc. Toutes héritent de `PayletError` (attributs
|
|
97
|
+
`code`, `message`, `status_code`, `details`).
|
|
98
|
+
|
|
99
|
+
### Signature et vendeur (`paylet.signing`, `paylet.vendor`)
|
|
100
|
+
|
|
101
|
+
- `sign_payload` / `verify_payload` : primitives HMAC-SHA256.
|
|
102
|
+
- `compute_payload_hash(body)` : empreinte `sha256:<hex>` du corps payant.
|
|
103
|
+
- `create_challenge` / `verify_challenge` : challenge x402 côté vendeur.
|
|
104
|
+
- `verify_receipt` : vérification locale d'un reçu (ressource, montant,
|
|
105
|
+
bénéficiaire), sans appel réseau.
|
|
106
|
+
- `Vendor` : regroupe ces opérations sous un objet.
|
|
107
|
+
|
|
108
|
+
## Exemples runnables
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
python exemples/demo_locale.py # démo de bout en bout, 100 % locale
|
|
112
|
+
python exemples/basic.py # usage minimal (clé + gateway réelles)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Tests
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
python -m unittest discover -t . -s tests -v
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Note d'interopérabilité
|
|
122
|
+
|
|
123
|
+
Le format exact du champ de signature des objets signés (challenge et reçu) —
|
|
124
|
+
champ `sig` ajouté au JSON canonique, le tout encodé en base64url — n'est pas
|
|
125
|
+
figé par ARCHITECTURE.md (qui ne précise que « HMAC-SHA256 + base64url »). Ce
|
|
126
|
+
SDK fixe donc une convention, identique en Python et en TypeScript, à valider
|
|
127
|
+
par l'architecte pour garantir l'interopérabilité avec la gateway.
|
paylet-0.1.0/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Paylet FR — SDK Python
|
|
2
|
+
|
|
3
|
+
SDK Python de la passerelle Paylet FR, passerelle de micro-paiement
|
|
4
|
+
Machine-to-Machine (M2M) compatible x402 / HTTP 402 Payment Required.
|
|
5
|
+
|
|
6
|
+
Le SDK enveloppe la gateway Paylet et orchestre le flux de paiement à la
|
|
7
|
+
volée : un agent appelle une ressource payante, reçoit un challenge 402, le
|
|
8
|
+
règle, puis rejoue la requête avec la preuve de paiement.
|
|
9
|
+
|
|
10
|
+
- Aucune dépendance runtime (bibliothèque standard uniquement).
|
|
11
|
+
- Montants exacts en micro-crédits (entiers), zéro flottant.
|
|
12
|
+
- Idempotence automatique (`Idempotency-Key`), retries avec backoff.
|
|
13
|
+
- Helpers de signature HMAC-SHA256 côté vendeur.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install ./sdk-python
|
|
19
|
+
# ou, en développement :
|
|
20
|
+
pip install -e ./sdk-python
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Démarrage rapide
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from paylet import Paylet, Money
|
|
27
|
+
|
|
28
|
+
client = Paylet("ak_live_<votre-cle>") # clé M2M, header X-API-Key
|
|
29
|
+
|
|
30
|
+
# Solde du compte
|
|
31
|
+
solde = client.get_balance()
|
|
32
|
+
print(solde.available) # -> 3.42 EUR
|
|
33
|
+
print(solde.available.minor) # -> 3420000 micro-crédits
|
|
34
|
+
|
|
35
|
+
# Accès à une ressource payante : le 402 est géré automatiquement
|
|
36
|
+
data = client.fetch_paid("GET", "https://vendor.example.com/data/42")
|
|
37
|
+
print(data)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Le flux `fetch_paid` exécute la séquence x402 complète : appel sans preuve
|
|
41
|
+
-> 402 `payment_required` -> règlement (`POST /v1/payments`) -> rejeu avec
|
|
42
|
+
l'en-tête `X-Payment` -> livraison de la ressource.
|
|
43
|
+
|
|
44
|
+
## Fonctions exposées
|
|
45
|
+
|
|
46
|
+
### Classe `Paylet` (client gateway + flux x402)
|
|
47
|
+
|
|
48
|
+
| Méthode | Endpoint | Description |
|
|
49
|
+
|------------------------|-----------------------------|--------------------------------------------------|
|
|
50
|
+
| `get_balance()` | GET /v1/balance | solde courant, réservé, disponible |
|
|
51
|
+
| `get_ledger(**f)` | GET /v1/ledger | écritures du grand livre (pagination curseur) |
|
|
52
|
+
| `list_transactions(**f)` | GET /v1/transactions | liste des transactions |
|
|
53
|
+
| `get_transaction(id)` | GET /v1/transactions/{id} | une transaction |
|
|
54
|
+
| `get_payment(id)` | GET /v1/payments/{id} | un paiement |
|
|
55
|
+
| `get_payment_receipt(id)` | GET /v1/payments/{id}/receipt | récupère un reçu signé perdu |
|
|
56
|
+
| `settle(challenge, ...)` | POST /v1/payments | règle un challenge 402, renvoie un `Payment` |
|
|
57
|
+
| `fetch_paid(method, url, ...)` | — (vendeur tiers) | flux x402 de bout en bout |
|
|
58
|
+
|
|
59
|
+
### Type `Money` (montants exacts, zéro flottant)
|
|
60
|
+
|
|
61
|
+
- `Money.from_minor(1500000)` : depuis un entier de micro-crédits.
|
|
62
|
+
- `Money.from_eur("1.50")` : depuis un prix en euros (chaîne ou `Decimal`).
|
|
63
|
+
- `.minor` : l'entier de micro-crédits.
|
|
64
|
+
- `.to_eur_str()` : la valeur en euros sous forme de chaîne.
|
|
65
|
+
|
|
66
|
+
`1 EUR = 1 000 000 micro-crédits`. Aucune conversion silencieuse : passer un
|
|
67
|
+
flottant à `Money` lève `TypeError`.
|
|
68
|
+
|
|
69
|
+
### Exceptions (`paylet.errors`)
|
|
70
|
+
|
|
71
|
+
Hiérarchie typée par code d'erreur (contrat section 4.4) :
|
|
72
|
+
`InsufficientFundsError`, `ChallengeExpiredError`, `ChallengeInvalidError`,
|
|
73
|
+
`IdempotencyConflictError`, `AuthenticationError`, `RateLimitedError`,
|
|
74
|
+
`NotFoundError`, etc. Toutes héritent de `PayletError` (attributs
|
|
75
|
+
`code`, `message`, `status_code`, `details`).
|
|
76
|
+
|
|
77
|
+
### Signature et vendeur (`paylet.signing`, `paylet.vendor`)
|
|
78
|
+
|
|
79
|
+
- `sign_payload` / `verify_payload` : primitives HMAC-SHA256.
|
|
80
|
+
- `compute_payload_hash(body)` : empreinte `sha256:<hex>` du corps payant.
|
|
81
|
+
- `create_challenge` / `verify_challenge` : challenge x402 côté vendeur.
|
|
82
|
+
- `verify_receipt` : vérification locale d'un reçu (ressource, montant,
|
|
83
|
+
bénéficiaire), sans appel réseau.
|
|
84
|
+
- `Vendor` : regroupe ces opérations sous un objet.
|
|
85
|
+
|
|
86
|
+
## Exemples runnables
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
python exemples/demo_locale.py # démo de bout en bout, 100 % locale
|
|
90
|
+
python exemples/basic.py # usage minimal (clé + gateway réelles)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Tests
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
python -m unittest discover -t . -s tests -v
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Note d'interopérabilité
|
|
100
|
+
|
|
101
|
+
Le format exact du champ de signature des objets signés (challenge et reçu) —
|
|
102
|
+
champ `sig` ajouté au JSON canonique, le tout encodé en base64url — n'est pas
|
|
103
|
+
figé par ARCHITECTURE.md (qui ne précise que « HMAC-SHA256 + base64url »). Ce
|
|
104
|
+
SDK fixe donc une convention, identique en Python et en TypeScript, à valider
|
|
105
|
+
par l'architecte pour garantir l'interopérabilité avec la gateway.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Paylet FR — SDK Python.
|
|
2
|
+
|
|
3
|
+
Client M2M de la passerelle Paylet, compatible x402 (HTTP 402 Payment
|
|
4
|
+
Required). Fournit :
|
|
5
|
+
|
|
6
|
+
- ``Paylet`` : client gateway (solde, grand livre, transactions, paiements)
|
|
7
|
+
et orchestration du flux x402 (``fetch_paid``).
|
|
8
|
+
- ``Money`` : montants exacts en micro-crédits (entiers, zéro flottant).
|
|
9
|
+
- ``errors`` : hiérarchie d'exceptions typées par code d'erreur.
|
|
10
|
+
- ``signing`` : primitives HMAC-SHA256 (challenge et reçu x402).
|
|
11
|
+
- ``vendor`` : helpers côté marchand vendeur (signer un challenge, vérifier
|
|
12
|
+
un reçu sans appel réseau).
|
|
13
|
+
|
|
14
|
+
Exemple minimal ::
|
|
15
|
+
|
|
16
|
+
from paylet import Paylet
|
|
17
|
+
|
|
18
|
+
client = Paylet("ak_live_<votre-cle>")
|
|
19
|
+
solde = client.get_balance()
|
|
20
|
+
print(solde.available.to_eur_str()) # "1.50"
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .client import Paylet, Balance, HTTPResponse, Page, Payment, Transport
|
|
24
|
+
from .errors import (
|
|
25
|
+
PayletAPIError,
|
|
26
|
+
PayletError,
|
|
27
|
+
AuthenticationError,
|
|
28
|
+
ChallengeExpiredError,
|
|
29
|
+
ChallengeInvalidError,
|
|
30
|
+
ForbiddenError,
|
|
31
|
+
IdempotencyConflictError,
|
|
32
|
+
InsufficientFundsError,
|
|
33
|
+
InternalError,
|
|
34
|
+
InvalidRequestError,
|
|
35
|
+
NetworkError,
|
|
36
|
+
NotFoundError,
|
|
37
|
+
PaymentRequiredError,
|
|
38
|
+
RateLimitedError,
|
|
39
|
+
RetryExhaustedError,
|
|
40
|
+
SignatureError,
|
|
41
|
+
)
|
|
42
|
+
from .money import (
|
|
43
|
+
FEE_FLOOR_MINOR,
|
|
44
|
+
FEE_RATE_BASIS_POINTS,
|
|
45
|
+
MICRO_CREDITS_PER_EUR,
|
|
46
|
+
Money,
|
|
47
|
+
compute_fee_minor,
|
|
48
|
+
)
|
|
49
|
+
from .signing import (
|
|
50
|
+
b64url_decode,
|
|
51
|
+
b64url_encode,
|
|
52
|
+
canonical_json,
|
|
53
|
+
compute_payload_hash,
|
|
54
|
+
sign_payload,
|
|
55
|
+
verify_payload,
|
|
56
|
+
)
|
|
57
|
+
from .vendor import Vendor, create_challenge, verify_challenge, verify_receipt
|
|
58
|
+
|
|
59
|
+
__version__ = "0.1.0"
|
|
60
|
+
|
|
61
|
+
__all__ = [
|
|
62
|
+
"Paylet",
|
|
63
|
+
"Balance",
|
|
64
|
+
"Page",
|
|
65
|
+
"Payment",
|
|
66
|
+
"HTTPResponse",
|
|
67
|
+
"Transport",
|
|
68
|
+
"Money",
|
|
69
|
+
"MICRO_CREDITS_PER_EUR",
|
|
70
|
+
"FEE_RATE_BASIS_POINTS",
|
|
71
|
+
"FEE_FLOOR_MINOR",
|
|
72
|
+
"compute_fee_minor",
|
|
73
|
+
"Vendor",
|
|
74
|
+
"create_challenge",
|
|
75
|
+
"verify_challenge",
|
|
76
|
+
"verify_receipt",
|
|
77
|
+
"compute_payload_hash",
|
|
78
|
+
"sign_payload",
|
|
79
|
+
"verify_payload",
|
|
80
|
+
"canonical_json",
|
|
81
|
+
"b64url_encode",
|
|
82
|
+
"b64url_decode",
|
|
83
|
+
"PayletError",
|
|
84
|
+
"PayletAPIError",
|
|
85
|
+
"InvalidRequestError",
|
|
86
|
+
"AuthenticationError",
|
|
87
|
+
"ForbiddenError",
|
|
88
|
+
"NotFoundError",
|
|
89
|
+
"IdempotencyConflictError",
|
|
90
|
+
"InsufficientFundsError",
|
|
91
|
+
"ChallengeExpiredError",
|
|
92
|
+
"ChallengeInvalidError",
|
|
93
|
+
"PaymentRequiredError",
|
|
94
|
+
"RateLimitedError",
|
|
95
|
+
"InternalError",
|
|
96
|
+
"NetworkError",
|
|
97
|
+
"RetryExhaustedError",
|
|
98
|
+
"SignatureError",
|
|
99
|
+
"__version__",
|
|
100
|
+
]
|