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

  1. Postez POST /v1/pay-in sans otp ni redirectUrls.
  2. Si vous recevez 200, la demande est acceptée : passez à l'attente du webhook.
  3. Si vous recevez 422, lisez status et data.workflow, obtenez l'élément manquant auprès du payeur, et re-postez avec le même orderId.

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 » :

CodeCe qui s'est passéCe qu'il faut faire
422Rien n'a été crééCompléter et rejouer avec le même orderId
409La 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 exige redirectUrls.
  • 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.

On this page