Aller au contenu

WordPress et WooCommerce

Un plugin, neuf intégrations et les hooks nécessaires pour créer la vôtre.

Le plugin Wajub ajoute Wajub comme moyen de paiement aux plugins d'e-commerce, de dons, de LMS, d'adhésion et de formulaires déjà installés sur votre site WordPress, et vous donne des shortcodes pour tout le reste. Un jeu de clés et un webhook suffisent pour toutes les intégrations.

Fonctionnement du plugin

Neuf intégrations fournissent une véritable passerelle. Chacune s'active lorsque le plugin correspondant est actif.

IntégrationCheckoutRemboursements depuis WordPress
WooCommerceRedirection, en ligne, superposition, moyens séparés Mobile Money et Carte bancaire, BlocksOui
Easy Digital DownloadsRedirectionOui, chaque remboursement fait dans EDD
GiveWP 3.xRedirectionOui
GiveWP avant 2.18RedirectionOui, au changement de statut
CharitableRedirectionOui
Tutor LMSCheckout Ecommerce natifOui
LifterLMSRedirectionOui
LearnDashBouton shortcodeAucun modèle de commande à rembourser
MemberPressRedirectionOui
Gravity FormsRedirectionOui

Cinq autres apparaissent dans l'administration avec un badge shortcode. Ils n'ont pas de passerelle de paiement à laquelle se brancher. Ajoutez plutôt [wajub_pay] sur la page : WPForms, Bookly, The Events Calendar, WP Simple Pay et Amelia. WP Crowdfunding passe par WooCommerce. L'activation de l'intégration WooCommerce le prend donc en charge.

Prérequis

ComposantMinimumRemarque
WordPress6.2Testé jusqu'à la version 7.0
PHP8.1En dessous, le plugin affiche une notification et s'arrête
WooCommerce8.0Seulement si vous l'utilisez. Testé jusqu'à la version 11.0
HTTPSObligatoireL'adresse de retour de chaque paiement en a besoin, tout comme un webhook live
Un compte WajubObligatoireLa sandbox suffit pour commencer. Le live exige un compte activé

Wajub ne renvoie un payeur que vers une adresse en https://. La sandbox fait une exception, pour un site installé sur votre ordinateur : http://localhost et http://127.0.0.1. Un site servi en HTTP simple à toute autre adresse ne peut lancer aucun paiement, sauf avec les moyens Mobile Money et Carte bancaire, qui ne peuvent alors pas ramener un payeur depuis la page de son fournisseur.

Le plugin prend en charge High Performance Order Storage ainsi que le panier et le checkout Blocks de WooCommerce.

Installer le plugin

Installez le plugin depuis le répertoire WordPress.org : dans l'administration WordPress, allez dans Extensions, Ajouter une extension, recherchez Wajub, cliquez sur Installer maintenant, puis sur Activer. WP-CLI fait de même avec wp plugin install wajub --activate. WordPress propose ensuite chaque nouvelle version dans Extensions, et l'installe de lui-même une fois ses mises à jour automatiques activées.

Vous pouvez aussi l'installer depuis son archive zip, que la page du plugin sur WordPress.org propose au téléchargement.

  1. 1

    Téléverser l'archive zip

    Dans l'administration WordPress, allez dans Extensions, Ajouter une extension, Téléverser une extension, choisissez l'archive zip et installez-la. Activez le plugin à la fin du téléversement.

  2. 2

    Ou l'installer depuis la ligne de commande

    WP-CLI accepte directement le chemin ou l'URL de l'archive zip.

  3. 3

    Ou déposer le dossier par SFTP

    Décompressez l'archive localement et téléversez le dossier dans wp-content/plugins/, puis activez-le depuis l'écran des extensions.

Depuis l'archive zip, WP-CLI effectue la même installation en une ligne. La seconde commande confirme que le plugin est actif sous le bon nom de dossier.

WP-CLI
wp plugin install ./wajub.zip --activate

wp plugin list --name=wajub --fields=name,status,version

L'activation crée trois pages, « Paiement réussi », « Paiement non finalisé » et « Paiement en cours de traitement » sur un site en français, chacune avec un shortcode [wajub_pay_message]. L'assistant de configuration s'ouvre ensuite, sauf si le site a déjà une clé ou si vous avez activé plusieurs plugins à la fois, tout le réseau, ou depuis WP-CLI.

Ces trois pages sont des pages ordinaires : modifiez-les et adaptez-les à votre thème. Wajub, Réglages vous permet d'en choisir d'autres.

Connecter votre compte Wajub

Le plugin est traduit en français : cette page reprend les libellés de son administration en français. L'assistant de configuration, Wajub, Configuration, compte quatre étapes : connexion, webhooks, paiement, puis test et mise en production. Il reste dans le menu Wajub tant que l'environnement utilisé n'a pas de clé. Ensuite, Wajub, Réglages le rouvre avec Relancer l'assistant de configuration.

Le site a besoin d'une clé secrète par environnement. Laissez Wajub la créer avec Connexion avec Wajub, ou collez la vôtre.

Connexion avec Wajub

Vous approuvez le site dans le Dashboard Wajub, et Wajub crée sa clé : rien à copier, et la clé n'atteint jamais le navigateur. Seuls les administrateurs WordPress voient les boutons.

  1. 1

    Lancer la connexion depuis WordPress

    Cliquez sur Connecter avec Wajub (Test) ou Connecter en production dans l'assistant, ou sur Connecter en mode Test, Connecter en production (Reconnecter en mode Test, Reconnecter en production une fois une clé enregistrée) dans Wajub, Réglages. Le site affiche un code, par exemple K7QD-9XHT, et ouvre la page d'approbation du Dashboard dans un nouvel onglet. Gardez la page WordPress ouverte.

  2. 2

    Approuver dans le Dashboard

    Vérifiez que le Dashboard affiche le même code. La page démarre sur Sandbox, quel que soit le bouton cliqué : choisissez l'environnement sur cette page. Elle démarre aussi sur une clé restreinte, avec les permissions dont le plugin a besoin déjà cochées : paiements, remboursements et webhooks, en lecture et en écriture. Choisissez Accès complet si vous préférez. Choisissez la durée de la clé, 90 jours ou Durée indéterminée, puis cliquez sur Autoriser et saisissez votre code de sécurité.

  3. 3

    De retour dans WordPress

    Le site enregistre la clé, enregistre le webhook avec elle et indique ce qu'il a enregistré. Il vous prévient si vous avez approuvé un autre environnement que celui demandé, si une clé restreinte risque de manquer d'une permission nécessaire au plugin, et si la clé appartient à une autre entreprise que celle que le site utilisait.

