API mobile money en Afrique : le guide pour intégrer les paiements
Encaisser et payer par mobile money ne ressemble pas à un paiement par carte. Voici comment fonctionne une intégration solide, de la première requête au passage en production.
Si vous avez déjà intégré le paiement par carte, le mobile money va vous surprendre. Pas de numéro de carte à saisir, pas de formulaire à valider : le client confirme le paiement sur son propre téléphone, dans le menu de son opérateur, parfois quelques secondes plus tard, parfois quelques minutes. Votre intégration doit composer avec ce délai, et avec le fait que chaque pays a ses opérateurs, sa devise et ses habitudes.
Ce guide décrit à quoi ressemble une intégration mobile money digne de la production : les flux, les statuts, les cas limites et les garde-fous. Les exemples utilisent l’API Monerails, mais les principes valent pour tout prestataire que vous envisagez.
Ce qui change par rapport à la carte
Trois différences conditionnent tout le reste.
- Le client valide sur son téléphone. Vous envoyez une demande de paiement ; l’opérateur contacte le client, qui valide avec son code PIN. Certains opérateurs envoient plutôt un code à usage unique par SMS, que le client doit vous communiquer.
- La réponse est asynchrone. Au moment où vous créez le paiement, vous connaissez rarement son issue. L’opérateur répond quand le client agit, ou quand la demande expire.
- Chaque marché est local. Opérateurs, devises, formats de numéro et plafonds changent d’un pays à l’autre. Même deux pays qui partagent une monnaie, comme le Cameroun et le Gabon avec le franc CFA (XAF), n’ont pas les mêmes opérateurs.
Une bonne intégration accepte ces contraintes au lieu de les combattre : elle affiche au client des instructions claires, attend un webhook et ne considère jamais un silence comme un échec.
Encaissements, paiements et reversements
Une API mobile money couvre en général trois mouvements d’argent.
- Les encaissements : un client vous paie depuis son portefeuille. Le montant net, après frais, arrive sur votre solde.
- Les paiements sortants : vous envoyez de l’argent depuis votre solde vers le portefeuille ou le compte bancaire d’un tiers : un fournisseur, un livreur, un salarié, un client que vous remboursez.
- Les reversements : vous transférez votre propre solde vers votre propre compte bancaire ou mobile money.
Chez Monerails, les trois partagent les mêmes soldes et le même registre : chaque mouvement se rapproche depuis une seule liste de transactions. Monerails couvre 22 pays d’Afrique ; au Nigeria, seuls les paiements sortants sont ouverts pour l’instant, l’encaissement arrive. La liste complète figure sur la page Couverture.
Un encaissement, étape par étape
Voici une demande d’encaissement au Cameroun. Les montants sont des entiers dans l’unité mineure de la devise ; pour le franc CFA, c’est le franc lui-même.
curl https://api.monerails.com/v1/collections \
-H "Authorization: Bearer $MONERAIL_KEY" \
-H "Idempotency-Key: commande-42" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"currency": "XAF",
"phone": "237670000999",
"operator": "MTN",
"customer": { "name": "Awa Ndiaye" },
"client_reference": "commande_42"
}'
L’encaissement passe ensuite par un petit nombre de statuts :
| Statut | Signification |
|---|---|
pending | La demande est chez l’opérateur ; le client doit la valider sur son téléphone. |
requires_otp | Le client a reçu un code à usage unique ; renvoyez-le avec authorize. |
processing | L’opérateur traite le paiement. |
succeeded | Payé. Les frais et le net sont connus, et le net est sur votre solde. |
failed / expired | Non payé, ou non validé à temps. Il suffit de recréer l’encaissement. |
La réponse contient aussi un champ next_action qui indique quoi afficher dans votre application : soit un message invitant le client à valider sur son téléphone, avec un code USSD à composer si la notification n’apparaît pas, soit une demande du code reçu. Affichez-le tel quel : un client qui voit des instructions claires abandonne beaucoup moins.
Opérateurs, devises et numéros de téléphone
Trois détails expliquent la plupart des bugs d’intégration.
Les devises partagées
Le franc XAF est utilisé en Afrique centrale, le franc XOF dans huit pays d’Afrique de l’Ouest. La devise seule ne dit donc pas le pays. Envoyez le champ country dès que vous encaissez ou payez hors du pays par défaut de la devise (le Cameroun pour le XAF, le Sénégal pour le XOF).
Les codes opérateurs
Plutôt que de coder en dur une liste d’opérateurs par pays, appelez GET /v1/operators pour une devise, et un pays si besoin, et remplissez votre sélecteur d’opérateur avec la réponse. Mettez-la en cache quelques minutes : les nouveaux opérateurs apparaissent alors dans votre parcours de paiement sans changer une ligne de code.
Les numéros de téléphone
Acceptez les numéros tels que vos clients les tapent, puis normalisez-les. L’API accepte le format international (237670000999, +237 670 00 09 99) et le format local lorsque le pays est connu. Contrôlez la longueur dans votre formulaire pour attraper les fautes de frappe avant l’envoi.
Des webhooks plutôt que des relances
Puisque le résultat arrive plus tard, votre serveur doit être prévenu au bon moment. Déclarez une adresse HTTPS et abonnez-vous aux événements utiles : collection.succeeded, collection.failed, collection.expired, payout.succeeded, payout.failed, etc.
Trois règles rendent un gestionnaire de webhooks fiable :
- Vérifiez la signature. Monerails signe chaque événement en HMAC-SHA256 dans l’en-tête
Monerail-Signature. Calculez la signature sur le corps brut, comparez en temps constant et refusez les horodatages de plus de cinq minutes. - Répondez vite, traitez ensuite. Renvoyez d’abord un code 2xx, puis faites le travail lourd. Un gestionnaire trop lent est relancé.
- Dédoublonnez par identifiant. Un même événement peut arriver plusieurs fois. Traitez chaque
idune seule fois.
Livrez la commande à la réception de collection.succeeded, jamais au retour du client sur votre site. Le guide des webhooks fournit le code de vérification dans huit langages.
Idempotence : ne jamais payer deux fois
Une erreur réseau ne vous dit pas si votre requête est arrivée. Pour un encaissement, une relance à l’aveugle est gênante : le client reçoit deux demandes. Pour un paiement sortant, elle coûte cher : vous risquez de payer deux fois.
La parade : un en-tête Idempotency-Key sur chaque requête qui déplace de l’argent. Utilisez une valeur liée à l’opération dans votre système, par exemple paiement-fact-118. Si la même requête est renvoyée avec la même clé, l’API rend la réponse d’origine au lieu de l’exécuter à nouveau. Deux habitudes complètent le dispositif :
- Une réponse
202signifie que l’opération est en route. Ne la recréez pas : attendez le webhook ou consultez l’objet. - Relancez les erreurs réseau et les réponses
5xxavec la même clé, en espaçant les tentatives. Ne relancez pas une erreur4xxsans avoir corrigé la requête.
Frais et rapprochement
Sur un encaissement, les frais sont déduits de ce que vous recevez : l’objet indique amount, fee et net une fois réussi. Sur un paiement sortant, les frais s’ajoutent : le bénéficiaire reçoit le montant complet. Les opérations échouées ne sont pas facturées ; pour un paiement sortant, le montant et les frais reviennent sur votre solde.
Placez votre numéro de commande ou de facture dans client_reference et le reste du contexte dans metadata. Les deux reviennent sur l’objet et dans chaque événement : le rapprochement devient trivial. Rapprochez une fois par jour depuis la liste des transactions, et rattrapez une éventuelle interruption avec la liste des événements. Les tarifs par pays sont sur la page Tarifs, sans abonnement mensuel.
Du mode test à la production
Construisez tout en mode test. Les clés de test commencent par mr_test_ et ne voient que les données de test ; les clés de production commencent par mr_live_. Le mode test est une copie séparée de votre compte, avec ses propres soldes, événements et webhooks, et il ne déplace jamais d’argent réel.
Avant de passer en production, vérifiez cette liste :
- La vérification de votre entreprise est validée, et votre clé de production n’a que le rôle nécessaire à votre intégration.
- Les webhooks de production sont créés, avec leurs propres secrets, et chaque signature est vérifiée.
- Chaque
POSTqui déplace de l’argent porte uneIdempotency-Key. - Chaque statut final est traité : encaissements échoués ou expirés, paiements sortants échoués.
- Vos tests contrôlent
"livemode": false: une clé mal placée fait échouer vos tests au lieu de déplacer de l’argent.
Quand l’API n’est pas nécessaire
Toutes les entreprises n’ont pas besoin d’une intégration. Si vous vendez par WhatsApp, sur les réseaux sociaux ou sur facture, un lien de paiement vous offre le même encaissement, avec les mêmes frais et les mêmes webhooks, sans écrire de code. Et si votre besoin principal est de payer des personnes, lisez notre guide des paiements de masse.
Quand vous êtes prêt à développer, le démarrage rapide vous mène de votre premier appel d’API à votre premier webhook de test en quelques minutes.
Prêt à encaisser, payer et émettre des cartes ?
Ouvrez un compte en quelques minutes. Le bac à sable est gratuit, sans abonnement.