Withdrawal
Free implementation of Article 11a of Directive 2023/2673 for WooCommerce. Withdrawal button, two-step form, declaration on durable medium, operator panel. No limits, no hidden costs.
Features
What the plugin does
Withdrawal button (Art. 11a)
Visible button in order details in My Account. One click, two-step form with confirmation.
Variable product support
The customer selects exactly which items to return; the operator sees the same details in the admin panel.
Guest order support
Works without registration. Verification via email and order number.
Declaration on durable medium
Withdrawal declaration stored in accordance with Art. 11a(3) of Directive 2023/2673, available for download.
Operator panel
Complete list of declarations in the WooCommerce panel with audit history and wc-withdrawal order status.
GDPR-ready, no external APIs
All data stays on your server. No external services. WCAG 2.2 AA compliant.
What does the law require from your store?
From June 19, 2026, every online store selling to consumers in the EU must have a visible withdrawal button. A clause in the terms of service is not enough. The customer must be able to submit their declaration directly on the store’s website, in a few clicks, and immediately receive an email confirmation.
The obligation applies to every online seller, regardless of where they are based. Enforcement is handled by national consumer protection authorities.
The free version is a complete solution for the basic obligation under Directive 2023/2673. If you run a store with manual return handling and sell primarily physical or simple digital products — the free version is sufficient. The Pro version adds a workflow layer on top (automated refunds, PDF, reports) and support for complex orders (subscriptions, bundles). If none of that applies to your store, you don’t need Pro.
Comparison
Free vs Pro
What Pro adds on top of full compliance.
| Feature | Free | Pro |
|---|---|---|
| Withdrawal button from contract (Article 11a) | ||
| Two-step withdrawal form | ||
| Variable product support | ||
| Guest order support (without registration) | ||
| Article 16(m) consent for digital products | ||
| Confirmation email as durable medium (Art. 11a(3)) | ||
| Declaration as legal artefact | ||
| Withdrawal history in My Account | ||
| Declaration list in WooCommerce panel | ||
| Declaration details page with audit trail | ||
| Declaration registration metabox on order page | ||
| Admin notification email | ||
| wc-withdrawal order status with audit trail | ||
| Annex I(A) and I(B) page generator | ||
| Automatic refund on acceptance | ||
| PDF declaration generation | ||
| Declaration reports and CSV export | ||
| Webhook notifications and Slack integration | ||
| WooCommerce Subscriptions support | ||
| Active subscription cancellation on withdrawal | ||
| Proportional subscription period settlement | ||
| WooCommerce Product Bundles support | ||
| Refund calculation for partial bundle return |
Changelog
- New Confirmed compatible with WordPress 7.0
- Sec Nonce is now verified before incrementing the rate-limit counter — attackers can no longer exhaust a guest's hourly budget with unauthenticated probes
- Sec Guest rate-limit buckets scoped per hashed IP instead of a shared pool — parallel guest sessions no longer share a single quota
- Sec Withdrawal form items validated against the actual order before processing — crafted requests cannot attach foreign line items to a declaration
- Sec Declaration items filter output re-validated — malformed entries from third-party plugins are stripped before the declaration is saved
- Sec Operator endpoints now explicitly block unauthenticated (user_id=0) requests regardless of order customer_id
- Sec Manual operator registration checks excluded order statuses at handler entry — the block cannot be bypassed by changing the status after the initial check
- Sec Declaration filing date validated for format and non-zero value — invalid date strings rejected before database write
- Sec Rate limiter returns a blocking value when its database table is unavailable — the limiter can no longer silently become a no-op
- Fix Fractional product quantities now sum correctly — IEEE-754 epsilon errors (e.g. 0.1 + 0.2) no longer cause quantity mismatches in declarations
- Fix Removed a spurious user_register hook from the Privacy Manager — no phantom calls on standard WordPress user registration
- Fix All plugin identifiers (AJAX actions, script handles, nonce names, metabox IDs) renamed from the short bpw_ prefix to the full buddypilot_withdrawal_ prefix — satisfies WordPress.org unique-prefix requirement; no functional changes for stores not customising plugin internals
- Sec All admin and AJAX handlers now check user capabilities before verifying the nonce — consistent with WordPress security guidelines
- Sec Operator AJAX handler uses check_ajax_referer() and returns a proper JSON error on nonce failure — correct behaviour for JavaScript error handling
- Sec Information-page creation button is now restricted to users with the required capability
- Sec Currency symbol and number separators escaped on the JavaScript side before DOM insertion — XSS protection in withdrawal form price display
- Fix Operator JavaScript moved to an enqueued file — better caching and separation from template markup
- Fix Removed manual load_plugin_textdomain() call — WordPress 4.6+ and WP.org handle translation loading automatically
- New First stable release: two-step withdrawal form, guest verification, operator manual registration, declarations admin list, configurable withdrawal period and delivered statuses, Article 16(m) consent capture for digital goods, Annex I(A)/(B) page generator, customer and admin emails, My Account withdrawal history, HPOS support, GDPR hooks, WCAG 2.2 AA compliance, Polish and English translations
Frequently asked questions
Get started for free
Activation takes 5 minutes. Hosted on WordPress.org with native WordPress updates.