RègleDétail
Qui approuveLe propriétaire, un Administrator ou un Developer de votre compte Wajub, ou un Sandbox User pour une clé sandbox seulement, après un code de sécurité. Wajub envoie un e-mail au propriétaire et à chaque Administrator pour chaque clé créée ainsi. N'approuvez qu'un code affiché par votre site
LiveLa page d'approbation le propose une fois votre compte activé pour les paiements réels, à un membre dont le rôle n'est pas limité à la sandbox
15 minutesUne demande attend son approbation 15 minutes. Le site doit ensuite récupérer la clé dans les 15 minutes qui suivent l'approbation, sinon Wajub la supprime et vous recommencez
Une demande à la foisUne demande lancée dans un autre onglet ou une autre fenêtre remplace la première, et la première page l'indique

Toute application peut demander une clé de la même façon : voir Connecter votre application à Wajub. add_filter('wajub_pairing_enabled', '__return_false'); masque Connexion avec Wajub, et les clés se collent alors.

Expiration d'une clé connectée

Une clé de 90 jours cesse de fonctionner à sa date. Wajub, Réglages, l'assistant et la carte de connexion de Wajub, Vue d'ensemble affichent cette date. Dès 14 jours avant :

  • l'adresse e-mail d'administration du site reçoit un e-mail par clé, sandbox ou live ;
  • pour la clé de l'environnement utilisé, une notification sur les autres écrans d'administration, Votre clé Wajub expire bientôt., propose de vous reconnecter en un clic, et peut être masquée pendant 7 jours. Une fois la date passée, elle indique Votre clé Wajub a expiré. jusqu'au remplacement de la clé, et l'état de la connexion indique que la clé a expiré.

Choisissez Durée indéterminée pour une boutique dont le checkout ne doit pas s'arrêter.

Se reconnecter

Wajub, Réglages indique, pour chaque environnement, le jour où Connexion avec Wajub a fourni sa clé, tant que cette clé est celle enregistrée. Se reconnecter remplace la clé de l'environnement, et la clé fournie par une connexion précédente est supprimée. Si elle ne peut pas l'être, le site vous invite à la supprimer dans le Dashboard, sous Paramètres → Développeurs → Clés API. Une clé que vous avez collée n'est jamais supprimée, et supprimer le plugin ne supprime aucune clé : supprimez dans le Dashboard les clés créées par Connexion avec Wajub.

Coller vos clés

Ouvrez Coller plutôt vos clés dans l'assistant, ou utilisez les champs de clé de Wajub, Réglages. Copiez les clés depuis le Dashboard.

CléEnvironnementAcceptée
sk_test.SandboxOui
rk_test.SandboxOui, comme clé restreinte
sk.LiveOui
rk.LiveOui, comme clé restreinte
pk_test., pk.L'un ou l'autreNon : une clé publique est refusée

Une clé restreinte a besoin des scopes de paiements, de remboursements et de webhooks, en lecture et en écriture : payment.read, payment.write, refund.read, refund.write, webhook.read et webhook.write. Sans ceux des webhooks, le site ne peut pas enregistrer son webhook et vous donne les étapes pour le faire à la main.

Chaque clé est vérifiée auprès de Wajub avant d'être conservée. Une clé collée dans le champ de l'autre environnement, une clé publique ou une clé que Wajub refuse n'est pas enregistrée, et le message en donne la raison. Une clé enregistrée alors que Wajub était injoignable le signale : utilisez Tester la connexion un peu plus tard. Une clé enregistrée s'affiche masquée, avec son préfixe et ses quatre derniers caractères. Le navigateur ne reçoit jamais de clé.

Tester la connexion, dans Wajub, Réglages, vérifie auprès de Wajub la clé utilisée.

Clés issues de l'environnement

Les clés et l'option de sandbox sont des options WordPress.

OptionContenu
wajub_test_modeOption de sandbox, activée par défaut
wajub_secret_key_testClé sk_test. ou rk_test.
wajub_webhook_secret_testSecret whsec_test_
wajub_secret_keyClé sk. ou rk.
wajub_webhook_secretSecret whsec_

Pour garder les secrets hors de la base de données, lisez-les depuis l'environnement avec le filtre WordPress pre_option_.

Clés issues de l'environnement dans un plugin must-use
<?php
// wp-content/mu-plugins/wajub-keys.php

foreach ([
    'wajub_secret_key' => 'WAJUB_SECRET_KEY',
    'wajub_secret_key_test' => 'WAJUB_SECRET_KEY_TEST',
    'wajub_webhook_secret' => 'WAJUB_WEBHOOK_SECRET',
    'wajub_webhook_secret_test' => 'WAJUB_WEBHOOK_SECRET_TEST',
] as $option => $env) {
    add_filter("pre_option_{$option}", static function () use ($env) {
        $value = getenv($env);

        return $value === false || $value === '' ? false : $value;
    });
}

// The keys live in the environment: Connect with Wajub could not replace them.
add_filter('wajub_pairing_enabled', '__return_false');

Renvoyer false permet à WordPress de lire normalement l'option enregistrée. Les champs de l'administration fonctionnent donc toujours sur une machine où les variables ne sont pas définies.

Sandbox et live

Chaque environnement paie uniquement avec sa propre clé : la sandbox avec la clé sandbox, le live avec la clé live. La sandbox prend des paiements de test, sans mouvement d'argent réel. Le live prend des paiements réels. Le plugin en français appelle la sandbox Test et le live Production.

La sandbox sans clé sandbox ne prend aucun paiement, même avec une clé live enregistrée. Tous les moyens Wajub sont alors masqués au checkout WooCommerce, les autres intégrations et les boutons de paiement refusent de lancer un paiement, et une notification rouge dans l'administration, Wajub n'accepte aucun paiement., propose Ajouter une clé de test ou Passer en production. Les réglages Wajub de WooCommerce indiquent Test — aucun paiement.

