Architecture
websource-credit.php fichier principal : constantes, chargeur PSR-4, compatibilité HPOS et blocs, amorçage
src/Plugin.php amorçage (inerte sans WooCommerce), tâche quotidienne, routes REST
src/Settings.php réglages (option wsx_credit_settings)
src/Money.php montants en centimes, pourcentages en points de base, saisie et affichage
src/Rule.php règle d'avoir d'un produit (métadonnées du produit)
src/Store.php tables et requêtes SQL
src/Wallet.php portefeuille : expiration, solde, ajout, débit atomique, restitution, annulation
src/Allocator.php logique pure : répartition sur les lots, plan total / partiel / refusé
src/Issuer.php cycle de vie de la commande : émission, règlement, annulation
src/Gateway.php moyen de paiement wsx_credit et état de commande wc-wsx-partial
src/Checkout.php montants d'un panier ou d'une commande, paiement (verrou par commande)
src/BlocksSupport.php paiement par blocs et extension du panier de l'API Store
src/Settlement.php règlement du solde : commande de règlement ou confirmation manuelle
src/PayLink.php liens de paiement à usage unique
src/Mailer.php e-mails « lien de paiement » et « solde reçu »
src/Account.php pages Mon compte, avis sur la commande et dans les e-mails
src/Block.php bloc et code court
src/Privacy.php export et effacement RGPD
src/Admin.php, AdminOrder.php, AdminProduct.php, Cli.php administration, WP-CLI
src/Notes.php libellés de l'historique (codes traduits à l'affichage)
tests/ parcours HTTP, Chrome, double dépense, cas limites (site de test local uniquement)
Espace de noms : Websource\Credit. Préfixes : options wsx_credit_*, tables wsx_credit_*, métadonnées _wsx_credit_*, classes CSS wsc-* (boutique) et wsx-credit-* (administration).
Les commandes sont lues et écrites uniquement par l'API de WooCommerce : stockage HPOS et stockage historique sont pris en charge. Tous les montants sont des entiers en unités mineures (centimes) de la devise de la boutique ; les pourcentages sont en points de base (12,5 % = 1250).
Bloc et code court
| Élément | Nom | Attributs |
|---|---|---|
| Bloc « Solde d'avoir (Websource) » | websource/credit-balance | showHistory (booléen, défaut true), limit (entier, défaut 20) |
| Code court | [websource_credit_balance history="1" limit="20"] | history (0 masque l'historique), limit |
Rendu serveur : carte div.wsc-card (solde) puis tableau table.wsc-table (mouvements). Un visiteur non connecté voit un lien vers la page Mon compte. La feuille assets/front.css n'est chargée que lorsque le bloc, le code court, la page « Mes avoirs », la page du lien ou un avis de solde est rendu.
Emplacements automatiques :
| Emplacement | Hook | Contenu |
|---|---|---|
| Mon compte, menu | woocommerce_account_menu_items | Entrée « Mes avoirs » (avec le solde s'il est positif) |
Mon compte, /store-credit/ | woocommerce_account_store-credit_endpoint | Solde et 100 derniers mouvements |
Mon compte, /pay-balance/?token=… | woocommerce_account_pay-balance_endpoint | Page du lien de paiement |
| Détail de commande et page de confirmation | woocommerce_order_details_after_order_table, woocommerce_thankyou | Avis « Solde à régler » |
| E-mails de commande | woocommerce_email_after_order_table | Solde à régler et part payée avec l'avoir |
| Fiche produit (administration) | woocommerce_product_data_tabs, woocommerce_product_data_panels | Onglet « Avoirs » |
| Commande (administration) | add_meta_boxes | Encart « Solde à régler (avoir) » |
Moyen de paiement et état de commande
| Élément | Valeur |
|---|---|
| Identifiant du moyen de paiement | wsx_credit (classe Websource\Credit\Gateway) |
| Option WooCommerce | woocommerce_wsx_credit_settings (enabled, title) |
| État de commande | wc-wsx-partial (« Paiement partiel – solde à régler ») |
| Paiement par blocs | script assets/checkout-block.js, données wsx_credit_data |
Le moyen de paiement est proposé si le client est connecté et si Allocator::plan() ne renvoie pas refused pour le panier. Il n'est jamais proposé sur la page « Payer la commande » (order-pay).
L'état wc-wsx-partial n'est pas un état payé (woocommerce_order_is_paid_statuses). Il est accepté par payment_complete() (woocommerce_valid_order_statuses_for_payment_complete), exclu de la page « Payer la commande » et de l'annulation par le client. À l'entrée dans cet état, les e-mails WooCommerce WC_Email_New_Order et WC_Email_Customer_On_Hold_Order sont déclenchés une fois.
Extension du panier de l'API Store (GET /wp-json/wc/store/v1/cart, clé extensions) :
{"websource-credit": {"available": true, "credit": 1110, "due": 3580, "description": "Votre avoir sera utilisé : 11,10 €. Il restera 35,80 € à régler ensuite : nous vous enverrons un lien de paiement."}}
Métadonnées de commande :
| Clé | Contenu |
|---|---|
_wsx_credit_paid | Montant réglé avec l'avoir (centimes) |
_wsx_credit_due | Solde à régler à la validation (centimes) |
_wsx_credit_balance_paid, _wsx_credit_balance_method, _wsx_credit_balance_reference | Règlement du solde : montant, moyen, référence |
_wsx_credit_settles_order, _wsx_credit_link_id, _wsx_credit_settlement_done | Sur une commande de règlement : commande d'origine, lien, traitement (settled ou duplicate) |
_wsx_credit_partial_mailed | E-mails de l'état partiel déjà envoyés |
Métadonnées de produit (une règle par produit) : _wsx_credit_active (yes / no), _wsx_credit_kind (fixed / percent), _wsx_credit_value (centimes ou points de base), _wsx_credit_validity (jours), _wsx_credit_usable (any / product).
Liens publics
| URL | Effet |
|---|---|
/mon-compte/store-credit/ | Page « Mes avoirs » du client connecté. |
/mon-compte/pay-balance/?token=<jeton> | Page du lien de paiement. Le client doit être connecté au compte de la commande. |
Le début de l'URL est celui de la page Mon compte de WooCommerce. Le jeton est une chaîne de 64 caractères hexadécimaux (256 bits aléatoires). Seule son empreinte SHA-256 est enregistrée. Un lien est à usage unique, expire après link_days jours, et un nouveau lien révoque les précédents. Le formulaire de la page (POST, champs token, wsx_credit_nonce, wsx_credit_pay) crée ou réutilise la commande de règlement, puis redirige vers sa page de paiement WooCommerce.
Hooks et filtres
Actions
| Action | Paramètres | Moment |
|---|---|---|
wsx_credit_issued | WC_Order $order, int $cents | Après l'émission des avoirs d'une commande (total émis en centimes). |
wsx_credit_balance_paid | WC_Order $order, int $cents, string $method | Après le règlement du solde d'une commande. |
wsx_credit_daily | — | Tâche quotidienne (WP-Cron) : expiration des lots échus. |
Filtres
| Filtre | Paramètres | Rôle |
|---|---|---|
wsx_credit_issue_for_order | bool $issue, WC_Order $order | Renvoyez false pour ne pas émettre les avoirs d'une commande à ce moment. L'émission est retentée au prochain état payé. |
wsx_credit_partial_emails | bool $send, int $orderId | Renvoyez false pour ne pas envoyer les e-mails WooCommerce à l'entrée dans l'état partiel. |
Exemple : n'émettre l'avoir d'une commande en paiement à la livraison qu'à l'état « Terminée ».
add_filter('wsx_credit_issue_for_order', function ($issue, WC_Order $order) {
if ($order->get_payment_method() === 'cod' && !$order->has_status('completed')) {
return false;
}
return $issue;
}, 10, 2);
Exemple : prévenir un outil externe quand un solde est réglé.
add_action('wsx_credit_balance_paid', function (WC_Order $order, int $cents, string $method) {
error_log(sprintf('Commande %d : solde de %d centimes réglé (%s)', $order->get_id(), $cents, $method));
}, 10, 3);
Hooks WooCommerce écoutés : woocommerce_payment_complete, woocommerce_order_status_processing, woocommerce_order_status_completed (émission ou règlement), woocommerce_order_status_cancelled (restitution, retrait, clôture du solde).
Routes REST
Espace de noms : websource-credit/v1. Authentification WordPress habituelle (cookie + en-tête X-WP-Nonce, ou mot de passe d'application).
| Méthode | Chemin | Accès | Rôle |
|---|---|---|---|
GET | /me | Utilisateur connecté | Solde et 20 derniers mouvements de l'utilisateur. |
GET | /customers/<id> | manage_woocommerce | Solde et 100 derniers mouvements d'un client. |
POST | /customers/<id>/adjust | manage_woocommerce | Ajout ou retrait manuel. |
Paramètres de /customers/<id>/adjust :
| Paramètre | Type | Rôle |
|---|---|---|
direction | credit (défaut) ou debit | Ajout ou retrait. |
amount | chaîne, obligatoire | Montant TTC, ex. 12.50 ou 12,50. |
reason | chaîne | Motif écrit dans l'historique. |
validity_days | entier | Validité d'un ajout. 0 = sans limite, -1 (défaut) = réglage de l'extension. |
Exemple de requête :
GET /wp-json/websource-credit/v1/me
X-WP-Nonce: <nonce wp_rest>
Réponse :
{
"user_id": 3,
"currency": "EUR",
"balance": 800,
"balance_formatted": "8,00 €",
"history": [
{"date": "2026-10-09 19:06:02", "type": "manual_plus", "amount": 800, "order_id": 0, "note": "Geste commercial"},
{"date": "2026-10-09 19:05:57", "type": "debit", "amount": -600, "order_id": 251, "note": "Règlement de commande (commande n°251)"}
]
}
Exemple d'ajustement :
POST /wp-json/websource-credit/v1/customers/3/adjust
Content-Type: application/json
{"direction": "credit", "amount": "4.20", "reason": "Geste commercial", "validity_days": 0}
La réponse a la même forme que /me. Codes d'erreur : 401 (non connecté), 403 (droit insuffisant), 404 (client introuvable), 422 (montant invalide ou retrait supérieur au solde). Les dates sont en UTC. Types de mouvement : credit, manual_plus, debit, manual_minus, expire, restore, cancel.
WP-CLI
wp websource-credit balance <client>
wp websource-credit grant <client> <montant> [--days=<jours>] [--reason=<motif>]
wp websource-credit withdraw <client> <montant> [--reason=<motif>]
wp websource-credit expire
<client> est un identifiant, un e-mail ou un nom d'utilisateur. expire applique l'expiration à tous les lots échus.
Variables CSS
assets/front.css lit les variables du thème Websource, avec une valeur de repli :
| Variable | Repli | Usage |
|---|---|---|
--color-surface, --wst-surface | #fff | Fond des cartes |
--color-line, --wst-line | #d9e6e4 | Bordures |
--color-ink, --wst-ink | #14282b | Texte |
--color-brand-600, --wst-brand | #0f766e | Solde, montants positifs, contour de focus |
--radius-2xl, --wst-radius-lg | 1.5rem | Arrondi des cartes |
--radius-xl, --wst-radius | 1rem | Arrondi des boutons |
--wst-card-shadow | none | Ombre des cartes |
Fonctions publiques
| Appel | Rôle |
|---|---|
(new Websource\Credit\Wallet())->balance(int $userId): int | Solde disponible en centimes (applique d'abord l'expiration). |
Wallet::usable(int $userId, array $productCaps): int | Avoir utilisable sur un panier ($productCaps : identifiant de produit => montant payé pour ce produit, en centimes). |
Wallet::grant(...), Wallet::debit(...), Wallet::rollback(array $receipt) | Ajout d'un lot, débit atomique (tout ou rien), annulation d'un débit. |
Websource\Credit\Admin::adjust(int $userId, string $direction, string $amount, string $reason, int $validityDays, int $authorId) | Ajustement manuel (formulaire, REST, WP-CLI). Lève InvalidArgumentException. |
Websource\Credit\Rule::load(int $productId): ?Rule, Rule::creditForLine(int $lineCents, int $qty): int | Règle d'un produit et avoir d'une ligne. |
Websource\Credit\Allocator::plan(int $total, int $usable, bool $allowPartial): array | ['mode' => full|partial|refused, 'credit' => int, 'due' => int]. |
Websource\Credit\PayLink::create(WC_Order $order, int $authorId): array | Crée un lien : ['url', 'amount', 'expires']. |
(new Websource\Credit\Settlement())->settle(WC_Order $order, int $cents, string $method, string $reference, int $authorId = 0) | Enregistre le règlement du solde exact. Lève RuntimeException si le solde est déjà réglé ou si le montant diffère. |
Websource\Credit\Plugin::balancePayload(int $userId, int $limit): array | Tableau renvoyé par les routes REST. |
Règles de calcul :
- avoir fixe :
min(valeur × quantité, total TTC de la ligne); - avoir en pourcentage :
intdiv(total TTC de la ligne × points de base, 10000)(arrondi à l'inférieur) ; - les lignes d'un même produit sont additionnées ; un lot par produit et par commande, clé d'origine
o<commande>p<produit>(émission idempotente) ; - débit : lots à l'expiration la plus proche d'abord ; à expiration égale, lots réservés à un produit d'abord ; un lot réservé est plafonné au montant payé pour ce produit dans le panier ;
- débit d'un lot par mise à jour conditionnelle (
amount_remaining >= montant), verrou MySQLGET_LOCKpar commande, restitution si la validation échoue ; - règlement d'un solde par une seule requête conditionnelle : montant égal au reste dû, solde encore ouvert.
Données enregistrées
| Table | Contenu |
|---|---|
wsx_credit_lot | Un avoir accordé : client, montant initial, montant restant, expiration, produit de restriction, commande et clé d'origine. |
wsx_credit_ledger | Chaque mouvement : client, lot, type, montant signé, commande, note, auteur, date (UTC). |
wsx_credit_due | Solde d'une commande payée en partie : total, part réglée par l'avoir, part réglée ensuite, état (open, paid, cancelled). |
wsx_credit_paylink | Liens de paiement : empreinte du jeton, montant, état (pending, used, revoked), commande de règlement, dates. |
Options : wsx_credit_settings, wsx_credit_db, woocommerce_wsx_credit_settings. Tâche planifiée : wsx_credit_daily. Traduction des contenus saisis (instructions hors ligne, titre du moyen de paiement) : wpml-config.xml et pll_register_string.
Désinstallation (uninstall.php) : les commandes à l'état wc-wsx-partial repassent à wc-on-hold avec une note ; la tâche planifiée est retirée. Si « Conserver les données » est décoché : tables, options, métadonnées de produit et données temporaires sont supprimées. Les métadonnées de commande sont conservées.
Écarts par rapport au module PrestaShop
Le module d'origine est websourcecredit 1.1.1.
| Module PrestaShop | Extension WordPress |
|---|---|
| Multiboutique (avoirs propres à chaque boutique) | Non repris : une boutique par site WordPress. |
| Multidevise (lot dans sa devise, conversion à l'usage, écart d'arrondi tracé) | Non repris : WooCommerce n'a qu'une devise. Chaque lot garde le code de la devise ; un lot d'une autre devise que celle de la boutique n'est pas utilisable. |
Règles dans une table websourcecredit_rule | Métadonnées du produit. |
| Avoir émis quand l'état de commande est « payé » | Émis aux états « En cours » et « Terminée », que WooCommerce traite comme payés (paiement à la livraison compris). Filtre wsx_credit_issue_for_order. |
Règlement en ligne par un panier dédié et un produit technique WSCREDIT-SOLDE | Commande de règlement portant une ligne de frais du montant exact, sans TVA, payée sur la page « Payer la commande » de WooCommerce. Le panier du client n'est pas remplacé. |
| Verrou par panier | Verrou par commande (WooCommerce crée la commande avant le paiement). |
Paiement de l'avoir enregistré comme OrderPayment | Métadonnées _wsx_credit_paid / _wsx_credit_due et note de commande. |
| Encart de commande en Ajax | Formulaire classique (rechargement de la page). Le lien créé s'affiche dans l'encart. |
| Instructions hors ligne : un champ par langue | Un seul champ, traduit par Polylang ou WPML. |
E-mails en fichiers mails/fr, mails/en | E-mails dans le gabarit WooCommerce, traduits par le fichier de langue de l'extension. |
| Expiration à la lecture, sans cron | Expiration à la lecture, plus une tâche quotidienne. |
| Panier en plusieurs colis refusé | Sans objet : WooCommerce crée une seule commande. |
| — | Ajoutés : bloc et code court, routes REST, WP-CLI, export et effacement RGPD, e-mails WooCommerce à l'entrée dans l'état partiel, solde dans le menu Mon compte. |