From 93077dfba7232504be4e2de211d05d99e8759dbf Mon Sep 17 00:00:00 2001 From: Chris Portscheller Date: Wed, 21 Oct 2026 14:24:08 -0500 Subject: [PATCH] Fix classic WooCommerce checkout hook load order --- cdn-files/plugin-info.json | 6 +++--- changelog.txt | 3 +++ readme.txt | 8 +++++++- tests/wp-compat/woo.sh | 17 +++++++++++++++++ webdecoy.php | 27 +++++++++++++++++++-------- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/cdn-files/plugin-info.json b/cdn-files/plugin-info.json index 4530fa2..5c3d045 100644 --- a/cdn-files/plugin-info.json +++ b/cdn-files/plugin-info.json @@ -1,17 +1,17 @@ { "name": "WebDecoy Bot Detection", "slug": "webdecoy", - "version": "2.10.5", + "version": "2.10.6", "author": "WebDecoy", "author_profile": "https://webdecoy.com", "requires": "6.1", "tested": "7.1", "requires_php": "7.4", - "download_url": "https://cdn.webdecoy.com/wordpress/webdecoy-2.10.5.zip", + "download_url": "https://cdn.webdecoy.com/wordpress/webdecoy-2.10.6.zip", "sections": { "description": "

WebDecoy provides enterprise-grade bot detection and fraud protection for WordPress websites. Unlike simple CAPTCHA solutions, WebDecoy uses a layered defense approach that analyzes visitors from multiple angles — including deterministic tripwires that catch scanners with zero false positives.

Key Features

", "installation": "
  1. Upload the plugin files to /wp-content/plugins/webdecoy
  2. Activate the plugin through the Plugins menu
  3. Tripwires and local protection are active out of the box — no API key required
  4. Optionally go to WebDecoy > Settings > WebDecoy Cloud to connect for centralized monitoring and enforcement
", - "changelog": "

2.10.5

2.10.4

2.10.3

2.10.2

2.10.1

2.10.0

2.9.1

2.9.0

2.3.1

2.3.0

2.1.0

2.0.0

1.3.0

", + "changelog": "

2.10.6

2.10.5

2.10.4

2.10.3

2.10.2

2.10.1

2.10.0

2.9.1

2.9.0

2.3.1

2.3.0

2.1.0

2.0.0

1.3.0

", "faq": "

Does WebDecoy slow down my site?

No. WebDecoy adds negligible latency; tripwire checks are a fast path lookup and clearance minting is idle-deferred.

Will it block search engines?

No. WebDecoy automatically allows 60+ known good bots including all major search engines, and tripwires only fire on hidden paths no legitimate crawler follows.

" }, "icons": { diff --git a/changelog.txt b/changelog.txt index 64c769d..a188ca6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ *** WebDecoy Bot Detection Changelog *** += 2.10.6 - 2026-10-21 = +* Fixed: classic WooCommerce checkout protection and attempt tracking now register after all plugins load. Previously, loading WebDecoy before WooCommerce silently skipped these hooks. + = 2.10.5 - 2026-10-04 = * Fixed: maybe_flag_proxy() flagged an unconfigured proxy whenever an admin request carried any forwarding header. Hosts that rewrite REMOTE_ADDR to the visitor (WordPress.com, nginx real_ip, mod_remoteip) still forward X-Forwarded-For, so the notice showed on nearly every install and enforcement was suppressed with no cause. It now flags only when REMOTE_ADDR is absent from every forwarded address (WebDecoy_Blocker::unresolved_forwarding_header()); stale flags clear on the next admin page load. * Fixed: the state notices linked to admin.php?page=webdecoy-settings, which is not a registered page; the settings slug is webdecoy. The proxy button is also anchored to the trusted-proxies field. diff --git a/readme.txt b/readme.txt index d6b438e..4a7c1b2 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://webdecoy.com Tags: bot detection, security, spam protection, woocommerce, ai bots Requires at least: 6.1 Tested up to: 7.1 -Stable tag: 2.10.5 +Stable tag: 2.10.6 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -285,6 +285,9 @@ The bundled good-bot list (sdk/src/GoodBotList.php) stores a documentation URL f == Changelog == += 2.10.6 = +* Fixed: classic WooCommerce checkout protection and attempt tracking now register after all plugins load. Previously, loading WebDecoy before WooCommerce silently skipped these hooks. + = 2.10.5 = * Fixed: the warning that WebDecoy is not blocking because the site is behind an unconfigured proxy no longer appears on hosts that already pass the visitor's real address to WordPress, such as WordPress.com. On those sites blocking was being withheld for no reason. * Fixed: the warning's "Configure trusted proxies" button, and the monitor-mode "Review and turn on blocking" button, led to a "not allowed to access this page" error. They now open the settings page. @@ -473,6 +476,9 @@ Safety release. Please update. This version deliberately makes the plugin do les == Upgrade Notice == += 2.10.6 = +Restores classic WooCommerce checkout protection when WebDecoy loads before WooCommerce. Recommended for WooCommerce stores. + = 2.10.5 = Fixes a false "behind a proxy" warning that switched off blocking on many managed hosts, and the broken button in that warning. diff --git a/tests/wp-compat/woo.sh b/tests/wp-compat/woo.sh index d49d3c3..2374858 100755 --- a/tests/wp-compat/woo.sh +++ b/tests/wp-compat/woo.sh @@ -23,6 +23,23 @@ WP plugin is-installed woocommerce || WP plugin install woocommerce ${WOO_VERSIO WP plugin activate woocommerce | tail -1 echo "WooCommerce $(WP plugin get woocommerce --field=version) on WordPress $(WP core version) / PHP $(WP eval 'echo PHP_VERSION;')" +echo "## classic checkout callbacks exist after both plugins load" +# On a fresh install WordPress loads webdecoy before woocommerce. The old +# constructor-time class_exists() gate silently skipped these callbacks. +WP eval ' +$callbacks = [ + "woocommerce_checkout_process" => "check_checkout", + "woocommerce_payment_complete" => "track_payment", + "woocommerce_checkout_order_processed" => "track_checkout_attempt", +]; +foreach ($callbacks as $hook => $method) { + if (has_action($hook, [webdecoy(), $method]) === false) { + WP_CLI::error("Missing checkout callback: " . $hook); + } +} +WP_CLI::success("Classic validation, payment and attempt callbacks registered."); +' || fail=1 + echo "## store setup (guest checkout, COD, one virtual product)" WP option update woocommerce_onboarding_profile '{"skipped":true}' --format=json >/dev/null WP option update woocommerce_coming_soon no >/dev/null diff --git a/webdecoy.php b/webdecoy.php index dabac6e..4538ea2 100644 --- a/webdecoy.php +++ b/webdecoy.php @@ -3,7 +3,7 @@ * Plugin Name: WebDecoy Bot Detection * Plugin URI: https://webdecoy.com/wordpress * Description: Protect your WordPress site from bots, spam, and carding attacks with WebDecoy's advanced threat detection. - * Version: 2.10.5 + * Version: 2.10.6 * Requires at least: 6.1 * Requires PHP: 7.4 * Author: WebDecoy @@ -41,7 +41,7 @@ function str_starts_with(string $haystack, string $needle): bool } // Plugin constants -define('WEBDECOY_VERSION', '2.10.5'); +define('WEBDECOY_VERSION', '2.10.6'); define('WEBDECOY_PLUGIN_FILE', __FILE__); define('WEBDECOY_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('WEBDECOY_PLUGIN_URL', plugin_dir_url(__FILE__)); @@ -921,12 +921,9 @@ private function init_hooks(): void add_action('register_form', [$this, 'inject_register_honeypot']); } - // WooCommerce hooks - if ($this->options['protect_checkout'] && class_exists('WooCommerce')) { - add_action('woocommerce_checkout_process', [$this, 'check_checkout']); - add_action('woocommerce_payment_complete', [$this, 'track_payment']); - add_action('woocommerce_checkout_order_processed', [$this, 'track_checkout_attempt']); - } + // WooCommerce may load after this plugin. Register checkout callbacks + // only after all plugin entry points and our includes have loaded. + add_action('plugins_loaded', [$this, 'register_woocommerce_hooks'], 20); // AJAX handlers (admin) add_action('wp_ajax_webdecoy_test_connection', [$this, 'ajax_test_connection']); @@ -995,6 +992,20 @@ private function init_hooks(): void add_filter('script_loader_tag', [$this, 'add_defer_to_scanner'], 10, 3); } + /** + * Register classic checkout protection independently of plugin load order. + */ + public function register_woocommerce_hooks(): void + { + if (!$this->options['protect_checkout'] || !class_exists('WooCommerce')) { + return; + } + + add_action('woocommerce_checkout_process', [$this, 'check_checkout']); + add_action('woocommerce_payment_complete', [$this, 'track_payment']); + add_action('woocommerce_checkout_order_processed', [$this, 'track_checkout_attempt']); + } + /** * Declare WooCommerce feature compatibility: High-Performance Order Storage * and the block-based Cart & Checkout. The Store API hooks in