Workflows de pay-in
OTP, redirection, et pourquoi le 422 est le chemin nominal.
Le corridor payant n'est connu qu'au pay-in
GET /v1/corridors/available renvoie un workflowType par couple (opérateur,
devise). C'est un indice d'affichage, pas le contrat. Le corridor qui
encaissera réellement est résolu au moment du pay-in, à partir du numéro complet
et du montant — il peut différer de celui que la découverte a suggéré.
N'écrivez donc pas votre logique « faut-il un OTP ? » à partir du
workflowType de la découverte. Écrivez-la à partir de la réponse du pay-in —
ou, en amont, de GET /v1/pay-in/preview (voir Montants),
qui résout le même dispatch MSISDN sans créer de transaction.
Le protocole canonique
- Postez
POST /v1/pay-insansotpniredirectUrls. - Si vous recevez
200, la demande est acceptée : passez à l'attente du webhook. - Si vous recevez
422, lisezstatusetdata.workflow, obtenez l'élément manquant auprès du payeur, et re-postez avec le mêmeorderId.
Le point 3 est sûr, et c'est la propriété qui rend ce protocole utilisable :
sur un 422, aucune transaction n'a été créée. Le refus intervient avant
toute écriture et avant tout appel au PSP. Rejouer à l'identique n'expose à
aucun doublon.
Ne confondez pas les deux codes qui ressemblent à « recommencez » :
| Code | Ce qui s'est passé | Ce qu'il faut faire |
|---|---|---|
422 | Rien n'a été créé | Compléter et rejouer avec le même orderId |
409 | La transaction existe déjà | Ne rien rejouer, ne surtout pas changer d'orderId |
OTP_REQUIRED
Le corridor résolu est en workflow pre_authorized : il attend un code que le
payeur génère lui-même sur son combiné, typiquement via un code USSD propre
à l'opérateur. Ce n'est pas un code qu'az54 envoie.
La marche à suivre à afficher au payeur est dans le champ instructions de
l'opérateur, sur GET /v1/corridors/available. Ce champ est facultatif et
parfois vide : prévoyez un repli.
otp n'a aucun format garanti — ni longueur, ni jeu de caractères. Ne le
validez pas côté client, transmettez-le tel quel.
REDIRECT_URLS_REQUIRED
Le corridor résolu est en workflow redirect_url : le payeur doit être renvoyé
vers une page hébergée par le PSP. Fournissez redirectUrls.success et
redirectUrls.failure. Seuls les schémas http:// et https:// sont acceptés.
Ce sont des URLs de retour de navigateur, pas des notifications : ne les traitez jamais comme la preuve d'un paiement. Un payeur peut fermer l'onglet avant la redirection, ou l'atteindre sans que le paiement soit acquis. Seul le webhook fait foi.
L'URL de paiement n'est pas dans la réponse
La réponse 200 de POST /v1/pay-in ne contient jamais d'authorizationUrl.
Pour un corridor en workflow redirect_url, l'URL vers laquelle envoyer le
payeur est livrée hors-bande, par le webhook sortant.
Conséquence : sans webhookUrl et sans secret de webhook actif, un pay-in
sur un corridor redirect_url ne peut pas aboutir — vous n'obtiendrez jamais
l'URL à présenter.
operatorCode
Ce champ sert à choisir Wave, et à rien d'autre.
Wave n'est pas un opérateur télécom : c'est un service de mobile money qui se superpose aux opérateurs des pays où il est actif. En Côte d'Ivoire, un même abonné peut détenir un compte Orange Money et un compte Wave sur le même numéro, et choisit avec lequel il paie. Le préfixe du numéro identifie le telco ; il ne dit rien du rail à emprunter. Pour tous les autres opérateurs, à l'inverse, le préfixe suffit : il n'y a rien à désambiguïser.
D'où le comportement :
wave, en minuscules — sensible à la casse — force le rail Wave quel que soit le préfixe du numéro. Elle exigeredirectUrls.- Toute autre valeur est ignorée en silence.
orange_ci,ORANGE_CI,Wave, une chaîne vide : l'opérateur est déduit du préfixe du numéro comme si le champ était absent. Aucune erreur n'est levée.
Envoyez-le donc uniquement quand votre payeur a explicitement choisi Wave. Ne construisez pas d'autre routage dessus : un code d'opérateur telco n'a aucun effet aujourd'hui.
