Valsoria Pay Console →
Documentation

Démarrer

IntroductionDémarrageAuthentification

API

PaiementsPage de paiementDécaissementsRelevé de compteWebhooksRéférenceErreurs

Outils

Numéros de testSDK JavaScriptVersions

Numéros de test

La sandbox n'est pas une maquette : un paiement de test traverse la même file, le même ledger et le même webhook qu'un paiement réel. Seul l'opérateur est simulé.

Le scénario est choisi par les QUATRE DERNIERS CHIFFRES du numéro. Tout numéro non listé réussit : le cas nominal ne doit demander aucun effort.

Ils n'ont d'effet qu'avec une clé de test. En production, le numéro est celui du vrai payeur — ou du vrai bénéficiaire.

Le catalogue — encaissements

Le numéro est celui du payeur.

NuméroStatut finalCode d'échecCe qui se passe
…0000succeededEncaissement réussi.
…0001faileddeclined_by_payerLe payeur refuse la demande sur son téléphone.
…0002failedinsufficient_fundsLe compte du payeur n'est pas assez approvisionné.
…0003succeededL'opérateur ne répond pas. L'issue est INCERTAINE : l'appel n'est jamais rejoué, une re-vérification tranche — ici en faveur du succès. C'est le scénario à éprouver en priorité.
…0004succeededRéponse 200 au corps inexploitable. Issue incertaine également, résolue par re-vérification.
…0005failedoperator_unavailableL'opérateur est momentanément hors service.
…0006succeededLe paiement reste pending le temps que le payeur valide, puis réussit.
…0007failedlimit_exceededLe montant dépasse le plafond du payeur.
…0008failedinvalid_recipientNuméro inconnu chez cet opérateur.
…0009faileddeclined_by_payerLe paiement reste pending, puis échoue faute de validation à temps.

Les mêmes numéros pilotent les décaissements

Le numéro est alors celui du bénéficiaire. Statuts et codes d'échec sont identiques — le connecteur simulé emprunte le même chemin pour l'entrée et pour la sortie.

NuméroStatut finalCode d'échecCe qui se passe
…0000succeededDécaissement réussi : le bénéficiaire reçoit les fonds.
…0001faileddeclined_by_payerLe compte du bénéficiaire refuse le versement. Le code reste declined_by_payer — il est écrit du point de vue de l'encaissement.
…0002failedinsufficient_fundsLe flotteur de l'opérateur est à sec. Ce n'est pas votre solde : une provision insuffisante chez vous est refusée bien plus tôt, en 409.
…0003succeededL'opérateur ne répond pas. Issue INCERTAINE — l'envoi est peut-être parti.
…0004succeededRéponse inexploitable. Issue incertaine également.
…0005failedoperator_unavailableL'opérateur est hors service ; rien n'est parti.
…0006succeededL'envoi reste pending, puis aboutit.
…0007failedlimit_exceededLe versement dépasse un plafond de l'opérateur. Distinct de VOS plafonds, qui mettent la demande en attente de validation sans jamais l'envoyer.
…0008failedinvalid_recipientNuméro inconnu chez cet opérateur : le bénéficiaire n'existe pas.
…0009faileddeclined_by_payerL'envoi reste pending, puis échoue.

Deux codes sont écrits du point de vue de l'encaissement et se lisent de travers sur un décaissement. Nous ne les renommons pas : votre intégration les traite peut-être déjà, et changer un code stable coûte plus cher que l'expliquer.

Un échec de décaissement vous rend l'argent, commission comprise — l'événement payout.failed porte reverted: true. Éprouvez-le : c'est le chemin qu'une intégration oublie le plus souvent de traiter.

Le scénario qu'il faut vraiment éprouver

…0003 et …0004 produisent une issue incertaine : l'appel est parti, aucune réponse exploitable n'est revenue, et l'argent a peut-être bougé.

Nous ne rejouons jamais un appel dans cet état — un rejeu débiterait possiblement deux fois. Le paiement reste en cours, une re-vérification est programmée, et c'est elle qui tranche.

Pour vous, cela veut dire une chose : un paiement peut rester pending plus longtemps que d'habitude, puis conclure. Si votre intégration considère qu'un paiement non conclu en dix secondes a échoué, elle se trompera — et sur ces deux numéros, elle se trompera en votre défaveur.

Essayer

curl -X POST "https://qkmvexkljdcfarulydao.supabase.co/functions/v1/v1-payments" \
  -H "Authorization: Bearer $VALSORIA_CLE" \
  -H "Idempotency-Key: essai-refus-1" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 5000, "currency": "XOF", "operator": "orange_ci",
        "counterparty": { "msisdn": "0779140002" } }'

Le paiement naît created, puis échoue en insufficient_funds. Vous recevez payment.failed sur votre endpoint.

Pour une confirmation synchrone, sans passer par la file, ajoutez "simulate": "succeed" au corps. Pratique pour un test d'intégration continue ; inutile pour éprouver votre gestion des échecs.

Version d'API 2026-08-25 · changements · spécification OpenAPI