Concepts clés
Cycle de vie d'un paiement, environnements, jetons de session, API keys et modèle d'orchestration.
Avant d'écrire du code, prenez quelques minutes pour comprendre les concepts de base. Ensuite, chaque appel d'API et chaque événement webhook vous paraîtra clair tout de suite.
Cycle de vie d'un paiement
Un paiement est une conversation entre trois parties : votre serveur, Wajub et la personne qui paie. Chaque changement d'état vient de l'action de l'une d'elles. Le plus rapide pour comprendre le cycle de vie est donc de regarder qui fait quoi, et dans quel ordre.
Le parcours d'un paiement réussi
Six mouvements, dont deux seulement vous reviennent. Vous ouvrez le paiement, vous redirigez, puis vous attendez. Wajub choisit un prestataire, encaisse l'argent et vous dit comment tout s'est terminé.
Quand le paiement n'aboutit pas
Les trois mêmes parties, le même ordre, mais le paiement quitte le parcours idéal. Chaque sortie produit son propre événement : votre endpoint l'apprend exactement comme il apprend un succès.
Quatre états mettent fin à la tentative : succeeded, failed, cancelled et expired. Rien de ce
que fait le client ne fait sortir un paiement de ces états. pending, processing et partial sont
encore en cours : traitez-les comme ouverts, jamais comme un échec. Les remboursements sont la seule
chose qui continue après la fin : un paiement succeeded peut encore devenir refunded ou
partially_refunded des jours plus tard.
| État | Signification | Action suivante |
|---|---|---|
pending | Initialisé, en attente d'une action du client. | Redirigez le client vers la page de paiement. |
processing | Le prestataire traite le débit. | Attendez. Le webhook payment.* vous indique comment il se termine. |
succeeded | Fonds reçus. Vous pouvez livrer la commande. | Livrez le produit ou le service. |
failed | Refusé, sans réponse à temps, ou jamais transmis à un prestataire. | Affichez une erreur, proposez de réessayer. |
cancelled | Annulé par le client ou le marchand. | Aucune action nécessaire. |
expired | La fenêtre de paiement s'est fermée avant la fin. | Relancez le paiement si nécessaire. |
partial | Une partie du montant est réglée, le reste est encore en cours. | Gardez la commande ouverte. Elle peut encore atteindre succeeded. |
refunded | Un paiement réussi a été entièrement remboursé. | Gérez le retour. |
partially_refunded | Un remboursement partiel a été appliqué. | Suivez le montant restant. |
Comment un paiement passe d'un état à l'autre
- Vous appelez
POST /payments, ce qui crée une transaction enpending. - Le client effectue le paiement sur la page hébergée (
pay.wajub.com). - Wajub traite le débit avec le meilleur prestataire disponible (voir Orchestration).
- Wajub envoie un webhook
payment.succeededà votre serveur. - Vous vérifiez le statut via
GET /payments/{id}et livrez la commande.
C'est à l'étape 4 que la machine à états vous atteint. Chaque transition enregistrée par Wajub émet
un événement, et un événement livré à votre endpoint ressemble à ceci. Le type se trouve dans
event, et data contient le paiement exactement tel que GET /payments/{id} le renverrait :
Sandbox ou live
Wajub fournit deux environnements entièrement isolés. Une seule URL de base sert les deux. L'environnement est déterminé par l'API key que vous utilisez.
| Sandbox | Live | |
|---|---|---|
| Clés | pk_test.… / sk_test.… | pk.… / sk.… |
| Argent | Aucun mouvement de fonds réel | Paiements réels |
| Données de test | Numéros de téléphone de test | Données clients réelles |
| Périmètre | Paiements, remboursements, transferts, clients, webhooks | Tout, y compris les liens, les factures, les taxes et Shield |
Ne mélangez jamais les environnements
Une clé sandbox ne peut pas accéder aux données live, et inversement. Stockez les clés dans des variables d'environnement distinctes pour chaque environnement.
API keys
Trois types de clés, chacun avec un rôle précis :
Clé publique (pk.… / pk_test.…)sûre côté clientfacultatifClé privée (sk.… / sk_test.…)serveur uniquementfacultatifClé restreinte (rk.… / rk_test.…)serveur uniquementfacultatifLes clés privées sont bloquées dans les navigateurs
Wajub rejette toute requête faite avec une clé privée depuis un navigateur ou une application mobile
(détection via les en-têtes Origin/Referer). C'est un filet de sécurité. Stockez sk.… dans des
variables d'environnement. Jamais dans du code côté client.
Jetons de session
La page de checkout hébergée (pay.wajub.com) s'exécute dans le navigateur du client : elle ne peut
donc pas détenir d'API key. Elle utilise à la place un jeton de session, renvoyé par
POST /payments sous le nom authorization_token et déjà inclus dans l'authorization_url vers
laquelle vous redirigez. Le jeton est limité à un seul paiement, il ne peut rien faire d'autre que
payer ce paiement, et vous pouvez le confier sans risque à un navigateur.
Sa durée de vie suit celle du paiement. La fenêtre de paiement est de 24 heures par défaut, ajustable
de 5 minutes à 30 jours avec expires.in. Une fois que le paiement atteint un état final, le jeton
reste valable pendant un court délai de grâce : 5 minutes après un succès, pour que le payeur puisse
recharger son reçu, et 60 secondes après un échec, une annulation ou une expiration, pour qu'un
onglet de checkout encore ouvert puisse découvrir le résultat. Ensuite, il ne fonctionne plus.
Vous ne manipulez le jeton vous-même que si vous intégrez le checkout dans votre propre page au lieu de rediriger. Votre serveur crée le paiement comme d'habitude :
import { Wajub } from '@wajub/node';
const wajub = new Wajub({ apiKey: process.env.WAJUB_API_KEY! });
const payment = await wajub.payments.create({
amount: 5000,
currency: 'XAF',
customer: { email: 'amina@example.com' },
});
// Send payment.authorization_token to your frontend.Votre frontend transmet ce jeton au SDK navigateur, qui est un package différent et ne voit jamais votre API key :
import { mount } from '@wajub/js';
await mount('#checkout', { sessionId: authorizationToken });Consultez Wajub Components pour le checkout intégré complet.
Modèle d'orchestration
Quand vous traitez un paiement, Wajub ne se contente pas de le transmettre. Il l'orchestre :
- Routage : choisit le meilleur prestataire selon le canal, le pays et le montant.
- Exécution : appelle l'API du prestataire.
- Repli : si le prestataire principal échoue, réessaie avec le suivant.
- Rapprochement : associe les callbacks du prestataire à la transaction d'origine.
Tout cela est transparent pour vous. Il vous suffit de créer un paiement et d'écouter le webhook.
Suivez l'orchestration en temps réel
Ouvrez Konsole → Event Stream pour voir la décision de routage et les réponses des prestataires au moment où elles arrivent.
Identifiants de ressources
Chaque identifiant de ressource se compose d'un préfixe, puis de test_ quand l'objet vit dans la
sandbox, puis de 20 à 24 caractères aléatoires selon la ressource. Un identifiant vous indique donc
deux choses d'un coup d'œil : ce qu'il désigne, et quel environnement l'a produit. Stockez les
identifiants en texte, avec de la place pour 40 caractères.
| Préfixe | Ressource | Live | Sandbox |
|---|---|---|---|
trx_ | Transaction de paiement | trx_CSUGajfv9xh0XQ5wu2lx | trx_test_CSUGajfv9xh0XQ5wu2lx |
po_ | Transfert (payout) | po_225KMKULRQqYvlhrgUOE | po_test_225KMKULRQqYvlhrgUOE |
rfd_ | Remboursement | rfd_9xh0XQ5wu2lxCSUGajfv | rfd_test_9xh0XQ5wu2lxCSUGajfv |
ben_ | Bénéficiaire | ben_LRQqYvlhrgUOE225KMKU | ben_test_LRQqYvlhrgUOE225KMKU |
dsp_ | Litige | dsp_hrgUOE225KMKULRQqYvlh | dsp_test_hrgUOE225KMKULRQqYvlh |
pm_ | Moyen de paiement | pm_sAaim5apjocIgtlhzJY3x | pm_test_sAaim5apjocIgtlhzJY3x |
cus_ | Client | cus_sAaim5apjocIgtlhzJY3wQ8s | cus_test_sAaim5apjocIgtlhzJY3wQ8s |
evt_ | Événement webhook | evt_aio5DpN577tNU2vOxdmuZGhT | evt_test_aio5DpN577tNU2vOxdmuZGhT |
Trois ressources suivent leur propre règle. Une facture commence toujours par inv_, sans segment
d'environnement. Un lien de paiement n'a aucun préfixe : son identifiant fait neuf caractères, comme
kQ7vB4nL6, car c'est aussi l'URL publique que reçoivent les gens. Un message de litige est un UUID.
Servez-vous du préfixe comme garde-fou
Un identifiant test_ qui arrive dans votre base de données de production est un bug de
configuration, pas un paiement. Vérifier le préfixe avant de livrer une commande repère une API key
mal choisie bien avant votre comptable.
Montants
Contrairement à beaucoup de prestataires de paiement, Wajub exprime les montants dans l'unité
principale de la devise (par ex. 5000 = 5 000 XAF, et non 500 000 centimes). Les devises en franc
CFA n'ont pas de subdivision courante, ce qui évite toute confusion.
« Paiement » ou « transaction »
Wajub utilise les deux termes, et ils désignent le même objet :
- Paiement. Le concept métier. Vous créez un paiement, un client paie, vous livrez la commande.
- Transaction. La représentation interne. La réponse de l'API utilise
"transaction": {...}comme clé racine, et le champidest préfixé partrx_.
En pratique : vous appelez POST /payments, recevez transaction.id = "trx_xxx", et écoutez les
webhooks payment.succeeded. Dans cette documentation, les deux termes sont interchangeables.
Étapes suivantes
- Démarrage rapide : codez votre premier paiement.
- Orchestration : le fonctionnement du routage et du repli.
- Webhooks : recevez
payment.succeededde manière fiable.