Aller au contenu

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.

POST/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

Fenêtre de terminal
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 PROCESSING
import os
import 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.