Passer au contenu principal
Chaque appel à POST /v1/payments peut spécifier un champ scenario qui pilote de façon déterministe le résultat de la simulation : statut final, latence, message d’erreur. C’est le levier principal pour tester vos chemins d’échec.

Tableau de référence

La latence est tirée aléatoirement dans la fourchette indiquée à chaque appel — pour reproduire les variations naturelles d’un opérateur réel.
Passez un scenario explicite pour forcer un résultat déterministe (idéal pour les tests / la CI). Si vous l’omettez, le résultat dépend de votre registre de clients de test — voir la section ci-dessous.

Sans scénario : le registre SIM (clients de test)

Si vous omettez le champ scenario, SandPay se comporte comme un opérateur réel et utilise vos clients de test (/clients dans le tableau de bord) comme un registre SIM :
Créez au moins un client de test dans /clients avant d’envoyer un paiement sans scénario, sinon tous les numéros renvoient UNKNOWN_MSISDN. Pour un résultat déterministe, passez plutôt un scenario explicite — il l’emporte toujours.
Comportement configurable par environnement : la politique unknownMsisdnPolicy vaut reject par défaut (numéro inconnu → UNKNOWN_MSISDN). En mode passthrough, un numéro inconnu est transmis à l’adaptateur opérateur (ancien comportement). Les cas bloqué / solde insuffisant restent toujours définitifs.

Exemple — déclencher pin_invalid

Réponse :

Statuts et finalité

Les 11 statuts canoniques sont stables — votre switch peut les compter. PENDING est le seul statut non-final : il indique qu’une transaction est en cours de traitement (utile sur les flots asynchrones). Tous les autres statuts sont définitifs et déclenchent le webhook payment.completed.

Hors-scénario : description

Le champ description (optionnel) est purement informatif — il est conservé dans la transaction et renvoyé dans le payload du webhook, mais n’influence pas le résultat.

Raw operator response (raw)

Chaque réponse de paiement (POST /v1/payments, GET /v1/payments/{id}, items de GET /v1/payments, et webhook payment.completed) contient un champ raw avec la shape native de l’opérateur correspondante au scénario joué. Cette shape est synthétisée avec _simulated: true au top-level — elle reproduit fidèlement la structure native que renvoie chaque opérateur. Exemple MTN — scenario: "success" :
Exemple Moov — scenario: "low_balance" :
Exemple Orange — scenario: "success" (notez la faute d’orthographe SUCCESSFULL reproduite fidèlement de l’API réelle) :

Voir aussi