Volume total
0 XAF
— Depuis le début
Transactions
0
— En attente
Taux de succès
—
Données insuffisantes
Solde disponible
0 XAF
— Collecté - Frais - Payouts
Volume par jour — 7 derniers jours
Collecte
Payout
Aucune donnée pour l'instant — les graphiques se mettront à jour automatiquement
Dernières transactions
Aucune transaction
Vos transactions apparaîtront ici dès que vous aurez intégré l'API NDSGPay.
Toutes les transactions
Aucune transaction pour l'instant
Intégrez l'API NDSGPay pour commencer à collecter des paiements mobile money.
Relevé
Aucune ligne pour l'instant
Ton relevé apparaîtra ici dès qu'une transaction sera complétée.
Demandez le virement de votre solde disponible vers votre compte bancaire.
Historique des virements
Aucune demande de virement
Cliquez sur "Demander un virement" pour transférer votre solde vers votre compte bancaire.
Collecte (total)
0 XAF
Frais : 3% / tx
Payout (total)
0 XAF
Frais : 2% / tx
Taux de succès
—
Insuffisant
Frais générés
0 XAF
Depuis le début
Répartition par opérateur
Données insuffisantes
Les analytics se rempliront automatiquement dès vos premières transactions.
Clés API
Clé publique
Chargement...
Clé secrète
sk_live_••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Webhook
URL callback
Non configurée — allez dans Paramètres pour la définir
NDSGPay enverra un POST sur cette URL à chaque transaction confirmée ou échouée. Configurez-la dans Paramètres.
Correspondants disponibles
| Pays | Opérateur | Code correspondent | Devise |
|---|---|---|---|
| 🇬🇦 Gabon | Airtel Money | AIRTEL_GAB | XAF |
| 🇨🇲 Cameroun | MTN MoMo | MTN_MOMO_CMR | XAF |
| 🇨🇲 Cameroun | Orange Money | ORANGE_CMR | XAF |
| 🇨🇬 Congo | Airtel Money | AIRTEL_COG | XAF |
| 🇨🇬 Congo | MTN MoMo | MTN_MOMO_COG | XAF |
| 🇧🇯 Bénin | MTN MoMo | MTN_MOMO_BEN | XOF |
| 🇧🇯 Bénin | Moov Money | MOOV_BEN | XOF |
| 🇨🇮 Côte d'Ivoire | MTN MoMo | MTN_MOMO_CIV | XOF |
| 🇨🇮 Côte d'Ivoire | Orange Money | ORANGE_CIV | XOF |
| 🇸🇳 Sénégal | Orange Money | ORANGE_SEN | XOF |
| 🇸🇳 Sénégal | Free Money | FREE_SEN | XOF |
| 🇨🇩 RDC | Airtel Money | AIRTEL_COD | CDF |
| 🇨🇩 RDC | Orange Money | ORANGE_COD | CDF |
| 🇨🇩 RDC | Vodacom | VODACOM_MPESA_COD | CDF |
| 🇰🇪 Kenya | M-Pesa | MPESA_KEN | KES |
| 🇷🇼 Rwanda | Airtel Money | AIRTEL_RWA | RWF |
| 🇷🇼 Rwanda | MTN MoMo | MTN_MOMO_RWA | RWF |
| 🇺🇬 Ouganda | Airtel Money | AIRTEL_OAPI_UGA | UGX |
| 🇺🇬 Ouganda | MTN MoMo | MTN_MOMO_UGA | UGX |
| 🇿🇲 Zambie | Airtel Money | AIRTEL_OAPI_ZMB | ZMW |
| 🇿🇲 Zambie | MTN MoMo | MTN_MOMO_ZMB | ZMW |
| 🇿🇲 Zambie | Zamtel | ZAMTEL_ZMB | ZMW |
| 🇸🇱 Sierra Leone | Orange Money | ORANGE_SLE | SLE |
Solde disponible
—
Collecté – Frais – Payouts
Soldes par opérateur
Chargement...
Initier un retrait
Opérateur
Numéro mobile
Préfixe pays sans 0 (ex: 24174XXXXXX)
Montant (XAF)
Min : 100 XAF
Tout retirer
Description (max 22 car.)
Historique des retraits
Aucun retrait
Initiez votre premier retrait depuis le formulaire.
Base URL
# Production NDSGPay https://ndsgpay-backend.vercel.app/api # Authentification : utilisez votre clé secrète NDSGPay (sk_live_) # NE PAS utiliser un token PawaPay — NDSGPay gère PawaPay pour vous # Les requêtes POST doivent envoyer l'en-tête Content-Type: application/json # Limites par clé API : 60 créations de paiement/min, 120 consultations/min (HTTP 429 au-delà) # Opérateurs : contactez support@ndsgservices.com pour la liste activée sur votre compte
Endpoints
const res = await fetch("https://ndsgpay-backend.vercel.app/api/pay/deposits", { method: "POST", headers: { "Authorization": `Bearer ${votre_sk_live_xxx}`, "Content-Type": "application/json" }, // Pas de depositId à envoyer : NDSGPay génère l'identifiant et vous le renvoie. body: JSON.stringify({ amount: "5000", // en XAF currency: "XAF", correspondent: "AIRTEL_GAB", // code opérateur : AIRTEL_GAB, MTN_MOMO_CMR, MTN_MOMO_BEN... msisdn: "24177000000", // numéro du client, format international sans + ni espaces description: "Commande 1042" // facultatif, vu par votre client : accents et symboles sont retirés, 22 caractères max }) }); const data = await res.json(); // Réponse 200 // { // "success": true, // "depositId": "b3f0c8e2-...", // généré par NDSGPay : conservez-le pour suivre la transaction // "status": "INITIATED", // "message": "Paiement initié. Le client va recevoir une demande de confirmation sur son téléphone." // } // // Erreurs // 400 { "success": false, "error": "Champs requis manquants : msisdn" } (liste les champs manquants) // 400 { "success": false, "error": "Corps de requête vide ou illisible. Envoyez du JSON avec l'en-tête Content-Type: application/json." } // 400 { "success": false, "error": "Montant invalide : indiquez un nombre positif, sans espace ni séparateur (ex : 5000)." } // 400 { "success": false, "error": "Correspondant invalide : ..." } ou refus de l'opérateur // 401 clé API manquante ou invalide 403 compte non activé // 429 trop de requêtes 500 erreur à l'initiation (voir le champ "details")
const res = await fetch("https://ndsgpay-backend.vercel.app/api/pay/payouts", { method: "POST", headers: { "Authorization": `Bearer ${votre_sk_live_xxx}`, "Content-Type": "application/json" }, body: JSON.stringify({ amount: "10000", currency: "XAF", correspondent: "AIRTEL_GAB", msisdn: "24166000000", // numéro du bénéficiaire, format international sans + ni espaces description: "Remboursement client" // facultatif, vu par votre client : accents et symboles retirés, 22 car. max }) }); const data = await res.json(); // Réponse 200 // { "success": true, "payoutId": "...", "status": "INITIATED", "message": "Virement initié. ..." } // // Le payout est prélevé sur votre solde NDSGPay (collectes encaissées, moins les frais). // Le montant PLUS les frais NDSGPay doivent tenir dans ce solde, sinon : // 400 { "success": false, "error": "Solde insuffisant. Maximum : 9708 XAF (frais NDSGPay inclus)" } // 400 { "success": false, "error": "..." } si l'opérateur refuse (ex : montant au-dessus de sa limite)
const res = await fetch(`https://ndsgpay-backend.vercel.app/api/deposits/${depositId}`, { headers: { "Authorization": `Bearer ${votre_sk_live_xxx}` } }); const data = await res.json(); // Réponse 200 // { // "success": true, // "deposit": { // "depositId": "b3f0c8e2-...", // "status": "COMPLETED", // "amount": 5000, // "currency": "XAF", // "correspondent": "AIRTEL_GAB", // "msisdn": "24177000000", // "description": "Commande 1042", // "failureCode": null, // "failureMessage": null // // ... autres champs // } // } // // status : INITIATED, SUBMITTED (en cours), puis COMPLETED ou FAILED (définitifs) // 404 transaction introuvable 403 transaction d'un autre compte
const res = await fetch(`https://ndsgpay-backend.vercel.app/api/payouts/${payoutId}`, { headers: { "Authorization": `Bearer ${votre_sk_live_xxx}` } }); const data = await res.json(); // Réponse 200 : { "success": true, "payout": { "payoutId": "...", "status": "COMPLETED", "amount": 10000, ... } } // // status : INITIATED, SUBMITTED, ACCEPTED, ENQUEUED (en cours), puis COMPLETED ou FAILED (définitifs)
Webhooks (NDSGPay vers votre serveur)
// Renseignez votre URL dans Paramètres > URL webhook. // NDSGPay envoie un POST à chaque statut final (COMPLETED ou FAILED) : { "event": "deposit.updated", // ou "payout.updated" "timestamp": "2026-10-11T10:15:00.000Z", "data": { "depositId": "b3f0c8e2-...", // ou "payoutId" : l'identifiant renvoyé à la création "status": "COMPLETED" // ou "FAILED" // ... autres champs du message PawaPay : ne vous fiez qu'à l'identifiant et au statut } } // En-têtes envoyés : // Content-Type: application/json // X-NDSGPay-Event: deposit.updated // X-NDSGPay-Merchant: <votre identifiant marchand> // X-NDSGPay-Signature: t=1760177700,sha256=<signature> (secret affiché dans Paramètres) // // À savoir // - Répondez en 2xx en moins de 5 secondes. NDSGPay n'essaie qu'une seule fois : il n'y a pas de nouvel envoi. // - Ne vous reposez pas uniquement sur les webhooks : pour une transaction encore en cours après quelques // minutes, interrogez GET /api/deposits/:id (ou /api/payouts/:id). // - Une transaction corrigée plus tard par la réconciliation automatique de NDSGPay n'émet pas de webhook.
const crypto = require("crypto"); const express = require("express"); const app = express(); // Vérifie que le webhook vient bien de NDSGPay (secret : Paramètres > Secret de signature webhook) function verifierSignatureNdsgpay(corpsBrut, entete, secret, toleranceSec = 300) { const parts = Object.fromEntries(entete.split(",").map((p) => p.split("="))); const t = parts.t; const signature = parts.sha256; if (!t || !signature) return false; if (Math.abs(Date.now() / 1000 - Number(t)) > toleranceSec) return false; // anti-rejeu const attendu = crypto.createHmac("sha256", secret).update(`${t}.${corpsBrut}`).digest("hex"); const a = Buffer.from(attendu); const b = Buffer.from(signature); return a.length === b.length && crypto.timingSafeEqual(a, b); } // IMPORTANT : vérifiez sur le corps BRUT (le texte exact reçu), jamais sur un JSON ré-sérialisé app.post("/webhooks/ndsgpay", express.raw({ type: "application/json" }), (req, res) => { const corps = req.body.toString("utf8"); const entete = req.headers["x-ndsgpay-signature"] || ""; if (!verifierSignatureNdsgpay(corps, entete, process.env.NDSGPAY_WEBHOOK_SECRET)) { return res.sendStatus(400); } const evenement = JSON.parse(corps); // ... mettez à jour votre commande avec evenement.data.depositId (ou payoutId) et evenement.data.status res.sendStatus(200); });
Membres de l'équipe
Chargement…
Caisses POS
Clés API restreintes pour vos caissiers
Chargement...
Informations du compte
NDSGPay enverra un POST sur cette URL à chaque transaction confirmée ou échouée.
Secret de signature webhook
Webhook secret
••••••••••••••••••••••••
Utilisez ce secret pour vérifier l'authenticité des webhooks NDSGPay. Header : X-NDSGPay-Signature
Environnement
Le passage en production nécessite la validation de votre dossier KYC par l'équipe NDSG.
Sécurité