Sommaire · Exemples de code

Exemples de code

Une petite fonction d’appel par langage, puis la création d’un paiement. Les mêmes règles partout :

  • la clé secrète vient de la configuration du serveur ;
  • le montant vient de votre base de données, jamais du navigateur ;
  • la clé d’idempotence est liée à la commande, et réutilisée si l’on recommence ;
  • la livraison se décide sur le webhook payment.succeeded.

Serveur

// Node.js 18+ (fetch natif). La clé secrète vient de l'environnement, jamais du code.
import { randomUUID } from 'node:crypto'

const GALSEN = 'https://backend.v1.pay.galsen.tech'

async function galsen(chemin, { methode = 'GET', corps, idempotence } = {}) {
  const reponse = await fetch(GALSEN + chemin, {
    method: methode,
    headers: {
      Authorization: `Bearer ${process.env.GALSEN_SECRET_KEY}`,
      ...(corps && { 'Content-Type': 'application/json' }),
      ...(idempotence && { 'Idempotency-Key': idempotence }),
    },
    body: corps ? JSON.stringify(corps) : undefined,
    signal: AbortSignal.timeout(30_000),
  })
  const enveloppe = await reponse.json()
  if (!enveloppe.success) {
    const erreur = new Error(enveloppe.error.message)
    erreur.code = enveloppe.error.code
    erreur.requestId = enveloppe.requestId
    throw erreur
  }
  return enveloppe.data
}

// Créer le paiement d'une commande : la clé d'idempotence est liée à la commande.
const paiement = await galsen('/v1/payment-intents', {
  methode: 'POST',
  idempotence: commande.cleIdempotence ?? randomUUID(),
  corps: { amount: commande.total, currency: 'XOF', provider: 'WAVE', description: `Commande ${commande.numero}` },
})
// Rediriger le client : paiement.nextAction.url

Applications web et mobiles

Jamais de clé secrète dans un navigateur ou une application

Le code d’une application mobile ou d’une page web se lit facilement. Créez le paiement depuis votre serveur, transmettez seulement l’adresse de paiement, l’identifiant et le clientSecret.
// Next.js (App Router) — app/api/paiement/route.ts
// La clé secrète reste sur le serveur ; le navigateur ne reçoit que l'adresse de paiement.
export async function POST(requete: Request) {
  const { commandeId } = await requete.json()
  const commande = await trouverCommande(commandeId) // votre base : le montant vient d'elle, jamais du navigateur
  const reponse = await fetch(`${process.env.GALSEN_URL}/v1/payment-intents`, {
    method: 'POST',
    cache: 'no-store',
    headers: {
      Authorization: `Bearer ${process.env.GALSEN_SECRET_KEY}`,
      'Idempotency-Key': commande.cleIdempotence,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ amount: commande.total, currency: 'XOF', provider: 'WAVE', metadata: { commande: commande.id } }),
  })
  const { success, data, error } = await reponse.json()
  if (!success) return Response.json({ erreur: error.code }, { status: 502 })
  return Response.json({ url: data.nextAction?.url, id: data.id, clientSecret: data.clientSecret })
}

Webhooks

La vérification de signature en Node.js, PHP et Python est détaillée sur la page Webhooks.