FedaPay Connector
Un client asynchrone robuste pour l'API FedaPay, offrant une gestion automatisée des paiements avec support complet des webhooks.
✨ Caractéristiques
- 🔄 Pattern Singleton - Une seule instance partagée dans toute l'application
- ⚡ Entièrement Asynchrone - Performances optimales avec asyncio
- 🔒 Sécurisé - Validation des signatures et gestion sécurisée des webhooks
- 💾 Persistence Automatique - Sauvegarde et restauration des transactions
- 🎯 Callbacks Personnalisables - Hooks pour tous les événements
- 🚀 Simple à Utiliser - API intuitive et documentation complète
- 🛠️ Module bas niveau pour controle granulaire - Pour les dev qui veulent avoir plus de controle
Installation
Via pip
pip install fedapay_connector
Via poetry
poetry add fedapay_connector
🛠️ Configuration
Prérequis
- Python 3.9+
- Un compte FedaPay avec les clés API
- Pour le serveur webhook : une URL accessible publiquement pointant vers votre serveur (via ngrok, un reverse proxy, etc.)
Variables d'Environnement
| Variable | Description | Requis | Défaut |
|---|---|---|---|
FEDAPAY_API_KEY |
Clé API FedaPay | ✅ | - |
FEDAPAY_API_URL |
URL API (sandbox/production) | ✅ | - |
FEDAPAY_AUTH_KEY |
Clé secrète webhook | ✅ | - |
FEDAPAY_ENDPOINT_NAME |
Endpoint webhook | ❌ | webhooks |
FEDAPAY_DB_URL |
URL sqlalchemy base de données | ❌ | sqlite:///fedapay_connector_persisted_data/processes.db |
Exemple de .env
FEDAPAY_API_KEY=fp_key_live_123456789
FEDAPAY_API_URL=https://api.fedapay.com
FEDAPAY_AUTH_KEY=webhook_secret_123456789
FEDAPAY_ENDPOINT_NAME=webhooks
📚 Guide d'Utilisation
Modes d'Utilisation module FedapayConnector
-
Mode Simple (non recommandé)
- Polling manuel du statut
- Sans gestion des webhooks
-
Mode Serveur Intégré (recommandé)
- Serveur webhook intégré
- Gestion automatique des événements
- Parfait pour une apllication python hors context d'API
-
Mode Serveur Intégré (options avancées) (recommandé)
- Serveur webhook intégré
- Gestion automatique des événements
- Sauvegarde et restauration automatique des processus découtes apres arrêt ou redemarrage de l'app
- Parfait pour une apllication python hors context d'API
-
Mode API Existante
- Intégration avec FastAPI/Django/etc
- Gestion personnalisée des webhooks
1. Mode Simple
from fedapay_connector import Pays, MethodesPaiement, FedapayConnector, PaiementSetup, UserData, EventFutureStatus, PaymentHistory, WebhookHistory
import asyncio
async def main():
# Creation de l'instance Fedapay Connector
fedapay = FedapayConnector(use_listen_server= False)
# Configuration paiement
setup = PaiementSetup(
pays=Pays.benin,
method=MethodesPaiement.mtn_open
)
client = UserData(
nom="Doe",
prenom="John",
email="john@example.com",
tel="0162626262"
)
# Exécution paiement
resp = await fedapay.fedapay_pay(
setup=setup,
client_infos=client,
montant_paiement=1000,
payment_contact="0162626262"
)
while True:
# vérifier le resultat manuellement par polling
status = await fedapay.fedapay_check_transaction_status(resp.id_transaction)
if status.status == TransactionStatus.created or status.status == TransactionStatus.pending:
await asyncio.sleep(0.1)
else:
break
if __name__ == "__main__":
asyncio.run(main())
2. Mode Serveur Intégré
Cette option nécéssite que vous ayez un reverse proxy pointant sur votre machine au port d'ecoute configurer pour le serveur (défaut : 3000) depuis une url qui sera utiliseée pour la configuration des webhook sur votre panel fedapay. lien doc fedapay
from fedapay_connector import Pays, MethodesPaiement, FedapayConnector, PaiementSetup, UserData, EventFutureStatus, PaymentHistory, WebhookHistory
import asyncio
async def main():
# Creation des callbacks
async def payment_callback(data:PaymentHistory):
# s'execute chaque fois qu'un nouveau paiement est initialisé avec fedapay_pay()
print(f"Callback de paiement reçu : {data.__dict__}")
async def webhook_callback(data:WebhookHistory):
# s'execute chaque fois qu'un nouveau webhook est reçu de fedapay
print(f"Webhook reçu : {data.__dict__}")
# Creation de l'instance Fedapay Connector
fedapay = FedapayConnector(use_listen_server= True)
# Configuration des callbacks
fedapay.set_payment_callback_function(payment_callback) # executer a chaques appels reussi a fedapay_pay()
fedapay.set_webhook_callback_function(webhook_callback) # executer à la réception de webhooks fedapay valides
# Démarrage du listener interne
fedapay.start_webhook_server()
# Configuration paiement
setup = PaiementSetup(
pays=Pays.benin,
method=MethodesPaiement.mtn_open
)
client = UserData(
nom="Doe",
prenom="John",
email="john@example.com",
tel="0162626262"
)
# Exécution paiement
resp = await fedapay.fedapay_pay(
setup=setup,
client_infos=client,
montant_paiement=1000,
payment_contact="0162626262"
)
# Attente résultat
status, webhooks = await fedapay.fedapay_finalise(resp.id_transaction)
if status == EventFutureStatus.RESOLVED:
print("\nTransaction réussie\n")
print(f"\nDonnées finales : {webhooks}\n")
# ATTENTION : Ce cas indique le reception d'une webhook valide et la clôture de la transaction mais ne veut pas systématiquement dire due l'opération à été approuvée
# Il faudra implementer par la suite votre gestion des webhook pour la validation ou tout autre traitement du paiement effectuer à partir de la liste d'objet WebhookTransaction reçu.
elif status == EventFutureStatus.TIMEOUT:
# La vérification manuelle du statut de la transaction se fait automatiquement si timeout donc si timeout est levé pas besoin de revérifier manuellement le status.
print("\nLa transaction a expiré.\n")
elif status == EventFutureStatus.CANCELLED:
print("\nTransaction annulée par l'utilisateur\n")
elif status == EventFutureStatus.CANCELLED_INTERNALLY:
print("\nTransaction annulée en interne -- probable redemarrage ou arret de l'application\n")
if __name__ == "__main__":
asyncio.run(main())
3. Mode Serveur Intégré (options avancées)
from fedapay_connector import Pays, MethodesPaiement, FedapayConnector, PaiementSetup, UserData, EventFutureStatus, PaymentHistory, WebhookHistory
import asyncio
async def main():
# Creation des callbacks
async def payment_callback(data:PaymentHistory):
# s'execute chaque fois qu'un nouveau paiement est initialisé avec fedapay_pay()
print(f"Callback de paiement reçu : {data.__dict__}")
async def webhook_callback(data:WebhookHistory):
# s'execute chaque fois qu'un nouveau webhook est reçu de fedapay
print(f"Webhook reçu : {data.__dict__}")
async def run_after_finalise(
status: EventFutureStatus, data: list[WebhookHistory] | None
):
# s'execute après la récupération d'écoute perdue une fois que la reponse de fedapay est reçue
# ou que le timeout naturel survient
if status == EventFutureStatus.RESOLVED:
print("\nTransaction réussie\n")
print(f"\nDonnées finales : {data}\n")
# ATTENTION : Ce cas indique le reception d'une webhook valide et la clôture de la transaction mais ne veut pas systématiquement dire due l'opération à été approuvée
# Il faudra implementer par la suite votre gestion des webhook pour la validation ou tout autre traitement du paiement effectuer à partir de la liste d'objet WebhookTransaction reçu.
elif status == EventFutureStatus.TIMEOUT:
# La vérification manuelle du statut de la transaction se fait automatiquement si timeout donc si timeout est levé pas besoin de revérifier manuellement le status sur le coup.
print("\nLa transaction a expiré.\n")
elif status == EventFutureStatus.CANCELLED:
print("\nTransaction annulée par l'utilisateur\n")
elif status == EventFutureStatus.CANCELLED_INTERNALLY:
print("\nTransaction annulée en interne -- probable redemarrage ou arret de l'application\n")
# Creation de l'instance Fedapay Connector
fedapay = FedapayConnector(use_listen_server= True)
# Configuration des callbacks
fedapay.set_payment_callback_function(payment_callback) # executer a chaques appels reussi a fedapay_pay()
fedapay.set_webhook_callback_function(webhook_callback) # executer à la réception de webhooks fedapay valides
fedapay.set_on_persited_listening_processes_loading_finished_callback(run_after_finalise)
# éxectuer lors de la récupération des ecoutes d'event fedapay perduent lors d'un potentiel
# redemarrage de l'app pendant que des ecoutes sont actives.
# lancement de la restauration des processus d'écoute
await fedapay.load_persisted_listening_processes()
# Démarrage du listener interne
fedapay.start_webhook_server()
# Configuration paiement
setup = PaiementSetup(
pays=Pays.benin,
method=MethodesPaiement.moov
)
client = UserData(
nom="Doe",
prenom="John",
email="john@example.com",
tel="0164000001"
)
# Exécution paiement
resp = await fedapay.fedapay_pay(
setup=setup,
client_infos=client,
montant_paiement=1000,
payment_contact="0162626262"
)
# Attente résultat
status, webhooks = await fedapay.fedapay_finalise(resp.transaction.id)
if __name__ == "__main__":
asyncio.run(main())
4. Mode API Existante (Intégration FastAPI ou framework similaire)
Dans des cas d'usage comme pour un backend FastAPI vous devrez faire l'initialisation du module dans le lifespan au demarrage de FastAPI puis l'utiliser directement dans vos logiques métiers pour le traitement des transaction.
from fastapi import FastAPI
from contextlib import asynccontextmanager
from fedapay_connector import FedapayConnector
... code du fichier main.py ...
@asynccontextmanager
async def lifespan(app: FastAPI):
# Creation de l'instance Fedapay Connector
fedapay = FedapayConnector(use_listen_server= False)
# importer ou definissez prealablement les callabacks si voulu
# Configuration des callbacks
fedapay.set_payment_callback_function(payment_callback) # executer a chaques appels reussi a fedapay_pay()
fedapay.set_webhook_callback_function(webhook_callback) # executer à la réception de webhooks fedapay valides
fedapay.set_on_persited_listening_processes_loading_finished_callback(run_after_finalise) # éxectuer lors de la récupération des ecoutes d'event fedapay perduent lors d'un potentiel redemarrage de l'app pendant que des ecoutes sont actives.
# lancement de la restauration des processus d'écoute
await fedapay.load_persisted_listening_processes()
yield
#permet un arret propre de fedapay connector
await fedapay.shutdown_cleanup()
app = FastAPI(lifespan=lifespan)
@app.post("/webhooks/fedapay")
async def fedapay_webhook(request: Request):
payload = await request.body()
headers = request.headers
# Validation signature
signature = headers.get("x-fedapay-signature")
FedapayConnector().verify_signature(payload, signature)
# Traitement webhook
event = await request.json()
await FedapayConnector().fedapay_save_webhook_data(event)
return {"status": "success"}
... suite de votre code ...
Si les methodes de paiement que vous souhaiter utilisés ne sont pas disponibles en paiement sans redirection vous devrez recupérer le paiement link et le retourner au front end pour affichage dans une webview ou un element similaire pour finalisation par l'utilisateur. Le satut sera toutefois toujours capturer par le backend directement donc il n'est pas neccessaire de le recupérer coté client.
Modes d'Utilisation module Integration (Utilisation avancée)
Pour les utilisateurs qui souhaitent un contrôle plus granulaire des appels HTTP vers l'API FedaPay (CRUD complet sur Transactions, Events, Balances, Currencies, Logs, Webhooks), utilisez la classe Integration fournie dans le package.
Principales caractéristiques :
- Fournit un point d'entrée unique pour les services bas-niveau :
Transactions,Balances,Currencies,Events,Logs,Webhooks. - Utilisée quand vous ne voulez pas du workflow automatique (Listeners / Futures) géré par
FedapayConnectoret préférez appeler manuellement les endpoints.
Constructeur :
Integration(api_url: str = os.getenv("FEDAPAY_API_URL"), logger: logging.Logger = None, default_api_key: Optional[str] = os.getenv("FEDAPAY_API_KEY"))- Remarque importante :
api_urletdefault_api_keysont requis (ou doivent être fournis via les variables d'environnement). Si l'un d'eux manque, le constructeur lèveraValueError.
Exemple d'utilisation basique :
import asyncio
from fedapay_connector.integration import Integration
async def main():
integ = Integration() # lit FEDAPAY_API_URL et FEDAPAY_API_KEY depuis l'env
# Récupérer une transaction par ID Fedapay
tx = await integ.get_transaction_by_fedapay_id("12345")
print(tx)
# Créer une transaction (voir models.PaiementSetup / UserData)
setup = PaiementSetup(...)
client = UserData(...)
new_tx = await integ.create_transaction(setup, client, montant_paiement=1000)
# Récupérer lien / token
token = await integ.get_transaction_link(new_tx.id)
# Lister les événements
events = await integ.get_all_events(params={})
asyncio.run(main())
Notes pratiques :
- Les méthodes
Integrationrenvoient les modèles Pydantic présents dansfedapay_connector.models(ex:Transaction,TransactionListResponse,EventResponse). - Pour les tests, mockez les méthodes des services internes (par ex.
Transactions._get_transaction_by_fedapay_id) lorsque vous vérifiez la logique métier dépendante du réseau. Integrationest synchrone avec l'API asynchrone (utiliseaiohttpen interne) — appelez-le depuis une coroutine ou viaasyncio.run().
Fonctionnalités Avancées
Gestion des Webhooks
# 1. Serveur Intégré
fedapay = FedapayConnector(
use_listen_server=True,
listen_server_port=3000,
listen_server_endpoint_name="webhooks"
)
fedapay.start_webhook_server() # convenience wrapper -> calls `WebhookServer.start_webhook_listenning()`
# 2. Intégration API Existante
fedapay = FedapayConnector(use_listen_server=False)
await fedapay.fedapay_save_webhook_data(webhook_data)
Cycle de vie du serveur interne:
- Le serveur interne est lancé dans un thread d'arrière-plan. FedapayConnector expose :
start_webhook_server()-> Démarre le serveur interne .shutdown_cleanup()-> méthode asynchrone qui annule les futures d'événements en attente, attend les tâches de rappel (avec un délai d'attente) et arrête le serveur webhook viastop_webhook_listenning().
Recommendation: call await fedapay.shutdown_cleanup() from your application's shutdown handler (FastAPI lifespan or SIGTERM) to ensure persisted listeners and callback tasks are cleaned up correctly.
Callbacks Personnalisés
async def on_payment(payment: PaymentHistory):
"""Appelé après chaque paiement"""
print(f"Nouveau paiement: {payment.transaction.id}")
async def on_webhook(webhook: WebhookHistory):
"""Appelé pour chaque webhook"""
print(f"Webhook reçu: {webhook.name}")
async def run_after_finalise(
status: EventFutureStatus, data: list[WebhookHistory] | None
):
"""Appelé après la résolution d'écoutes récupérées """
if status == EventFutureStatus.RESOLVED:
print("\nTransaction réussie\n")
print(f"\nDonnées finales : {data}\n")
elif status == EventFutureStatus.TIMEOUT:
print("\nLa transaction a expiré.\n")
elif status == EventFutureStatus.CANCELLED:
print("\nTransaction annulée par l'utilisateur\n")
elif future_event_status == EventFutureStatus.CANCELLED_INTERNALLY:
print("\nTransaction annulée en interne -- probable redemarrage ou arret de l'application\n")
fedapay.set_payment_callback_function(on_payment)
fedapay.set_webhook_callback_function(on_webhook)
fedapay.set_on_persited_listening_processes_loading_finished_callback(run_after_finalise)
Persistence et Restauration
Le module gère automatiquement :
- Sauvegarde des transactions en cours
- Restauration après redémarrage
- Reprise des écouteurs interrompus
- Synchronisation avec FedaPay
🔧 Dépannage
Problèmes Courants
-
Les webhooks ne sont pas reçus
- Vérifier l'URL configurée dans FedaPay
- Vérifier la clé secrète webhook
-
Erreurs de timeout
- Augmenter la valeur du timeout
- Vérifier la connexion réseau
- Consulter les logs pour plus de détails
Contribution
Les contributions sont les bienvenues!
Licence
Ce projet est sous licence GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later). Consultez le fichier LICENSE pour plus d'informations.
🔒 Sécurité
- Ne jamais exposer les clés API
- Toujours valider les signatures webhook
- Utiliser HTTPS en production
- Implémenter des timeouts appropriés
Metadata
Release files for fedapay-connector 2.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fedapay_connector-2.0.3.tar.gz | 46.3 kB | Without provenance | Details for fedapay_connector-2.0.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fedapay_connector-2.0.3-py3-none-any.whl | Python 3 | none | any | Details for fedapay_connector-2.0.3-py3-none-any.whl |
Total release size: 93.3 kB
Release files / fedapay_connector-2.0.3.tar.gz
| Download URL | fedapay_connector-2.0.3.tar.gz |
|---|---|
| Size | 46.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f0ffd3073e418d5cf987512f5c2732d65608550241f51704a4cfd9289be7b01c
|
|
BLAKE2b-256 checksum How to use checksums |
2753b05c8d8f14d7febe0b44966eb510c5f4e8f23ddc17275244e226713301cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.8
|
Release files / fedapay_connector-2.0.3-py3-none-any.whl
| Download URL | fedapay_connector-2.0.3-py3-none-any.whl |
|---|---|
| Size | 47.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9aef9b423d9837a1b18575cf1020925f171023247c01ce9b760ba526d870508a
|
|
BLAKE2b-256 checksum How to use checksums |
17f2b769e9343f0278878650a7ea002caef58b65350befd205e9769efd5bf362
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.8
|
Security for fedapay-connector 2.0.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.