NaabigaPay · Node.js
QuickstartsDocs

DocsQuickstarts › Node.js

Backend

Intégrer NaabigaPay en Node.js

Votre serveur Express détient la clé secrète : il crée les liens de paiement et vérifie les webhooks.

Deux choses à faire côté serveur : créer un lien de paiement quand un client veut payer, puis vérifier la signature du webhook que NaabigaPay envoie une fois le paiement réussi. La clé secrète (sk_live_…) reste sur ce serveur et n'est jamais exposée au navigateur.

1.Créer le lien

Votre front (web ou mobile) appelle cette route ; c'est elle qui appelle POST/v1/payment-links avec la clé secrète, puis renvoie l'url de paiement.

Node.js · Express
// npm i express node-fetch  (Node 18+ : fetch est déjà global)
import express from 'express';
import fetch from 'node-fetch';

const app = express();
app.use(express.json());

const NPAY = 'https://api.pay.naabiga.com/api/v1';
const SECRET = process.env.NPAY_SECRET; // sk_live_... : ne quitte jamais le serveur

// Votre application appelle CETTE route, jamais NaabigaPay directement.
app.post('/api/pay', async (req, res) => {
  const { commande, amount } = req.body;
  const r = await fetch(`${NPAY}/payment-links`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${SECRET}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': `cmd-${commande}`, // évite un double lien en cas de retry
    },
    body: JSON.stringify({
      amount,                              // entier, en FCFA
      reference: commande,                 // votre numéro de commande
      description: `Commande ${commande}`,
      return_url: 'https://monsite.com/merci',
      cancel_url: 'https://monsite.com/panier',
      single_use: true,
    }),
  });
  if (!r.ok) return res.status(502).json({ error: await r.text() });
  const link = await r.json();
  res.json({ url: link.url }); // le front ouvre cette URL
});

La réponse contient url (ex. https://pay.naabiga.com/link/9f3c…) : la page où le client paie. Pour un montant libre, remplacez amount par amount_min, amount_max et une description.

2.Vérifier le webhook

NaabigaPay envoie POST à l'URL enregistrée dans le portail marchand, avec les en-têtes X-NPay-Event et X-NPay-Signature (HMAC-SHA256 du corps brut). Utilisez express.raw pour disposer du corps brut, recalculez le HMAC, comparez en temps constant, et ne créditez qu'ensuite.

Node.js · webhook
import crypto from 'crypto';

const WEBHOOK_SECRET = process.env.NPAY_WEBHOOK_SECRET;

// express.raw (et non express.json) : la signature porte sur le corps BRUT.
app.post('/webhooks/naabiga', express.raw({ type: '*/*' }), (req, res) => {
  const signature = req.get('X-NPay-Signature') || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)          // req.body est un Buffer (corps brut, non modifié)
    .digest('hex');

  const a = Buffer.from(signature);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(400).send('signature invalide');
  }

  const payload = JSON.parse(req.body.toString('utf8'));
  if (req.get('X-NPay-Event') === 'payment.succeeded') {
    // Créditez selon le montant de VOTRE commande (payload.reference), pas celui du corps.
    marquerCommandePayee(payload.reference);
  }
  res.sendStatus(200);
});

Astuce. Déclarez la route webhook avant tout express.json() global, sinon le corps est déjà transformé et la signature ne correspond plus.

Référence rapide

MéthodeEndpointRôle
POST/v1/payment-linksCréer un lien de paiement
GET/v1/payments/{reference}Statut d'un paiement

Base : https://api.pay.naabiga.com/api/v1 · Auth : Authorization: Bearer sk_…. Voir la documentation complète et le format des webhooks.