Aller au contenu

Tester en sandbox

En sandbox, il n’y a pas de vrai téléphone ni de vrai opérateur : MafPay simule Wave et Orange Money, avec exactement le même parcours qu’en production.

Votre serveur ──1. initiate──► MafPay (statut PROCESSING, lien + QR code)
Le client ──2. ouvre le lien / scanne le QR──► page de paiement de test MafPay
Le client ──3. clique sur « Payer »──► MafPay (statut SUCCESS)
MafPay ──4. notification signée──► votre serveur (transaction.success)

Avant de commencer : les identifiants de test

Configurez le moyen de paiement dans l’onglet Sandbox avec les valeurs de test (liste complète) : comme l’opérateur, MafPay refuse l’initiation si l’identifiant est incorrect (« Identifiants sandbox invalides »).

Méthode principale : la page de paiement de test

Après l’initiation, ouvrez le lien de deep_links (ou scannez le qr_code avec un téléphone) : vous arrivez sur une page MafPay qui affiche le marchand, le montant déjà chargé et le moyen de paiement.

Vous cliquez sur Résultat Notification reçue par votre serveur
Payer le paiement passe à SUCCESS transaction.success
Annuler le paiement passe à CANCELLED transaction.cancelled
(rien, le délai passe) à l’ouverture de la page, le paiement passe à EXPIRED transaction.expired

Une fois le paiement terminé, la page affiche le résultat et un bouton « Retourner sur le site » qui renvoie le client vers votre success_url (ou error_url en cas d’échec ou d’annulation), comme le ferait l’opérateur.

  • Recharger la page ou cliquer deux fois ne change rien : un paiement terminé le reste, et une seule notification est envoyée.
  • Cette page n’existe qu’en sandbox : un paiement live n’est jamais joignable par ce lien.
  • Rien de sensible n’y est affiché (ni vos clés, ni vos metadata).

Méthode avancée : jouer l’opérateur avec curl

Pour automatiser vos tests (scripts, intégration continue) ou simuler un cas particulier, vous pouvez envoyer vous-même à MafPay le message que l’opérateur aurait envoyé. C’est ce que fait, en coulisses, le bouton Payer.

Comment simuler

POST/api/v1/{endpoint_key}/webhooks/{provider}/
  • {provider} vaut wave ou orange-money.
  • Envoyez vos clés sandbox (X-Api-Key / X-Api-Secret) : c’est ce qui indique à MafPay que vous simulez.
  • Vous devez indiquer la reference du paiement (MAFPAY-XXXXXXXX) dans un champ précis selon l’opérateur, et le montant exact du paiement.

Wave

La référence se place dans data.client_reference.

Paiement réussi

Fenêtre de terminal
curl -X POST "$MAFPAY_URL/api/v1/$ENDPOINT_KEY/webhooks/wave/" \
-H "X-Api-Key: $MAFPAY_PK" -H "X-Api-Secret: $MAFPAY_SK" \
-H "Content-Type: application/json" \
-d '{
"type": "checkout.session.completed",
"data": {
"id": "cos-sandbox-1",
"client_reference": "MAFPAY-W7VOB6J6",
"payment_status": "succeeded",
"amount": "5000",
"currency": "XOF"
}
}'
const response = await fetch(
`${process.env.MAFPAY_URL}/api/v1/${process.env.MAFPAY_ENDPOINT_KEY}/webhooks/wave/`,
{
method: "POST",
headers: {
"X-Api-Key": process.env.MAFPAY_PK,
"X-Api-Secret": process.env.MAFPAY_SK,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "checkout.session.completed",
data: { id: "cos-sandbox-1", client_reference: "MAFPAY-W7VOB6J6", payment_status: "succeeded", amount: "5000", currency: "XOF" },
}),
}
);
console.log(await response.json());
import os
import requests
response = requests.post(
f"{os.environ['MAFPAY_URL']}/api/v1/{os.environ['MAFPAY_ENDPOINT_KEY']}/webhooks/wave/",
headers={"X-Api-Key": os.environ["MAFPAY_PK"], "X-Api-Secret": os.environ["MAFPAY_SK"]},
json={
"type": "checkout.session.completed",
"data": {"id": "cos-sandbox-1", "client_reference": "MAFPAY-W7VOB6J6",
"payment_status": "succeeded", "amount": "5000", "currency": "XOF"},
},
timeout=15,
)
print(response.json())

