EU Withdrawal Button for WooCommerce

Descrición

EU Directive 2023/2673 introduces new requirements for online stores regarding consumer withdrawal rights, taking effect on June 19, 2026.

EU Withdrawal Button for WooCommerce helps you implement a clear, accessible withdrawal flow for your customers:

The 4-Step Flow

  1. Visible Button — Sticky bar with a withdrawal button on every page
  2. Withdrawal Form — Customer enters order number + email for verification
  3. Confirmation Step — Order summary with a separate “Confirm withdrawal” button
  4. Notifications — Confirmation email to customer + notification to merchant

Features

  • Sticky bar with configurable text and button
  • Modal popup or dedicated page mode
  • Order validation (order number + email + 14-day window check)
  • Custom WooCommerce order status: “Withdrawal Requested”
  • WooCommerce email integration (shows in WooCommerce Settings Emails)
  • Support for custom order number plugins (Sequential Order Numbers, etc.)
  • WCAG 2.1 AA accessible (keyboard navigation, focus trap, ARIA labels)
  • Rate limiting for abuse prevention
  • Translation-ready with .pot file
  • HPOS (High-Performance Order Storage) compatible

Who Is This For?

WooCommerce store owners who sell to EU consumers and want to provide a clear withdrawal process for their customers.

Disclaimer

This plugin is a technical tool that helps implement a withdrawal flow. It does not constitute legal advice and does not guarantee compliance with any specific regulation. Consult a legal professional to ensure your store meets all applicable requirements.

Capturas

  • Sticky bar with withdrawal button on the storefront
  • Withdrawal form modal
  • Confirmation step with order summary
  • WooCommerce settings page

Instalación

  1. Upload the eu-withdrawal-button-for-woocommerce folder to /wp-content/plugins/
  2. Activate the plugin through the ‘Plugins’ menu in WordPress
  3. Go to WooCommerce Settings Withdrawal Button to configure
  4. The withdrawal button will appear on your storefront

Preguntas frecuentes

What does this plugin do?

It adds a visible withdrawal button to your store, along with a form where customers can submit withdrawal requests. The plugin validates the order, notifies both parties via email, and tracks the request.

What happens when a customer submits a withdrawal?

The customer receives a confirmation email, the merchant receives a notification, an order note is added, and the order status changes to “Withdrawal Requested” (configurable).

Can I exclude certain products?

Product category exclusions and per-product exceptions are available in the paid version.

Does it work with custom order number plugins?

Yes, the plugin searches by WooCommerce order ID, custom order number meta fields, and order number output — compatible with Sequential Order Numbers and similar plugins.

Is my data sent to third parties?

The plugin stores withdrawal data in your own WordPress database. The Freemius SDK is used for license management and asks for your opt-in consent on activation.

Comentarios

Non hai recensións para este plugin.

Colaboradores e desenvolvedores

“EU Withdrawal Button for WooCommerce” é un software de código aberto. As seguintes persoas colaboraron con este plugin.

Colaboradores

“EU Withdrawal Button for WooCommerce” foi traducido a 1 idioma. Grazas aos desenvolvedores polas súas contribucións.

Traduce “EU Withdrawal Button for WooCommerce” ao teu idioma.

Interesado no desenvolvemento?

Revisa o código, bota unha ollada aorepositorio SVN, ou subscríbete ao log de desenvolvemento por RSS.

Rexistro de cambios

2.0.0

  • WordPress.org edition. First release published on the WordPress.org plugin directory. Feature parity with 1.5.x, Lite tier only. Paid upgrades continue to be distributed via riin.eu.
  • Code: Full prefix refactor to ra_euwb_ / RA_EUWB_ / ra-euwb- across options, hooks, CSS classes, JS globals, nonces and admin menu slugs, to comply with the WordPress.org guidelines on unique prefixes. Existing WC order status slugs (wc-ewb-withdrawn, wc-ewb-completed), the database table ({prefix}ewb_withdrawals) and the _ra_euwb_deactivated_withdrawal order meta key are preserved so existing installations continue to work without data migration.
  • Code: Removed all inline <style> and <script> output. Admin order-status colours and the frontend ra-euwb-hidden utility class are now part of the enqueued stylesheets. Frontend button colours are static (overridable via theme CSS) instead of dynamic option-backed inline styles.
  • Code: Custom CSS setting removed from the free build (WordPress.org guideline: plugins must not execute arbitrary user-supplied CSS from options).
  • Code: Text domain updated from eu-withdrawal-button to eu-withdrawal-button-for-woocommerce to match the WordPress.org plugin slug.
  • Misc: Removed the now-unused class-ewb-i18n.php helper (text domain is loaded directly via load_plugin_textdomain() on init).

