Aller au contenu
🛒 Commandes en double dans WooCommerce : 3 scripts pour le blocage au niveau du panier

🛒 Commandes en double dans WooCommerce : 3 scripts pour le blocage au niveau du panier

Vous avez cliqué deux fois sur «Passer la commande» et maintenant, deux commandes identiques apparaissent dans le panneau d'administration à quelques secondes d'intervalle. Le montant a été débité deux fois, le client est furieux et vous devez gérer un remboursement.

Les commandes en double ne sont pas une situation hypothétique. Environ un magasin sur trois sous WooCommerce y est confronté, notamment avec un hébergement instable ou des passerelles de paiement lentes. Mais même sur un serveur rapide, un utilisateur peut réajouter un produit via l'URL ou acheter un produit numérique gratuit des dizaines de fois.

Nous avons préparé trois scripts fonctionnels qui couvrent différents scénarios de duplication: de l'obligation de vente à l'unité au blocage des ajouts répétés par URL. Voici un décryptage complet avec le code.

Pourquoi les commandes sont-elles dupliquées dans WooCommerce

💡 Aperçu rapide:

  • Vous allez comprendre pourquoi les commandes sont dupliquées au niveau du panier, de l'URL et de l'achat répété
  • Vous allez installer un script pour forcer la vente à l'unité via des champs meta
  • Vous allez empêcher les achats répétés de variations gratuites (biens numériques, coupons)
  • Vous allez éliminer la duplication par URL avec add-to-cart lors du rafraîchissement de la page
  • Vous allez tester la protection et découvrir ce qui peut aussi causer des doublons au niveau du serveur

Les doublons de commande proviennent de trois scénarios principaux.

Premièrement, l'utilisateur clique plusieurs fois sur «Passer la commande». Cela se produit lorsque la page rame, que la personne ne voit aucune réaction et clique à nouveau sur le bouton. Sur un hébergement lent, c'est un grand classique.

Deuxième scénario, les produits gratuits. Si vous avez un produit numérique gratuit, rien n'empêche un utilisateur de l'«acheter» dix fois de suite. WooCommerce, dans sa version de base, ne vérifie pas si ce client a déjà pris le même produit gratuit auparavant.

Troisièmement, un lien direct avec le paramètre ?add-to-cart=123. On rafraîchit la page du panier, le produit est ajouté une nouvelle fois. On suit un lien depuis une newsletter deux fois, deux exemplaires dans le panier.

Ces trois scénarios se résolvent côté serveur via les hooks WooCommerce. Pas de plugins, juste du code.

Méthode 1: forcer la vente à l'unité via des champs meta

Le premier script force WooCommerce à traiter un produit spécifique comme «vendu individuellement», même si cette case n'est pas cochée dans les réglages du produit. Le contrôle se fait via un champ meta.

Lorsque le champ meta maximum_allowed_quantity est égal à 1, le filtre woocommerce_is_sold_individually renvoie true, et WooCommerce bloque lui-même l'ajout d'une deuxième unité au panier. Fonctionne aussi bien pour les produits simples que pour les variations.

Ajoutez le code au fichier functions.php de votre thème enfant ou via le plugin Code Snippets:

1function sd_woocommerce_is_sold_individually( $return, $product ) {
2 switch ( $product->get_type() ) {
3 case 'variation':
4 if ( $product->get_meta( 'variation_maximum_allowed_quantity' ) == 1 ) {
5 return true;
6 }
7 break;
8 case 'simple':
9 if ( $product->get_meta( 'maximum_allowed_quantity' ) == 1 ) {
10 return true;
11 }
12 break;
13 }
14 return $return;
15}
16add_filter( 'woocommerce_is_sold_individually', 'sd_woocommerce_is_sold_individually', 10, 2 );

Ce qui se passe ici: le hook woocommerce_is_sold_individually se déclenche chaque fois que WooCommerce vérifie si un produit peut être ajouté au panier plus d'une fois. La fonction examine les champs meta du produit et, si elle voit maximum_allowed_quantity = 1, elle active de force le mode «Vendu individuellement». Pour les variations, le champ s'appelle variation_maximum_allowed_quantity.

Comment l'appliquer. Allez dans l'édition de n'importe quel produit ou variation, ajoutez un champ personnalisé avec le nom maximum_allowed_quantity (ou variation_maximum_allowed_quantity pour une variation) et la valeur 1. Enregistrez. C'est tout, ce produit ne peut plus être mis au panier en double.

Méthode 2: empêcher les achats répétés de variations gratuites

