Aller au contenu

Dépannage de Wajub Components

Le symptôme, sa cause et la ligne qui le corrige.

Presque tous les problèmes de Wajub Components proviennent de quatre causes : un jeton qui n'est plus valide, une page qui a chargé le SDK sur le serveur, un callback non configuré ou une clé de configuration que le SDK ne reconnaît pas. Commencez ici avant de lire le code.

Rien ne s'affiche

SymptômeCauseCorrection
Conteneur vide sans erreurJeton inconnu, ou jeton qui n'est plus valide parce que son paiement est terminéConfigurez onLoadError. Il contient session_not_found ou session_terminal_expired
Intégration embed incorrecte (Embed configuration error en anglais)URL de checkout collée manuellement dans une iframeAppelez mount(), open() ou CheckoutEmbed
Aucune action ni requête réseaumount() s'est exécuté sur le serveurImportez depuis @wajub/js/pure ou marquez le fichier avec 'use client'
Error lors de l'appelAucun sessionId ou sélecteur sans correspondancewindow.wajub la lève de façon synchrone ; les helpers de @wajub/js (mount(), open()…) sont asynchrones et renvoient plutôt une promesse rejetée : attendez-les avec await dans un try
L'iframe n'apparaît jamaisload_error dans onLoadErrorL'origine du checkout est inaccessible. Vérifiez l'onglet réseau et les règles de contenu
Un cadre vide sur un site, normal sur un autre, sans aucun callbackParamètres → Intégration de la page de paiement ne contient pas l'origine de cette pageAjoutez https:// suivi du domaine, port compris s'il y en a un. Où le checkout peut être intégré
La console signale une violation de Content Security PolicyLa politique de votre page n'autorise pas les hôtes de WajubAutorisez les hôtes listés dans Content Security Policy

onLoadError explique une intégration vide

onError concerne les paiements qui échouent. onLoadError concerne les checkouts qui ne démarrent jamais, comme dans la plupart des lignes ci-dessus. Configurez-le en premier dans chaque intégration.

Clés

Les clés live commencent par pk. ou sk., les clés de sandbox par pk_test. ou sk_test..

SymptômeCauseCorrection
secret_key_in_browserClé secrète transmise à Wajub()Le navigateur reçoit un jeton de session, jamais une clé secrète
invalid_publishable_keyLa valeur n'est pas une clé publiqueElle commence par pk et ne correspond pas au jeton de session
missing_publishable_keyAppel de createPayment() sans cléConfigurez-la sur le client ou créez la session sur votre serveur
Réponse 403 de l'API et e-mailClé secrète envoyée depuis un navigateurL'API la refuse et alerte son propriétaire. Renouvelez la clé
CORS sur createPaymentAppel direct de l'API depuis le code de la pageCréez la session sur votre backend

Pour distinguer la sandbox du mode live dans le navigateur, lisez la session plutôt que la clé.

La session connaît l'environnement
import { fetchSession } from '@wajub/js';

const preview = await fetchSession(sessionId);
if (preview.environment === 'sandbox') showSandboxBanner();

Champs de paiement

SymptômeCauseCorrection
complete ne devient jamais trueChamp obligatoire encore vide ou invalideEnregistrez event.error dans le handler change, il identifie le champ
confirmPayment rejette avec wallet_not_supportedComposant walletApple Pay et Google Pay utilisent leur propre bouton
confirmPayment rejette avec address_not_paymentComposant addressIl collecte sans débiter. Lisez-le avec getValue()
confirmPayment rejette avec missing_componentAucun composant transmis ou composant jamais montéConservez l'instance de onInstance ou de l'événement ready
confirmation_timeoutAucun résultat reçu à temps. Le paiement continue et peut encore réussirAugmentez timeout ou transmettez 0 pour attendre indéfiniment. Avant de proposer de payer à nouveau, écoutez success ou attendez le webhook
onLoadError ou loaderror reçoit ready_timeoutLe champ n'était pas prêt avant la fin de readyTimeout : un cadre bloqué, une origine absente de Paramètres → Intégration de la page de paiement, ou une panne réseauVérifiez la console et les réglages d'intégration. Proposez un autre moyen de payer : retirez les champs, passez la commande, puis envoyez le payeur sur authorization_url. Quand le formulaire n'arrive pas
Un champ affiche, à la place de son formulaire, un message disant que le paiement a expiré, a été annulé ou a échouéSa session est déjà terminée sans paiement : loaderror avec session_terminal_expired, session_terminal_cancelled ou session_terminal_failedCréez un nouveau paiement et montez le champ sur son jeton. Un champ dont la session est déjà payée envoie ready à la place
loaderror reçoit component_origin_missingLe composant n'a pas été monté avec Wajub.js ou un paquet frameworkMontez-le avec l'un d'eux
confirmPayment rejette avec component_unmountedLe champ a quitté la page pendant que vous l'attendiez : démonté, détruit, ou son conteneur retiré par votre frameworkGardez le champ sur la page jusqu'à la fin du paiement, et verrouillez plutôt vos propres contrôles
confirmPayment rejette avec checkout_validationonBeforeSubmit a renvoyé false, a levé une exception ou a dépassé 30 secondesRépondez en moins de 30 secondes, et ne renvoyez false que si la commande a été refusée
confirmPayment rejette avec payment_error, « Validate the order before confirming this payment. »Le paiement a été préparé avec deferred: true et jamais activéActivez-le depuis votre endpoint de commande avant que onBeforeSubmit renvoie true
getValue() renvoie nullAucune valeur encore saisieLa valeur arrive au premier change. Lisez-la dans le handler
submission_failed, depuis confirmPayment() ou sur errorLe formulaire n'était pas prêt lors de votre envoi : un champ vide, incomplet ou invalide, un formulaire encore en chargement, un numéro de carte refusé, ou une fenêtre bloquée par le navigateurAffichez message, rédigé pour le payeur dans sa langue, et réactivez votre bouton
Votre bouton, pressé de nouveau pendant le paiement, ne fait rienUn paiement est en cours. Un nouvel envoi, quel que soit le moyen, ne débite pas deux fois et ne rappelle pas onBeforeSubmitComportement attendu. C'est le paiement en cours qui vous donne son résultat
Le payeur a appuyé sur Entrée dans un champ et vous n'avez rien reçuLe formulaire n'était pas prêt : le refus d'un appui sur Entrée reste dans le composantComportement attendu. Le composant montre ce qui manque, et vous n'êtes informé que des envois que vous demandez
Votre page part vers un autre site après l'envoi du payeurLe paiement se poursuit sur la page sécurisée du prestataire, pour un wallet ou un paiement en crypto par exemple, juste après l'événement redirectComportement attendu. Définissez callback sur le paiement : le payeur y revient, et vous lisez le résultat sur votre serveur. Quand le paiement se poursuit sur la page du prestataire