1.5.0

  • Compliance Update — EU Directive 2023/2673. All compliance-critical features are available in the free version.
  • Guest-friendly direct link in order emails: The WooCommerce customer “processing” and “completed” order emails now include a “Withdraw from this order” button. The link opens the withdrawal form pre-verified against the order — no login required. Solves the guest-checkout compliance gap (the directive explicitly requires that withdrawal must not depend on having a customer account).
  • Dismissible sticky bar: Visitors can close the sticky bar with an X button. Dismissal is remembered for a configurable number of days (default 7, configurable 0–30) via localStorage. My Account pages ignore the dismissal and always show the bar (EU compliance — customer must be able to request a withdrawal there).
  • Partial withdrawal support: Customers can now select specific items and quantities to withdraw instead of the whole order. The confirmation step shows per-item checkboxes and quantity inputs, pre-filled with the full order.
  • Optional IBAN field: Customers can provide a bank account for the refund (useful when they paid by card or want the refund sent to a different account). Leaving it empty tells the merchant to refund to the original payment method. The IBAN is shown prominently in the merchant notification email and in the admin withdrawals list.
  • Configurable sticky bar display: New “Show sticky bar on” multiselect under Withdrawal Button General lets merchants pick which page types show the sticky bar (Homepage, Shop & product pages, Cart & checkout, Other). The My Account pages always show the sticky bar (EU compliance — customer must be able to request a withdrawal there). Existing installations default to My Account pages only after the upgrade, so update your settings if you want the sticky bar elsewhere.
  • Discreet footer link: Optional small “Right of withdrawal” link can be shown in the footer (useful when the sticky bar is disabled on most pages).
  • Admin: Withdrawals list now shows a Full / Partial badge and a hoverable list of the selected items per request, plus a dedicated IBAN column.
  • Emails: Customer confirmation and merchant notification emails now list only the selected withdrawn items (with a partial-withdrawal notice when applicable) and show the IBAN. Legacy rows from pre-1.5.0 fall back to the full-order view.
  • Database: New withdrawn_items (JSON) and iban columns on {prefix}ewb_withdrawals. The upgrade runs automatically on plugin load via dbDelta() — no manual action required.
  • Security: Submitted item selections are re-validated server-side against the actual order (quantities clamped, unknown items rejected) to prevent tampering.
  • Security hardening (CIA audit pass): (a) CSV export now escapes spreadsheet formula injection (leading =, +, -, @, tab, CR) and includes the Withdrawn Items + IBAN columns that were previously silently misaligned. (b) Client IP detection no longer trusts HTTP_X_FORWARDED_FOR / HTTP_CLIENT_IP by default — sites behind a trusted reverse proxy (e.g. Cloudflare) can opt in via the ewb_trust_forwarded_ip filter. (c) Submission now holds a MySQL advisory lock per order around the duplicate check + insert, closing the race window that allowed two simultaneous clicks to create duplicate withdrawal rows. (d) The public ewb_validate_order and ewb_lookup_by_key endpoints are now rate-limited (30 requests per 5 minutes per IP). (e) “Order not found” and “email does not match the order” are collapsed into a single generic verification error to prevent order enumeration. (f) Support form Reply-To header explicitly strips CR/LF defending against header injection.