Le changement d'environnement est protégé dans les deux sens. Wajub, Réglages refuse le live tant qu'aucune clé live n'est enregistrée, et vous demande de confirmer avant d'enregistrer le live. Il reste en live si vous repassez en sandbox sans clé sandbox, car le site cesserait de prendre des paiements.

L'environnement s'affiche sur chaque écran Wajub. Tant que la sandbox est utilisée, les administrateurs voient Wajub · Test dans la barre d'administration, dans l'administration comme sur la boutique, et une notification prévient lorsqu'un site de production est encore en sandbox.

Tant que la sandbox est utilisée, les webhooks live règlent toujours les commandes live passées avant le changement, sauf sur une copie dont WP_ENVIRONMENT_TYPE n'est pas production. Une livraison sandbox ne modifie jamais une commande tant que le live est utilisé.

MemberPress, LifterLMS, GiveWP 3, Easy Digital Downloads 3 et Charitable enregistrent un paiement Wajub comme test ou comme paiement live selon la clé avec laquelle Wajub le prend, et non selon leur propre mode test : un paiement réel n'est jamais enregistré comme test. LifterLMS n'affiche aucun réglage de mode test pour Wajub : Wajub, Réglages décide.

Enregistrer le webhook

Le webhook est obligatoire. Lui seul confirme un paiement lorsque le client ferme l'onglet, perd le réseau après avoir approuvé sur son téléphone ou utilise un canal dont le règlement prend plusieurs minutes. Toutes les intégrations de ce plugin en dépendent, et le retour d'un payeur ne passe jamais à lui seul une commande en échec.

Le plugin l'enregistre pour vous. Configurer les webhooks automatiquement, dans l'assistant, ou Configurer automatiquement, dans Wajub, Réglages, crée l'endpoint de chaque environnement qui a une clé et enregistre le secret de signature renvoyé par Wajub. Connexion avec Wajub fait de même pour l'environnement qu'elle connecte. Le webhook s'abonne aux événements de paiement, de remboursement et de litige que traite le plugin ; le filtre wajub_webhook_events modifie la liste.

Wajub ne peut pas joindre un site à une adresse locale ou privée, et un webhook live exige https://. Dans ces cas, l'assistant donne les étapes à suivre à la main : enregistrez l'URL dans le Dashboard, puis collez le secret de signature dans Wajub, Réglages. Pour tester depuis votre ordinateur, wajub listen, de la CLI Wajub, transmet les événements de votre compte au site, sans adresse publique ni port entrant :

Transmettre les événements à un site local
wajub listen --forward-to https://shop.test/wp-json/wajub/v1/webhook

Ajoutez --insecure-tls si le site utilise un certificat auto-signé, et --live avec une clé live. Collez ensuite dans l'assistant, sous Configurer plutôt manuellement, le secret de signature qu'affiche la commande.

ÉlémentValeur
URLhttps://your-site.com/wp-json/wajub/v1/webhook
MethodPOST
En-tête de signatureX-Wajub-Signature: v1=<hmac>
En-tête d'horodatageX-Wajub-Timestamp
Payload signéL'horodatage, un point, puis le corps brut
AlgorithmeHMAC SHA-256 avec votre secret de webhook
Tolérance300 secondes

Vous pouvez vérifier le fonctionnement de l'endpoint depuis votre terminal. Signez un payload comme Wajub, puis envoyez-le.

Envoyer un événement de test signé
SECRET='whsec_test_your_secret_here'
BODY='{"id":"evt_local_test","event":"payment.succeeded","data":{"reference":"wc_42_1757000000","status":"succeeded","amount":25000,"currency":"XAF","metadata":{"source":"woocommerce","source_id":"42"}}}'
TS=$(date +%s)

SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d" " -f1)

curl -i -X POST https://your-site.com/wp-json/wajub/v1/webhook \
  -H "Content-Type: application/json" \
  -H "X-Wajub-Timestamp: $TS" \
  -H "X-Wajub-Signature: v1=$SIG" \
  -d "$BODY"

Une signature valide renvoie {"received":true}, une signature incorrecte 403. L'événement de test ne règle rien : le plugin ne finalise une commande qu'avec un paiement qu'il a créé pour elle.

WooCommerce

WooCommerce bénéficie de l'intégration la plus complète : trois modes de checkout pour le moyen Wajub, des moyens séparés Mobile Money et Carte bancaire, la prise en charge de Blocks, les remboursements dans les deux sens, les notifications de litige sur la commande et un parcours de nouvelle tentative pour un paiement qui n'a pas abouti.

Activer la passerelle

Accédez à WooCommerce, Réglages, Paiements et activez Wajub. Son titre par défaut est Mobile Money ou carte bancaire. Lorsque le moyen Mobile Money ou Carte bancaire est activé, il devient Autres moyens de paiement. Chaque moyen Wajub reste masqué dans le checkout tant que l'environnement utilisé n'a pas de clé. Si aucun n'apparaît, la clé est absente.

Choisir un mode de checkout

ModeLieu du paiement
redirectSur le checkout hébergé Wajub, puis retour vers votre page de remerciement
inlineSur votre page de checkout, dans un cadre intégré
overlaySur votre page de checkout, dans une fenêtre modale

La redirection est le mode par défaut et le meilleur point de départ. C'est le seul mode qui fonctionne lorsque JavaScript est désactivé. Les modes en ligne et en superposition fonctionnent dans le checkout classique comme dans le checkout Blocks. Pour encaisser le Mobile Money et les cartes dans les blocs de paiement du checkout lui-même, voir Moyens séparés Mobile Money et Carte bancaire.

Les modes en ligne et en superposition chargent Wajub.js depuis https://js.wajub.com et gardent le client sur la page de checkout. Langue du formulaire de paiement s'applique à tous les modes. Couleurs du formulaire de paiement (system, light ou dark) s'applique aux modes en ligne et en superposition, où Système suit l'appareil du client, et aux formulaires Mobile Money et Carte bancaire, où il suit votre site. Si Wajub.js ne se charge pas, le client paie la même commande sur la page de paiement Wajub.

Moyens séparés Mobile Money et Carte bancaire

