Sommaire · Paiements

Paiements

Un paiement (une payment intent) représente une somme que votre client doit vous payer. Vous le créez depuis votre serveur ; le client paie sur la page du fournisseur ; Galsen Pay confirme l’issue auprès du fournisseur et vous prévient par webhook.

Le parcours

  1. Votre serveur crée le paiement : POST /v1/payment-intents.
  2. Vous redirigez le client vers data.nextAction.url (ou lui envoyez ce lien).
  3. Le client paie. Le fournisseur le renvoie vers votre successUrl ou cancelUrl.
  4. Galsen Pay reçoit la confirmation du fournisseur, la vérifie, crédite votre solde et envoie payment.succeeded à votre webhook.
  5. Vous livrez la commande à réception du webhook (ou après avoir relu le paiement).

Ne livrez jamais sur la seule redirection

L’arrivée du client sur votre successUrl ne prouve rien : n’importe qui peut ouvrir cette adresse. Seuls le webhook signé payment.succeeded ou la lecture GET /v1/payment-intents/{id} avec le statut SUCCEEDED font foi.

Créer un paiement

POST/v1/payment-intents

Permission payments:write. En-tête Idempotency-Key obligatoire. Alias : POST /v1/payments.
ParamètreTypeDescription
amountrequisentierMontant en F CFA (unités mineures), au moins 1.
currencyrequis"XOF"Seule devise acceptée.
providerrequis"WAVE" | "SANDBOX" | "ORANGE_MONEY"Fournisseur. SANDBOX en mode test.
customerfacultatifobjetphone (format international, +221…), name, email, ou id d’un client existant. Un client est créé ou retrouvé à partir du téléphone.
descriptionfacultatifchaîne ≤ 255Texte libre, visible dans vos rapports.
metadatafacultatifobjet plat30 clés au plus ([A-Za-z0-9_.-], 40 caractères), valeurs : texte (≤ 500), nombre, booléen ou null. Rendu tel quel dans les réponses et webhooks.
successUrlfacultatifURL httpsOù le fournisseur renvoie le client après paiement.
cancelUrlfacultatifURL httpsOù il le renvoie après abandon ou échec.
cURL
curl -sX POST https://backend.v1.pay.galsen.tech/v1/payment-intents \
  -H "Authorization: Bearer $GALSEN_SECRET_KEY" \
  -H "Idempotency-Key: 5f0c7b9e-2d1a-4b8e-9c3f-7a6d5e4c3b2a" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 25000,
    "currency": "XOF",
    "provider": "WAVE",
    "customer": { "phone": "+221771234567", "name": "Awa Diop" },
    "description": "Commande #A-1042",
    "metadata": { "commande": "A-1042" },
    "successUrl": "https://boutique.sn/merci",
    "cancelUrl": "https://boutique.sn/panier"
  }'

L’objet paiement

ChampTypeDescription
idfacultatifuuidIdentifiant du paiement.
referencefacultatifchaîneRéférence lisible GSP-XXXXXXXXXXXX.
statusfacultatifchaîneVoir le tableau des statuts.
amount, currencyfacultatifentier, "XOF"Montant demandé au client.
feesfacultatifobjetproviderFee (frais du fournisseur) et galsenFee (frais Galsen Pay), selon votre grille.
netAmountfacultatifentierCe qui vous revient : amount − frais.
nextActionfacultatifobjet | null{ type: "redirect", url } tant que le client doit payer ; null ensuite.
clientSecretfacultatifchaîneRenvoyé une seule fois, à la création. Sert au statut public (ci-dessous).
paymentIdfacultatifuuid | nullIdentifiant du paiement encaissé, une fois réussi : c’est lui qu’on rembourse.
customerfacultatifobjet | null{ id, phone } — téléphone masqué.
failurefacultatifobjet | null{ code, message } si le paiement a échoué.
createdAt, expiresAt, succeededAtfacultatifdates ISOCréation, expiration de la session, réussite.

Statuts

StatutSignification
CREATEDCréé, pas encore transmis au fournisseur (très bref).
PENDINGSession ouverte chez le fournisseur : le client doit payer.
REQUIRES_ACTIONLe client doit agir (par exemple valider sur son téléphone).
PROCESSINGPaiement en cours de traitement chez le fournisseur.
SUCCEEDEDPayé et confirmé par le fournisseur. Vous pouvez livrer.
FAILEDRefusé ou échoué. Aucun argent encaissé.
CANCELLEDAnnulé par vous avant paiement.
EXPIREDLe client n’a pas payé à temps (30 minutes par défaut).
PARTIALLY_REFUNDEDRéussi, puis remboursé en partie.
REFUNDEDRéussi, puis remboursé en totalité.
UNKNOWNLe fournisseur n’a pas répondu : issue inconnue pour l’instant (voir ci-dessous).

Un statut ne se change jamais par l’API : seule une réponse vérifiée du fournisseur peut rendre un paiement SUCCEEDED.

UNKNOWN : ne recréez pas le paiement

UNKNOWN signifie que le fournisseur n’a pas répondu à temps : le client a peut-être payé. Ne créez pas un second paiement. Attendez le webhook, ou relisez le paiement : Galsen Pay interroge le fournisseur et tranche dès qu’il a la réponse.

Lire et lister

GET/v1/payment-intents/{id}

Permission payments:read.

GET/v1/payment-intents

Permission payments:read. Filtres : status, provider, reference, amountMin, amountMax, createdFrom, createdTo (dates ISO), plus limit et cursor.
cURL
curl -s "https://backend.v1.pay.galsen.tech/v1/payment-intents?status=SUCCEEDED&createdFrom=2026-11-01T00:00:00Z&limit=50" \
  -H "Authorization: Bearer $GALSEN_SECRET_KEY"

Annuler

POST/v1/payment-intents/{id}/cancel

Permission payments:write. Ferme d’abord la session chez le fournisseur, puis passe le paiement en CANCELLED. Impossible une fois le paiement réussi : remboursez-le.

Paiements encaissés

GET/v1/payments · /v1/payments/{id}

Permission payments:read. Les paiements réussis, avec refundedAmount, refundableAmount, les frais, capturedAt et settledAt (date où les fonds deviennent disponibles). L’id d’un paiement encaissé est le paymentId de l’intention.

Statut public, depuis un navigateur ou une application

Pour afficher « Paiement reçu » sur une page ou dans une application sans exposer votre clé secrète : votre serveur transmet au client l’id et le clientSecret du paiement, et le client interroge l’API avec une clé publique.

GET/v1/public/payment-intents/{id}?client_secret=pi_secret_…

Clé publique (gsp_…_pk_…) du même compte. Réponse : { id, status, amount, currency } uniquement.

C’est un affichage de confort : la décision de livrer reste côté serveur, sur le webhook. Exemples complets dans Exemples de code.