Skip to main content
Une collecte Mobile Money n’a pas toujours le même parcours. Le flux dépend du pays, de l’opérateur et de la configuration active pour cet opérateur. Ne codez pas le flux à partir du nom de la marque. Chargez GET /v1/countries, utilisez l’opérateur retourné par le catalogue, puis inspectez la réponse de POST /v1/collect. Toutes les collectes et confirmations OTP exigent user_id dans le JSON. Utilisez l’identifiant du profil AshTech Pay associé à la clé Bearer. Les lectures de transaction exigent aussi user_id dans la query string.

Résumé des flux

Dans tous les cas, la transaction reste pending jusqu’à la confirmation du paiement. Ne livrez jamais une commande uniquement parce que la requête initiale a répondu 202.

1. USSD Push

Le flux USSD Push est utilisé par la plupart des opérateurs qui ne demandent pas une saisie OTP dans votre application.
  1. Vous appelez POST /v1/collect.
  2. AshTech Pay renvoie 202 et status: "pending".
  3. Le client reçoit une demande sur son téléphone et la valide avec son code secret opérateur.
  4. Votre serveur reçoit le webhook final, ou vérifie périodiquement GET /v1/transaction/:id?user_id=VOTRE_USER_ID.
Exemple de réponse :
L’application cliente doit afficher un état d’attente et permettre au client de terminer l’autorisation sur son téléphone.

2. Wave et autres redirections

Pour Wave, la réponse de collecte contient une URL de validation :
Ouvrez wave_url dans le navigateur ou dans l’application Wave si votre intégration mobile le permet. Ne remplacez pas cette URL par une URL construite manuellement. Après la décision du client, utilisez le webhook payment.completed ou payment.failed, puis vérifiez le statut côté serveur avant de livrer. Le flux Wave est actuellement détecté notamment pour Wave en Côte d’Ivoire et au Sénégal lorsque l’opérateur est actif dans le catalogue.

3. OTP envoyé par SMS

Selon le parcours configuré, un OTP peut être envoyé par SMS. La première requête ne finalise pas le paiement :
Conservez la valeur reference retournée. Après réception du SMS, relancez la même collecte avec le code OTP et cette référence :
Le champ reference de cette confirmation doit être celui reçu dans la réponse 400 otp_required. Ne générez pas une nouvelle référence pour la confirmation.

4. OTP obtenu par USSD

Pour certains opérateurs Orange, le client doit composer un code USSD pour obtenir son OTP. L’API renvoie le code à utiliser :
Affichez ussd_code directement au client. Après saisie de l’OTP, renvoyez aussi le même reference de session. Certains codes contiennent le montant exact, par exemple pour le Burkina Faso. N’utilisez donc pas une table codée en dur dans votre application. Exemples de familles de flux actuellement configurées : Cette matrice décrit le routage actuellement configuré pour les opérateurs concernés. Le statut actif peut changer. La réponse de GET /v1/countries reste la source de vérité pour votre formulaire.

Exemples cURL

Requête commune

La requête de départ est la même pour un flux USSD Push, Wave ou OTP :
Utilisez la devise et le nom exacts retournés par /v1/countries. Le champ reference est votre référence marchand et doit rester unique pour chaque commande.

Exemple USSD Push : Cameroun

Réponse attendue : 202, status: "pending". Le client valide ensuite la demande reçue sur son téléphone.

Exemple Wave : Côte d’Ivoire

Si le flux est Wave, la réponse 202 contient flow: "wave" et wave_url. Ouvrez cette URL pour que le client confirme le paiement.

Exemple OTP Orange : première requête

La réponse peut être 400 otp_required avec un ussd_code, ou avec une reference si le code est envoyé par SMS. Affichez l’instruction retournée par l’API au client.

Exemple OTP : confirmation

Après réception du code OTP, reprenez les mêmes paramètres et ajoutez otp. Si la première réponse contenait reference, envoyez exactement cette valeur :
Ne remplacez pas la référence de session OTP par votre référence de commande. Une session expirée renvoie 400 otp_expired : recommencez alors une nouvelle collecte sans réutiliser l’ancien OTP. Après avoir affiché le code, demandez au client de saisir le code OTP reçu, puis relancez la collecte avec exactement les mêmes amount, currency, phone, operator et country_code, ainsi que le reference de session renvoyé par otp_required et le champ otp. Le serveur réserve atomiquement la session pendant la confirmation : une seconde confirmation concurrente renvoie 409 otp_confirmation_in_progress. Un OTP explicitement invalide renvoie 400 invalid_otp et peut être réessayé avec la même session. Si le résultat de la confirmation reste incertain, l’API renvoie 202 pending : ne renvoyez pas le code et consultez le statut ou attendez le webhook.

Gestion des réponses et des erreurs

202 pending

Le paiement est accepté par AshTech Pay et attend la confirmation opérateur. Enregistrez transaction_id et reference, puis attendez le webhook ou interrogez le statut.

400 otp_required

Le paiement attend une action du client. Vérifiez si la réponse contient :
  • reference : OTP envoyé par SMS ou session OTP nécessitant une référence ;
  • ussd_code : code à composer pour obtenir l’OTP ;
  • les deux champs selon le parcours.

400 otp_expired

La session OTP a expiré. Recommencez une nouvelle collecte sans réutiliser l’ancien code ou l’ancienne référence.

payment.completed et payment.failed

Traitez ces événements de manière idempotente. Répondez rapidement 2xx, vérifiez la transaction côté serveur et ne créditez ou ne livrez qu’une seule fois.

Bonnes pratiques

  • Utilisez le catalogue /v1/countries pour les pays et opérateurs actifs.
  • N’associez pas vous-même un pays à un flux fixe.
  • N’affichez pas success après la réponse initiale 202.
  • N’exposez jamais votre clé API dans le navigateur.
  • Ne stockez pas les codes OTP plus longtemps que nécessaire.
  • Utilisez le webhook et GET /v1/transaction/:id?user_id=VOTRE_USER_ID pour confirmer le résultat final.