Paiements
Statut pending bloqué, échec sans motif, double débit ou erreur 404 sur un identifiant valide.
Sept symptômes couvrent presque toutes les questions liées aux paiements. Repérez le vôtre et lisez la cause avant la solution. Trois d'entre eux proviennent de la même incompréhension.
Le paiement reste pending sans évolution
Un paiement Mobile Money attend une personne. Wajub a interrogé l'opérateur, qui a envoyé une demande
sur un téléphone. Tant que personne ne saisit son code PIN, aucun résultat n'est disponible.
pending n'est pas un état bloqué, mais un état d'attente.
Effectuez les vérifications suivantes dans cet ordre.
| Vérification | Méthode |
|---|---|
| Le payeur a-t-il ouvert la page ? | authorization_url est à usage unique et expire avec le paiement |
| La demande est-elle arrivée ? | L'opérateur l'envoie, pas Wajub. La page hébergée affiche le code USSD en solution de repli |
| Le paiement est-il simplement trop récent ? | En période de pointe, les opérateurs peuvent mettre une minute à envoyer la demande |
Le paiement ne reste pas indéfiniment pending. Il expire automatiquement et passe à expired.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"currency": "XAF",
"email": "buyer@example.com",
"expires": { "in": 30 }
}'Le champ imbriqué est expires.in et sa valeur s'exprime en minutes, de 5 à 43200, soit 30 jours.
La valeur par défaut est 1440. Écrire expires_in au premier niveau ne produit aucun effet. La
valeur est ignorée et le délai reste fixé à 24 heures.
Le paiement a échoué sans motif visible
L'objet contient reason, un code stable que votre programme peut traiter. Le message lisible qui
l'accompagne provient du prestataire et peut changer sans préavis.
curl https://api.wajub.com/payments/trx_test_CSUGajfv9xh0XQ5wu2lx \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
| jq '.transaction | { status, reason, channel, amount }'Motifs d'échec répertorie chaque code et précise ceux qu'une nouvelle
tentative peut résoudre. En résumé, le payeur doit corriger insufficient_funds, wrong_pin et
authorization_timeout. channel_unavailable et operator_declined justifient une nouvelle
tentative. invalid_number et fraud_blocked échoueront toujours tant que la situation ne change pas.
Mon appel a expiré et j'ignore si le paiement existe
Cette situation est dangereuse, car les deux résultats sont possibles et un seul permet d'agir sans risque. Par défaut, le SDK abandonne après 30 secondes et lève une erreur de connexion. Cette erreur n'indique pas ce que le serveur a effectué.
Ne créez pas un second paiement pour le vérifier. Renvoyez la même requête avec la même
Idempotency-Key. Wajub renvoie le paiement initial s'il existe ou le crée dans le cas contraire.
const payment = await wajub.payments.create(params, {
idempotencyKey: `ORDER-${order.id}`,
});Sans cette clé, la nouvelle tentative provoque un second débit. Idempotence explique comment construire une clé qui survit au redémarrage de votre processus.
Le client a été débité deux fois
Ce problème provient presque toujours de l'une de deux causes.
La première est une nouvelle tentative sans clé d'idempotence, présentée ci-dessus. La seconde vient
de l'idée que reference évite les doublons. Ce n'est pas le cas. reference est une chaîne libre
sans règle d'unicité. Envoyer deux fois la même valeur crée deux paiements qui débitent tous les deux.
Si le problème s'est déjà produit, remboursez le doublon au lieu de l'annuler. Un paiement
succeeded ne peut plus être annulé, seulement remboursé. Consultez Remboursements.
GET /payments/{something} renvoie 404 pour mon identifiant
Il existe trois causes, de la plus fréquente à la plus rare.
Vous avez transmis votre propre référence. L'endpoint accepte uniquement l'uid Wajub. Un
paiement créé avec "reference": "ORDER-4172" n'est pas accessible depuis
/payments/ORDER-4172 et répond avec 404 Payment Not Found. Enregistrez le champ id de la
réponse de création avec votre commande, puis utilisez-le pour la recherche.
id permet de retrouver le paiement. reference vous appartient et sert à vos propres recherches.
Vous utilisez le mauvais environnement. Une clé de la sandbox ne voit aucun paiement live, et
inversement. Les bases sont distinctes. La réponse est donc 404, pas une erreur d'autorisation. Le
préfixe test_ de l'identifiant indique l'environnement concerné.
Le paiement appartient à une autre équipe. Les identifiants ne passent pas d'une équipe à
l'autre. La réponse reste volontairement 404 plutôt que 403.
Le montant est refusé avec une réponse 422
Trois règles s'appliquent. Les utilisateurs provenant d'une autre plateforme rencontrent souvent la première.
Les montants utilisent les unités principales. 5000 signifie cinq mille francs, pas cinquante.
Aucun centime ne doit être converti. XAF et XOF ne possèdent aucune sous-unité.
Chaque devise possède des limites. Le serveur les applique et la réponse 422 indique le champ
concerné. Lisez errors.amount au lieu de deviner. Pour XAF et XOF, le minimum est faible et le
maximum assez élevé. Vous les rencontrerez généralement après avoir envoyé une valeur dans la
mauvaise unité.
Le Mobile Money possède son propre plafond sans refuser le paiement. Au-dessus de 500 000 XAF ou
XOF, la page hébergée encaisse le montant par tranches plutôt qu'en un seul débit. Le paiement reste
dans partial tant qu'une partie seulement est encaissée. Il passe à succeeded après la dernière
tranche. Considérez partial comme « pas encore payé », jamais comme un signal de livraison partielle.
Tout fonctionne dans la sandbox, mais rien en live
Deux causes sont possibles.
Vos clés live peuvent exister alors que votre compte n'est pas encore activé. Les paiements live exigent la validation du KYC. Passer en live contient la checklist.
Vous utilisez peut-être aussi des numéros de test de la sandbox auprès de vrais opérateurs. Dans la
sandbox, les six derniers chiffres du numéro déterminent le résultat. En live, ils identifient
une personne. +237670000002 provoque un échec dans la sandbox, mais appartient à quelqu'un en
production.
| Suffixe de la sandbox | Résultat |
|---|---|
000000 | Réussite |
000001 | Échec avec insufficient_funds |
000002 | Échec |
000003 | Délai expiré |
000004 | Annulé par le payeur |
000009 | Paiement réussi, mais tous ses remboursements échouent |
Pages associées
- Motifs d'échecTous les codes de motif et les cas où une nouvelle tentative peut réussir.
- IdempotenceLa clé qui sécurise une nouvelle tentative après l'expiration d'un délai.
- Mode testLes numéros de test, les résultats simulés et les limites de la sandbox.
- Accepter un paiement, guide completLe cycle de vie de la commande dans lequel apparaissent ces symptômes.