Initier un paiement
Initier un paiement, c’est dire à MafPay : « mon client veut payer tant avec tel moyen de paiement ». MafPay contacte l’opérateur et vous renvoie de quoi afficher le paiement à votre client.
/api/v1/{endpoint_key}/payments/initiate/En-têtes : X-Api-Key, X-Api-Secret (voir Authentification) et Content-Type: application/json.
Les champs à envoyer
| Champ | Obligatoire | Type | Description |
|---|---|---|---|
provider |
oui | texte | Le moyen de paiement : WAVE_SN ou ORANGE_MONEY_SN (voir Moyens de paiement). |
amount |
oui | texte ou nombre | Le montant, au minimum 0.01. Envoyez-le de préférence entre guillemets : "5000". Orange Money n’accepte que des montants entiers. |
currency |
non | texte | La devise. XOF (franc CFA) par défaut. |
description |
non | texte (500 max) | Un libellé pour vous (ex : « Commande #123 »). |
customer_phone |
non | texte (20 max) | Téléphone du client, au format international : +221771234567. |
customer_name |
non | texte | Nom du client. |
metadata |
non | objet JSON | Vos propres données (numéro de commande, id client…). MafPay les conserve telles quelles et vous les renvoie dans la réponse, dans le statut et dans les notifications. |
success_url |
non | URL | Où renvoyer le client après un paiement réussi. Par défaut : l’URL de succès configurée dans votre application. |
error_url |
non | URL | Où renvoyer le client après un échec. Par défaut : l’URL d’échec de l’application. |
Exemple de requête
curl -X POST "$MAFPAY_URL/api/v1/$ENDPOINT_KEY/payments/initiate/" \ -H "X-Api-Key: $MAFPAY_PK" \ -H "X-Api-Secret: $MAFPAY_SK" \ -H "Content-Type: application/json" \ -d '{ "provider": "WAVE_SN", "amount": "5000", "currency": "XOF", "description": "Commande #123", "customer_phone": "+221771234567", "customer_name": "Awa Diop", "metadata": { "order_id": 123 }, "success_url": "https://maboutique.sn/merci", "error_url": "https://maboutique.sn/paiement-echoue" }'const response = await fetch( `${process.env.MAFPAY_URL}/api/v1/${process.env.MAFPAY_ENDPOINT_KEY}/payments/initiate/`, { method: "POST", headers: { "X-Api-Key": process.env.MAFPAY_PK, "X-Api-Secret": process.env.MAFPAY_SK, "Content-Type": "application/json", }, body: JSON.stringify({ provider: "WAVE_SN", amount: "5000", currency: "XOF", description: "Commande #123", customer_phone: "+221771234567", customer_name: "Awa Diop", metadata: { order_id: 123 }, }), });
const payment = await response.json();if (!response.ok) throw new Error(payment.message); // voir la page « Erreurs »console.log(payment.reference, payment.status); // MAFPAY-W7VOB6J6 PROCESSINGimport osimport requests
response = requests.post( f"{os.environ['MAFPAY_URL']}/api/v1/{os.environ['MAFPAY_ENDPOINT_KEY']}/payments/initiate/", headers={ "X-Api-Key": os.environ["MAFPAY_PK"], "X-Api-Secret": os.environ["MAFPAY_SK"], }, json={ "provider": "WAVE_SN", "amount": "5000", "currency": "XOF", "description": "Commande #123", "customer_phone": "+221771234567", "customer_name": "Awa Diop", "metadata": {"order_id": 123}, }, timeout=20,)payment = response.json()if not response.ok: raise RuntimeError(payment["message"])print(payment["reference"], payment["status"])<?php$ch = curl_init(getenv('MAFPAY_URL') . '/api/v1/' . getenv('MAFPAY_ENDPOINT_KEY') . '/payments/initiate/');curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 20, CURLOPT_HTTPHEADER => [ 'X-Api-Key: ' . getenv('MAFPAY_PK'), 'X-Api-Secret: ' . getenv('MAFPAY_SK'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'provider' => 'WAVE_SN', 'amount' => '5000', 'currency' => 'XOF', 'description' => 'Commande #123', 'customer_phone' => '+221771234567', 'customer_name' => 'Awa Diop', 'metadata' => ['order_id' => 123], ]),]);$body = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);$payment = json_decode($body, true);if ($status !== 201) { throw new Exception($payment['message'] ?? 'Erreur MafPay'); }echo $payment['reference'] . ' ' . $payment['status'];La réponse (code 201)
{ "transaction_uuid": "dcea6fb6-4786-456f-85cc-0450bdccc0a7", "reference": "MAFPAY-W7VOB6J6", "provider": "WAVE_SN", "environment": "sandbox", "amount": "5000.00", "currency": "XOF", "status": "PROCESSING", "deep_links": { "Wave": "https://portail.mafpay.metalafrique-it.com/pay/cos-sandbox-efbbcc6513fe489d9b04" }, "qr_code": "iVBORw0KGgoAAAANSUhEUgAA…", "provider_reference": "cos-sandbox-efbbcc6513fe489d9b04", "expires_at": "2026-09-25T14:04:17Z", "metadata": { "order_id": 123 }, "created_at": "2026-09-25T13:34:17.515299Z"}| Champ | Signification |
|---|---|
reference |
L’identifiant du paiement (MAFPAY-XXXXXXXX). Enregistrez-le dans votre base : vous en aurez besoin pour suivre le paiement. |
transaction_uuid |
Un autre identifiant du même paiement (utile pour retrouver la transaction dans le portail). |
environment |
sandbox ou live, déduit de vos clés. |
status |
PROCESSING : MafPay attend que le client paie. Voir Suivre un paiement. |
deep_links |
Des liens qui ouvrent l’application de l’opérateur sur le téléphone du client. Wave : une clé Wave. Orange Money : OM (application Orange Money) et MAXIT (application Max it). |
qr_code |
Un QR code à scanner, sous forme d’image PNG encodée en base64 (sans préfixe). |
provider_reference |
L’identifiant du paiement chez l’opérateur. |
expires_at |
Date limite : passé ce délai, le paiement n’est plus possible. |
metadata |
Vos données, renvoyées telles quelles. |
Afficher le paiement à votre client
Vous avez deux façons complémentaires de faire payer :
1. Le bouton « Payer avec Wave » (mobile)
Sur téléphone, redirigez le client (ou affichez un bouton) vers le lien de deep_links : l’application de l’opérateur s’ouvre avec le paiement prêt à être validé.
<a href="https://portail.mafpay.metalafrique-it.com/pay/cos-sandbox-efbbcc6513fe489d9b04">Payer avec Wave</a>2. Le QR code (ordinateur)
Sur ordinateur, affichez le QR code : le client le scanne avec son téléphone. Le champ qr_code est une image PNG en base64 sans le préfixe data: ; ajoutez-le vous-même :
<img alt="QR code de paiement" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA…">En JavaScript : `data:image/png;base64,${payment.qr_code}`.
Après l’initiation
Le paiement est en cours (PROCESSING) mais pas encore payé. Ne livrez rien à ce stade. Attendez la confirmation par notification (webhook), ou interrogez le statut.
Ce qui peut mal se passer
| Code | Cause fréquente |
|---|---|
400 |
Champ manquant ou invalide (amount absent…), provider inconnu, provider non activé pour votre application, montant décimal avec Orange Money, ou refus de l’opérateur. Le détail par champ est dans errors. |
401 |
Clés absentes ou invalides (Authentification). |
429 |
Trop de requêtes (Limites). |
Exemple d’erreur de validation :
{ "status": 400, "error": "Bad Request", "message": "This field is required.", "timestamp": "2026-09-25T13:34:17.709235+00:00", "errors": { "amount": ["This field is required."] }}Toutes les erreurs sont détaillées dans Erreurs.