À côté du moyen Wajub, deux moyens de paiement WooCommerce à part entière contiennent le formulaire de paiement de Wajub dans leur bloc de paiement, dans le checkout classique comme dans le checkout Blocks. Un payeur Mobile Money saisit le numéro avec lequel il paie et approuve le paiement sur son téléphone ; un payeur par carte saisit sa carte. Personne ne quitte la boutique.

MoyenId de passerelleAccepteLogos
Wajub Mobile Money, intitulé Mobile Money au checkoutwajub_mobile_moneyLe Mobile Money uniquement. Le payeur choisit l'opérateur dans une listeMTN MoMo, Orange Money, Wave, Moov Money, Airtel Money, M-Pesa
Wajub Carte bancaire, intitulé Carte bancaire au checkoutwajub_cardLes cartes uniquementVisa, Mastercard

Les deux restent désactivés tant que vous ne les activez pas : une boutique existante ne voit aucun changement. Choisissez Moyens séparés à l'étape de paiement de l'assistant, où Mobile Money et Carte bancaire sont cochés selon ce que votre compte propose pour la devise de la boutique, ou activez-les dans WooCommerce, Réglages, Paiements. Chacun a son titre, sa description et ses logos, ceux des marques elles-mêmes.

Un payeur Mobile Money choisit l'opérateur dans une liste qui affiche le logo de chacun, celui de son numéro étant déjà sélectionné. Reconnaître l'opérateur à partir du numéro au lieu d'afficher la liste (operator_from_number, désactivé par défaut), sous Opérateur dans les réglages du moyen Mobile Money, masque la liste : le formulaire déduit l'opérateur du numéro, et n'affiche la liste que si le numéro ne permet pas de le reconnaître.

Le formulaire s'ouvre dans la langue réglée pour le moyen Wajub, et reprend la police, les tailles, les couleurs, les arrondis et l'apparence claire ou sombre de votre checkout. Le réglage Couleurs du formulaire de paiement du moyen Wajub impose cette apparence avec Clair ou Sombre ; Système, la valeur par défaut, suit votre site.

Le moyen Wajub devient Autres moyens de paiement

Les moyens séparés n'acceptent que les paiements de leur type. Lorsque Mobile Money ou Carte bancaire est activé, le moyen Wajub, gardé activé à côté d'eux, devient Autres moyens de paiement : il ne propose que ce qu'ils ne proposent pas, comme PayPal, les portefeuilles ou le virement bancaire, son paiement est limité à ces types, et il n'apparaît que lorsque votre compte Wajub en propose un pour la commande. Aucun moyen de paiement n'apparaît donc deux fois. Le titre et la description que vous avez rédigés vous-même sont conservés. Dans l'assistant, la case Proposer aussi les autres moyens de paiement de votre compte Wajub (PayPal, portefeuilles…) est cochée par défaut ; si vous la décochez, l'assistant désactive le moyen Wajub. Choisir plus tard la redirection, la superposition ou le mode en ligne désactive les moyens séparés et réactive le moyen Wajub.

Chaque moyen n'apparaît que lorsque votre compte Wajub propose son type de paiement pour la commande.

  1. 1

    Le payeur choisit le moyen

    Le formulaire se charge dans le bloc de paiement du moyen. Rien n'est débité tant que le payeur n'a pas passé la commande.

  2. 2

    Le payeur passe la commande

    WooCommerce crée la commande, puis le paiement passe par le formulaire. Il porte la référence de la commande (wc_<order id>_<timestamp>), s'affiche « Commande n° 123 » dans le Dashboard et porte l'id de la commande dans metadata.order_id. Un formulaire resté ouvert trop longtemps, ou remplacé dans un autre onglet, est plutôt actualisé avec un message, et rien n'est débité : le payeur le vérifie et passe de nouveau la commande.

  3. 3

    Le paiement aboutit, ou non

    Un paiement refusé peut être retenté dans le même formulaire, sans nouvelle commande. Choisir un autre moyen de paiement rend le checkout, et Continuer sur la page Wajub sécurisée termine le même paiement sur la page de Wajub. Un payeur qui part pendant que Wajub confirme encore est envoyé sur la page de la commande, qui affiche le résultat dès qu'il est connu, et ne se voit jamais proposer un second paiement.

Les webhooks, le retour du payeur, la page de confirmation de commande, Vérifier le statut dans le bloc Paiement Wajub de la commande et les remboursements depuis WooCommerce fonctionnent pour ces commandes comme pour le moyen Wajub.

La page de paiement de Wajub prend le relais sans JavaScript, sur la page de paiement de la commande, et lorsque le formulaire ne peut pas se charger ; elle ne propose alors que ce moyen. Si vous avez limité les sites où Wajub peut être intégré (Paramètres, Intégration de la page de paiement dans le Dashboard), ajoutez-y l'adresse de votre boutique, sinon le formulaire ne se charge pas.

Un numéro Mobile Money refusé par le formulaire, ou une fenêtre bloquée par le navigateur, est expliqué dans le bloc de paiement, et le payeur peut corriger puis réessayer. Un payeur dont l'opérateur Mobile Money prend toute la page revient à la commande.

Quand un paiement ne couvre pas la commande

Une commande est payée quand les paiements Wajub faits pour elle couvrent son total, dans sa devise et dans un même environnement. Chaque paiement compte pour ce qu'il a encaissé, moins ce qui en a été remboursé. Des frais pris en charge par le client ne compensent jamais un total relevé après le début du paiement. Une clé restreinte a besoin de refund.read pour que les remboursements soient comptés : sans elle, la commande reçoit une note.

Un paiement dans une autre devise que celle de la commande ne compte pour rien, et le client doit toujours le total de la commande. La commande reçoit une note par paiement de ce genre, avec ce qu'il a encaissé dans sa propre devise et l'indication de le rembourser depuis le Dashboard Wajub, et Vérifier le statut le dit aussi.

Un paiement ne couvre pas la commande quand vous clôturez plus tôt un paiement en plusieurs fois dans le Dashboard Wajub, ou quand vous modifiez la commande après le début de son paiement. Ce qu'il a encaissé compte quand même. La commande reste en attente avec une note de ce qui reste à payer, et sa page de confirmation affiche Une partie de votre commande est payée avec un bouton Payer le reste. Le client paie le reste depuis la page de paiement de la commande, que vous pouvez lui envoyer avec Envoyer les détails de la commande au client. Le nouveau paiement ne demande que ce qui reste, et la page de Wajub le décrit ainsi : Commande n° N : X déjà reçus ; Y restent à payer. Un client ne paie jamais deux fois la même commande.

