Aller au contenu

Checkout hébergé

Trois façons d'afficher la page de paiement Wajub et les options de chacune.

Le checkout hébergé est la page de paiement complète affichée par Wajub : choix du moyen de paiement, récapitulatif de commande, OTP, 3DS. Les coupons et l'étape de livraison y sont désactivés aujourd'hui, quel que soit le contenu de la session. Vous choisissez son emplacement. La configuration reste identique dans les trois cas. Vous devez seulement choisir entre une intégration en ligne, une superposition ou une redirection.

Vous cherchez plutôt la présentation du produit ?

Cette page présente l'interface d'intégration. Pour découvrir les fonctionnalités de la page hébergée destinées au payeur et savoir quand la préférer à votre propre mise en page, consultez Paiements, Checkout hébergé.

Quelle option choisir ?

ModeAppelLe payeurÀ choisir lorsque
En lignemount(el, config)Reste sur votre pageLe checkout constitue la page
Superpositionopen(config)Reste sur votre page, dans une fenêtre modaleLe checkout interrompt une autre action
Redirectioncheckout(config)Accède à pay.wajub.comVous souhaitez écrire un minimum de code front-end

Les trois options nécessitent un sessionId, qui correspond à la valeur authorization_token de POST /payments. Aucune ne nécessite de clé.

Les modes en ligne et en superposition affichent le checkout dans un cadre de votre page. Déclarez les origines qui l'intègrent dans Settings → Checkout embedding avant d'encaisser en live : une fois la liste remplie, seules ces origines peuvent l'afficher. La page existe sur tous les plans. Voir où le checkout peut être intégré.

En ligne

mount accepte un sélecteur ou un élément et renvoie l'instance que vous pouvez ensuite piloter.

La plus petite version fonctionnelle
import { mount } from '@wajub/js';

const checkout = await mount('#checkout', {
  sessionId,
  onSuccess: () => (window.location.href = '/order/complete'),
  onError: (error) => showRetry(error),
});

Vous n'avez pas besoin de réserver la hauteur

Le SDK attribue une valeur min-height: 480px à son espace réservé de chargement et à son iframe. Il définit lui-même la hauteur réelle à chaque agrandissement du checkout. Un élément vide <div id="checkout"></div> suffit.

Deux situations échouent immédiatement : l'absence de sessionId et un sélecteur qui ne correspond à aucun élément, toutes deux avec une simple Error avant toute requête réseau. window.wajub la lève lors de l'appel ; les helpers de @wajub/js sont asynchrones, leur promesse est donc rejetée avec cette erreur.

Configuration

Chaque option ci-dessous est aussi une prop de CheckoutEmbed dans React, Vue et Svelte.

OptionTypeValeur par défautFonction
sessionIdstringObligatoireLa valeur authorization_token de votre serveur
localestringValeur de la sessionLa langue dans laquelle le checkout s'ouvre : fr, en, es, pt, ar
layoutCheckoutLayoutValeur de la sessionclassic, compact, tabs, accordion
appearanceAppearanceConfigVotre image de marque du DashboardApparence
embedOriginstringOrigine de la page actuelleVotre origine canonique pour les boutiques sur plusieurs domaines
loadingTextstringVideTexte dans l'espace réservé
showLoadingbooleantrueDéfinissez false pour afficher votre propre squelette
themeEmbedThemeDérivéeAncienne option remplie par le SDK depuis appearance

Callbacks

Callbacks à configurer dès le premier jour
await mount('#checkout', {
  sessionId,
  onReady: (instance) => (checkoutRef = instance),
  onSuccess: (transaction) => markPaidInTheInterface(transaction),
  onError: (error) => console.error(error.code, error.message),
  onLoadError: (error) => showSessionExpired(error),
  onBreakdown: (b) => (total.textContent = `${b.total.toLocaleString()} ${b.currency}`),
});
CallbackDéclenchementValeur reçue
onReadySession chargée et formulaire visibleCheckoutInstance
onSuccessPaiement réussiPaymentSuccess : id, reference, amount en unités normales…
onErrorÉchec du paiement, ou submit() sans bouton sur lequel appuyer (nothing_to_submit)WajubError
onLoadErrorLe checkout n'a pas pu démarrer : jeton inconnu, jeton qui n'est plus valide, ou refus de chargement de l'iframeWajubError
onCancelAnnulation explicite par le payeurRien
onExpiredExpiration de la session pendant le paiementRien
onBreakdownModification des totaux{ subtotal, discount, tax, total, currency }, en unités normales
onStateChangePassage du checkout à un autre état{ state, method }
onMethodChangeChoix d'un autre moyen de paiement par le payeur{ methodId, method_id }
onResizeModification de la hauteur de l'iframe, uniquement en ligneheight en pixels
onCloseFermeture de la superposition, bouton Terminé de la confirmation en ligne, ou appel à close()Rien

onLoadError contient session_not_found pour un jeton que Wajub ne connaît pas, session_terminal_expired pour un jeton dont le paiement est terminé et qui n'est plus valide, et load_error lorsque l'iframe elle-même n'a pas chargé. onError n'en reçoit aucun : il concerne un paiement qui a échoué. À partir de Wajub.js 1.6.0, juste après le callback, la superposition se ferme ou le checkout en ligne quitte la page. onClose n'est pas appelé : le checkout n'a jamais démarré, rien n'a donc été fermé. Affichez votre propre message depuis le callback.

