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.- Vous appelez
POST /v1/collect. - AshTech Pay renvoie
202etstatus: "pending". - Le client reçoit une demande sur son téléphone et la valide avec son code secret opérateur.
- Votre serveur reçoit le webhook final, ou vérifie périodiquement
GET /v1/transaction/:id?user_id=VOTRE_USER_ID.
2. Wave et autres redirections
Pour Wave, la réponse de collecte contient une URL de validation :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 :reference retournée. Après réception du SMS, relancez la même collecte avec le code OTP et cette référence :
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 :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 :- Node.js
- Python
- cURL
- PHP / Laravel
/v1/countries. Le champ reference est votre référence marchand et doit rester unique pour chaque commande.
Exemple USSD Push : Cameroun
202, status: "pending". Le client valide ensuite la demande reçue sur son téléphone.
Exemple Wave : Côte d’Ivoire
202 contient flow: "wave" et wave_url. Ouvrez cette URL pour que le client confirme le paiement.
Exemple OTP Orange : première requête
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 ajoutezotp. Si la première réponse contenait reference, envoyez exactement cette valeur :
- Node.js
- Python
- cURL
- PHP / Laravel
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/countriespour les pays et opérateurs actifs. - N’associez pas vous-même un pays à un flux fixe.
- N’affichez pas
successaprès la réponse initiale202. - 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_IDpour confirmer le résultat final.