Les produits numériques gratuits sont la principale faille dans la protection contre les doublons. L'utilisateur est connecté, le prix du produit est zéro, WooCommerce laisse passer la commande sans poser de question. Dix commandes de ce type pour un seul client, dix entrées identiques dans le panneau d'administration.

Le script ci-dessous vérifie via wc_customer_bought_product() si cet utilisateur a déjà acheté le même produit auparavant. Si oui, l'ajout au panier est bloqué avec un message clair.

1function sd_disable_repeat_purchase_for_free_products( $passed, $product_id, $quantity, $variation_id = 0 ) {
2 $current_user = wp_get_current_user();
3 $product = $variation_id > 0 ? wc_get_product( $variation_id ) : wc_get_product( $product_id );
4 $target_id = $variation_id > 0 ? $variation_id : $product_id;
5
6 if ( floatval( $product->get_price() ) == 0 ) {
7 if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $target_id ) ) {
8 wc_add_notice(
9 sprintf( __( 'You have already purchased "%s" and cannot purchase it again.', 'sd' ), $product->get_name() ),
10 'error'
11 );
12 return false;
13 }
14 }
15 return $passed;
16}
17add_filter( 'woocommerce_add_to_cart_validation', 'sd_disable_repeat_purchase_for_free_products', 10, 4 );

Après installation, l'utilisateur voit un message d'erreur lorsqu'il essaie d'ajouter au panier un produit gratuit déjà acheté. La commande elle-même n'est pas créée.

Deux conditions importantes. Premièrement, le client doit être connecté. Pour les visiteurs non connectés, wp_get_current_user() renvoie un objet vide et la vérification ne fonctionnera pas. Deuxièmement, le prix du produit doit être exactement zéro (floatval élimine les problèmes de formatage). Le script ne touchera pas aux produits dont le prix est supérieur à zéro.

Méthode 3: protection contre la duplication par URL avec add-to-cart

WooCommerce permet d'ajouter un produit au panier via un lien direct: /cart/?add-to-cart=123. Pratique pour le marketing, mais si l'utilisateur rafraîchit la page ou suit à nouveau le lien, le produit est ajouté une fois de plus.

Ce script intercepte le chargement de la page panier ou commande et, si le produit du paramètre URL est déjà dans le panier, supprime silencieusement les paramètres de requête et redirige vers une URL propre.

1function sd_prevent_duplicate_add_to_cart_redirect() {
2 if ( ( is_cart() || is_checkout() ) && isset( $_GET['add-to-cart'] ) ) {
3 $current_url = home_url( add_query_arg( null, null ) );
4 $product_id = intval( $_GET['add-to-cart'] );
5 $variation_id = isset( $_GET['variation_id'] ) ? intval( $_GET['variation_id'] ) : 0;
6
7 foreach ( WC()->cart->get_cart() as $cart_item ) {
8 if ( $cart_item['product_id'] == $product_id
9 && ( $variation_id == 0 || $cart_item['variation_id'] == $variation_id ) ) {
10 wp_redirect( remove_query_arg( array( 'add-to-cart', 'variation_id' ), $current_url ) );
11 exit;
12 }
13 }
14 }
15}
16add_action( 'template_redirect', 'sd_prevent_duplicate_add_to_cart_redirect' );

Le hook template_redirect se déclenche avant que WordPress ne commence à générer la page. Le script vérifie si le paramètre add-to-cart est dans l'URL, cherche ce produit dans le contenu du panier (WC()->cart->get_cart()), et s'il le trouve, effectue une wp_redirect vers la même page sans les paramètres de requête.

L'ajout répété par URL est éliminé. En même temps, le premier ajout (quand le produit n'est pas encore dans le panier) fonctionne normalement.

Mise en place de l'ensemble

Les trois scripts n'entrent pas en conflit et fonctionnent indépendamment:

  • Le premier limite la quantité d'un seul produit à 1, protection contre les ajouts multiples.
  • Le deuxième bloque les achats répétés de produits gratuits, protection contre le «clic intempestif» sur les cadeaux.
  • Le troisième supprime la duplication par URL, protection contre les ajouts répétés accidentels.

Ajoutez le code via le plugin Code Snippets sur WP.org, pas directement dans le functions.php du thème. Le plugin vous permet d'activer et de désactiver les extraits un par un sans casser le site en cas d'erreur, et ne perd pas le code lors du changement de thème. Créez trois extraits distincts, c'est plus facile à déboguer ainsi.

Quoi vérifier d'autre si les doublons persistent

Les scripts ci-dessus couvrent les doublons au niveau du panier et de la commande. Mais il existe deux autres sources de problème que le code ne peut pas corriger.

