Guide de gestion des erreurs¶
Ce guide explique comment gérer efficacement les erreurs qui peuvent survenir lors de l'utilisation de la bibliothèque MVola API.
Introduction¶
La bibliothèque MVola API utilise un système d'exceptions hiérarchique pour vous permettre de gérer facilement les différents types d'erreurs qui peuvent se produire lors des opérations avec l'API MVola. Ce guide couvre les codes d'erreur standard de l'API MVola et comment les gérer efficacement dans votre application.
Hiérarchie des exceptions¶
MVolaError (Exception de base)
├── MVolaAuthError (Erreurs d'authentification)
│ ├── MVolaInvalidCredentialsError
│ └── MVolaTokenExpiredError
├── MVolaTransactionError (Erreurs de transaction)
│ ├── MVolaTransactionValidationError
│ ├── MVolaTransactionStatusError
│ └── MVolaTransactionCreationError
├── MVolaValidationError (Erreurs de validation)
│ └── MVolaInvalidParameterError
├── MVolaConnectionError (Erreurs de connexion)
│ ├── MVolaRequestTimeoutError
│ └── MVolaServerError
└── MVolaConfigError (Erreurs de configuration)
Cette hiérarchie vous permet de capturer des erreurs à différents niveaux de spécificité selon vos besoins.
Codes d'erreur HTTP de l'API MVola¶
L'API MVola utilise les codes d'erreur HTTP standard pour indiquer si une requête a réussi ou échoué. Voici les principaux codes que vous pourriez rencontrer :
Code | Description | Traitement recommandé |
---|---|---|
200 | OK - La requête a réussi | Traiter la réponse normalement |
400 | Bad Request - Requête incorrecte, souvent en raison d'un paramètre manquant | Vérifier les paramètres de votre requête |
401 | Unauthorized - Clé API invalide fournie | Vérifier vos identifiants d'API ou générer un nouveau token |
402 | Request Failed - Les paramètres sont valides mais la requête a échoué | Vérifier l'état du compte MVola ou les limites de transaction |
403 | Forbidden - La clé API n'a pas les permissions nécessaires | Demander les autorisations appropriées pour votre application |
404 | Not Found - La ressource demandée n'existe pas | Vérifier l'URL ou l'ID de la ressource |
409 | Conflict - La requête est en conflit avec une autre requête | Éviter les requêtes dupliquées ou attendez et réessayez |
429 | Too Many Requests - Trop de requêtes envoyées à l'API trop rapidement | Implémenter un système de backoff exponentiel |
500, 502, 503, 504 | Server Errors - Erreur au niveau du serveur | Attendre et réessayer plus tard |
Format des réponses d'erreur¶
Les erreurs de l'API MVola sont généralement retournées au format JSON avec la structure suivante :
{
"ErrorCategory": "Catégorie de l'erreur",
"ErrorCode": "Code d'erreur spécifique",
"ErrorDescription": "Description détaillée de l'erreur",
"ErrorDateTime": "Date et heure de l'erreur",
"ErrorParameters": {
"key1": "value1",
"key2": "value2"
}
}
Pour les erreurs d'authentification, le format peut être différent :
{
"fault": {
"code": 900901,
"message": "Invalid Credentials",
"description": "Invalid Credentials. Make sure you have given the correct access token"
}
}
La bibliothèque MVola API analyse ces réponses d'erreur et les convertit en exceptions appropriées que vous pouvez gérer dans votre code.
Importation des exceptions¶
from mvola_api.exceptions import (
MVolaError, # Exception de base
MVolaAuthError, # Erreurs d'authentification
MVolaInvalidCredentialsError, # Identifiants invalides
MVolaTokenExpiredError, # Token expiré
MVolaTransactionError, # Erreurs de transaction
MVolaTransactionValidationError, # Validation de transaction
MVolaTransactionStatusError, # Erreur de statut
MVolaTransactionCreationError, # Création de transaction
MVolaValidationError, # Erreurs de validation
MVolaInvalidParameterError, # Paramètre invalide
MVolaConnectionError, # Erreurs de connexion
MVolaRequestTimeoutError, # Timeout
MVolaServerError, # Erreur serveur
MVolaConfigError # Erreurs de configuration
)
Gestion basique des erreurs¶
La façon la plus simple de gérer les erreurs est d'utiliser un bloc try/except pour capturer toutes les erreurs MVola :
from mvola_api import MVolaClient
from mvola_api.exceptions import MVolaError
try:
# Initialiser le client
client = MVolaClient(
consumer_key="votre_consumer_key",
consumer_secret="votre_consumer_secret",
partner_name="Nom de votre application",
partner_msisdn="0343500003",
sandbox=True
)
# Initier un paiement
transaction_info = client.initiate_payment(
amount=1000,
debit_msisdn="0343500003",
credit_msisdn="0343500004",
reference="REF123456",
description="Paiement test"
)
print(f"Transaction initiée avec succès: {transaction_info}")
except MVolaError as e:
print(f"Une erreur MVola s'est produite: {e}")
# Gérer l'erreur (journalisation, notification, etc.)
Gestion avancée des erreurs¶
Pour une gestion plus précise, vous pouvez capturer des types d'exceptions spécifiques :
from mvola_api import MVolaClient
from mvola_api.exceptions import (
MVolaInvalidCredentialsError,
MVolaTransactionValidationError,
MVolaConnectionError,
MVolaError
)
try:
# Initialiser le client
client = MVolaClient(
consumer_key="votre_consumer_key",
consumer_secret="votre_consumer_secret",
partner_name="Nom de votre application",
partner_msisdn="0343500003",
sandbox=True
)
# Initier un paiement
transaction_info = client.initiate_payment(
amount=1000,
debit_msisdn="0343500003",
credit_msisdn="0343500004",
reference="REF123456",
description="Paiement test"
)
print(f"Transaction initiée avec succès: {transaction_info}")
except MVolaInvalidCredentialsError as e:
print(f"Identifiants invalides: {e}")
# Suggérer de vérifier les identifiants API
except MVolaTransactionValidationError as e:
print(f"Données de transaction invalides: {e}")
# Afficher des messages d'erreur spécifiques aux champs
except MVolaConnectionError as e:
print(f"Erreur de connexion: {e}")
# Suggérer de vérifier la connexion Internet ou de réessayer plus tard
except MVolaError as e:
print(f"Autre erreur MVola: {e}")
# Gérer les autres erreurs MVola
except Exception as e:
print(f"Erreur inattendue: {e}")
# Capturer toute autre erreur non prévue
Types d'erreurs spécifiques¶
Erreurs d'authentification¶
try:
# Tenter de générer un token avec des identifiants invalides
client.generate_token()
except MVolaInvalidCredentialsError as e:
print(f"Identifiants invalides: {e}")
print(f"Code d'erreur: {e.error_code}")
# Suggérer de vérifier les identifiants ou de générer de nouvelles clés
except MVolaTokenExpiredError as e:
print(f"Token expiré: {e}")
# Rafraîchir le token et réessayer
client.refresh_token()
Erreurs de transaction¶
try:
# Tenter un paiement avec des données invalides
client.initiate_merchant_payment(
amount=-100, # Montant négatif (invalide)
currency="Ar",
debit_msisdn="0343500003",
credit_msisdn="0343500004",
requesting_organisation_transaction_reference="REF123456",
description="Paiement test"
)
except MVolaTransactionValidationError as e:
print(f"Validation échouée: {e}")
print(f"Champ en erreur: {e.field}")
print(f"Détails: {e.details}")
# Afficher un message d'erreur approprié à l'utilisateur
except MVolaTransactionStatusError as e:
print(f"Erreur de statut: {e}")
print(f"ID de transaction: {e.transaction_id}")
# Suggérer de vérifier l'ID de transaction
except MVolaTransactionCreationError as e:
print(f"Erreur lors de la création: {e}")
print(f"Détails: {e.details}")
# Suggérer de réessayer plus tard
Erreurs de validation¶
from mvola_api.utils import validate_msisdn
try:
# Valider un numéro de téléphone
validate_msisdn("abcdef") # Format invalide
except MVolaValidationError as e:
print(f"Erreur de validation: {e}")
# Afficher un message d'erreur approprié
Erreurs de connexion¶
try:
# Tenter une opération qui peut échouer en raison de problèmes réseau
status = client.get_transaction_status(
transaction_id="transaction-id-12345",
msisdn="0343500003"
)
except MVolaRequestTimeoutError as e:
print(f"Délai d'attente dépassé: {e}")
print(f"URL: {e.url}")
print(f"Timeout: {e.timeout} secondes")
# Suggérer de réessayer plus tard
except MVolaServerError as e:
print(f"Erreur serveur MVola: {e}")
print(f"Code HTTP: {e.status_code}")
print(f"Réponse: {e.response}")
# Suggérer de contacter le support MVola si le problème persiste
Techniques de gestion des erreurs¶
Approche hiérarchique¶
Attrapez d'abord les exceptions les plus spécifiques, puis les plus générales :
try:
# Code utilisant MVola API
except MVolaInvalidCredentialsError as e:
# Gérer les erreurs d'identifiants spécifiquement
print(f"Identifiants invalides: {e}")
except MVolaAuthError as e:
# Gérer les autres erreurs d'authentification
print(f"Erreur d'authentification: {e}")
except MVolaTransactionError as e:
# Gérer les erreurs de transaction
print(f"Erreur de transaction: {e}")
except MVolaError as e:
# Gérer toutes les autres erreurs MVola
print(f"Erreur MVola: {e}")
except Exception as e:
# Attraper toutes les autres exceptions Python
print(f"Erreur inattendue: {e}")
Gestion avec retries¶
Pour certaines erreurs temporaires (timeout, erreurs serveur), vous pouvez implémenter une stratégie de retry :
from mvola_api.exceptions import MVolaRequestTimeoutError, MVolaServerError
import time
max_retries = 3
retry_count = 0
backoff_factor = 2 # Pour le backoff exponentiel
while retry_count < max_retries:
try:
# Tenter une opération MVola
result = client.initiate_payment(
amount=1000,
debit_msisdn="0343500003",
credit_msisdn="0343500004",
reference="REF123456",
description="Paiement test"
)
# Succès, sortir de la boucle
break
except (MVolaRequestTimeoutError, MVolaServerError) as e:
# Incrémenter le compteur de tentatives
retry_count += 1
# Si nous avons atteint le maximum de tentatives, lever l'exception
if retry_count >= max_retries:
print(f"Échec après {max_retries} tentatives: {e}")
raise
# Calculer le temps d'attente avec backoff exponentiel
wait_time = backoff_factor ** retry_count
print(f"Erreur temporaire: {e}. Nouvelle tentative dans {wait_time}s...")
# Attendre avant de réessayer
time.sleep(wait_time)
Validation préventive¶
Pour éviter certaines exceptions, validez vos données avant d'appeler l'API :
from mvola_api.utils import validate_msisdn, validate_required_params
# Données à valider
payment_data = {
"amount": 1000,
"debit_msisdn": "0343500003",
"credit_msisdn": "0343500004",
"reference": "REF123456",
"description": "Paiement test"
}
# Paramètres requis
required_params = ["amount", "debit_msisdn", "credit_msisdn", "reference", "description"]
try:
# Valider que tous les paramètres requis sont présents
validate_required_params(payment_data, required_params)
# Valider les numéros de téléphone
validate_msisdn(payment_data["debit_msisdn"])
validate_msisdn(payment_data["credit_msisdn"])
# Valider le montant
if payment_data["amount"] <= 0:
raise MVolaValidationError("Le montant doit être positif")
# Si toutes les validations passent, initier le paiement
transaction_info = client.initiate_payment(**payment_data)
except MVolaValidationError as e:
# Gérer les erreurs de validation
print(f"Erreur de validation: {e}")
Journalisation des erreurs¶
Il est recommandé de journaliser les erreurs pour faciliter le débogage :
import logging
# Configurer le logger
logger = logging.getLogger("mvola")
logger.setLevel(logging.DEBUG)
# Ajouter un handler pour écrire dans un fichier
file_handler = logging.FileHandler("mvola_errors.log")
file_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
logger.addHandler(file_handler)
try:
# Code utilisant MVola API
result = client.initiate_payment(...)
except MVolaError as e:
# Journaliser l'erreur avec les détails appropriés
logger.error(f"Erreur MVola: {e}", exc_info=True)
logger.error(f"Détails: {e.details if hasattr(e, 'details') else 'Pas de détails'}")
# Vous pouvez également inclure des informations contextuelles
logger.error(f"Contexte: initiation de paiement pour la référence {reference}")
# Répondre à l'utilisateur avec un message approprié
print("Une erreur s'est produite lors du traitement de votre paiement. Veuillez réessayer plus tard.")
Messages d'erreur conviviaux¶
Transformez les erreurs techniques en messages compréhensibles pour l'utilisateur final :
def get_user_friendly_message(exception):
"""Convertit une exception MVola en message utilisateur convivial"""
if isinstance(exception, MVolaInvalidCredentialsError):
return "Impossible de se connecter au service MVola. Veuillez contacter le support."
elif isinstance(exception, MVolaTokenExpiredError):
return "Votre session a expiré. Veuillez rafraîchir la page et réessayer."
elif isinstance(exception, MVolaTransactionValidationError):
if getattr(exception, 'field', '') == 'amount':
return "Le montant spécifié n'est pas valide. Veuillez vérifier et réessayer."
elif getattr(exception, 'field', '') in ['debit_msisdn', 'credit_msisdn']:
return "Le numéro de téléphone fourni n'est pas valide. Veuillez vérifier et réessayer."
else:
return "Certaines informations de paiement ne sont pas valides. Veuillez vérifier et réessayer."
elif isinstance(exception, MVolaTransactionStatusError):
return "Impossible de vérifier le statut de la transaction. Veuillez réessayer plus tard."
elif isinstance(exception, MVolaConnectionError):
return "Problème de connexion au service MVola. Veuillez vérifier votre connexion Internet et réessayer."
elif isinstance(exception, MVolaError):
return "Une erreur s'est produite lors du traitement de votre paiement. Veuillez réessayer plus tard."
else:
return "Une erreur inattendue s'est produite. Veuillez réessayer plus tard."
# Exemple d'utilisation
try:
# Code utilisant MVola API
result = client.initiate_payment(...)
except Exception as e:
# Journaliser l'erreur technique détaillée
logger.error(f"Erreur: {e}", exc_info=True)
# Afficher un message convivial à l'utilisateur
user_message = get_user_friendly_message(e)
print(user_message)
Bonnes pratiques pour la gestion des erreurs¶
-
Utilisez la hiérarchie d'exceptions pour capturer les erreurs à différents niveaux de spécificité.
-
Validez les données en amont pour éviter les erreurs prévisibles.
-
Implémentez des retries pour les erreurs temporaires, avec un backoff exponentiel.
-
Journalisez les erreurs avec suffisamment de contexte pour faciliter le débogage.
-
Présentez des messages d'erreur conviviaux à l'utilisateur final, sans exposer les détails techniques.
-
Testez vos scénarios d'erreur pour vous assurer que votre application les gère correctement.
-
Mettez en place une surveillance pour être alerté des erreurs récurrentes.
Exemple complet¶
Voici un exemple complet combinant plusieurs techniques de gestion des erreurs :
import time
import logging
from mvola_api import MVolaClient
from mvola_api.exceptions import (
MVolaInvalidCredentialsError,
MVolaTokenExpiredError,
MVolaTransactionValidationError,
MVolaConnectionError,
MVolaRequestTimeoutError,
MVolaServerError,
MVolaError
)
# Configuration du logging
logger = logging.getLogger("mvola")
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler("mvola.log")
handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
logger.addHandler(handler)
def process_payment(amount, debit_msisdn, credit_msisdn, description):
"""
Traite un paiement MVola avec une gestion complète des erreurs.
Args:
amount: Montant du paiement
debit_msisdn: Numéro du payeur
credit_msisdn: Numéro du bénéficiaire
description: Description du paiement
Returns:
dict: Résultat de la transaction ou information d'erreur
"""
# Générer une référence unique
from mvola_api.utils import generate_reference
reference = generate_reference(prefix="PAY")
# Initialiser le client
try:
client = MVolaClient(
consumer_key="votre_consumer_key",
consumer_secret="votre_consumer_secret",
partner_name="Nom de votre application",
partner_msisdn="0343500003",
sandbox=True,
logger=logger
)
except MVolaInvalidCredentialsError as e:
logger.error(f"Erreur d'initialisation - identifiants invalides: {e}")
return {"success": False, "message": "Configuration incorrecte du service de paiement"}
except MVolaError as e:
logger.error(f"Erreur d'initialisation: {e}")
return {"success": False, "message": "Impossible d'initialiser le service de paiement"}
# Validation des données
try:
from mvola_api.utils import validate_msisdn
validate_msisdn(debit_msisdn)
validate_msisdn(credit_msisdn)
if amount <= 0:
raise MVolaTransactionValidationError("Le montant doit être positif", field="amount")
except MVolaTransactionValidationError as e:
logger.error(f"Validation échouée: {e}")
if e.field == "amount":
return {"success": False, "message": "Le montant spécifié n'est pas valide"}
else:
return {"success": False, "message": "Le numéro de téléphone fourni n'est pas valide"}
# Initier le paiement avec retry pour les erreurs temporaires
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
transaction_info = client.initiate_payment(
amount=amount,
debit_msisdn=debit_msisdn,
credit_msisdn=credit_msisdn,
reference=reference,
description=description
)
# Transaction initiée avec succès
transaction_id = transaction_info.get('server_correlation_id')
logger.info(f"Transaction initiée avec succès. ID: {transaction_id}")
# Vérification du statut initial
status_info = client.get_transaction_status(
transaction_id=transaction_id,
msisdn=debit_msisdn
)
return {
"success": True,
"transaction_id": transaction_id,
"reference": reference,
"status": status_info.get('status'),
"message": "Transaction initiée avec succès"
}
except (MVolaRequestTimeoutError, MVolaServerError) as e:
# Erreurs temporaires - implémenter retry
retry_count += 1
wait_time = 2 ** retry_count
logger.warning(f"Erreur temporaire: {e}. Tentative {retry_count}/{max_retries} dans {wait_time}s")
if retry_count >= max_retries:
logger.error(f"Échec après {max_retries} tentatives: {e}")
return {"success": False, "message": "Le service de paiement est temporairement indisponible"}
time.sleep(wait_time)
except MVolaTokenExpiredError as e:
# Token expiré - rafraîchir et réessayer
logger.warning(f"Token expiré: {e}")
try:
client.refresh_token()
# Continuer la boucle pour réessayer
except MVolaError as e:
logger.error(f"Erreur lors du rafraîchissement du token: {e}")
return {"success": False, "message": "Erreur d'authentification avec le service de paiement"}
except MVolaTransactionValidationError as e:
# Erreur de validation - pas de retry
logger.error(f"Validation échouée: {e}")
if e.field == "amount":
return {"success": False, "message": "Le montant spécifié n'est pas valide"}
elif e.field in ["debit_msisdn", "credit_msisdn"]:
return {"success": False, "message": "Le numéro de téléphone fourni n'est pas valide"}
else:
return {"success": False, "message": "Certaines informations de paiement ne sont pas valides"}
except MVolaConnectionError as e:
# Erreur de connexion
logger.error(f"Erreur de connexion: {e}")
return {"success": False, "message": "Problème de connexion au service MVola"}
except MVolaError as e:
# Autres erreurs MVola
logger.error(f"Erreur MVola: {e}")
return {"success": False, "message": "Une erreur s'est produite lors du traitement de votre paiement"}
except Exception as e:
# Erreur inattendue
logger.error(f"Erreur inattendue: {e}", exc_info=True)
return {"success": False, "message": "Une erreur inattendue s'est produite"}
# Ne devrait jamais atteindre ce point à cause des returns dans la boucle
return {"success": False, "message": "Erreur inattendue lors du traitement du paiement"}
# Exemple d'utilisation
result = process_payment(
amount=1000,
debit_msisdn="0343500003",
credit_msisdn="0343500004",
description="Paiement test"
)
if result["success"]:
print(f"Paiement en cours: {result['transaction_id']}")
print(f"Statut: {result['status']}")
else:
print(f"Erreur: {result['message']}")
Voir aussi¶
- Référence des exceptions - Documentation technique détaillée de toutes les exceptions
- Guide d'authentification - Comment gérer l'authentification
- Guide des transactions - Comment effectuer des transactions
- Exemples d'utilisation basique - Exemples simples d'utilisation de la bibliothèque
Prochaines étapes¶
- Consultez le guide des transactions pour en savoir plus sur l'initiation des paiements
- Explorez les exemples d'intégration web pour voir comment gérer les erreurs dans un contexte d'application web