Style sans effet

Une clé appearance que le SDK ne reconnaît pas reste sans effet et ne lève aucune erreur. Une faute de frappe ressemble donc exactement à un bug du checkout.

SymptômeCause
Bloc rules ignoréLe sélecteur n'est pas .Input ou .Label avec au maximum un pseudo-élément autorisé
Propriété d'une règle ignoréeElle ne figure pas parmi les 31 propriétés autorisées
Image d'arrière-plan ou importation de police ignoréeCertaines valeurs sont refusées par sécurité, dont toute valeur qui chargerait une ressource externe
Clé variables ignoréeSeules les seize clés documentées sont acceptées

Les trois listes figurent dans Apparence. Le comportement propre à chaque framework est présenté dans React, Vue, Svelte et Angular.

Mise en page et dimensions

SymptômeCauseCorrection
L'intégration est coupéeParent avec overflow: hidden ou hauteur fixeLaissez le parent grandir
La page se décale au chargement du checkoutAucun espace réservé autour de votre contenuRéservez la place de votre récapitulatif, pas celle de l'intégration
Un composant de champ reste minusculeSon parent utilise display: none lors du montageMontez-le une fois visible ou après l'ouverture de l'onglet
Un écran OTP, PIN ou 3D Secure est coupé dans un composant de champParent avec une hauteur fixe ou overflow: hidden. Un tel écran est plus haut que le formulaireLaissez le parent grandir
Avec loader: 'skeleton', le formulaire s'affiche tard, sans erreurLe champ a mis longtemps à être prêt, et aucun readyTimeout n'était définiDéfinissez readyTimeout : onLoadError reçoit alors ready_timeout, et vous pouvez proposer un autre moyen de payer
Avec loader: 'skeleton', le bloc d'un champ reste plus haut que son formulaireLa hauteur réservée ne descend jamais sous le min-height propre du conteneurNe donnez pas de min-height au conteneur, ou remettez-le à 0 juste avant mount()

Paiement

SymptômeCauseCorrection
Moyen de paiement absent du checkoutLa session ne contient pas ce canalLisez fetchSession().payment_methods avant le montage
Commande livrée deux foisonSuccess et le webhook déclenchent tous deux la livraisonLivrez avec le webhook et utilisez onSuccess pour l'interface
Commande jamais livréeonSuccess s'est exécuté puis l'onglet s'est ferméMême réponse. Le navigateur n'est pas une source fiable
onError se déclenche avec un decline_codeLe prestataire a refusé le paiementretryable indique si une nouvelle tentative doit être proposée
onError se déclenche avec nothing_to_submitsubmit() n'a trouvé aucun bouton de paiement sur lequel appuyer : aucun moyen choisi, une étape d'OTP, le bouton propre d'un wallet, ou un paiement déjà en coursAppelez submit() une fois que le payeur a choisi un moyen, et pas pendant un paiement en cours

Avant de passer en live

  • onError et onLoadError sont tous deux configurés.
  • La session est créée sur votre serveur avec la clé secrète dans une variable d'environnement.
  • Votre site et votre URL de callback utilisent HTTPS.
  • La commande est livrée à la réception du webhook, pas dans le navigateur.
  • L'intégration utilise mount(), open() ou un composant de framework, jamais une URL construite à la main.
  • onBreakdown maintient votre total à jour s'il apparaît à côté d'une intégration en ligne.
  • Un paiement réel d'un petit montant a été effectué en mode live.

Les cartes et numéros Mobile Money de test figurent dans Scénarios de test.

Le problème persiste ?

Écrivez à support@wajub.com avec la référence de transaction, le domaine de votre marchand et le code de onLoadError ou onError. N'envoyez jamais de clé.

Que pensez-vous de ce contenu ?