Tant que Wajub détient une partie d'une commande, le nettoyage des commandes impayées de WooCommerce la laisse en place, et un autre moyen de paiement est refusé pour elle : « Part of this order is already paid. Pay the rest with … ». Ce nettoyage n'annule pas non plus une commande dont un paiement a abouti sans pouvoir encore être compté : la commande reste en attente avec une note.

Les autres intégrations (GiveWP, Easy Digital Downloads, Charitable, LifterLMS, Tutor LMS, MemberPress, Gravity Forms) demandent qu'un seul paiement couvre à lui seul le montant dû. Un paiement qui ne le couvre pas ne complète rien, et l'achat reste en attente avec une note, sauf dans MemberPress et Tutor LMS, où seuls les logs de débogage du plugin le signalent.

Remboursements

Les remboursements fonctionnent dans les deux sens, pour les commandes payées avec n'importe lequel des trois moyens.

Un remboursement lancé dans WooCommerce est envoyé à Wajub. Un remboursement lancé dans le Dashboard Wajub crée le remboursement WooCommerce correspondant, sans déplacer l'argent une seconde fois. Aucun des deux n'est jamais enregistré deux fois, et un montant supérieur au solde remboursable est refusé.

Le remboursement d'une commande payée par plusieurs paiements est réparti entre eux, du plus récent au plus ancien, chacun jusqu'à ce qu'il peut encore rembourser. Si Wajub refuse une part après en avoir fait d'autres, WooCommerce abandonne son remboursement et les parts déjà faites sont enregistrées séparément. Un remboursement est refusé pour une commande jamais payée en entier, une commande payée dans l'autre environnement, comme un remboursement lancé en Sandbox sur une commande payée en Live, ou, pour une commande payée par plusieurs paiements, un montant supérieur à ce qu'ils détiennent. Un remboursement fait dans le Dashboard Wajub alors que la commande n'était pas encore payée n'est pas enregistré dans WooCommerce : le client repaie ce montant.

Quand Wajub refuse un remboursement supérieur à ce qu'il peut rembourser, sans en avoir rien fait, le plugin relit les remboursements des paiements de la commande : un remboursement fait dans le Dashboard Wajub dont le webhook n'est jamais arrivé est enregistré comme son webhook l'aurait fait, et la fenêtre de remboursement dit ce qui a été rattrapé.

Métadonnées de commande écrites par le plugin

Clé de métadonnéeContenu
_wajub_referenceVotre référence, wc_<order id>_<timestamp>
_wajub_payment_idL'identifiant du paiement Wajub, trx_…
_wajub_dispute_statusLe dernier événement de litige reçu pour cette commande

Lisez-les avec $order->get_meta() dans votre code. Consignez la référence dans les logs, car elle apparaît dans le Dashboard Wajub et dans chaque webhook.

Litiges

Un événement dispute.created, dispute.won ou dispute.lost ajoute une note sur la commande avec le motif et le montant, inscrit le litige dans _wajub_dispute_status, puis envoie au responsable du site un e-mail avec l'échéance de réponse. Les autres événements de litige sont notés sur la commande sans e-mail.

Nouvelle tentative après un échec

Lorsqu'un paiement échoue ou que la confirmation expire, le client reçoit un lien de nouvelle tentative. Ce lien n'annule jamais la commande. Une commande encore payable ouvre sa propre page de paiement, et une commande déjà payée ouvre sa confirmation. Seule une commande que WooCommerce a annulée, à la fin de sa réservation de stock, voit ses produits et variations remis dans le panier, avec une notification qui explique la situation.

Une commande annulée, à la fin de sa réservation de stock ou par vous, voit son paiement Wajub que personne n'a commencé à payer annulé chez Wajub aussi, peu après, pour qu'il ne puisse plus aboutir. Un paiement en cours, un paiement qui a abouti ou un paiement en plusieurs échéances ne l'est pas : Wajub ne peut pas arrêter un paiement que l'opérateur ou la banque confirme, et la commande dit de le rembourser depuis le Dashboard Wajub s'il encaisse de l'argent.

Dons avec GiveWP

Les deux générations de GiveWP sont prises en charge, sans rien de différent à configurer.

Activez Wajub dans Dons, Réglages, Passerelles de paiements. Les donateurs paient sur le checkout hébergé et reviennent sur votre page de réussite.

Chaque statut Wajub correspond à un statut GiveWP précis, au lieu de se réduire à un seul échec :

Statut WajubStatut du don GiveWP
succeededComplété
cancelled, expiredAnnulé
failedÉchec
refunded, partially_refundedRemboursé

Un remboursement depuis l'administration GiveWP est envoyé à Wajub. Les dons récurrents ne sont pas pris en charge.

GiveWP utilise uniquement la redirection

Le formulaire de don redirige vers le checkout hébergé. Pour une expérience en ligne ou en superposition, construisez plutôt la page avec le shortcode [wajub_pay type="donation"], qui prend en charge les trois modes. GiveWP n'enregistre pas ce paiement : il n'apparaît que dans Wajub, Transactions.

Dons avec Charitable

La passerelle apparaît d'elle-même dans Charitable, sans rien à remplir sur son écran de réglages : elle utilise les clés de Wajub, Réglages.

Les donateurs paient sur le checkout hébergé. Une fois le paiement confirmé, le don est marqué comme terminé et le donateur arrive sur la page du reçu. Un remboursement depuis l'administration Charitable est envoyé à Wajub une seule fois.

Easy Digital Downloads

Wajub apparaît dans le checkout EDD sous Mobile Money ou carte bancaire. Les clients paient sur le checkout hébergé, puis le paiement EDD est finalisé avec une note contenant la référence, ou marqué comme échoué avec son motif.

Avec EDD 3, chaque remboursement fait dans EDD, total ou partiel, est envoyé à Wajub avec son propre montant. Le remboursement qui rembourse entièrement la commande, ou un statut passé à Remboursé là où EDD ne crée pas de commande de remboursement, demande à Wajub ce qui reste du paiement.