onResize est fourni à titre informatif

Le SDK applique déjà la nouvelle hauteur à sa propre iframe. Utilisez ce callback pour déplacer un autre élément de la page, comme un récapitulatif fixe ou un pied de page, pas pour dimensionner le checkout.

onSuccess se déclenche dans un navigateur. Traitez-le comme un signal de l'interface. Livrez la commande à la réception du webhook. Il reçoit le résumé du paiement par le checkout : id est l'identifiant Wajub du paiement, celui que prend GET /payments/{id}, reference est la vôtre, et amount est en unités normales comme dans l'API.

En ligne, la confirmation garde un bouton Terminé. Quand le payeur l'utilise, onClose se déclenche et le checkout quitte la page : placez-y votre propre étape suivante.

Piloter l'instance

CheckoutInstance
checkout.getState();                  // 'COLLECTING_DETAILS', 'PROCESSING', …
checkout.update({ locale: 'en' });
checkout.update({ appearance: { colorScheme: 'dark' } });
checkout.update({ currency: 'USD' }); // multi currency sessions only
checkout.selectMethod('pm_momo');
checkout.submit();                    // presses the checkout's own pay button
checkout.retry();
checkout.cancel();
checkout.unmount();                   // off the page, the instance is kept
checkout.mount();                     // back on the page
checkout.destroy();

submit() appuie sur le bouton de paiement du moyen en cours. Le checkout valide le formulaire comme il le fait pour le payeur et affiche ses propres messages. Suivez donc le résultat avec onStateChange. S'il n'y a aucun bouton sur lequel appuyer (avant le choix d'un moyen, sur une étape d'OTP ou de confirmation, avec Apple Pay et Google Pay, qui ne répondent qu'au geste du payeur, et pendant qu'un paiement est déjà en cours), rien n'est pressé et onError reçoit une WajubError de code nothing_to_submit, à partir de Wajub.js 1.6.0. Les versions précédentes ne disaient rien.

unmount() retire le checkout de la page et conserve l'instance. mount() le remet en place, en ligne comme en superposition. À son retour, le checkout est rechargé à partir de son jeton : onReady se déclenche à nouveau, avec la locale, l'apparence et la mise en page transmises au dernier update(). En superposition, unmount() n'appelle pas onClose. Après destroy(), ou close() en superposition, mount() n'a plus d'effet.

Superposition

Même configuration, mêmes callbacks et même instance, avec la fenêtre modale en plus.

Payer sans quitter la page
import { open } from '@wajub/js';

const popup = await open({
  sessionId,
  width: 960,
  closeOnOverlay: true,
  onSuccess: (transaction) => fulfillOrder(transaction),
  onClose: () => console.log('dismissed'),
});

popup.isOpen();
OptionValeur par défautFonction
width920Largeur maximale de la fenêtre modale en pixels
height680Hauteur de la fenêtre modale en pixels
closeOnOverlayfalseFerme lors d'un clic sur l'arrière-plan
closeOnEscapetrueFerme avec la touche Échap
closeOnSuccesstrueFerme peu après l'exécution de onSuccess
closeOnCanceltrueFerme peu après l'exécution de onCancel
closeOnExpiredtrueFerme peu après l'exécution de onExpired

La fermeture de la fenêtre modale masque uniquement l'interface. La session reste ouverte jusqu'à sa réussite, son expiration ou son annulation dans le checkout. Le même jeton permet donc encore de la monter.

onResize ne se déclenche jamais en mode superposition, car la fenêtre modale possède une hauteur fixe.

Redirection

Ce mode demande le moins de code et constitue le seul où callback est utile.

Deux façons de quitter la page
// The URL your server already received from POST /payments
window.location.href = authorizationUrl;

// Or, when the browser only has the token
import { checkout } from '@wajub/js';
await checkout({ sessionId });

Le payeur revient sur l'URL de callback définie lors de la création du paiement, avec ?status=succeeded|cancelled|failed|expired, reference, l'identifiant Wajub du paiement, et trxref, votre propre référence, quelle que soit l'issue (le retour après un paiement échoué ne portait que status). Lisez le paiement avec ce reference sur votre serveur : ces paramètres d'URL sont une indication. Le webhook fournit la confirmation. Consultez Sessions et sécurité pour le contrat complet.

Style

Le checkout utilise déjà l'image de marque de votre compte, configurée une fois dans le Dashboard. Transmettez appearance uniquement pour modifier cette intégration précise, par exemple pour un bouton de mode sombre ou la couleur d'une campagne.

Remplacement propre à une intégration
await mount('#checkout', {
  sessionId,
  layout: 'tabs',
  appearance: { theme: 'night', primaryColor: '#6366f1', labels: 'floating' },
});

La liste complète des clés figure dans Apparence. Les valeurs par défaut du compte sont présentées dans Image de marque et thème.

Que pensez-vous de ce contenu ?