Aller au contenu

React

Provider, hooks, props d'intégration et configuration Next.js associée.

@wajub/react enveloppe @wajub/js avec la syntaxe React : un provider qui charge une fois l'environnement d'exécution, cinq composants de champs et quatre hooks. L'API de paiement ne change pas. Le comportement de chaque option est présenté dans Checkout hébergé et Champs de paiement. Cette page traite des éléments propres à React.

@wajub/react

Stable · GA

npm

Version
1.4.0
Runtime
React 18+ · Next.js 13+

Couvre

  • Paiements
  • Liens de paiement

Absent de ce paquet : Facturation, Transferts, Sync, Shield, Taxes.

Installer

@wajub/js est une dépendance homologue, non intégrée. Installez-la donc sur la même ligne. Le package est uniquement ESM et déclare sideEffects: false.

npm install @wajub/react @wajub/js

Provider

WajubProvider appelle loadWajub() depuis @wajub/js/pure et conserve l'environnement d'exécution dans le contexte. Un provider couvre toute une sous-arborescence. Placez-le donc au niveau de la mise en page ou de la page, pas autour de chaque composant.

app/checkout/layout.tsx
'use client';

import { WajubProvider } from '@wajub/react';

export default function CheckoutLayout({ children }: { children: React.ReactNode }) {
  return <WajubProvider>{children}</WajubProvider>;
}
PropTypeValeur par défautFonction
loadOptions{ jsOrigin?, jsUrl? }Valeurs du CDNRemplace l'origine de chargement de l'environnement d'exécution
deferbooleanfalseIgnore le chargement automatique et le confie à useLoadWajub()

Utilisez defer si un parent a déjà chargé l'environnement d'exécution ou si le chargement doit attendre une action de l'utilisateur. Sans cette option, le provider commence le chargement dès son montage.

Hooks

La forme sûre
import { useWajubOptional } from '@wajub/react';

function UpgradeButton({ sessionId }: { sessionId: string }) {
  const runtime = useWajubOptional();

  return (
    <button
      disabled={!runtime}
      onClick={() => runtime?.wajub.open({ sessionId, onSuccess: onUpgraded })}
    >
      Upgrade plan
    </button>
  );
}
HookValeur renvoyéeRemarques
useWajub(){ wajub, Wajub, WajubError }Génère une erreur pendant le chargement, en cas d'échec ou sans environnement
useWajubOptional()La même valeur ou nullSûr pendant le SSR et avant l'arrivée du script
useLoadWajub(){ runtime, loading, error, loadWajub }Vous laisse piloter le chargement avec defer
useConfirmPayment(sessionId){ confirm, isConfirming }Envoie un composant de champ monté

loading et error proviennent directement du contexte du provider. useLoadWajub() permet donc aussi d'afficher un indicateur de chargement ou une nouvelle tentative pendant l'arrivée de l'environnement.

CheckoutEmbed

Le checkout hébergé dans votre propre mise en page. Chaque option de EmbeddedConfig est une prop. L'enveloppe en ajoute quatre autres.

app/checkout/CheckoutClient.tsx
'use client';

import { CheckoutEmbed } from '@wajub/react';

export function CheckoutClient({ sessionId }: { sessionId: string }) {
  return (
    <CheckoutEmbed
      sessionId={sessionId}
      layout="tabs"
      minHeight={480}
      onSuccess={() => (window.location.href = '/order/complete')}
      onError={(error) => console.error(error.code, error.message)}
    />
  );
}
PropTypeValeur par défautFonction
sessionIdstringObligatoireLa valeur authorization_token de POST /payments
classNamestringaucuneClasse de l'élément conteneur
styleCSSPropertiesaucunStyles en ligne du conteneur
minHeightnumber480Hauteur réservée en pixels pendant le chargement de l'iframe
onReady(instance) => voidaucunReçoit la CheckoutInstance à piloter ensuite
Changer de thème après le montage
const checkout = useRef<CheckoutInstance | null>(null);

<CheckoutEmbed sessionId={sessionId} onReady={(instance) => (checkout.current = instance)} />;

