Sessions et sécurité
Où utiliser chaque clé, comment créer un jeton de session et ce qu'il permet de faire.
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
Une clé Wajub se compose d'un préfixe, d'un point, puis de 96 caractères. Le préfixe indique à lui seul où la clé peut être utilisée.
| Identifiant | Format | Emplacement | Possibilités |
|---|---|---|---|
| Clé publique | pk. ou pk_test. | Navigateur, votre HTML | Créer une session, rien d'autre |
| Clé secrète | sk. ou sk_test. | Serveur, variable d'environnement | Tout faire sur l'API |
| Jeton de session | authorization_token | Navigateur, comme sessionId | Ré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.
Une clé secrète dans un navigateur est refusée et signalée
L'API répond 403 à toute requête qui contient sk. ou sk_test. avec un en-tête Origin ou
Referer. Le propriétaire de la clé reçoit aussi une alerte par e-mail. Le SDK la refuse avant
même l'appel avec une erreur secret_key_in_browser. Vous ne devriez jamais compter sur ces protections.
Le flux correct
Respectez toujours ces deux étapes dans cet ordre.
- Votre serveur appelle
POST /paymentsavec la clé secrète et reçoit unauthorization_token. - Votre navigateur reçoit uniquement ce jeton et le transmet comme
sessionId.
curl https://api.wajub.com/payments \
-H "Authorization: sk_test.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-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.
| Champ | Utilité |
|---|---|
authorization_token | Le sessionId du navigateur. Envoyez-lui uniquement cette valeur |
authorization_url | La page hébergée pour un checkout avec redirection |
transaction.id | Votre clé de rapprochement à la réception du webhook |
const { sessionId } = await fetch('/api/checkout/session', { method: 'POST' })
.then((r) => r.json());
await mount('#checkout', { sessionId });Créer une session depuis le navigateur
Wajub(publishableKey).createPayment() existe et fonctionne. 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.
const client = Wajub('pk_test.mT9xW2kQ7vB4nL6hR1cY8dF3jS5aG0eU2pA…');
const { sessionId } = await client.createPayment({
amount: 35000,
currency: 'XOF',
customer: { email: 'buyer@example.com' },
});
await client.mount('#checkout');Le prix fait partie du périmètre de confiance
Une clé publique ne peut pas lire votre compte, mais elle peut ouvrir un paiement pour tout montant demandé par la page. Toute valeur qu'un client pourrait modifier à son avantage doit être définie sur votre serveur.
Ce que le jeton permet de faire
Le jeton de session autorise exactement un paiement. L'environnement d'exécution applique cette limite.
- Il monte le checkout, ouvre la superposition ou pilote les composants de champs.
- Il lit l'aperçu de la session avec
fetchSession(sessionId). Le même jeton sert d'identifiant bearer auprès de l'origine du checkout. - Il reste valide tant que le paiement n'a pas atteint un état final, puis expire peu après
succeeded,failed,expiredoucancelled. - Il reste valide après un nouveau montage. Un composant démonté puis remonté réutilise donc le même jeton.
Un jeton arrivé à son état final déclenche onLoadError au lieu d'afficher une intégration vide.
Configurez donc ce callback, même sur une page où vous pensez que ce cas ne peut pas se produire.
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'URL | Valeurs |
|---|---|
status | complete, cancelled, failed, expired |
reference | La référence de transaction Wajub, si disponible |
trxref | Votre propre référence, si disponible |
https://shop.example.com/order/complete?status=complete&reference=trx_CSUGajfv9xh0XQ5wu2lx&trxref=ORDER-123status=complete est une indication, pas une preuve de paiement
Il s'agit d'un paramètre dans une URL que le payeur peut modifier. Livrez la commande lorsque
payment.succeeded arrive sur votre endpoint, ou lorsqu'un
appel serveur GET /payments/{id} le confirme.
Une intégration ne quitte jamais votre page, callback n'y a donc aucun effet. Utilisez onSuccess
pour l'interface et le webhook comme source fiable.
Boutiques sur plusieurs domaines
Le SDK envoie l'origine de la page actuelle au checkout. Un domaine unique ne demande donc aucune configuration. Si votre checkout s'exécute sur un second domaine, indiquez explicitement le domaine canonique.
await mount('#checkout', { sessionId, embedOrigin: 'https://shop.example.com' });
const factory = await components(sessionId, {
componentOrigin: 'https://shop.example.com',
});Avant de passer en live
| Règle | Raison |
|---|---|
HTTPS sur votre site et pour callback | Les iframes de paiement et les redirections refusent le HTTP simple |
sk. uniquement dans les variables d'environnement du serveur | Jamais dans un bundle ni dans une variable PUBLIC_ |
Seul authorization_token atteint le navigateur | C'est le seul identifiant qui ne donne aucun accès sensible |
| Montage par le SDK | Une URL de checkout construite à la main renvoie une erreur d'intégration |
| Confirmation par webhook | onSuccess est un événement du navigateur, qui peut être fermé |