Aller au contenu

Démarrage rapide

Votre premier paiement de bout en bout, de l'API key au webhook vérifié, en cinq minutes environ.

Ce guide vous emmène d'un compte vide à un paiement vérifié, avec un webhook qui fonctionne. Il vous faut un compte Wajub (gratuit) et quelques minutes.

1. Créez votre compte et récupérez vos clés

Créez un compte sur le Dashboard. Une fois connecté, ouvrez Settings → Developer → API Keys. Chaque compte possède quatre clés, deux par environnement :

CléEnvironnementOù l'utiliser
pk_test.…SandboxPublique. Sans risque dans un navigateur, initialise les paiements côté client.
sk_test.…SandboxPrivée. Côté serveur uniquement, aucun argent réel ne circule.
pk.…ProductionPublique. Même rôle côté client, sur des fonds réels.
sk.…ProductionPrivée. Côté serveur uniquement, déplace de l'argent réel.

Tout ce guide s'exécute sur votre serveur, il utilise donc partout la clé privée sandbox. La clé publique existe pour le seul cas où du code s'exécute dans un navigateur : initialiser un paiement depuis la page elle-même. Wajub rejette une clé privée envoyée depuis un navigateur et vous prévient par e-mail quand cela arrive, pour qu'une clé divulguée ne passe pas inaperçue.

2. Installez le SDK de votre langage

Les SDKs enveloppent la même API HTTP avec des ressources typées, une Idempotency-Key sur chaque appel qui modifie des données, un délai d'expiration par requête et la vérification de signature des webhooks. Si vous préférez appeler l'API directement, chaque exemple ci-dessous a un onglet cURL.

npm install @wajub/node

Ruby, Java, C#, Kotlin, Flutter et React Native ont leurs propres SDKs et leurs propres guides. Consultez SDKs et bibliothèques pour la liste complète et la référence de configuration.

3. Créez un paiement

Un paiement commence par une requête. Vous envoyez le montant, la devise, la personne qui paie et la page vers laquelle la renvoyer. Wajub crée le paiement, le garde en pending et répond avec une page hébergée où le client choisit son opérateur et confirme. Personne n'est encore débité.

Décrivez le payeur dans l'objet customer. L'API accepte aussi un email au premier niveau, et les deux aboutissent sur la même fiche client, mais l'objet est la structure qui évolue avec vous : il porte aussi name, phone, address et metadata.

POSThttps://api.wajub.com/payments
curl https://api.wajub.com/payments \
  -H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "currency": "XAF",
    "customer": { "email": "amina@example.com" },
    "callback": "https://shop.example.com/order/complete"
  }'

Wajub répond 201 Created avec le paiement, son id et la page vers laquelle envoyer le client :

Réponse · 201 Created
{
"code": 201,
"status": "Created",
"message": "Payment initiated",
"authorization_url": "https://pay.wajub.com/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"authorization_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"transaction": {
"id": "trx_test_CSUGajfv9xh0XQ5wu2lx",
"amount": 5000,
"amount_paid": 0,
"currency": "XAF",
"status": "pending",
"customer": {
"id": "cus_test_sAaim5apjocIgtlhzJY3wQ8s",
"email": "amina@example.com"
},
"callback": "https://shop.example.com/order/complete",
"sandbox": true,
"created_at": "2026-09-11T10:24:00Z"
}
}

Enregistrez transaction.id avec votre commande, puis redirigez le client vers authorization_url.

Les montants sont en unité principale, jamais en centimes

"amount": 5000 signifie 5 000 XAF, pas 50 XAF. Wajub n'utilise jamais de sous-unités. Envoyez 500 pour 500 NGN et 10.50 pour 10,50 USD. Consultez Concepts clés → Montants.

4. Payez avec un numéro sandbox

Ouvrez authorization_url dans votre navigateur. En mode test, la page de paiement accepte de faux numéros Mobile Money dont les 6 derniers chiffres décident du résultat. Les mêmes suffixes fonctionnent pour tous les opérateurs et tous les pays :

