Woo Withdrawal Modal for WooCommerce
Overview
EU-based online stores are legally required to accept product returns within a mandated period under the EU Consumer Rights Directive (2011/83/EU) — the right of withdrawal. Most WooCommerce stores handle this the same way: customer emails, phone calls, and a spreadsheet somewhere to keep track of who asked for what.
Woo Withdrawal Modal for WooCommerce replaces that with a structured, auditable workflow built directly into the store. It's a PHP 8.1 plugin, WooCommerce HPOS-compatible, currently at v1.3.0.
Customer-Facing Withdrawal Request
A floating action button opens a modal where customers can look up an order by order ID, billing email, and phone, then submit a partial or full product withdrawal request against it. The button can also be placed anywhere on the site via a shortcode, independent of the floating widget.
Admin Dashboard & Order Management
On the admin side, a dedicated dashboard lists incoming withdrawal requests for review, approval, or rejection. Each order's edit screen also gets a meta box showing its withdrawal history, so staff don't have to leave the order they're already looking at. Requests can be exported to CSV, and a daily cleanup job — with configurable data retention — keeps old records from piling up indefinitely.
Automated Notifications
Customers and staff are kept in sync through automated email notifications, with both HTML and plain-text templates that stores can override from their theme. The emails render WooCommerce-style product tables — thumbnails, SKU, variation attributes — so a withdrawal request email reads like a proper order document, not a generic notice.
Configurable Business Rules
The legal withdrawal window isn't the same for every store or every product, so the rules are configurable rather than hardcoded:
- Eligibility period length
- Whether the window starts at order creation or order completion
- Which order statuses are eligible
- Excluded product categories/tags, for goods legally exempt from withdrawal (customized or perishable items, for example)
Security & Compliance
Because the plugin handles order lookups and personal data, security and GDPR compliance were treated as first-class requirements, not an afterthought:
- Optional Cloudflare Turnstile CAPTCHA on search and submit
- Nonce-protected AJAX endpoints, with sanitized input and escaped output
- IP-based rate limiting and a honeypot bot check
- Generic error messages, so failed lookups can't be used to enumerate orders
- Full WordPress Privacy integration — policy text, personal-data export, and erasure handlers
Engineering Practices
- A PHPUnit test suite covers the plugin's core helpers
- Versioning is iterative (currently v1.3.0), with a maintained changelog documenting each release
- Performance and code-quality work — caching, query efficiency, autoload tuning — is tracked as a separate optimization backlog fed by internal code review, rather than mixed into feature work
Conclusion
Compliance features are easy to bolt on badly — a form that emails an admin and calls it done. The goal here was the opposite: treat the right of withdrawal as a real workflow with rules, audit trails, and data lifecycle management, built to the same security and testing standards as the rest of the store.
