Paiements
Un paiement est une demande de paiement PI-SPI (« request to pay ») envoyée à la banque du client : rien n'est prélevé sans sa validation dans son application. Il n'y a ni carte, ni QR code.
Statuts
| Statut | Signification | Final |
|---|---|---|
created | Paiement créé, le client n'a pas encore saisi son alias | non |
request_sent | Demande transmise à la banque du client | non |
accepted_deferred | Le client a accepté et paiera plus tard (à la livraison) | non |
succeeded | Paiement reçu, montant net crédité sur votre compte | oui |
declined | Le client a refusé | oui |
expired | Délai dépassé sans paiement | oui |
canceled | Annulé par vous | oui |
failed | Erreur technique côté banque | oui |
Un statut final ne change plus. Ne livrez une commande que sur succeeded (ou, à la livraison,
sur accepted_deferred : voir plus bas).
Tentatives
Le client peut se tromper d'alias ou refuser, puis réessayer depuis la page de paiement : chaque
alias saisi crée une tentative (attempts), avec son propre tx_id, l'identifiant transmis
à la banque. Tant qu'un nouvel essai est possible, un refus ne rend pas le paiement declined.
Un paiement accepte 5 tentatives au plus (too_many_attempts).
L'alias du client n'est jamais renvoyé en clair : payer_alias_masked vaut par exemple
+225 07 •• •• 42.
Expiration
- Paiement immédiat (
mode: immediate, par défaut) : le client a quelques minutes pour valider (5 par défaut). Vous pouvez fixerexpires_at, entre 1 minute et 24 heures. - Paiement à la livraison (
mode: on_delivery) :expires_atest obligatoire, au plus 30 jours. Le client accepte la demande à la commande (accepted_deferred) : vous pouvez expédier. Il la valide à la réception du colis (succeeded). Sans validation avantexpires_at, le paiement expire.
Montant et frais
amount est un entier en FCFA. À la réussite, fee_amount (frais CajouPay) et net_amount
(amount - fee_amount, crédité sur votre compte) sont renseignés.
Annuler
POST /v1/payments/{id}/cancel annule un paiement qui n'est pas final. Une demande déjà envoyée
ne peut pas être retirée de l'application du client : s'il la valide malgré tout, il est
remboursé automatiquement. Un paiement réussi ne s'annule pas (payment_already_final).
Paiements en double
Si le client valide deux tentatives du même paiement, seule la première règle le paiement. La
seconde est marquée duplicate: true, n'est jamais créditée sur votre compte et le client est
remboursé automatiquement (webhook payment.duplicate_refunded).
Idempotence
Envoyez un en-tête Idempotency-Key unique (votre numéro de commande, un UUID…) sur chaque
création. Si la réponse se perd (coupure réseau), renvoyez la même requête avec la même clé :
vous obtenez le même paiement, jamais un second. Même clé avec un autre corps : erreur
409 idempotency_key_reused. Les clés sont conservées 24 heures.
Lister et retrouver
GET /v1/payments liste vos paiements du plus récent au plus ancien, filtrés par status,
reference (exacte), created_from, created_to. Pagination : limit (1 à 100) et
starting_after (id du dernier élément reçu), tant que has_more vaut true.
metadata accepte 20 clés de votre choix (valeurs de 500 caractères au plus), renvoyées dans le
paiement et ses webhooks : utile pour retrouver votre commande.