Cours avec Tutor LMS, LifterLMS et LearnDash

Les trois plugins LMS proposent trois niveaux d'intégration différents, car leurs surfaces d'extension ne sont pas les mêmes.

Tutor LMS bénéficie d'une passerelle native : Wajub apparaît dans le checkout Tutor Ecommerce normal et l'inscription suit le flux de commande de Tutor. Les remboursements lancés dans Tutor sont envoyés à Wajub. Si Tutor Ecommerce est désactivé, un bouton [wajub_pay] apparaît sur la page du cours.

LifterLMS bénéficie aussi d'une véritable passerelle. Une commande payante redirige vers le checkout hébergé, et une fois le paiement confirmé, la transaction est enregistrée sur la commande LifterLMS et l'étudiant inscrit.

LearnDash ne propose aucun modèle de commande exploitable par ce plugin. Un bouton de paiement est donc ajouté aux boutons du cours, et l'accès est accordé une fois le paiement confirmé. Aucun remboursement n'est possible depuis WordPress. Utilisez plutôt le Dashboard Wajub.

Les boutons de cours (LearnDash, l'option du tableau tarifaire LifterLMS, et le [wajub_pay] de Tutor lorsque Tutor Ecommerce est désactivé) demandent à un visiteur déconnecté de se connecter, ou de créer un compte lorsque l'inscription est ouverte, et un paiement inscrit le compte qui l'a fait.

Adhésions avec MemberPress

La passerelle gère les paiements uniques d'adhésion. Un achat redirige vers le checkout hébergé, et une fois le paiement confirmé, la transaction MemberPress est finalisée et le reçu envoyé.

La facturation récurrente n'est pas implémentée. Une adhésion avec un tarif d'abonnement ne sera pas débitée automatiquement une nouvelle fois.

Gravity Forms

L'extension fonctionne comme tout autre feed de paiement Gravity Forms : créez un feed sur le formulaire, associez le montant et l'e-mail, puis Wajub s'occupe du reste.

Les soumissions redirigent vers le checkout hébergé. Une fois le paiement confirmé, l'entrée est marquée Paid et gform_post_payment_status se déclenche pour exécuter vos feeds et notifications. Un remboursement depuis l'entrée est envoyé à Wajub une seule fois.

Tout autre plugin avec des shortcodes

Trois shortcodes couvrent tous les plugins sans passerelle et toutes vos pages personnalisées. Aucune clé n'atteint le navigateur.

Un bouton de paiement

[wajub_pay] affiche un petit formulaire qui demande un e-mail et, facultativement, un nom. Il lance ensuite le paiement dans le mode choisi.

amountnumberfacultatif
Montant dans l'unité principale. 25 000 XAF représente vingt-cinq mille francs.
currencystringfacultatifdéfaut : XAF
Code de trois lettres. Toute autre valeur utilise XAF en repli.
moderedirect | inline | overlayfacultatifdéfaut : redirect
Toute autre valeur utilise redirect en repli.
typepayment | donationfacultatifdéfaut : payment
Un don affiche un champ de montant rempli par le donateur.
amountsstringfacultatif
Montants proposés pour un don, par exemple 1000,2500,5000.
descriptionstringfacultatif
Affichée dans le checkout et enregistrée sur le paiement. Limitée à 500 caractères.
product_idnumberfacultatif
Identifiant de produit WooCommerce. Son prix et son nom remplacent le montant et la description.
content_idstringfacultatif
Indique que le paiement déverrouille un contenu.
button_textstringfacultatifdéfaut : Payer <montant>
Libellé du bouton d'envoi. Un don affiche Faire un don.
classstringfacultatif
Classe CSS supplémentaire sur le wrapper.
Trois façons de placer le bouton
[wajub_pay amount="25000" currency="XAF" description="Consultation" mode="redirect"]

[wajub_pay product_id="482" mode="overlay" button_text="Buy now"]

[wajub_pay type="donation" currency="XAF" mode="inline" button_text="Support us"]

Contenu verrouillé

[wajub_pay_content] enveloppe un contenu qui apparaît seulement après le paiement du lecteur. En attendant, il affiche le même formulaire et utilise par défaut le mode en superposition afin que la page ne change pas sous ses yeux.

Une section payante
[wajub_pay_content content_id="masterclass-2026" amount="15000" currency="XAF"]
The full recording, the slides, and the worksheet live here.
[/wajub_pay_content]

L'accès est mémorisé de deux façons : sur le compte lorsque l'acheteur est connecté, ou pendant trente jours dans le navigateur d'où le paiement a été lancé lorsqu'il ne l'est pas. Un acheteur déconnecté qui change de navigateur devra payer de nouveau. Cet outil convient donc à un téléchargement numérique ou à un article unique, pas à une adhésion. MemberPress ou LifterLMS gèrent correctement ce dernier cas.

Le prix est celui écrit dans le shortcode, et le payeur ne peut pas le modifier. Donnez à chaque prix son propre content_id : payer l'un ouvre tous les blocs qui le partagent. Modifier la page demande aux payeurs qui ont une copie plus ancienne de la recharger.

Message de résultat

[wajub_pay_message] affiche le message de réussite, d'échec ou de traitement. Les trois pages créées à l'activation le contiennent, et il reste vide lors d'une visite directe.

Un paiement qui a encaissé moins que ce qu'il demandait, comme un paiement en plusieurs fois clôturé plus tôt, affiche Paiement partiel reçu, avec ce qui a été payé sur ce qui était dû et qui contacter, au lieu de Paiement reçu. Il ne débloque rien : un contenu verrouillé le reste. Un paiement Gravity Forms revient sur les mêmes pages.

Shortcodes dans un template de thème

En dehors de l'éditeur, exécutez-les avec do_shortcode().

Dans un fichier de template
<?php
$amount = (float) get_post_meta(get_the_ID(), 'ticket_price', true);

if ($amount > 0) {
    echo do_shortcode(sprintf(
        '[wajub_pay amount="%s" currency="XAF" description="%s" mode="overlay"]',
        esc_attr((string) $amount),
        esc_attr(get_the_title())
    ));
}

Créer votre propre intégration

Trois éléments du plugin sont à votre disposition dans votre propre code : ses hooks, son client API et son jeton de callback signé.

Hooks

HookArgumentsDéclenché lorsque
wajub_payment_complete$reference, $data, $source, $sourceIdUn paiement réussit
wajub_payment_failed$reference, $data, $source, $sourceIdUn paiement échoue, est annulé ou expire
wajub_refund_succeeded$paymentRef, $data, $source, $sourceIdUn remboursement réussit, fait dans le Dashboard Wajub ou dans WordPress, une fois par remboursement
wajub_refund_complete$paymentRef, $data, 'woocommerce', $orderIdUn remboursement réussit sur une commande WooCommerce
wajub_dispute_received$eventType, $dataTout événement de litige
wajub_webhook_received$eventType, $dataChaque événement vérifié, une fois traité par le plugin
wajub_webhook_missing_secret$reason, $environmentUn événement arrive sans secret configuré. $environment est l'environnement qu'il annonce (live, test ou vide) ; son corps, que personne n'a vérifié, n'est pas transmis
wajub_webhook_invalid_signature$reason, $environmentUn événement échoue à la vérification de signature ou d'horodatage (mêmes arguments)
wajub_default_phone_country_code'237'Un numéro à neuf chiffres a besoin d'un indicatif pays
wajub_webhook_eventsLa liste des événementsLe plugin enregistre son webhook
wajub_fields_prepare_limits['ip' => 10, 'site' => 30]Le bloc Mobile Money ou Carte bancaire peut demander son paiement, par minute, par adresse de visiteur et pour tout le site
wajub_pairing_enabledtrueL'administration propose Connexion avec Wajub ; false la masque
wajub_charitable_gateway_name'Wajub'Charitable affiche la passerelle ; renvoyez un autre nom pour l'afficher

Les cinq derniers sont des filtres. Les autres sont des actions. $source et $sourceId proviennent directement des metadata définies à la création du paiement. Votre propre nom de source peut ainsi fonctionner, mais quiconque crée un paiement peut les définir : vérifiez le paiement par rapport à vos propres données avant d'agir. Une livraison que le site ne traite pas, comme une livraison signée pour l'environnement non utilisé ou une répétition, ne déclenche aucune de ces actions.

Livrer votre propre enregistrement

Définissez votre propre metadata.source lors de la création du paiement, puis traitez-la. Le hook s'exécute quand le webhook confirme le paiement, et non quand le navigateur le suppose réussi.

Marquer votre propre réservation comme payée
<?php

add_action('wajub_payment_complete', static function (
    string $reference,
    array $data,
    string $source,
    $sourceId
): void {
    if ($source !== 'bookings' || empty($sourceId)) {
        return;
    }

    $booking = get_post((int) $sourceId);
    if (! $booking || $booking->post_type !== 'booking') {
        return;
    }

    update_post_meta($booking->ID, 'payment_status', 'paid');
    update_post_meta($booking->ID, 'wajub_reference', $reference);
    update_post_meta($booking->ID, 'paid_amount', (float) ($data['amount'] ?? 0));

    do_action('bookings_confirmed', $booking->ID);
}, 10, 4);

Créer un paiement depuis votre code

Client::getInstance() fournit un client avec la clé de l'environnement choisi dans Wajub, Réglages, et uniquement celle-là : en sandbox sans clé sandbox, il n'a aucune clé, isConfigured() renvoie false et chaque appel lève une exception. Les montants utilisent l'unité principale.

Lancer un paiement et rediriger
<?php

use WajubPay\API\Client;
use WajubPay\Security\CallbackToken;

function bookings_start_payment(int $bookingId, float $amount, string $email): string
{
    $callback = add_query_arg([
        'bookings' => 'wajub_return',
        'booking_id' => $bookingId,
        '_wajub_token' => CallbackToken::generate($bookingId),
    ], home_url('/'));

    $result = Client::getInstance()->createPayment([
        'amount' => $amount,
        'currency' => 'XAF',
        'description' => sprintf('Booking #%d', $bookingId),
        'reference' => 'booking_' . $bookingId . '_' . time(),
        'callback' => $callback,
        'customer' => ['email' => $email],
        'metadata' => [
            'source' => 'bookings',
            'source_id' => (string) $bookingId,
        ],
    ]);

    $parsed = Client::parsePaymentResponse($result);
    // The Wajub id (trx_...): the API reads a payment by its id, not by your reference.
    update_post_meta($bookingId, 'wajub_payment_id', $parsed['id']);

    return $parsed['authorization_url'];
}

parsePaymentResponse() aplatit l'enveloppe de l'API en id, reference, session_id, authorization_url et status. Envoyez le client vers authorization_url pour un checkout avec redirection, ou passez session_id à wajub.mount() pour une intégration en ligne.

L'URL de callback est la destination du client à son retour, et elle suit la règle HTTPS. Il s'agit d'une redirection du navigateur. Utilisez-la seulement pour choisir la page à afficher, jamais comme preuve de paiement. Vérifiez le jeton, puis le paiement.

Gérer le retour en toute sécurité
<?php

use WajubPay\API\Client;
use WajubPay\Security\CallbackToken;

add_action('init', static function (): void {
    $action = isset($_GET['bookings']) ? sanitize_text_field(wp_unslash($_GET['bookings'])) : '';
    if ($action !== 'wajub_return') {
        return;
    }

    $bookingId = absint($_GET['booking_id'] ?? 0);
    $token = sanitize_text_field(wp_unslash($_GET['_wajub_token'] ?? ''));

    if (! $bookingId || ! CallbackToken::verify($bookingId, $token)) {
        wp_safe_redirect(home_url('/'));
        exit;
    }

    $paymentId = (string) get_post_meta($bookingId, 'wajub_payment_id', true);
    $status = 'pending';

    try {
        $payment = Client::getInstance()->retrievePayment($paymentId);
        $status = (string) (Client::extractTransaction($payment)['status'] ?? 'pending');
    } catch (\Throwable) {
        // The webhook is still the source of truth. Show a waiting page.
    }

    wp_safe_redirect(Client::isSucceededStatus($status)
        ? home_url('/booking-confirmed/')
        : home_url('/booking-pending/'));
    exit;
});

CallbackToken::generate() lie le jeton à l'identifiant, et à une seconde valeur facultative comme une clé de commande. Il empêche un visiteur de confirmer la réservation d'une autre personne en modifiant l'identifiant dans l'URL. Passez toujours à verify() le même second argument qu'à generate().

Modifier l'indicatif pays par défaut

Un numéro de téléphone à neuf chiffres sans indicatif est considéré comme camerounais. Modifiez ce réglage une fois pour tout le site.

Le Sénégal par défaut
<?php

add_filter('wajub_default_phone_country_code', static fn (): string => '221');

Fonctionnalités du client API

MéthodeRôle
createPayment(array $params)POST /payments, renvoie l'enveloppe brute
retrievePayment(string $id)GET /payments/{id}. Passez l'identifiant Wajub (trx_…) : l'API ne trouve pas un paiement par votre référence
cancelPayment(string $id)DELETE /payments/{id}, avec l'identifiant Wajub également
createRefund(string $paymentId, ?float $amount, ?string $reason, string $currency)POST /refunds
paymentOptions(string $currency, float $amount, string $country = '', array $accept = [])GET /payments/options : les canaux avec lesquels un paiement de cette devise et de ce montant pourrait être payé, tels que le compte les propose
isConfigured(), isTestMode()Indique si le client a une clé, et si c'est la clé sandbox

Les échecs déclenchent une exception typée : AuthenticationException, PermissionException, NotFoundException, RateLimitException, InvalidRequestException ou ApiConnectionException. Toutes étendent ApiException avec les propriétés en lecture seule errorCode, httpStatus et body.

Transactions

Wajub, Transactions liste chaque paiement et chaque remboursement enregistrés par le site, quelle que soit leur intégration : une commande WooCommerce, un don GiveWP et un paiement par shortcode y apparaissent ensemble. La liste offre recherche, filtres et export CSV. Wajub, Vue d'ensemble totalise le volume réussi par devise : un site qui accepte le XAF et le GHS affiche donc deux chiffres.

Supprimer le plugin supprime cette liste ainsi que ses réglages, clés et secrets. Le désactiver ne les supprime pas. Les commandes, dons et entrées gardent leurs détails Wajub, et les endpoints de webhook ainsi que les clés créées par Connexion avec Wajub restent dans votre compte Wajub. Exportez les données nécessaires avant de supprimer le plugin.

Passer en live

  1. 1

    Tester tout le parcours dans la sandbox

    Passez une vraie commande avec un numéro Mobile Money de la sandbox et vérifiez que la commande atteint un état payé sans intervention dans l'administration. Testez aussi une annulation et un remboursement.

  2. 2

    Confirmer le déclenchement du webhook

    La commande doit se terminer même si vous fermez l'onglet juste après l'approbation. Si elle se termine seulement à votre retour sur le site, le webhook n'est pas configuré et vous dépendez du callback.

  3. 3

    Ajouter les identifiants live

    Cliquez sur Connecter en production, ou collez la clé secrète live, puis laissez le plugin enregistrer le webhook live. Les endpoints live et sandbox sont distincts.

  4. 4

    Passer en live

    Choisissez Production dans Wajub, Réglages, ou à la dernière étape de l'assistant, puis confirmez. La barre d'administration n'affiche plus Wajub · Test.

  5. 5

    Encaisser un paiement réel

    Encaissez un petit montant sur un vrai téléphone, puis remboursez-le. C'est le seul test qui vérifie ensemble les clés live, le webhook live et votre processus de livraison.

L'activation du compte et le KYC qui déverrouille les clés live sont présentés dans Passer en live.

Dépannage

SymptômeCauseSolution
Wajub est absent du checkout WooCommerceAucune clé pour l'environnement utilisé. La sandbox n'utilise pas la clé liveAjoutez la clé, avec Connexion avec Wajub ou en la collant, ou passez en live
Wajub n'accepte aucun paiement. dans l'administrationLa sandbox est choisie et seule une clé live est enregistréeAjouter une clé de test, ou Passer en production pour prendre des paiements réels avec la clé live
Votre clé Wajub expire bientôt.La clé vient de Connexion avec Wajub et dure 90 joursReconnectez-vous, et choisissez Durée indéterminée si le checkout ne doit pas s'arrêter
Les commandes restent sur pending après un paiement réussiLe champ du secret de webhook est vide ou l'endpoint n'est pas enregistréChaque livraison est refusée avec 403 tant que le secret ne correspond pas. Configurer automatiquement, ou envoyez la requête de test signée ci-dessus
Le formulaire Mobile Money ou Carte bancaire n'apparaît jamais, et le payeur est envoyé sur la page WajubLe formulaire n'a pas pu se charger : bloqué, ou refusé par la restriction d'intégration de votre compteAjoutez l'adresse de la boutique sous Paramètres, Intégration de la page de paiement dans le Dashboard, et recherchez dans la console une requête bloquée vers js.wajub.com
Un payeur par carte reste sur la page de son fournisseurLa boutique est servie en HTTP simpleServez-la en HTTPS
Le formulaire du shortcode renvoie une erreur de requête invalideUn nonce expiré servi par un cache de page complèteExcluez la page du cache ou réduisez sa durée à moins de 24 heures
Le feed Gravity Forms n'apparaît pasLe dossier du plugin ne s'appelle pas wajubRenommez-le en wajub et réactivez le plugin
Le checkout en ligne envoie le payeur sur la page de paiement WajubWajub.js ne s'est pas chargéRecherchez dans la console une requête bloquée vers js.wajub.com. La page de paiement est le repli prévu
Un montant est cent fois trop élevéUtilisation habituelle des unités mineuresWajub utilise l'unité principale. Envoyez 25 000 pour vingt-cinq mille francs, pas 2 500 000
Rien n'apparaît dans les logsLes logs de débogage sont désactivésActivez Journaliser les requêtes Wajub et les événements webhook dans Wajub, Réglages, ou définissez WP_DEBUG. Lorsque WooCommerce est actif, la sortie va dans ses logs sous la source wajub. Sinon, elle va dans error_log

Pour tout autre problème, activez les logs de débogage, reproduisez-le, puis envoyez les logs au support avec la référence de transaction. N'envoyez jamais de clé.

Que pensez-vous de ce contenu ?