1.4.0

  • IMPORTANT: Clarified “Withdrawal Completed” semantics. Renamed the user-facing label to “Withdrawal Closed” everywhere it appeared (order status, emails, order notes, My Account box, admin). The status no longer implies that an automatic refund has been issued — merchants must refund manually via WooCommerce Orders. Automatic wc_create_refund() integration is planned for a future Pro release. Internal status slug (wc-ewb-completed) is unchanged so existing orders continue to work.
  • IMPORTANT FIX: The sticky bar, withdrawal form, confirmation email, “closed” email and admin information guide previously hardcoded “14 days” even when merchants configured a different ewb_withdrawal_days value. All texts now reflect the configured value dynamically with proper single/plural handling. Merchants can also use the {days} placeholder in the custom Bar text field.
  • Updated customer closed-request email to clearly state that the merchant will issue the refund manually, instead of claiming the refund has already been processed.
  • Added a “Heads up” admin notice on every plugin settings tab explaining the manual refund workflow.
  • Performance & reliability: Order number lookup fallback (step 3) now filters by the configured withdrawal window (days + 2 buffer) instead of the arbitrary “last 500 orders” limit, and is capped at 1000 orders scanned. Both bounds are adjustable via the ewb_order_lookup_cutoff_date and ewb_order_lookup_max_scan filters. A warning is logged if the fallback triggers — this helps merchants spot custom order number plugins that don’t use the standard _order_number meta key.
  • Code quality: Custom CSS (Basic+) now uses wp_add_inline_style() attached to the main ewb-frontend stylesheet handle instead of printing a raw <style> tag on wp_head. This integrates with minify/cache plugins and follows WordPress standards.

1.3.3

  • Fix: Removed the parent => woocommerce menu setting so the Freemius SDK can properly register its own admin pages (connect/opt-in, account, pricing). Previously the activation flow tried to redirect users to admin.php?page=ewb-withdrawal which WordPress rejected with “Sorry, you are not allowed to access this page.” because the submenu was never registered. Plugin Settings link still opens WooCommerce Settings Withdrawal Button via first-path.

1.3.2

  • Fix: Freemius “Opt In” and Account/Pricing pages now work correctly. Previously the menu used an embedded WooCommerce settings URL as its slug, which prevented the Freemius SDK from rendering its own admin pages (opt-in form, account, pricing, checkout)
  • Added a dedicated ewb-withdrawal plugin page for Freemius SDK, with first-path redirecting Settings link to the WooCommerce Settings Withdrawal Button tab (existing UX preserved)

1.3.1

  • Fix: “Get Basic” and “Get Pro” buttons in the Upgrade tab now open the Freemius in-admin checkout (iframe) instead of redirecting to the marketing site
  • Fix: Restored the “License” / “Activate License” link on the Plugins page by registering the Freemius account page (ewb-account)
  • Added dedicated Freemius pricing page (ewb-pricing) for in-admin checkout flow
  • Updated Upgrade tab FAQ to reflect the new in-admin checkout experience

1.3.0

  • Freemius: Premium code is now properly marked with is__premium_only() gates so Freemius can auto-generate a clean free build without premium features
  • Renamed class-ewb-rest-api.php to class-ewb-rest-api__premium_only.php so Freemius excludes it from the free build
  • Added Requires Plugins: woocommerce header (WordPress 6.5+ plugin dependencies)
  • readme.txt: added nalut to contributors

1.2.1

  • Fix: Plugin text domain is now properly loaded, enabling translations via WPML / Loco Translate / .mo files
  • Add wpml-config.xml for admin text translation support

1.2.0

  • Switched to Freemius-only distribution (independent of WordPress.org)
  • Disabled WordPress.org compliance mode in Freemius SDK

1.1.0

  • Added tier system (Lite / Basic / Pro)
  • Freemius integration for license management
  • Support tab with contact info
  • Upgrade tab with plan comparison
  • Improved custom order number compatibility
  • Various bug fixes and improvements

1.0.0

  • Initial release
  • 4-step withdrawal flow
  • Sticky bar with configurable text
  • Modal popup and page display modes
  • WooCommerce email integration
  • Custom order status: Withdrawal Requested
  • Rate limiting
  • HPOS compatibility
  • WCAG 2.1 AA accessibility
  • Translation-ready