Réponse :

{ "reference": "MAFPAY-W7VOB6J6", "previous_status": "PROCESSING", "new_status": "SUCCESS" }

Autres scénarios Wave

Vous voulez simuler type Autre champ à changer
Succès checkout.session.completed data.payment_status: "succeeded"
Échec checkout.session.completed data.payment_status: "failed"
Annulation checkout.session.completed data.payment_status: "cancelled"
Échec avec motif checkout.session.payment_failed ajouter data.last_payment_error: { "code": "insufficient_funds", "message": "Solde insuffisant" }
Expiration checkout.session.expired —

Orange Money

La référence se place dans metadata.mafpay_reference, et le montant dans amount.value.

Fenêtre de terminal
curl -X POST "$MAFPAY_URL/api/v1/$ENDPOINT_KEY/webhooks/orange-money/" \
-H "X-Api-Key: $MAFPAY_PK" -H "X-Api-Secret: $MAFPAY_SK" \
-H "Content-Type: application/json" \
-d '{
"amount": { "value": 2500, "unit": "XOF" },
"transactionId": "MP260924.1029.C58502",
"status": "SUCCESS",
"metadata": { "mafpay_reference": "MAFPAY-0X0GXXRR" }
}'
const response = await fetch(
`${process.env.MAFPAY_URL}/api/v1/${process.env.MAFPAY_ENDPOINT_KEY}/webhooks/orange-money/`,
{
method: "POST",
headers: {
"X-Api-Key": process.env.MAFPAY_PK,
"X-Api-Secret": process.env.MAFPAY_SK,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: { value: 2500, unit: "XOF" },
transactionId: "MP260924.1029.C58502",
status: "SUCCESS",
metadata: { mafpay_reference: "MAFPAY-0X0GXXRR" },
}),
}
);
console.log(await response.json());
import os
import requests
response = requests.post(
f"{os.environ['MAFPAY_URL']}/api/v1/{os.environ['MAFPAY_ENDPOINT_KEY']}/webhooks/orange-money/",
headers={"X-Api-Key": os.environ["MAFPAY_PK"], "X-Api-Secret": os.environ["MAFPAY_SK"]},
json={
"amount": {"value": 2500, "unit": "XOF"},
"transactionId": "MP260924.1029.C58502",
"status": "SUCCESS",
"metadata": {"mafpay_reference": "MAFPAY-0X0GXXRR"},
},
timeout=15,
)
print(response.json())
Vous voulez simuler status
Succès SUCCESS
Échec FAILED
Annulation CANCELLED
Expiration EXPIRED

Un autre statut ne change rien.

Ce que MafPay contrôle

Rien n’est modifié tant que tous ces contrôles ne sont pas passés :

Problème Code Message / effet
Clés fausses 401 « Clés API invalides. »
Clés live utilisées pour simuler 403 refusé : on ne simule qu’en sandbox
Corps illisible ou champ manquant 400 le message indique quoi corriger
Référence inconnue (ou d’une autre application) 404 « Transaction introuvable. »
Montant différent de celui du paiement 400 « Le montant annoncé ne correspond pas à celui de la transaction. »

Les doublons et les contradictions sont ignorés

Comme en vraie vie, un webhook en double, tardif, ou qui contredit un statut définitif (un « échec » après un « succès ») ne change rien :

{ "reference": "MAFPAY-0X0GXXRR", "previous_status": "FAILED", "new_status": "FAILED",
"message": "Statut inchangé (transition non applicable)." }

Aucune notification n’est renvoyée à votre serveur dans ce cas.

Scénarios de test à jouer avant la production

  1. Succès (bouton Payer) : la commande passe « payée », le stock est décrémenté, l’email de confirmation part.
  2. Échec : la commande reste « en attente de paiement », le client peut réessayer.
  3. Annulation (bouton Annuler) et expiration : idem, sans livraison.
  4. Notification en double : envoyez deux fois le même webhook : votre serveur ne doit livrer qu’une fois.
  5. Signature invalide : appelez votre propre webhook_url avec une fausse signature : votre serveur doit répondre 401.
  6. Montant décimal avec Orange Money : vérifiez que vous gérez l’erreur 400.