SuffixeRésultat
000000Paiement réussi
000001Fonds insuffisants
000002Échec, refusé par l'opérateur
000003Délai dépassé
000004En attente → annulé
000009Le paiement réussit, un remboursement ultérieur échoue

Choisissez un numéro pour l'opérateur que vous voulez tester :

Pays et opérateurPréfixeExemple, succès
Cameroun, MTNCameroun / MTN+23767+237670000000
Cameroun, OrangeCameroun / Orange+23769+237690000000
Côte d'Ivoire, MTNCôte d'Ivoire / MTN+22505+225050000000
Côte d'Ivoire, OrangeCôte d'Ivoire / Orange+22507+225070000000
Côte d'Ivoire, WaveCôte d'Ivoire / Wave+22503+225030000000
Sénégal, OrangeSénégal / Orange+22177+221770000000
Ghana, MTNGhana / MTN+23324+233240000000
Nigeria, MTNNigeria / MTN+2348+2348000000000
Kenya, M-PesaKenya / M-Pesa+25470+254700000000
Ouganda, MTNOuganda / MTN+25677+256770000000

N'importe quel code PIN est accepté sur la page de paiement sandbox.

5. Vérifiez le paiement côté serveur

Le client revient sur votre URL de callback, et ce retour ne prouve rien. N'importe qui peut ouvrir cette URL à la main, et un client qui ferme l'onglet ne l'ouvre jamais. Avant de livrer une commande, demandez à l'API ce qui s'est réellement passé, depuis votre serveur, avec l'id enregistré à l'étape 3.

GEThttps://api.wajub.com/payments/{id}
curl https://api.wajub.com/payments/trx_test_CSUGajfv9xh0XQ5wu2lx \
  -H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…"

La réponse contient le paiement tel que Wajub le connaît, quoi qu'ait affiché votre navigateur :

Réponse · 200 OK
{
"code": 200,
"status": "OK",
"message": "Payment retrieved",
"transaction": {
"id": "trx_test_CSUGajfv9xh0XQ5wu2lx",
"amount": 5000,
"amount_paid": 5000,
"currency": "XAF",
"status": "succeeded",
"channel": "cm.mtn",
"customer": {
"id": "cus_test_sAaim5apjocIgtlhzJY3wQ8s",
"email": "amina@example.com"
},
"sandbox": true,
"created_at": "2026-09-11T10:24:00Z"
}
}

Ne livrez la commande que lorsque status vaut succeeded, et seulement après avoir vérifié que amount et currency correspondent à ce que vous avez facturé. Un paiement encore en pending n'est pas un échec : c'est un client qui n'a pas encore terminé. Laissez donc la commande ouverte, et laissez le webhook de l'étape 6 vous prévenir quand le paiement aboutit.

Suivez la transaction dans Konsole

Ouvrez Konsole → API Logs pour voir la requête et la réponse exactes enregistrées par Wajub, ou le Routing Log pour voir quel prestataire a été choisi, et pourquoi.

6. Configurez un endpoint de webhook

Interroger l'API après chaque redirection ne couvre que les clients qui reviennent. Les webhooks couvrent le reste : un paiement confirmé dix minutes plus tard côté opérateur, un remboursement émis depuis le Dashboard, un litige ouvert par le client. Configurez-en un maintenant, avant de construire quoi que ce soit par-dessus.

Enregistrez l'endpoint

Dans Konsole → Webhooks → Endpoints (ou Settings → Developer → Webhooks dans le Dashboard) :

  1. Cliquez sur Add Endpoint.
  2. Saisissez votre URL publique, par exemple https://yourapp.com/webhooks/wajub.
  3. Sélectionnez les événements à recevoir. Commencez par payment.* pour tous les événements de paiement.
  4. Enregistrez, puis copiez le Signing Secret (whsec_…) dans votre environnement sous le nom WAJUB_WEBHOOK_SECRET.

