alphapay 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.
alphapay-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AlphaPay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: alphapay
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for the AlphaPay payment aggregator API.
5
+ License: MIT
6
+ Project-URL: Homepage, https://alphapay.me
7
+ Keywords: alphapay,payments,mobile-money,payment-gateway,africa
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Dynamic: license-file
21
+
22
+ # alphapay-python
23
+
24
+ SDK Python officiel pour l'API AlphaPay (agrégateur de paiement multi-gateway).
25
+
26
+ > **Statut : v0.1.0, non publié.** Couvre les ressources marchand
27
+ > principales (paiements, retraits, liens de paiement, checkout, clients,
28
+ > webhooks). Conçu en miroir des SDK [Node.js](../AlphaPaySDK-node) et
29
+ > [PHP](../AlphaPaySDK-php) — mêmes garanties, mêmes restrictions d'API
30
+ > découvertes en conditions réelles. Voir [CHECKLIST.md](./CHECKLIST.md)
31
+ > pour ce qui manque avant une publication PyPI.
32
+
33
+ Aucune dépendance runtime — uniquement la bibliothèque standard (`urllib`),
34
+ pas de `requests`. Python 3.8+.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install alphapay
40
+ ```
41
+
42
+ ## Démarrage rapide
43
+
44
+ ```python
45
+ import os
46
+ from alphapay import AlphaPayClient
47
+
48
+ alphapay = AlphaPayClient(os.environ["ALPHAPAY_SECRET_KEY"]) # sk_live_... ou sk_test_...
49
+
50
+ # Encaissement direct (push mobile money), sans page de checkout à suivre.
51
+ payment = alphapay.transactions.payin_initialize(
52
+ amount=5000,
53
+ currency="XOF",
54
+ country="BJ",
55
+ network="mtn_bj",
56
+ customer={"email": "ayaba@exemple.com", "first_name": "Ayaba", "last_name": "Client", "phone": "+22900000000"},
57
+ description="Commande #1234",
58
+ idempotency_key=True, # recommandé : évite un double push en cas de retry réseau
59
+ )
60
+
61
+ print(payment["status"])
62
+ ```
63
+
64
+ ### Options avancées des liens de paiement
65
+
66
+ `payment_links.create()`/`update()` acceptent aussi `require_phone`,
67
+ `facebook_pixel_id`, `google_ads_id`, `custom_fields`,
68
+ `show_confirmation_page` et `redirect_url`. `get_public()`/
69
+ `create_public_checkout()` sont les 2 seules méthodes de cette ressource qui
70
+ n'exigent PAS de clé secrète (page publique du lien) — ne les appelez jamais
71
+ depuis un front avec votre clé API en dur, seul `slug` doit y circuler.
72
+
73
+ ```python
74
+ link = alphapay.payment_links.create(
75
+ name="Facture #42",
76
+ amount_type="FIXED",
77
+ amount=5000,
78
+ currency="XOF",
79
+ google_ads_id="AW-123456789",
80
+ custom_fields=[{"key": "reference_client", "label": "Référence client", "required": True}],
81
+ )
82
+
83
+ # Côté public (mobile/web), sans clé API :
84
+ public_link = alphapay.payment_links.get_public(link["slug"])
85
+ checkout = alphapay.payment_links.create_public_checkout(
86
+ link["slug"],
87
+ customer={"email": "client@exemple.com", "first_name": "Client", "last_name": "Test"},
88
+ custom_field_values={"reference_client": "CMD-42"},
89
+ )
90
+ # checkout["slug"] est une CheckoutSession one-shot : pilotez la suite (réseau, push,
91
+ # statut) avec le SDK checkout public (mobile/web), jamais avec ce client à clé secrète.
92
+ ```
93
+
94
+ ## Sandbox vs live
95
+
96
+ L'environnement se déduit automatiquement du préfixe de la clé :
97
+
98
+ ```python
99
+ sandbox = AlphaPayClient("sk_test_...") # sandbox.environment == "sandbox"
100
+ live = AlphaPayClient("sk_live_...") # live.environment == "live"
101
+ ```
102
+
103
+ ## Gestion des erreurs
104
+
105
+ Toute erreur API est normalisée en une sous-classe de `AlphaPayError` —
106
+ jamais un code HTTP brut à interpréter soi-même :
107
+
108
+ ```python
109
+ from alphapay import AlphaPayValidationError, AlphaPayRateLimitError
110
+
111
+ try:
112
+ alphapay.settlements.create(country="BJ", requested_amount=100, payout_method=method_id)
113
+ except AlphaPayValidationError as e:
114
+ print(e.field_errors) # {"requested_amount": ["Montant minimum : 500 XOF."]}
115
+ except AlphaPayRateLimitError as e:
116
+ print(f"Réessayer dans {e.retry_after}s")
117
+ ```
118
+
119
+ `AlphaPayAuthenticationError`, `AlphaPayPermissionError`,
120
+ `AlphaPayNotFoundError`, `AlphaPayIdempotencyError` (409 — clé
121
+ Idempotency-Key réutilisée avec un payload différent), `AlphaPayServerError`
122
+ et `AlphaPayConnectionError` (réseau/timeout, jamais atteint l'API)
123
+ couvrent le reste. Le client retente automatiquement (backoff exponentiel +
124
+ gigue) sur 429/5xx/erreur réseau — 2 tentatives supplémentaires par défaut,
125
+ configurable via `max_retries=` au constructeur.
126
+
127
+ ## Pagination
128
+
129
+ `alphapay.paginate()` suit le lien `next` renvoyé par l'API (pas un numéro
130
+ de page recalculé côté SDK) — fonctionne aussi bien sur les ressources
131
+ paginées par page (`count` présent) que sur `transactions.list()`, paginée
132
+ par curseur (`TransactionListView` utilise `CreatedAtCursorPagination` côté
133
+ API, sans `count` ; y passer `page` n'a aucun effet) :
134
+
135
+ ```python
136
+ from alphapay import paginate
137
+
138
+ for tx in paginate(alphapay.http, alphapay.transactions.list(status="SUCCESS")):
139
+ print(tx["reference"], tx["amounts"]["net"])
140
+ ```
141
+
142
+ ## Vérifier un webhook reçu
143
+
144
+ Reproduit exactement le schéma de signature d'AlphaPayBack (HMAC-SHA256 de
145
+ `"<timestamp>.<corps>"`, comparaison en temps constant via
146
+ `hmac.compare_digest`, fenêtre anti-rejeu de 300s) :
147
+
148
+ ```python
149
+ from alphapay import verify_signature, AlphaPayWebhookSignatureError
150
+
151
+ # Exemple Flask -- adapter selon le framework.
152
+ @app.route("/webhooks/alphapay", methods=["POST"])
153
+ def alphapay_webhook():
154
+ try:
155
+ event = verify_signature(
156
+ payload=request.get_data(as_text=True), # corps BRUT, jamais déjà décodé en JSON
157
+ signature=request.headers["X-Webhook-Signature"],
158
+ timestamp=request.headers["X-Webhook-Timestamp"],
159
+ secret=os.environ["ALPHAPAY_WEBHOOK_SECRET"],
160
+ )
161
+ except AlphaPayWebhookSignatureError:
162
+ return "", 400
163
+ # traiter event["event"] / event["data"]
164
+ return "", 200
165
+ ```
166
+
167
+ ## ⚠️ Sécurité — ce SDK est côté serveur uniquement
168
+
169
+ La clé API (`sk_live_.../sk_test_...`) donne un accès complet au compte
170
+ marchand (créer des paiements, déclencher des retraits, lire l'historique).
171
+ **Ne l'embarquez jamais dans du code exécuté côté client** (un notebook
172
+ partagé, un script de démo, une app desktop distribuée). Gardez-la dans une
173
+ variable d'environnement ou un secret manager, jamais en clair dans un
174
+ dépôt versionné.
175
+
176
+ ## Ressources couvertes
177
+
178
+ | Ressource | Méthodes | Via clé API |
179
+ |---|---|---|
180
+ | `transactions` | `list`, `get`, `export`, `download_invoice`, `payin_initialize/payin_verify/payin_retry/payin_confirm_otp`, `payout_initialize/payout_verify` | ✅ |
181
+ | `payment_links` | `list`, `create`, `get`, `update`, `delete` | ✅ |
182
+ | `payment_links` | `get_public`, `create_public_checkout` | publiques (pas de clé requise) |
183
+ | `checkout_sessions` | `list`, `create`, `get`, `cancel` | ✅ |
184
+ | `customers` | `list`, `create`, `get`, `update`, `delete`, `transactions` | ✅ |
185
+ | `settlements` | `list`, `create`, `get`, `cancel` | ❌ dashboard-only |
186
+ | `wallet_transfers` | `list`, `create`, `get` | ❌ dashboard-only |
187
+ | `balances` | `list`, `get` | ✅ |
188
+ | `balances` | `ledger_entries` | ❌ dashboard-only |
189
+ | `api_keys` | `list`, `create`, `get`, `revoke`, `delete` | ❌ dashboard-only |
190
+ | `api_keys` | `ip_whitelist.{list,create,update,delete}` | ✅ |
191
+ | `webhook_endpoints` | `list`, `get`, `subscriptions.list`, `logs.{list,get}` | ✅ |
192
+ | `webhook_endpoints` | `create`, `update`, `rotate_secret`, `delete`, `subscriptions.{subscribe,unsubscribe}`, `logs.resend` | ❌ dashboard-only |
193
+
194
+ ### La colonne "Via clé API"
195
+
196
+ Vérifié en conditions réelles (`api.alphapay.me`, appels en lecture, via le
197
+ SDK Node.js jumeau — même API, même restriction) : une partie de l'API est
198
+ **volontairement inaccessible à une clé API**, même en lecture — jamais un
199
+ bug, toujours `apps.core.mixins.forbid_api_key` côté AlphaPayBack :
200
+
201
+ ```python
202
+ from alphapay import AlphaPayPermissionError
203
+
204
+ try:
205
+ alphapay.settlements.list()
206
+ except AlphaPayPermissionError as e:
207
+ if e.error_code == "dashboard_only":
208
+ pass # "La demande de retrait n'est possible que depuis le dashboard (compte utilisateur) — jamais via une clé API."
209
+ ```
210
+
211
+ Logique : les retraits, l'historique détaillé du grand livre et la gestion
212
+ des clés API elles-mêmes exigent qu'un humain soit connecté au dashboard —
213
+ une clé compromise ne peut ni sortir d'argent, ni fabriquer d'autres clés
214
+ pour elle-même, ni consulter le détail comptable.
215
+
216
+ Pas encore couvert (endpoints existants côté API, absents du SDK pour l'instant) :
217
+ gestion d'équipe, KYC marchand, configs marchand, journal d'audit,
218
+ référentiels (pays/réseaux/taux de change), support.
219
+
220
+ ## Développement
221
+
222
+ ```bash
223
+ python -m unittest discover -s tests -v # lance un vrai serveur HTTP local (tests/server.py, thread), aucun appel réseau réel vers AlphaPay
224
+ python -m py_compile src/alphapay/*.py src/alphapay/resources/*.py # équivalent d'un lint syntaxique
225
+ ```
226
+
227
+ ## Licence
228
+
229
+ MIT
@@ -0,0 +1,208 @@
1
+ # alphapay-python
2
+
3
+ SDK Python officiel pour l'API AlphaPay (agrégateur de paiement multi-gateway).
4
+
5
+ > **Statut : v0.1.0, non publié.** Couvre les ressources marchand
6
+ > principales (paiements, retraits, liens de paiement, checkout, clients,
7
+ > webhooks). Conçu en miroir des SDK [Node.js](../AlphaPaySDK-node) et
8
+ > [PHP](../AlphaPaySDK-php) — mêmes garanties, mêmes restrictions d'API
9
+ > découvertes en conditions réelles. Voir [CHECKLIST.md](./CHECKLIST.md)
10
+ > pour ce qui manque avant une publication PyPI.
11
+
12
+ Aucune dépendance runtime — uniquement la bibliothèque standard (`urllib`),
13
+ pas de `requests`. Python 3.8+.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install alphapay
19
+ ```
20
+
21
+ ## Démarrage rapide
22
+
23
+ ```python
24
+ import os
25
+ from alphapay import AlphaPayClient
26
+
27
+ alphapay = AlphaPayClient(os.environ["ALPHAPAY_SECRET_KEY"]) # sk_live_... ou sk_test_...
28
+
29
+ # Encaissement direct (push mobile money), sans page de checkout à suivre.
30
+ payment = alphapay.transactions.payin_initialize(
31
+ amount=5000,
32
+ currency="XOF",
33
+ country="BJ",
34
+ network="mtn_bj",
35
+ customer={"email": "ayaba@exemple.com", "first_name": "Ayaba", "last_name": "Client", "phone": "+22900000000"},
36
+ description="Commande #1234",
37
+ idempotency_key=True, # recommandé : évite un double push en cas de retry réseau
38
+ )
39
+
40
+ print(payment["status"])
41
+ ```
42
+
43
+ ### Options avancées des liens de paiement
44
+
45
+ `payment_links.create()`/`update()` acceptent aussi `require_phone`,
46
+ `facebook_pixel_id`, `google_ads_id`, `custom_fields`,
47
+ `show_confirmation_page` et `redirect_url`. `get_public()`/
48
+ `create_public_checkout()` sont les 2 seules méthodes de cette ressource qui
49
+ n'exigent PAS de clé secrète (page publique du lien) — ne les appelez jamais
50
+ depuis un front avec votre clé API en dur, seul `slug` doit y circuler.
51
+
52
+ ```python
53
+ link = alphapay.payment_links.create(
54
+ name="Facture #42",
55
+ amount_type="FIXED",
56
+ amount=5000,
57
+ currency="XOF",
58
+ google_ads_id="AW-123456789",
59
+ custom_fields=[{"key": "reference_client", "label": "Référence client", "required": True}],
60
+ )
61
+
62
+ # Côté public (mobile/web), sans clé API :
63
+ public_link = alphapay.payment_links.get_public(link["slug"])
64
+ checkout = alphapay.payment_links.create_public_checkout(
65
+ link["slug"],
66
+ customer={"email": "client@exemple.com", "first_name": "Client", "last_name": "Test"},
67
+ custom_field_values={"reference_client": "CMD-42"},
68
+ )
69
+ # checkout["slug"] est une CheckoutSession one-shot : pilotez la suite (réseau, push,
70
+ # statut) avec le SDK checkout public (mobile/web), jamais avec ce client à clé secrète.
71
+ ```
72
+
73
+ ## Sandbox vs live
74
+
75
+ L'environnement se déduit automatiquement du préfixe de la clé :
76
+
77
+ ```python
78
+ sandbox = AlphaPayClient("sk_test_...") # sandbox.environment == "sandbox"
79
+ live = AlphaPayClient("sk_live_...") # live.environment == "live"
80
+ ```
81
+
82
+ ## Gestion des erreurs
83
+
84
+ Toute erreur API est normalisée en une sous-classe de `AlphaPayError` —
85
+ jamais un code HTTP brut à interpréter soi-même :
86
+
87
+ ```python
88
+ from alphapay import AlphaPayValidationError, AlphaPayRateLimitError
89
+
90
+ try:
91
+ alphapay.settlements.create(country="BJ", requested_amount=100, payout_method=method_id)
92
+ except AlphaPayValidationError as e:
93
+ print(e.field_errors) # {"requested_amount": ["Montant minimum : 500 XOF."]}
94
+ except AlphaPayRateLimitError as e:
95
+ print(f"Réessayer dans {e.retry_after}s")
96
+ ```
97
+
98
+ `AlphaPayAuthenticationError`, `AlphaPayPermissionError`,
99
+ `AlphaPayNotFoundError`, `AlphaPayIdempotencyError` (409 — clé
100
+ Idempotency-Key réutilisée avec un payload différent), `AlphaPayServerError`
101
+ et `AlphaPayConnectionError` (réseau/timeout, jamais atteint l'API)
102
+ couvrent le reste. Le client retente automatiquement (backoff exponentiel +
103
+ gigue) sur 429/5xx/erreur réseau — 2 tentatives supplémentaires par défaut,
104
+ configurable via `max_retries=` au constructeur.
105
+
106
+ ## Pagination
107
+
108
+ `alphapay.paginate()` suit le lien `next` renvoyé par l'API (pas un numéro
109
+ de page recalculé côté SDK) — fonctionne aussi bien sur les ressources
110
+ paginées par page (`count` présent) que sur `transactions.list()`, paginée
111
+ par curseur (`TransactionListView` utilise `CreatedAtCursorPagination` côté
112
+ API, sans `count` ; y passer `page` n'a aucun effet) :
113
+
114
+ ```python
115
+ from alphapay import paginate
116
+
117
+ for tx in paginate(alphapay.http, alphapay.transactions.list(status="SUCCESS")):
118
+ print(tx["reference"], tx["amounts"]["net"])
119
+ ```
120
+
121
+ ## Vérifier un webhook reçu
122
+
123
+ Reproduit exactement le schéma de signature d'AlphaPayBack (HMAC-SHA256 de
124
+ `"<timestamp>.<corps>"`, comparaison en temps constant via
125
+ `hmac.compare_digest`, fenêtre anti-rejeu de 300s) :
126
+
127
+ ```python
128
+ from alphapay import verify_signature, AlphaPayWebhookSignatureError
129
+
130
+ # Exemple Flask -- adapter selon le framework.
131
+ @app.route("/webhooks/alphapay", methods=["POST"])
132
+ def alphapay_webhook():
133
+ try:
134
+ event = verify_signature(
135
+ payload=request.get_data(as_text=True), # corps BRUT, jamais déjà décodé en JSON
136
+ signature=request.headers["X-Webhook-Signature"],
137
+ timestamp=request.headers["X-Webhook-Timestamp"],
138
+ secret=os.environ["ALPHAPAY_WEBHOOK_SECRET"],
139
+ )
140
+ except AlphaPayWebhookSignatureError:
141
+ return "", 400
142
+ # traiter event["event"] / event["data"]
143
+ return "", 200
144
+ ```
145
+
146
+ ## ⚠️ Sécurité — ce SDK est côté serveur uniquement
147
+
148
+ La clé API (`sk_live_.../sk_test_...`) donne un accès complet au compte
149
+ marchand (créer des paiements, déclencher des retraits, lire l'historique).
150
+ **Ne l'embarquez jamais dans du code exécuté côté client** (un notebook
151
+ partagé, un script de démo, une app desktop distribuée). Gardez-la dans une
152
+ variable d'environnement ou un secret manager, jamais en clair dans un
153
+ dépôt versionné.
154
+
155
+ ## Ressources couvertes
156
+
157
+ | Ressource | Méthodes | Via clé API |
158
+ |---|---|---|
159
+ | `transactions` | `list`, `get`, `export`, `download_invoice`, `payin_initialize/payin_verify/payin_retry/payin_confirm_otp`, `payout_initialize/payout_verify` | ✅ |
160
+ | `payment_links` | `list`, `create`, `get`, `update`, `delete` | ✅ |
161
+ | `payment_links` | `get_public`, `create_public_checkout` | publiques (pas de clé requise) |
162
+ | `checkout_sessions` | `list`, `create`, `get`, `cancel` | ✅ |
163
+ | `customers` | `list`, `create`, `get`, `update`, `delete`, `transactions` | ✅ |
164
+ | `settlements` | `list`, `create`, `get`, `cancel` | ❌ dashboard-only |
165
+ | `wallet_transfers` | `list`, `create`, `get` | ❌ dashboard-only |
166
+ | `balances` | `list`, `get` | ✅ |
167
+ | `balances` | `ledger_entries` | ❌ dashboard-only |
168
+ | `api_keys` | `list`, `create`, `get`, `revoke`, `delete` | ❌ dashboard-only |
169
+ | `api_keys` | `ip_whitelist.{list,create,update,delete}` | ✅ |
170
+ | `webhook_endpoints` | `list`, `get`, `subscriptions.list`, `logs.{list,get}` | ✅ |
171
+ | `webhook_endpoints` | `create`, `update`, `rotate_secret`, `delete`, `subscriptions.{subscribe,unsubscribe}`, `logs.resend` | ❌ dashboard-only |
172
+
173
+ ### La colonne "Via clé API"
174
+
175
+ Vérifié en conditions réelles (`api.alphapay.me`, appels en lecture, via le
176
+ SDK Node.js jumeau — même API, même restriction) : une partie de l'API est
177
+ **volontairement inaccessible à une clé API**, même en lecture — jamais un
178
+ bug, toujours `apps.core.mixins.forbid_api_key` côté AlphaPayBack :
179
+
180
+ ```python
181
+ from alphapay import AlphaPayPermissionError
182
+
183
+ try:
184
+ alphapay.settlements.list()
185
+ except AlphaPayPermissionError as e:
186
+ if e.error_code == "dashboard_only":
187
+ pass # "La demande de retrait n'est possible que depuis le dashboard (compte utilisateur) — jamais via une clé API."
188
+ ```
189
+
190
+ Logique : les retraits, l'historique détaillé du grand livre et la gestion
191
+ des clés API elles-mêmes exigent qu'un humain soit connecté au dashboard —
192
+ une clé compromise ne peut ni sortir d'argent, ni fabriquer d'autres clés
193
+ pour elle-même, ni consulter le détail comptable.
194
+
195
+ Pas encore couvert (endpoints existants côté API, absents du SDK pour l'instant) :
196
+ gestion d'équipe, KYC marchand, configs marchand, journal d'audit,
197
+ référentiels (pays/réseaux/taux de change), support.
198
+
199
+ ## Développement
200
+
201
+ ```bash
202
+ python -m unittest discover -s tests -v # lance un vrai serveur HTTP local (tests/server.py, thread), aucun appel réseau réel vers AlphaPay
203
+ python -m py_compile src/alphapay/*.py src/alphapay/resources/*.py # équivalent d'un lint syntaxique
204
+ ```
205
+
206
+ ## Licence
207
+
208
+ MIT
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "alphapay"
7
+ version = "0.1.0"
8
+ description = "Official Python SDK for the AlphaPay payment aggregator API."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.8"
12
+ dependencies = []
13
+ keywords = ["alphapay", "payments", "mobile-money", "payment-gateway", "africa"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://alphapay.me"
28
+
29
+ [tool.setuptools.packages.find]
30
+ where = ["src"]
31
+
32
+ [tool.setuptools.package-data]
33
+ alphapay = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,36 @@
1
+ """Official Python SDK for the AlphaPay payment aggregator API."""
2
+
3
+ from .client import AlphaPayClient
4
+ from .exceptions import (
5
+ AlphaPayAuthenticationError,
6
+ AlphaPayConnectionError,
7
+ AlphaPayError,
8
+ AlphaPayIdempotencyError,
9
+ AlphaPayNotFoundError,
10
+ AlphaPayPermissionError,
11
+ AlphaPayRateLimitError,
12
+ AlphaPayServerError,
13
+ AlphaPayValidationError,
14
+ AlphaPayWebhookSignatureError,
15
+ )
16
+ from .pagination import paginate
17
+ from .webhook import verify_signature
18
+
19
+ __version__ = "0.1.0"
20
+
21
+ __all__ = [
22
+ "AlphaPayClient",
23
+ "AlphaPayError",
24
+ "AlphaPayAuthenticationError",
25
+ "AlphaPayPermissionError",
26
+ "AlphaPayNotFoundError",
27
+ "AlphaPayValidationError",
28
+ "AlphaPayRateLimitError",
29
+ "AlphaPayServerError",
30
+ "AlphaPayConnectionError",
31
+ "AlphaPayIdempotencyError",
32
+ "AlphaPayWebhookSignatureError",
33
+ "verify_signature",
34
+ "paginate",
35
+ "__version__",
36
+ ]
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from .http import DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT, Http
6
+ from .resources.api_keys import ApiKeysResource
7
+ from .resources.balances import BalancesResource
8
+ from .resources.checkout_sessions import CheckoutSessionsResource
9
+ from .resources.customers import CustomersResource
10
+ from .resources.payment_links import PaymentLinksResource
11
+ from .resources.settlements import SettlementsResource
12
+ from .resources.transactions import TransactionsResource
13
+ from .resources.wallet_transfers import WalletTransfersResource
14
+ from .resources.webhook_endpoints import WebhookEndpointsResource
15
+
16
+
17
+ class AlphaPayClient:
18
+ """Client principal du SDK AlphaPay. Une instance = une clé API = un
19
+ marchand + un environnement (live/sandbox, déduit automatiquement du
20
+ préfixe de la clé -- ``sk_live_...`` ou ``sk_test_...``).
21
+
22
+ :Example:
23
+
24
+ >>> alphapay = AlphaPayClient(os.environ["ALPHAPAY_SECRET_KEY"])
25
+ >>> payment = alphapay.transactions.payin_initialize(
26
+ ... amount=5000,
27
+ ... currency="XOF",
28
+ ... country="BJ",
29
+ ... network="mtn_bj",
30
+ ... customer={"email": "client@exemple.com", "first_name": "Client", "last_name": "Test", "phone": "+22900000000"},
31
+ ... idempotency_key=True,
32
+ ... )
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ api_key: str,
38
+ base_url: Optional[str] = None,
39
+ timeout: float = DEFAULT_TIMEOUT,
40
+ max_retries: int = DEFAULT_MAX_RETRIES,
41
+ ) -> None:
42
+ #: Client HTTP bas niveau -- nécessaire à :func:`alphapay.pagination.paginate`
43
+ #: pour suivre un lien "next" (URL absolue renvoyée par l'API), pas
44
+ #: destiné à un usage direct en dehors de ce cas.
45
+ self.http = Http(api_key, base_url, timeout, max_retries)
46
+ self.environment = self.http.environment
47
+
48
+ self.transactions = TransactionsResource(self.http)
49
+ self.payment_links = PaymentLinksResource(self.http)
50
+ self.checkout_sessions = CheckoutSessionsResource(self.http)
51
+ self.customers = CustomersResource(self.http)
52
+ self.settlements = SettlementsResource(self.http)
53
+ self.wallet_transfers = WalletTransfersResource(self.http)
54
+ self.balances = BalancesResource(self.http)
55
+ self.api_keys = ApiKeysResource(self.http)
56
+ self.webhook_endpoints = WebhookEndpointsResource(self.http)