La mise en cache des pages panier et commande. Les plugins de cache comme WP Rocket ou LiteSpeed Cache excluent ces pages par défaut, mais après une mise à jour des paramètres, l'exclusion peut être réinitialisée. Vérifiez: les pages panier, commande et mon compte ne doivent pas être mises en cache au niveau du plugin, du serveur ou du CDN.

Les nouvelles tentatives de la passerelle de paiement. Si la passerelle (Stripe, PayPal) ne reçoit pas de confirmation du serveur à temps, elle renvoie la notification, et WooCommerce crée une deuxième commande. La cause est généralement un hébergement lent ou un pare-feu qui bloque les requêtes de rappel. Solution: vérifiez les logs de la passerelle pour voir les envois répétés de webhooks et assurez-vous que l'URL de rappel est accessible de l'extérieur.

Comment tester la protection

Après avoir installé les scripts, assurez-vous de tester chaque scénario sur un site de test.

Méthode 1, créez un produit avec le champ meta maximum_allowed_quantity = 1 et essayez d'ajouter deux unités au panier. Une seule doit être ajoutée.

Méthode 2, connectez-vous, achetez un produit gratuit, puis essayez de l'acheter à nouveau. Vous devriez voir un message d'erreur.

Méthode 3, ajoutez un produit au panier via un lien direct avec ?add-to-cart=ID, puis rafraîchissez la page. Le nombre d'articles dans le panier ne doit pas changer.

Testez sur une installation séparée ou sur un site de staging. Sur une boutique en production, seulement après une vérification complète.

⁉️🤔 Questions fréquentes

Pourquoi les commandes sont-elles dupliquées si le bouton «Passer la commande» n'a été cliqué qu'une fois?

La raison est presque toujours une réponse lente du serveur. L'utilisateur clique sur le bouton, la requête part, mais la page ne se rafraîchit pas pendant plusieurs secondes. La personne pense ne pas avoir cliqué et clique à nouveau. Les deux requêtes arrivent à WooCommerce, et deux commandes sont créées. Les scripts de cet article ne couvrent pas cette situation; ici, une protection côté client (désactiver le bouton après le clic) ou une vérification d'unicité de commande côté serveur via un jeton nonce peut aider.

Une passerelle de paiement peut-elle créer des doublons toute seule?

Oui. Si la passerelle ne reçoit pas un HTTP 200 de votre serveur en réponse à un IPN/webhook, elle répète l'envoi. À chaque nouvelle tentative, WooCommerce peut créer une nouvelle commande. Le problème se résout en accélérant l'hébergement et en vérifiant que l'URL de rappel de la passerelle n'est pas bloquée par un pare-feu et ne nécessite pas d'authentification HTTP.

Cette protection bloque-t-elle les vraies commandes répétées d'un client?

Non. Les scripts agissent au stade de l'ajout au panier, pas au stade de la création de commande. Si un client a délibérément passé une commande, puis une deuxième une semaine plus tard, les scripts n'interféreront pas. Exception: la méthode 2, qui interdit l'achat répété d'un produit gratuit par le même utilisateur.

Est-il obligatoire d'utiliser Code Snippets, ou peut-on mettre le code dans functions.php?

Vous pouvez utiliser functions.php, mais nous recommandons Code Snippets. Avec une faute de frappe dans le code de functions.php, vous obtenez un écran blanc et un accès uniquement par FTP. Le plugin Code Snippets intercepte les erreurs fatales et désactive automatiquement l'extrait problématique, le site reste debout.

Les plugins pour empêcher les doublons sont-ils utiles?

Les plugins spécialisés comme WooCommerce Duplicate Order Blocker fonctionnent à un autre niveau; ils traquent les doublons par IP, email ou empreinte de navigateur au stade de la commande. Cela couvre le scénario du double clic que nos scripts ne couvrent pas. Cependant, les plugins ne résolvent pas le problème des doublons par URL add-to-cart et des achats répétés d'un produit gratuit. L'option idéale: les scripts de cet article plus un plugin bloqueur sur la page de commande.

Résumé: trois niveaux de protection contre les doublons

Trois scripts couvrent trois scénarios spécifiques de duplication de commande. Installez-les tous en même temps; chacun est responsable de son propre domaine et, ensemble, ils offrent une protection stricte au niveau du panier.

Si des doublons apparaissent encore après l'installation, tournez-vous vers l'hébergement et la passerelle de paiement. Un double clic sur le bouton «Passer la commande» ne peut pas être corrigé par du code au niveau du panier; ici, vous avez besoin soit d'un plugin bloqueur, soit d'une protection personnalisée du bouton via JavaScript.

Testez la protection sur un site de test, puis passez-la en production. Quinze minutes pour installer trois extraits vous feront gagner des heures de gestion de remboursements.