Checkout Mobile Money
Ce qui se passe entre l'invite et la confirmation, et comment adapter votre intégration.
Une machine décide d'un paiement par carte en environ deux secondes. Un paiement Mobile Money dépend d'une personne qui tient un téléphone. Elle doit le déverrouiller, lire une invite et saisir un code PIN. Toute la particularité de cette intégration vient de ce constat.
Ce guide traite de l'attente, des échecs et des nouvelles tentatives. Pour les appels d'API eux-mêmes, le Démarrage rapide Paiements est plus court et les explique correctement.
Déroulement réel
Quatre acteurs interviennent entre votre requête et l'argent. Seul le premier vous appartient.
Les trois étapes intermédiaires peuvent prendre de dix secondes à plusieurs minutes. Vous n'en contrôlez aucune. Votre interface doit le présenter clairement au lieu de rester bloquée sur un indicateur de chargement.
Le numéro de téléphone détermine l'opérateur
Vous n'indiquez pas à Wajub quel opérateur doit effectuer le débit. Vous envoyez le numéro du client au format E.164. En production, Wajub identifie l'opérateur grâce à la base de données de libphonenumber. La portabilité et les nouvelles plages de numéros sont donc prises en charge pour vous.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Idempotency-Key: order-9041" \
-H "Content-Type: application/json" \
-d '{
"amount": 15000,
"currency": "XAF",
"customer": {
"name": "Amina Nkosi",
"phone": "+237670000000",
"email": "amina@example.com"
},
"description": "Order #9041",
"reference": "order-9041",
"callback": "https://shop.example.com/orders/9041/return"
}'La réponse contient authorization_url. Redirigez le client vers cette URL. Wajub affiche le choix de l'opérateur, les instructions de l'invite et l'écran de résultat en anglais ou en français selon votre paramètre régional.
Ne créez pas votre propre table de préfixes
Vous pourriez être tenté d'associer +2376… à MTN dans votre code pour afficher rapidement un logo. Ces préfixes sont des valeurs artificielles de la sandbox. Ils deviennent incorrects en production dès qu'une plage est réattribuée ou qu'un client transfère son numéro. Envoyez le numéro, puis lisez la valeur channel du paiement. La page Formats de numéros de téléphone présente la règle complète.
Les montants possèdent un plafond plus bas que prévu
Mobile Money limite un débit à 500 000 XAF, et au même montant en XOF. L'API accepte toutefois les paiements jusqu'à 2 000 000 XAF. Ces deux plafonds diffèrent. La page hébergée gère cet écart en encaissant un paiement important en plusieurs tranches successives au lieu de le refuser.
Pendant ce processus, le paiement possède le statut partial, que votre code recevra réellement.
| Montant | Expérience du client |
|---|---|
| Jusqu'à 500 000 XAF | Une invite, un code PIN |
| Au-dessus de 500 000 XAF | Plusieurs invites successives, avec le statut partial entre les tranches |
| Au-dessus de 2 000 000 XAF | Erreur 422 à la création, avec le plafond dans errors.amount |
Considérez partial comme un paiement toujours en cours. Ce statut ne correspond ni à une réussite ni à un échec. Seul succeeded doit déclencher la livraison d'une commande.
Votre page pendant la confirmation
Le client quitte votre site le temps de trouver son téléphone. À son retour, le paiement possède très souvent encore le statut processing.
Ne présentez pas ce statut comme une erreur et n'interrogez pas l'API en boucle serrée. Effectuez une seule requête au chargement de la page, affichez honnêtement l'état et laissez le webhook gérer la suite. La route de retour est détaillée dans Accepter un paiement, guide complet. Elle doit gérer les trois cas suivants.
| Statut au retour | Message à afficher |
|---|---|
succeeded | Confirmation et prochaine étape |
pending, processing, partial | L'invite a été envoyée, la confirmation fonctionne encore et vous enverrez un e-mail |
failed, expired, cancelled | Aucun débit n'a été effectué, avec un bouton pour réessayer |
La page d'attente est souvent mal conçue. Elle doit expliquer la réalité : l'invite a été envoyée, sa validation sur le téléphone fonctionne encore et la commande se mettra à jour automatiquement. Envoyez ensuite la confirmation par e-mail à la réception du webhook afin que personne ne doive rester sur cette page.
Les causes d'échec et le message à afficher
Un échec provient généralement d'une personne ou du réseau, pas d'un bug. Le paiement contient une valeur failure_reason que vous pouvez enregistrer. Cette raison désigne un problème sur lequel une personne peut agir.
| Problème rencontré | Message à afficher au client |
|---|---|
| Solde insuffisant dans le portefeuille | Rechargez votre portefeuille et réessayez, la commande est toujours disponible |
| Invite refusée | Aucun débit n'a été effectué, réessayez lorsque vous êtes prêt |
| Délai de l'invite dépassé | L'opérateur n'a pas reçu de réponse à temps, réessayez |
| Numéro incorrect ou non pris en charge | Vérifiez le numéro au format international complet |
| Opérateur indisponible | Proposez un autre opérateur au lieu d'une nouvelle tentative avec le même |
`failure_reason` est un diagnostic, pas une énumération
Ses valeurs proviennent du prestataire qui a traité la tentative. De nouvelles valeurs peuvent donc apparaître sans préavis. Basez les branches de votre code sur status. Utilisez failure_reason dans les logs et pour choisir une phrase compréhensible dans une table qui prévoit une valeur par défaut. Consultez Cycle de vie d'un paiement pour en savoir plus.
Une nouvelle tentative crée un nouveau paiement
Vous ne pouvez pas renvoyer une invite pour un paiement existant. Un paiement échoué ou expiré est terminé. Réessayer signifie en créer un autre pour la même commande.
Cette règle entraîne une conséquence importante. Le nouveau paiement exige une nouvelle clé d'idempotence. La réutilisation de l'ancienne clé renvoie l'ancien paiement échoué au lieu d'ouvrir une nouvelle tentative.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Idempotency-Key: order-9041-attempt-2" \
-H "Content-Type: application/json" \
-d '{
"amount": 15000,
"currency": "XAF",
"customer": { "phone": "+237670000000" },
"reference": "order-9041",
"callback": "https://shop.example.com/orders/9041/return"
}'La commande pointe désormais vers le paiement le plus récent. Conservez les anciens identifiants quelque part si vous souhaitez disposer d'un historique complet. Wajub ne relie pas les différentes tentatives d'une même commande.
Prise en charge des frais
Par défaut, les frais sont déduits du montant que vous recevez. Définissez bearer sur customer pour les ajouter au montant. La page hébergée affiche alors clairement le montant, les frais et le total réellement débité.
Le client confirme le total sur son téléphone. Vous devez donc faire ce choix avant l'envoi de l'invite. Il ne peut pas être modifié ensuite.
Tester chaque cas sans opérateur
Dans la sandbox, les six derniers chiffres du numéro déterminent le résultat. Le préfixe sélectionne le pays et l'opérateur, tandis que le suffixe détermine le résultat. Tous les codes PIN sont acceptés.
| Suffixe | Résultat | Webhook reçu |
|---|---|---|
000000 | Le client confirme | payment.succeeded |
000001 | Solde insuffisant dans le portefeuille | payment.failed |
000002 | L'opérateur refuse | payment.failed |
000003 | L'opérateur ne répond pas | payment.failed |
000004 | Le client refuse l'invite | payment.failed |
000009 | Le paiement réussit, mais tous les remboursements échouent | payment.succeeded |
Pour MTN au Cameroun, le préfixe +23767 suivi de 000001 donne +237670000001. Ce numéro reproduit systématiquement un échec pour fonds insuffisants. Tous les préfixes de pays et d'opérateurs figurent dans Scénarios de test.
Retenez le numéro qui se termine par 000009. C'est le seul moyen de tester la gestion d'un échec de remboursement, autrement impossible à déclencher volontairement.
Observez le routage pendant son exécution
Ouvrez Konsole › Event Stream avant de déclencher un paiement de test. La sélection du prestataire, la réponse de l'opérateur et le résultat final apparaissent au fur et à mesure. Une fois le paiement terminé, Routing Log présente les mêmes informations.
Pages associées
- Accepter un paiement, guide completLe cycle de vie de la commande sur lequel repose ce parcours.
- Checkout hébergéToutes les décisions prises automatiquement par la page de paiement.
- Formats de numéros de téléphoneFormat E.164, identification de l'opérateur et réponse renvoyée pour un numéro incorrect.
- Moyens de paiement et canauxCouverture des opérateurs dans chaque pays.
- Cycle de vie d'un paiementChaque statut, dont `partial`, et leurs transitions.
- Scénarios de testChaque numéro, carte et résultat de test dans la sandbox.