Paiements
Ce guide couvre toutes les opérations liées aux paiements : initiation, vérification de statut, et gestion des webhooks.
Vue d’ensemble
Le processus de paiement Faso Arzeka se déroule en plusieurs étapes :
Initier le paiement : Créer une transaction et obtenir une URL de paiement
Rediriger l’utilisateur : L’utilisateur est redirigé vers la passerelle de paiement
Paiement : L’utilisateur effectue le paiement via Mobile Money
Notification : Arzeka envoie une notification à votre webhook (optionnel)
Vérification : Vous vérifiez le statut du paiement
Initier un paiement
Deux méthodes pour initier un paiement
Méthode 1 : Fonction de convenance
from fasoarzeka import initiate_payment
response = initiate_payment({
"amount": 1000,
"merchant_id": "MERCHANT_123",
"additional_info": {
"first_name": "Jean",
"last_name": "Dupont",
"mobile": "22670123456"
},
"mapped_order_id": "ORDER-2026-001",
"hash_secret": "votre_secret",
"link_for_update_status": "https://exemple.com/webhook",
"link_back_to_calling_website": "https://exemple.com/retour"
})
Méthode 2 : Méthode de classe
from fasoarzeka import ArzekaPayment
with ArzekaPayment() as client:
client.authenticate("username", "password")
response = client.initiate_payment(
amount=1000,
merchant_id="MERCHANT_123",
additional_info={
"first_name": "Jean",
"last_name": "Dupont",
"mobile": "22670123456"
},
mapped_order_id="ORDER-2026-001",
hash_secret="votre_secret",
link_for_update_status="https://exemple.com/webhook",
link_back_to_calling_website="https://exemple.com/retour"
)
Paramètres requis
Paramètre |
Type |
Description |
|---|---|---|
|
|
Montant en FCFA (minimum 100, maximum selon votre contrat) |
|
|
Votre identifiant marchand unique |
|
|
Informations du client (first_name, last_name, mobile) |
|
|
Votre clé secrète pour la génération de hash |
|
|
URL de votre webhook pour recevoir les notifications |
|
|
URL de retour après le paiement |
Paramètres optionnels
Paramètre |
Type |
Description |
|---|---|---|
|
|
ID unique de votre commande (généré automatiquement si absent) |
|
|
Description de la commande |
Réponse de l’API
Un dictionnaire contenant :
{
"mappedOrderId": "ORDER-2026-001",
"url": "https://pwg.fasoarzeka.com/payment/abc123",
"qrcode": "data:image/png;base64,iVBORw0KGgo...",
"status": "PENDING"
}
Exemple complet
from fasoarzeka import ArzekaPayment
import uuid
with ArzekaPayment() as client:
# Authentification
client.authenticate("username", "password")
# Générer un ID de commande unique
order_id = f"ORDER-{uuid.uuid4().hex[:10]}"
# Initier le paiement
response = client.initiate_payment(
amount=5000, # 5000 FCFA
merchant_id="MERCHANT_123",
additional_info={
"first_name": "Marie",
"last_name": "Kaboré",
"mobile": "22670123456",
"email": "marie@example.com" # Optionnel
},
mapped_order_id=order_id,
order_description="Achat de produits",
hash_secret="votre_hash_secret",
link_for_update_status="https://monsite.com/api/webhook",
link_back_to_calling_website="https://monsite.com/success"
)
# Afficher l'URL de paiement
print(f"Redirigez l'utilisateur vers : {response['url']}")
# Stocker l'order_id dans votre base de données
# save_to_database(order_id, response)
Vérifier un paiement
Après avoir initié un paiement, vous pouvez vérifier son statut.
Deux méthodes pour vérifier
Méthode 1 : Fonction de convenance
from fasoarzeka import check_payment
status = check_payment("ORDER-2026-001")
print(f"Statut : {status['status']}")
Méthode 2 : Méthode de classe
from fasoarzeka import ArzekaPayment
with ArzekaPayment() as client:
client.authenticate("username", "password")
status = client.check_payment("ORDER-2026-001")
Paramètres
Paramètre |
Type |
Description |
|---|---|---|
|
|
L’ID de commande retourné lors de l’initiation |
Réponse de l’API
{
"mappedOrderId": "ORDER-2026-001",
"status": "COMPLETED", # ou PENDING, FAILED, CANCELLED
"amount": 1000,
"orderDate": "2026-02-23T10:30:00",
"paymentDate": "2026-02-23T10:35:00",
"transactionId": "TX123456789"
}
Statuts possibles
Statut |
Description |
|---|---|
|
Paiement en attente, l’utilisateur n’a pas encore payé |
|
Paiement réussi et confirmé |
|
Paiement échoué (fonds insuffisants, annulation, etc.) |
|
Paiement annulé par l’utilisateur ou le système |
Exemple de vérification périodique
import time
from fasoarzeka import check_payment
def wait_for_payment(order_id, max_attempts=20, delay=5):
"""Attendre qu'un paiement soit complété"""
for attempt in range(max_attempts):
status = check_payment(order_id)
if status['status'] == 'COMPLETED':
print("✅ Paiement réussi !")
return status
elif status['status'] == 'FAILED':
print("❌ Paiement échoué")
return status
elif status['status'] == 'CANCELLED':
print("⚠️ Paiement annulé")
return status
else:
print(f"⏳ En attente... (tentative {attempt + 1}/{max_attempts})")
time.sleep(delay)
print("⏱️ Timeout : Paiement toujours en attente")
return None
# Utilisation
result = wait_for_payment("ORDER-2026-001")
Webhooks
Les webhooks permettent de recevoir des notifications en temps réel lorsque le statut d’un paiement change.
Configuration du webhook
Lors de l’initiation du paiement, spécifiez l’URL de votre webhook :
response = client.initiate_payment(
# ... autres paramètres
link_for_update_status="https://monsite.com/api/arzeka/webhook"
)
Format de la notification
Arzeka envoie une requête POST à votre URL avec ce format :
{
"mappedOrderId": "ORDER-2026-001",
"status": "COMPLETED",
"amount": 1000,
"transactionId": "TX123456789",
"paymentDate": "2026-02-23T10:35:00"
}
Exemple d’implémentation Flask
from flask import Flask, request, jsonify
from fasoarzeka import check_payment
app = Flask(__name__)
@app.route('/api/arzeka/webhook', methods=['POST'])
def arzeka_webhook():
# Récupérer les données
data = request.json
order_id = data.get('mappedOrderId')
status = data.get('status')
# Vérifier le statut auprès d'Arzeka (sécurité)
verified_status = check_payment(order_id)
if verified_status['status'] == 'COMPLETED':
# Mettre à jour votre base de données
update_order_status(order_id, 'PAID')
# Envoyer un email de confirmation
send_confirmation_email(order_id)
print(f"✅ Paiement {order_id} confirmé")
# Retourner une réponse 200 OK
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=5000)
Exemple d’implémentation Django
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from fasoarzeka import check_payment
import json
@csrf_exempt
@require_POST
def arzeka_webhook(request):
# Récupérer les données
data = json.loads(request.body)
order_id = data.get('mappedOrderId')
# Vérifier le statut
verified_status = check_payment(order_id)
if verified_status['status'] == 'COMPLETED':
# Mettre à jour la commande
order = Order.objects.get(order_id=order_id)
order.status = 'PAID'
order.save()
return JsonResponse({'status': 'received'})
Sécurité des webhooks
Avertissement
Important : Toujours vérifier le statut auprès d’Arzeka avant de valider la commande !
Bonnes pratiques :
Vérifier le statut : Appelez
check_payment()pour confirmerValider le hash : Vérifiez le hash si fourni par Arzeka
Idempotence : Gérer les notifications en double
Retourner 200 OK : Retourner rapidement une réponse HTTP 200
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.json
order_id = data.get('mappedOrderId')
# Vérifier si déjà traité (idempotence)
if is_already_processed(order_id):
return jsonify({'status': 'already_processed'}), 200
# Vérifier le statut auprès d'Arzeka
verified = check_payment(order_id)
if verified['status'] == 'COMPLETED':
# Traiter le paiement
process_payment(order_id)
mark_as_processed(order_id)
return jsonify({'status': 'received'}), 200
Gestion des erreurs
Exception lors de l’initiation
from fasoarzeka import (
ArzekaPayment,
ArzekaValidationError,
ArzekaAPIError
)
with ArzekaPayment() as client:
client.authenticate("username", "password")
try:
response = client.initiate_payment(
amount=1000,
merchant_id="MERCHANT_123",
# ... paramètres
)
except ArzekaValidationError as e:
print(f"❌ Données invalides : {e}")
except ArzekaAPIError as e:
print(f"❌ Erreur API : {e}")
print(f"Code : {e.status_code}")
print(f"Détails : {e.response_data}")
Exception lors de la vérification
from fasoarzeka import check_payment, ArzekaAPIError
try:
status = check_payment("ORDER-2026-001")
except ArzekaAPIError as e:
if e.status_code == 404:
print("❌ Commande introuvable")
else:
print(f"❌ Erreur : {e}")
Bonnes pratiques
IDs uniques
Toujours générer des IDs de commande uniques :
import uuid from datetime import datetime # Option 1 : UUID order_id = f"ORDER-{uuid.uuid4().hex[:10]}" # Option 2 : Timestamp + aléatoire order_id = f"T{datetime.now().strftime('%Y%m%d%H%M%S')}"
Timeout approprié
Configurez un timeout adapté :
client = ArzekaPayment(timeout=30) # 30 secondes
Retry avec backoff
La bibliothèque gère automatiquement les retries, mais vous pouvez configurer :
client = ArzekaPayment(max_retries=3, retry_delay=2)
Logging
Activez le logging pour déboguer :
import logging logging.basicConfig(level=logging.DEBUG)
Validation des données
Validez les données avant de les envoyer :
from fasoarzeka.utils import validate_phone_number if not validate_phone_number(mobile): raise ValueError("Numéro de téléphone invalide")
Prochaines étapes
Réauthentification automatique : Réauthentification automatique
Gestion des erreurs : Gestion avancée des erreurs
Bonnes pratiques : Bonnes pratiques et recommandations
Référence API : Référence complète de l’API