Aller au contenu

Sessions et sécurité

Où utiliser chaque clé, comment créer un jeton de session, ce qu'il permet de faire et où le checkout peut être intégré.

Toutes les fonctionnalités Wajub côté navigateur reposent sur une chaîne à courte durée de vie : le jeton de session. Cette page explique son origine, ce qu'il remplace et pourquoi la clé qui le crée ne doit jamais quitter votre serveur.

Trois identifiants, trois emplacements

Le préfixe d'une clé Wajub indique à lui seul où la clé peut être utilisée. Les clés live commencent par sk. ou pk., les clés de sandbox par sk_test. ou pk_test..

IdentifiantFormatEmplacementPossibilités
Clé publiquepk. ou pk_test.Navigateur, votre HTMLCréer une session, rien d'autre
Clé secrètesk. ou sk_test.Serveur, variable d'environnementTout faire sur l'API
Jeton de sessionauthorization_tokenNavigateur, comme sessionIdRégler un seul paiement, une seule fois

Grâce au jeton de session, les deux autres clés sont inutiles dans le navigateur. Il est limité à un seul paiement, ne donne aucun accès au compte et expire avec ce paiement.

Le flux correct

Respectez toujours ces deux étapes dans cet ordre.

  1. Votre serveur appelle POST /payments avec la clé secrète et reçoit un authorization_token.
  2. Votre navigateur reçoit uniquement ce jeton et le transmet comme sessionId.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.xxxxxxxxxxxxxxxx…" \
-H "Content-Type: application/json" \
-d '{
  "amount": 35000,
  "currency": "XOF",
  "reference": "ORDER-123",
  "customer": { "email": "buyer@example.com" }
}'

La réponse contient trois éléments à conserver.

ChampUtilité
authorization_tokenLe sessionId du navigateur. Envoyez-lui uniquement cette valeur
authorization_urlLa page hébergée pour un checkout avec redirection
transaction.idVotre clé de rapprochement à la réception du webhook
Étape 2, dans le navigateur
const { sessionId } = await fetch('/api/checkout/session', { method: 'POST' })
  .then((r) => r.json());

await mount('#checkout', { sessionId });

Avant que la commande existe

Les champs de paiement affichés pendant que l'acheteur est encore sur le checkout précèdent la commande. Créez leur session avec deferred: true : le paiement est seulement préparé, reste hors de vos paiements et n'envoie aucun webhook tant que votre serveur ne l'a pas activé avec le total final et le client. Avant que la commande existe détaille les trois appels.

Créer une session depuis le navigateur

Wajub(publishableKey).createPayment() crée la session depuis la page, avec une clé publique, de sandbox ou live. Cet outil convient à un prototype ou à une page de démonstration dont le prix est fixe. Il ne convient pas à une boutique, car le montant serait alors défini par du code que le client contrôle.

Depuis la page
const client = Wajub('pk_test.xxxxxxxxxxxxxxxx…');

const { sessionId } = await client.createPayment({
  amount: 35000,
  currency: 'XOF',
  customer: { email: 'buyer@example.com' },
});

await client.mount('#checkout');

Ce que le jeton permet de faire

Le jeton de session autorise exactement un paiement.

  • Il monte le checkout, ouvre la superposition ou pilote les composants de champs.
  • Il lit l'aperçu de la session avec fetchSession(sessionId).
  • Sur un paiement préparé, il affiche les moyens de paiement et ne débite rien tant que votre serveur n'a pas activé le paiement. L'activation conserve le jeton.
  • Il reste valide tant que le paiement n'a pas atteint un état final, puis expire peu après succeeded, failed, expired ou cancelled.
  • Il reste valide après un nouveau montage. Un composant démonté puis remonté réutilise donc le même jeton.
  • Il vit aussi longtemps que le paiement : 24 heures par défaut, ou les expires.in minutes fixées sur POST /payments (de 5 à 43 200). Au-delà, le paiement expire, onExpired se déclenche sur le checkout et un champ de paiement rejette avec session_expired.
  • Les tentatives de paiement sur une session sont limitées. Au-delà de la limite, la tentative est refusée avec rate_limited jusqu'à ce qu'un court délai soit écoulé.

Monter un jeton qui n'est plus valide appelle onLoadError avec session_terminal_expired, et un jeton que Wajub ne connaît pas l'appelle avec session_not_found. L'intégration elle-même reste vide. Configurez donc ce callback, même sur une page où vous pensez que ce cas ne peut pas se produire. Tant que le jeton est valide, un checkout monté sur un paiement terminé signale plutôt son résultat, par onSuccess, onError, onExpired ou onCancel.

L'URL de callback

callback est une destination de redirection. Elle ne concerne donc que le flux avec redirection. Transmettez une URL HTTPS de base sans vos propres paramètres d'URL. Wajub ajoute les siens.

Paramètre d'URLValeurs
statussucceeded, cancelled, failed, expired
referenceL'identifiant Wajub du paiement, celui que prend GET /payments/{id}, si disponible
trxrefVotre propre référence, si disponible

Chaque retour porte reference et trxref, y compris après un paiement échoué.

Destination du payeur
https://shop.example.com/order/complete?status=succeeded&reference=trx_CSUGajfv9xh0XQ5wu2lx&trxref=ORDER-123

L'intégration du checkout hébergé ne quitte jamais votre page, callback n'y a donc aucun effet. Utilisez onSuccess pour l'interface et le webhook comme source fiable. Les champs de paiement font exception : un paiement qui se poursuit sur la page du prestataire, un paiement en crypto par exemple, y emmène votre page, et le payeur revient sur callback, avec les paramètres ci-dessus ou, selon le moyen de paiement, sans eux. Quand le paiement se poursuit sur la page du prestataire explique ce que cette page doit faire.

Où le checkout peut être intégré

Paramètres → Intégration de la page de paiement contient les sites autorisés à intégrer votre checkout : jusqu'à 20 origines, chacune écrite https://domaine, avec un port facultatif et sans chemin. La page existe sur tous les plans, Pay as you go compris, et la liste s'applique en live et en sandbox. Une fois la liste remplie, le navigateur n'affiche votre checkout et vos champs de paiement que dans une page servie depuis l'une de ces origines.

Sur toute autre origine, le cadre reste vide, et ni onReady ni onLoadError ne se déclenchent. Ajoutez chaque origine qui monte le checkout ou un champ, préproduction comprise, avant de remplir la liste.

Boutiques sur plusieurs domaines

Une boutique sur plusieurs domaines n'a aucune option à passer dans le code : le checkout et les champs fonctionnent sur la page qui les monte. Ajoutez chaque domaine dans Paramètres → Intégration de la page de paiement.

Avant de passer en live

RègleRaison
HTTPS sur votre site et pour callbackLes iframes de paiement et les redirections refusent le HTTP simple
sk. uniquement dans les variables d'environnement du serveurJamais dans un bundle ni dans une variable PUBLIC_
Seul authorization_token atteint le navigateurC'est le seul identifiant qui ne donne aucun accès sensible
Montage par le SDKLe checkout ne fonctionne que lorsque le SDK le monte
Confirmation par webhookonSuccess est un événement du navigateur, qui peut être fermé

Que pensez-vous de ce contenu ?