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.urlApplications 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 leclientSecret.// 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.