Donnez le secret de signature au SDK

Le client que vous avez créé à l'étape 3 vérifie aussi les webhooks, dès qu'il connaît le secret de signature. Ajoutez-le au même constructeur, à côté de votre API key :

import { Wajub } from '@wajub/node';

export const wajub = new Wajub({
  apiKey: process.env.WAJUB_API_KEY!,
  webhookSecret: process.env.WAJUB_WEBHOOK_SECRET!,
});

Écrivez l'endpoint

Quatre règles rendent un endpoint de webhook correct, et le SDK ne gère que la première à votre place.

Vérifiez la signature, dans tous les environnements. Un endpoint qui saute la vérification accepte tout ce que n'importe qui lui envoie, y compris un faux payment.succeeded. constructEvent recalcule le HMAC sur X-Wajub-Timestamp et le corps brut, le compare à X-Wajub-Signature, rejette tout ce qui date de plus de cinq minutes, et seulement ensuite analyse le JSON. Il lui faut le corps brut : désactivez donc l'analyse du corps JSON sur cette route.

Accusez réception avant de travailler. Wajub attend votre 2xx pendant 10 secondes. Au-delà, la livraison compte comme échouée et fait l'objet d'une nouvelle tentative : répondez d'abord, et faites le travail lent ensuite, dans une file d'attente ou une goroutine.

Dédupliquez sur l'id de livraison. Une livraison échouée est retentée jusqu'à 5 fois, avec des écarts de 30 s, 1 min, 5 min, 10 min puis 1 h, et chaque tentative porte le même X-Wajub-Delivery-Id. C'est cet id qui empêche une nouvelle tentative de livrer deux fois la même commande.

Traitez ensuite l'événement. Le type se trouve dans event.event, et event.data contient l'objet concerné par l'événement, avec la même forme que celle renvoyée par l'API. Pour payment.succeeded, event.data.id est l'id du paiement enregistré à l'étape 3.

app.post('/webhooks/wajub', express.raw({ type: '*/*' }), async (req, res) => {
  const event = wajub.webhooks.constructEvent(
    req.body,
    req.headers['x-wajub-signature'],
    req.headers['x-wajub-timestamp'],
  );

  res.sendStatus(200);

  const deliveryId = req.headers['x-wajub-delivery-id'];

  if (await alreadyHandled(deliveryId)) return;

  await markHandled(deliveryId);

  if (event.event === 'payment.succeeded') {
    await fulfillOrder(event.data.id);
  }
});

Recevez les événements sur votre machine

Pas besoin d'URL publique, de déploiement ni d'endpoint enregistré pour commencer. La CLI ouvre une connexion sortante vers Wajub et envoie chaque événement sandbox à une adresse locale :

npm install -g @wajub/cli
wajub listen --forward-to http://localhost:3000/webhooks/wajub

Rien sur votre machine n'est exposé à Internet. wajub listen affiche le secret de signature avec lequel il signe les événements transférés : c'est ce secret que doit contenir votre WAJUB_WEBHOOK_SECRET local pendant que vous développez. Passez plutôt --secret whsec_… pour réutiliser le secret d'un endpoint enregistré. Consultez la commande CLI listen pour toutes les options.

Guide complet des webhooks

Vérification de signature, politique de nouvelles tentatives, catalogue d'événements et idempotence : tout est traité dans la section Webhooks.

Et maintenant ?

Checklist d'intégration

0/4
  • Inscrivez-vous sur le Dashboard Wajub et récupérez vos API keys sandbox.

    Voir le guide →
  • Initialisez une transaction sandbox avec votre clé publique.

    Voir le guide →
  • Abonnez-vous aux événements payment.succeeded et payment.failed.

    Voir le guide →
  • Remplacez les clés de test par les clés live, puis déployez en production.

    Voir le guide →

Que pensez-vous de ce contenu ?