useEffect(() => {
  checkout.current?.update({ appearance: { colorScheme: dark ? 'dark' : 'light' } });
}, [dark]);

Champs de paiement

Les cinq composants affichent chacun un groupe de champs : CardComponent, MobileMoneyComponent, WalletComponent, PaymentComponent et AddressComponent. Ils partagent les props de ComponentConfig, avec les props du wrapper ci-dessous. ComponentEmbed est le même composant avec un type explicite lorsque le choix intervient pendant l'exécution.

Votre mise en page et votre bouton
'use client';

import { useRef } from 'react';
import type { ComponentInstance } from '@wajub/js';
import { PaymentComponent, useConfirmPayment } from '@wajub/react';

export function PayForm({ sessionId }: { sessionId: string }) {
  const { confirm, isConfirming } = useConfirmPayment(sessionId);
  const field = useRef<ComponentInstance | null>(null);

  return (
    <>
      <PaymentComponent
        sessionId={sessionId}
        collectAddress="shipping"
        collectName
        onInstance={(instance) => (field.current = instance)}
      />
      <button
        onClick={() => field.current && confirm(field.current)}
        disabled={isConfirming}
      >
        {isConfirming ? 'Processing…' : 'Pay now'}
      </button>
    </>
  );
}
PropTypeValeur par défautFonction
typeComponentTypeDéfinie par l'aliasUniquement sur ComponentEmbed
minHeightnumber200Hauteur réservée pendant le chargement du champ
onInstance(instance | null) => voidaucuneSe déclenche au montage, puis avec null au démontage
onReady(instance) => voidaucuneSe déclenche lorsque le champ devient interactif

useConfirmPayment protège contre les doubles envois. Un second clic lorsque isConfirming vaut true est ignoré. Il réussit avec { status } et rejette avec une WajubError, dont confirmation_timeout après 60 secondes.

Les composants de champs se mettent à jour sur place

Contrairement à l'intégration, ils surveillent appearance, locale et layout, puis appellent update() avec les trois valeurs lorsque l'une change. La modification de sessionId ou type remonte plutôt le champ.

Next.js

La session est créée sur votre serveur. Aucun élément de ce package ne nécessite ni ne doit recevoir de clé secrète.

app/api/checkout/session/route.ts
import { NextResponse } from 'next/server';
import { Wajub } from '@wajub/node';

const wajub = new Wajub({ secretKey: process.env.WAJUB_SECRET_KEY! });

export async function POST(req: Request) {
  const { cartId } = await req.json();

  const payment = await wajub.payments.create(
    {
      amount: 25000,
      currency: 'XAF',
      description: `Cart ${cartId}`,
      callback: `${process.env.NEXT_PUBLIC_APP_URL}/order/return`,
      metadata: { cart_id: cartId },
    },
    { idempotencyKey: `cart-${cartId}` },
  );

  return NextResponse.json({ sessionId: payment.authorization_token });
}

L'App Router impose trois autres règles :

  • Tous les composants de cette page sont des composants client. Marquez le fichier avec 'use client' ou importez-le depuis un fichier qui le fait.
  • Placez WajubProvider dans une mise en page pour éviter qu'une navigation dans le flux de checkout recharge l'environnement d'exécution.
  • Transmettez sessionId comme prop depuis un composant serveur ou récupérez-le depuis la route ci-dessus.

Éléments exportés par le package

ExportDescription
WajubProviderCharge une fois l'environnement d'exécution pour la sous-arborescence
CheckoutEmbedCheckout hébergé en ligne
CardComponent, MobileMoneyComponent, WalletComponent, PaymentComponent, AddressComponentUn groupe de champs chacun
ComponentEmbedLe même composant avec le type transmis comme prop
useWajub, useWajubOptional, useLoadWajubDonnent accès à l'environnement d'exécution
useConfirmPaymentEnvoie un composant de champ
WajubContext, useWajubContextContexte brut pour votre propre hook

Les types sont inclus : WajubProviderProps, CheckoutEmbedProps, ComponentEmbedProps et WajubContextValue, avec tous les exports de @wajub/js.

Que pensez-vous de ce contenu ?