Title: BeziWorld Withdrawal for WooCommerce
Author: beziworld
Published: <strong>June 1, 2026</strong>
Last modified: July 10, 2026

---

Search plugins

![](https://ps.w.org/beziworld-withdrawal-for-woocommerce/assets/banner-772x250.
png?rev=3556797)

![](https://ps.w.org/beziworld-withdrawal-for-woocommerce/assets/icon.svg?rev=3556797)

# BeziWorld Withdrawal for WooCommerce

 By [beziworld](https://profiles.wordpress.org/beziworld/)

[Download](https://downloads.wordpress.org/plugin/beziworld-withdrawal-for-woocommerce.2.86.0.zip)

 * [Details](https://wordpress.org/plugins/beziworld-withdrawal-for-woocommerce/#description)
 * [Reviews](https://wordpress.org/plugins/beziworld-withdrawal-for-woocommerce/#reviews)
 *  [Installation](https://wordpress.org/plugins/beziworld-withdrawal-for-woocommerce/#installation)
 * [Development](https://wordpress.org/plugins/beziworld-withdrawal-for-woocommerce/#developers)

 [Support](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/)

## Description

Add a compliant **withdrawal button** (“right of withdrawal” / “Widerrufsbutton”/“
odstąpienie od umowy”) to your WooCommerce store. **BeziWorld Withdrawal for WooCommerce**
is a free, GPL-licensed plugin that gives EU shops the dedicated, one-click withdrawal-
from-contract function required by the EU Modernisation Directive (Directive (EU)
2023/2673, amending the Consumer Rights Directive via Article 11a), **in force since
19 June 2026**.

The directive requires online shops selling to EU consumers to provide a dedicated,
one-click withdrawal function inside the shop interface — separate from any generic
returns/RMA page. This plugin delivers that function and the surrounding workflow:
item-level partial withdrawals, a durable-medium acknowledgement, automatic refunds,
and a tamper-evident audit trail.

**This plugin is a technical tool; it does not provide legal advice and does not
by itself guarantee legal compliance. Responsibility for meeting the applicable 
consumer-law obligations remains with the shop operator.** How the directive applies
depends on your country’s transposition (for example, the dedicated withdrawal-function
obligation is in force in Germany, France, Italy and the Netherlands, but had not
been transposed in Poland at the time of writing). Consult a qualified lawyer for
your jurisdiction.

_This plugin is an independent project. It is not affiliated with, endorsed by or
sponsored by WooCommerce or Automattic Inc. “WooCommerce” is a trademark of its 
respective owner and is used here only to describe compatibility._

#### What this plugin gives you

 * A dedicated **Withdrawal** tab inside WooCommerce’s My Account area
 * **Item-level partial withdrawals** with per-line quantity selection
 * **Public withdrawal page** auto-created on activation — guests enter order number
   + email to authenticate, no account required
 * Single-use guest token automatically embedded in the order confirmation email
 * Immediate confirmation email on a durable medium, as required by Article 11(3)
   CRD
 * Configurable withdrawal period (14-60 days, default 14) — increase if you offer
   an extended return policy
 * Deadline calculator that rolls weekends and public holidays forward to the next
   working day
 * Polish public holidays preset for 2026-2028 (extensible to any locale through
   a filter)
 * Refund calculation that respects Article 13(2) CRD: items plus the cheapest standard
   shipping option you offered
 * **Automatic refunds** through the original payment gateway when supported (Stripe,
   PayU, Przelewy24, Tpay, Mollie, etc.)
 * Admin can override the calculated refund amount (restocking fee, partial damage)
 * Configurable rule engine: exclude products, categories, user roles or payment
   gateways from withdrawal
 * Storefront notices on **product / cart / checkout / thank-you** pages with WYSIWYG-
   editable text
 * Predefined reason picker, configurable from settings
 * Customer self-service cancellation while still pending
 * **Five status emails**: four to the customer (confirmation, received, refunded,
   rejected) plus a merchant notification when a new withdrawal is submitted — each
   with a **visual (WYSIWYG) body editor** and all overridable from your theme
 * **Editable withdrawal-form wording**: reword the form heading, labels and hints
   from the settings screen, with legally compliant defaults pre-filled
 * **Withdrawal form field manager**: choose which optional fields appear (reason,
   details, phone, IBAN), reorder them, and add your own custom fields — while the
   statutory item/name/email fields always stay required
 * Optional automatic transition of the order status when a withdrawal is submitted
 * **Full audit trail**: IP, user-agent, server-side timestamps in UTC
 * Trash / restore / delete for withdrawal records
 * CSV export of all withdrawal statements
 * WordPress privacy tools integration — exporter and eraser registered by default
 * WP-CLI commands: `wp bzww list`, `wp bzww refund`, `wp bzww cancel`, `wp bzww
   received`, `wp bzww stats`
 * REST API endpoints under `/wp-json/bzww/v1/` for headless and mobile clients
 * Gutenberg block and Elementor widget alternatives to the shortcode
 * WooCommerce HPOS (custom order tables) compatible
 * 30+ filters and actions for deep customization (see HOOKS.md in the source repository)
 * **Verifiable acknowledgement**: each confirmation carries a SHA-256 receipt code
   recomputable from the stored declaration, so the durable-medium record is tamper-
   evident
 * **Printable acknowledgement certificate** the consumer can save as a PDF with
   the browser print function
 * **Always-visible access**: a site-wide footer link plus an optional dismissible
   sticky bar, so the withdrawal function is reachable from every page
 * **Annex I generator**: one-click withdrawal-information (Annex I.A) and model-
   withdrawal-form (Annex I.B) pages, generated from your store details, plus `[
   bzww_withdrawal_policy]` and `[bzww_model_form]` shortcodes
 * **Optional two-step confirmation** with a read-only review screen (off by default)
 * **Optional IBAN field** for consumers who request a refund to a specific account(
   never mandatory; validated with the IBAN checksum)
 * **Compliance readiness panel** in settings — an at-a-glance checklist of what
   is configured for the directive
 * **Honeypot spam protection and per-IP rate limiting** on the public lookup and
   guest submission
 * **WCAG 2.1 AA** accessibility on the customer-facing forms

#### Built-in features (no premium upgrade required)

 * Item-level partial withdrawals with quantity
 * Guest withdrawal flow with email-based lookup
 * Automatic refunds via payment gateways
 * Weekend & public-holiday aware deadline
 * Audit trail with IP & user-agent
 * REST API
 * WP-CLI
 * CSV export
 * GDPR exporter/eraser
 * Gutenberg block + Elementor widget

#### Theme overrides

Every customer-facing template can be overridden by your theme. Drop a copy of any
file from `templates/` into `your-theme/beziworld-withdrawal-for-woocommerce/<same-
path>.php` and the plugin will use your version.

#### External services

This plugin performs **no** analytics, telemetry or remote downloads, and phones
nothing home. Everything runs inside your WordPress installation.

The single exception is entirely optional and off by default: if you enter a notification**
Webhook URL** in the settings (for Slack, Discord or your own endpoint), the plugin
sends a small JSON payload to that URL when a withdrawal is submitted and when it
changes status (received, refunded, rejected). The payload contains the event name
and the withdrawal and order identifiers (and the order number). No webhook is configured
by default and nothing is sent unless you set a URL; the destination is the address
you choose.

## Screenshots

[⌊Customer view of the Withdrawal tab inside My Account — eligible orders with the
14-day deadline.⌉⌊Customer view of the Withdrawal tab inside My Account — eligible
orders with the 14-day deadline.⌉[

Customer view of the Withdrawal tab inside My Account — eligible orders with the
14-day deadline.

[⌊Item-level partial withdrawal form — pick which items and how many units to return.⌉⌊
Item-level partial withdrawal form — pick which items and how many units to return
.⌉[

Item-level partial withdrawal form — pick which items and how many units to return.

[⌊Admin list of withdrawal statements with bulk actions and CSV export.⌉⌊Admin list
of withdrawal statements with bulk actions and CSV export.⌉[

Admin list of withdrawal statements with bulk actions and CSV export.

[⌊Settings page — customer-facing labels, refund policy and eligibility rules.⌉⌊
Settings page — customer-facing labels, refund policy and eligibility rules.⌉[

Settings page — customer-facing labels, refund policy and eligibility rules.

## Blocks

This plugin provides 1 block.

 *   Withdrawal Form Renders the EU 2023/2673 withdrawal-from-contract form. Same
   content as the [bzww_withdrawal_form] shortcode.

## Installation

 1. Activate WooCommerce 8.0 or newer if it is not already active.
 2. Upload the plugin via Plugins  Add New  Upload Plugin, or unzip into `/wp-content/
    plugins/`.
 3. Activate the plugin through the Plugins screen.
 4. A **Withdraw from contract** page is created automatically — link it from your 
    terms of sale.
 5. Go to **WooCommerce  Withdrawal Settings** to review the defaults (button labels,
    refund policy, eligibility rules, storefront notices).
 6. The plugin is now live. Logged-in customers see the **Withdrawal** tab inside My
    Account; guests can use the public page with the `[bzww_withdrawal_form]` shortcode.

## FAQ

### Is this plugin enough to make my shop compliant with EU 2023/2673?

The plugin covers the technical building blocks: a dedicated withdrawal function,
a clearly labelled button, immediate confirmation on a durable medium, item-level
selection, and a refund mechanism within 14 days. You still need to update your 
terms of sale, your privacy policy and the order summary copy. Whether — and exactly
how — the dedicated withdrawal-function obligation applies depends on your country’s
transposition of Directive (EU) 2023/2673: it is in force in Germany, France, Italy
and the Netherlands, while in Poland it had not been transposed at the time of writing(
so the function is voluntary there for now). **The plugin does not provide legal
advice and does not by itself guarantee compliance.** Consult a lawyer for the specifics
of your jurisdiction.

### Is a withdrawal button mandatory? (Ist der Widerrufsbutton Pflicht?)

It depends on your country’s transposition of Directive (EU) 2023/2673 (Article 
11a). A dedicated withdrawal function is mandatory in Germany (§356a BGB, with an
Abmahnung risk if missing), France, Italy and the Netherlands; in Poland the obligation
had not been transposed at the time of writing, so it is voluntary there for now
but still strengthens your consumer-law position. The plugin shows a jurisdiction-
aware status and never makes a single global “mandatory” claim.

### Does the 14-day withdrawal apply to a shop in Poland? (odstąpienie 14 dni)

Yes — the 14-day right of withdrawal for distance contracts applies to Polish consumers
under existing consumer law, independently of whether the newer dedicated-button
obligation has been transposed. The plugin calculates the 14-day deadline (rolling
weekends and Polish public holidays forward) and lets the consumer withdraw from
the conclusion of the contract; the deadline starts on delivery.

### Does it work with the block (Store API) checkout and block themes?

Yes. The statutory notices render on the block cart and block checkout, and the 
Article 16(m) digital-content consent is captured on the block checkout — not only
the classic shortcode checkout. The customer-facing UI adapts to block themes, dark
mode and high-contrast settings.

### How do guests (logged-out customers) submit a withdrawal?

The plugin auto-creates a public page on activation with the `[bzww_withdrawal_form]`
shortcode. Guests visit that page, enter their order number and the email used at
checkout. After verification, the plugin issues a single-use token and shows the
same withdrawal form a logged-in customer would see. The link is also embedded in
the order confirmation email for one-click access.

### Does it support multi-shipment orders?

Yes. The 14-day clock starts after the last parcel is delivered. Because WooCommerce
core does not track shipment-level delivery, the plugin uses the order completion
timestamp by default and exposes a `bzww/order/delivered_at` filter so a shipping/
tracking plugin can override it.

### How are digital products handled?

Per Article 16(m) CRD, sealed digital products and downloadable software are excluded
by default. Products flagged as Virtual + Downloadable in WooCommerce are skipped
automatically.

### Can a customer cancel a pending withdrawal?

Yes. While a statement is in the **pending** state the customer sees a “Cancel this
withdrawal” button on the success page in My Account.

### Does it work with HPOS / custom order tables?

Yes. The plugin declares full HPOS compatibility on activation.

### Where are records stored?

In a private custom post type, `bzww_withdrawal`. Each statement is one post with
meta fields holding order id, items, amount, IP and user-agent.

### How do I add public holidays for a country other than Poland?

Use the `bzww/eligibility/holidays` filter to return an array of `Y-m-d` strings.
The plugin will roll the 14-day deadline forward when it lands on one of those dates.

### Can I customise the withdrawal period?

Yes. WooCommerce  Withdrawal Settings  **Withdrawal period (days)** — set anywhere
between 14 and 60 days. The default is the 14 days mandated by EU law; the minimum
cannot go below the statutory 14.

### Can the admin adjust the refund amount before issuing?

Yes. Each withdrawal detail page has an editable **Refund amount** input pre-filled
with the calculated value. Override it to deduct a restocking fee or to account 
for the condition of returned goods.

### Where can I learn about the available hooks?

The plugin is built to be extended. The main filters and actions are listed below;
all pass the relevant order or withdrawal so you can tailor behaviour without touching
plugin files.

**Eligibility & deadlines (filters)**

 * `bzww/eligibility/excluded_statuses` — order statuses excluded from withdrawal.
 * `bzww/eligibility/deadline` — the computed withdrawal deadline (DateTime).
 * `bzww/eligibility/holidays` — extra non-working days for weekend/holiday roll-
   over.
 * `bzww/order/delivered_at` — override the delivery date the deadline is based 
   on.
 * `bzww/rules/order`, `bzww/rules/item` — allow or deny a specific order or line
   item.
 * `bzww/withdrawal/deny_duplicate` — whether to block a second statement for the
   same order.

**Refunds (filters)**

 * `bzww/refund/deadline_days` — statutory reimbursement deadline in days (default
   14).
 * `bzww/refund/args` — arguments passed to the WooCommerce refund.
 * `bzww/refund/cheapest_shipping` — override the cheapest-delivery amount (Art.
   13(2)).

**Lifecycle (actions)**

 * `bzww/withdrawal/submitted` ( $withdrawal_id, $request, $order )
 * `bzww/withdrawal/cancelled` ( $withdrawal_id )
 * `bzww/withdrawal/status_changed` ( $withdrawal_id, $previous, $current )
 * `bzww/withdrawal/transition_to_{status}` ( $withdrawal_id, $previous )
 * `bzww/refund/before`, `bzww/refund/after`, `bzww/refund/failed`
 * `bzww/plugin/booted` ( $plugin )

**Security, presentation & integration (filters)**

 * `bzww/submit/rate_limit`, `bzww/submit/rate_window`, `bzww/lookup/rate_limit`,`
   bzww/lookup/rate_window` — throttling.
 * `bzww/request/client_ip` — resolved client IP behind proxies.
 * `bzww/lookup/resolve_order` — custom guest order lookup.
 * `bzww/csv/columns`, `bzww/csv/row` — admin CSV export shape.
 * `bzww/webhook/payload` — outbound webhook body.
 * `bzww/templates/theme_directory`, `bzww/templates/located` — template overrides.
 * `bzww/placement/html`, `bzww/placement/tokens`, `bzww/access/label`, `bzww/access/
   url` — front-end placement.
 * `bzww/checkout/digital_consent_text`, `bzww/assets/should_enqueue`, `bzww/model_form/
   policy_html`, `bzww/model_form/model_form_html`.

A REST endpoint `GET /wp-json/bzww/v1/stats` (capability `manage_woocommerce`) and
the `wp bzww` CLI commands are also available for monitoring and automation.

## Reviews

![](https://secure.gravatar.com/avatar/186a8cb7d0a655f03e00f3d204705105caabdd7f93fd33573816a4069a49a962?
s=60&d=retro&r=g)

### 󠀁[Just created plugin and it’s already perfect](https://wordpress.org/support/topic/just-created-plugin-and-its-already-perfect/)󠁿

 [albiol](https://profiles.wordpress.org/albiol/) July 2, 2026

According to the latest European directives on the right of withdrawal, this is 
the essential plugin. It’s beautifully crafted, intuitive, and fully compliant with
the law.Congratulations to the author! (H)Bravo. Bravo. Bravo.

 [ Read all 1 review ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/)

## Contributors & Developers

“BeziWorld Withdrawal for WooCommerce” is open source software. The following people
have contributed to this plugin.

Contributors

 *   [ beziworld ](https://profiles.wordpress.org/beziworld/)

[Translate “BeziWorld Withdrawal for WooCommerce” into your language.](https://translate.wordpress.org/projects/wp-plugins/beziworld-withdrawal-for-woocommerce)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/beziworld-withdrawal-for-woocommerce/),
check out the [SVN repository](https://plugins.svn.wordpress.org/beziworld-withdrawal-for-woocommerce/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/beziworld-withdrawal-for-woocommerce/)
by [RSS](https://plugins.trac.wordpress.org/log/beziworld-withdrawal-for-woocommerce/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 2.86.0

 * New (compliance, Article 8(7)): when a consumer gives the Article 16(m) digital-
   content consent at checkout, the confirmation of that consent (the wording and
   the time it was recorded) is now included in the WooCommerce order emails — a
   durable-medium confirmation of the prior express consent, delivered to the consumer,
   not only kept in the order notes.

#### 2.85.0

 * Improved (internationalisation): the customer-facing styles now use CSS logical
   properties, so the withdrawal UI lays out correctly in right-to-left (RTL) languages.
   Left-to-right layouts are visually unchanged.

#### 2.84.0

 * Improved (consumer): the post-submission success page now has a “Print / Save
   this page” button and a print stylesheet, so the consumer can keep a clean paper
   or PDF copy of their submitted statement (in addition to the emailed acknowledgement).

#### 2.83.0

 * New (admin): a **Withdrawal SLA** report (WooCommerce menu) shows what percentage
   of refunds were issued within the statutory 14-day deadline (Article 13(3)), 
   with aging buckets (0–3 / 4–7 / 8–14 / over the deadline) — useful for monitoring
   and evidencing timely reimbursement.

#### 2.82.0

 * Improved (usability): on orders with several items, the withdrawal form now shows
   a “Select all / none” toggle and a live count of selected items, so choosing 
   what to withdraw from a large order is quicker. It is a convenience layer only—
   the server still determines what is withdrawn and the refund amount — and the
   form works exactly as before without JavaScript.

#### 2.81.0

 * Improved (integrations): the notification webhook now fires across the whole 
   withdrawal lifecycle — not only on submission but also when a statement is received,
   refunded or rejected — each with a distinct `event` value (`withdrawal.received`/`
   withdrawal.refunded` / `withdrawal.rejected`). The last dispatch attempt is recorded
   for basic visibility. Still opt-in and off by default.

#### 2.80.0

 * New (developers/headless): a versioned REST API v2 under `/wp-json/bzww/v2/` 
   adds `GET /withdrawals/{id}` (status lookup), `POST /withdrawals/{id}/cancel`(
   cancel a pending withdrawal) and `GET /schema` (resource introspection). Access
   uses the same owner-or-guest-token rule as the rest of the flow. The existing
   v1 endpoints are unchanged.

#### 2.79.0

 * Improved (compliance, Article 9(2)(b)): for orders delivered in several parcels,
   the 14-day withdrawal window now runs from the **last** parcel delivered. A tracking/
   fulfilment integration can supply the per-parcel delivery dates through the new`
   bzww/order/delivery_dates` filter; single-shipment orders are unaffected.

#### 2.78.0

 * New (admin): the withdrawals list now has a search box (by order number, consumer
   name or email) and a submitted-date range filter, making it much easier to find
   a specific statement in a busy store. The filters combine with the existing status
   tabs.

#### 2.77.0

 * New: a “Resend acknowledgement” button on each withdrawal’s admin screen re-sends
   the durable-medium acknowledgement to the consumer (for example, if the original
   email was lost or went to spam). Each resend is recorded on the record for the
   audit trail.

#### 2.76.0

 * New (admin): an **Import / export** tab lets you download all plugin settings
   as a JSON file and import them on another site — handy for moving a configuration
   from staging to production. Imported files are validated as a genuine export 
   of this plugin and run through the normal settings sanitiser before saving.

#### 2.75.0

 * New: a `wp bzww doctor` command runs a read-only health check of the plugin’s
   configuration — WooCommerce active, the withdrawal page published, Action Scheduler
   available, the Polish translation present, the webhook signed, the withdrawal
   period at least the statutory 14 days — and reports pass/warning/failure per 
   item, cutting support back-and-forth.

#### 2.74.0

 * New (developers): the withdrawal form’s custom-field types are now an extensible
   registry. A `bzww/form/field_types` filter lets a plugin or the Pro add-on register
   additional field types (they appear in the field-manager picker automatically),
   and a `bzww/form/render_custom_field` filter lets it render their markup — without
   forking the plugin. The built-in text/paragraph/checkbox/dropdown types are unchanged.

#### 2.73.0

 * Improved (compliance data): the Netherlands entry in the Jurisdiction panel now
   cites the specific transposition (Art. 6:230oa BW, the Dutch Implementation Act)
   instead of a generic reference, for a more precise, verifiable legal citation
   shown to merchants.

#### 2.72.0

 * New: after an update, a single dismissible admin notice on the plugin’s screens
   tells you the plugin was updated and links to what changed and to the settings.
   Shown once per version, gates nothing, and never nags.

#### 2.71.0

 * Improved (discoverability): refreshed the plugin listing — searchable tags, a
   keyword-led description leading with “withdrawal button” / “right of withdrawal”,
   present-tense framing now the directive is in force, and new FAQ entries answering
   the questions merchants actually search for (is the withdrawal button mandatory,
   does the 14-day right apply in Poland, does it work with the block checkout).
   No functional change.

#### 2.70.0

 * New: a single, dismissible admin notice invites you to leave a WordPress.org 
   review — shown only after you have processed a few refunds (real value), at most
   once, with no repeated nagging and nothing gated. The threshold is filterable
   and it never appears again once dismissed.

#### 2.69.0

 * Security (hardening): the acknowledgement certificate/PDF endpoint — an unauthenticated,
   code-authorised GET that serves personal data — is now rate-limited to blunt 
   automated scanning. Guest submissions also gain a second, order-scoped rate limit
   so an attacker hammering one order’s token from rotating IPs is stopped without
   risking a shared-IP lockout of legitimate consumers.

#### 2.68.0

 * Security (hardening): the CSV export’s formula-injection protection now also 
   catches triggers hidden behind leading whitespace or a newline, and covers the
   DDE pipe character — closing known spreadsheet bypasses of a first-character-
   only check. The webhook signing secret is now shown as a masked password field
   instead of clear text.

#### 2.67.0

 * Improved (Polish): consumer-facing wording is now gender-neutral (no masculine-
   only verb endings such as “użyłeś”, “zgubiłeś”, “zapoznałeś”) and the customer
   email greetings were unified to one consistent, professional salutation instead
   of a mix of casual forms.

#### 2.66.0

 * New: a one-click **Evidence pack (ZIP)** on each withdrawal’s admin screen, bundling
   the canonical declaration (JSON), the durable-medium acknowledgement (HTML), 
   the PDF certificate and the append-only audit chain with its integrity verdict—
   everything you would hand to a payment processor, ADR body or in a subject-access
   request, in a single download.

#### 2.65.0

 * Security (hardening): the acknowledgement certificate response now sends stricter
   headers — X-Frame-Options, Referrer-Policy: no-referrer, X-Content-Type-Options
   and a minimal Content-Security-Policy — so the personal-data document cannot 
   be framed and its code-bearing URL is not leaked via the referrer.
 * Internal (quality): the withdrawal form-handler’s authorization decision is now
   a small, pure, independently tested function, adding explicit coverage for the
   owner/guest-token IDOR guard.

#### 2.64.0

 * New (compliance): withdrawal is no longer offered on WooCommerce Subscriptions**
   renewal** orders. A renewal is a continuation of the original contract, so the
   right of withdrawal attaches to the initial subscription order, not to each renewal
   payment. Consumers who reach a renewal order see a clear explanation pointing
   them to cancel the subscription instead. A setting (off by default) can re-enable
   withdrawal on renewals if you need it.

#### 2.63.0

 * Improved (admin UX): the withdrawal form field manager now uses keyboard-accessible
   move up / move down controls to set field order, instead of typing raw numbers
   into an “Order” column. It also prevents a field from being marked “Required”
   while it is not “Shown”, matching the underlying rule. With JavaScript disabled
   the numeric order inputs remain as a fallback.

#### 2.62.0

 * New (admin): each unmet item on the compliance-readiness panel now has a “Fix
   this ” link that takes you straight to the relevant settings tab (or the WooCommerce
   email settings), so you can resolve it in one click.
 * New (safety): bulk actions on the withdrawals list now ask for confirmation, 
   showing how many records are selected, before issuing refunds, rejecting or permanently
   deleting — preventing accidental mass actions.

#### 2.61.0

 * Improved (accessibility & theming): the withdrawal UI now adapts to the visitor’s
   colour-scheme and contrast preferences — a dark-mode palette (`prefers-color-
   scheme`), a higher-contrast variant (`prefers-contrast`) and Windows High Contrast/
   forced-colours support. The site-wide “Withdraw from contract” access button 
   is now styled on every page (its stylesheet loads site-wide when the footer link
   or sticky bar is enabled), so it no longer degrades to a plain link off the withdrawal
   pages.

#### 2.60.0

 * Improved (accessibility, WCAG 2.2): the consumer status timeline no longer relies
   on colour alone to show each step’s state. Every step now carries a distinct 
   symbol (✓ completed, ● in progress, ○ upcoming, ✗ not accepted) and a screen-
   reader label, so the progress is understandable to colour-blind and assistive-
   technology users.

#### 2.59.0

 * Fixed (compliance, Article 9): consumers can now submit a withdrawal **before
   the goods are delivered**. The right of withdrawal exists from the conclusion
   of the contract, so an order that is paid but not yet delivered is no longer 
   blocked with “not delivered yet” — it is accepted with an open window, and the
   14-day deadline simply starts on delivery. A new “Require delivery before withdrawal”
   setting (off by default) lets shops keep the old behaviour if they specifically
   want it. Thanks to the merchant who reported this.

#### 2.58.0

 * Improved: when a withdrawal is not available for an order, the consumer now sees
   a clearer, neutral explanation of why — with the relevant article reference and
   a note that the message is informational and does not remove any right — plus
   a “Check another order” link. The wording never suggests the statutory right 
   itself is invalid.

#### 2.57.0

 * Improved (Article 16(m)): on the block checkout, the digital-content consent 
   checkbox now appears only when the cart actually contains a virtual, downloadable
   product, instead of showing on every checkout. When the cart contents cannot 
   be determined the checkbox still appears (fail-open), and the consent record 
   and enforcement remain governed server-side. A new `bzww/checkout/cart_has_digital`
   filter lets integrations override the determination.

#### 2.56.0

 * New: the pre-contractual withdrawal notice now also renders on the **block cart**(
   not only the block checkout), so shops using block themes show the notice consistently
   across the cart and checkout. On classic themes nothing changes.

#### 2.55.0

 * New (compliance, Article 6(1)(i)): a **return address and return instructions**
   you can configure (WooCommerce  Withdrawal Settings  Returns). They appear on
   the post-submission success page and are available in the editable emails through
   the `{return_address}` and `{return_instructions}` placeholders, so the consumer
   is told where to send goods being returned. The address falls back to your WooCommerce
   store address when left blank.

#### 2.54.0

 * New: each editable email now has a “Preview with sample data” and a “Send a test
   to me” button, so you can see exactly how a message will look before customers
   receive it.
 * New (safety): when you save an email whose body is missing a required placeholder(
   such as {amount} in the refund email) or contains a mistyped one, the settings
   screen now warns you, so legal or functional content is not silently dropped.

#### 2.53.0

 * New (evidence): every withdrawal now keeps an append-only, tamper-evident audit
   chain. Each lifecycle event (submission and each status change) is linked by 
   hash to the one before it, so altering or removing any past entry breaks the 
   chain and is detected. The admin record shows an “INTACT / BROKEN at entry N”
   badge, and the new `wp bzww verify-chain <id>` command reports the chain status
   from the command line.

#### 2.52.0

 * New: the acknowledgement certificate can now be downloaded as a real PDF file(
   not only printed from the browser), generated with no bundled library. A permanent,
   code-authorised download link is available on the certificate page.
 * Improved (clarity): the raw SHA-256 code on the certificate is now tucked inside
   an expandable “Unique fingerprint of your statement” section with a plain-language
   explanation, instead of being shown as a bare technical string.

#### 2.51.0

 * New (durable medium, Article 11a(4)): the confirmation email now includes a self-
   contained HTML acknowledgement file the consumer can save and reopen offline,
   independent of any live link. It contains the declaration details, the exact 
   submission date, time and time zone, the SHA-256 verification code, and the clear“
   receipt only, not a refund confirmation” separation. All styling is inline with
   no remote fonts, scripts or images, so it renders anywhere and meets the plugin-
   directory content-security expectations. The attachment can be turned off with
   the `bzww/email/attach_acknowledgement` filter.

#### 2.50.0

 * Improved (correctness): when the configured start date for the withdrawal clock
   is missing on an order (for example, an order that was delivered but never marked“
   completed”), the eligibility check now falls back through the other available
   dates (completed  paid  created) instead of refusing the withdrawal outright.
   The fallback favours the date closest to actual delivery and can only lengthen
   or leave the window unchanged, never shorten it. Shops that prefer the stricter
   behaviour can disable the chain with the new `bzww/eligibility/deadline_basis_fallback`
   filter.

#### 2.49.0

 * New (compliance, Article 10): an optional “Extend the window when uninformed”
   setting. Where the consumer was not given the required pre-contractual information
   about the right of withdrawal, Article 10 of the Consumer Rights Directive extends
   the withdrawal period by 12 months. When enabled, the deadline calculation applies
   that extension — it only ever lengthens the window, never shortens it — closing
   a case where an otherwise-eligible consumer could have been wrongly refused. 
   Per-order control is available through the new `bzww/eligibility/info_provided`
   filter.

#### 2.48.0

 * Improved (Polish): unified the wording for “plugin” to the Polish “wtyczka” across
   every message that previously used the borrowed word inconsistently (activation,
   requirements, uninstall and settings text), for a more professional and consistent
   Polish interface.
 * Internal (quality): added a Polish terminology glossary and an automated consistency
   validator, plus a per-locale translation-completeness gate (Polish must stay 
   100%; the French/Italian starter bundles are reported as informational), so terminology
   drift is caught before release.

#### 2.47.1

 * Fixed: a packaging error in 2.47.0 left a syntax error in the My Account withdrawal
   list template. This patch restores the page. Please update from 2.47.0.

#### 2.47.0

 * Improved (consumer clarity): the withdrawal status a customer sees in the My 
   Account list now uses the same wording as the progress timeline — “In review”,“
   Refund in progress”, “Refund issued”, “Not accepted” — instead of a second, different
   set of labels. A single shared vocabulary means the list and the timeline never
   disagree, and the “received” state is no longer worded in a way that could be
   mistaken for mere receipt of the declaration.
 * Fixed (Polish): the Article 16(m) digital-content consent recorded on block-checkout
   orders now reads “przyjął do wiadomości” (acknowledged), matching the classic-
   checkout wording and the checkbox the customer actually ticks, instead of the
   divergent “potwierdził”.

#### 2.46.0

 * Fixed (Polish interface): the form field-manager column that sets the display
   order of fields showed “Zamówienie” (purchase order) instead of “Kolejność” (
   order/sequence) — the two meanings shared one English word and collapsed onto
   one translation. The header now reads “Kolejność” while every purchase-order 
   label keeps saying “Zamówienie”.
 * Fixed (Polish interface): the two adjacent settings tabs “Refunds” and “Returns”
   both rendered as “Zwroty”. They are now distinct — “Zwroty środków” (money refunds)
   and “Zwroty towaru” (goods returns) — so it is clear which tab does what.

#### 2.45.0

 * Improved (translation quality, foundation): the Polish translation toolchain 
   now resolves each string by its gettext context first (falling back to the bare
   text), so a single English word used in two different places — such as “Order”
   meaning a purchase order versus the display order of form fields — can finally
   be translated independently instead of collapsing onto one Polish word. This 
   is the groundwork for the interface-wording corrections in the next releases.
 * New (quality gate): an automated msgid-collision detector runs in the test suite
   and continuous integration, flagging any English string reused in disjoint interface
   roles without a context, so this class of mistranslation cannot silently reappear.

#### 2.44.0

 * New: an **accessibility-statement generator** for the European Accessibility 
   Act (EAA, in force 28 June 2025). One click creates a ready-made statement page
   from your shop details (conformance status, feedback contact, enforcement reference),
   or use the `[bzww_accessibility_statement]` shortcode. The compliance-readiness
   panel now includes an accessibility-statement row.

#### 2.43.0

 * New (opt-in, transparency): on a product classified under an Article 16 withdrawal
   exemption (set in the product or category settings), the shop can show a short,
   neutral note explaining that the item may be excluded from the right of withdrawal—
   and why — reusing the existing exemption taxonomy. Off by default; enable it 
   under Storefront notices.

#### 2.42.0

 * New (opt-in): a **return-handling layer** with a stable extension point. The 
   free plugin still records returns manually and contacts no carrier; enabling 
   it (WooCommerce  Withdrawal Settings  Returns) exposes a documented `bzww/returns/
   registered` action and `bzww/returns/carrier_options` filter that a separate 
   Pro add-on can hook for carrier integrations and return labels.
 * New: a warning when a generic returns/RMA plugin is active, reminding you that
   the statutory withdrawal function must keep its own dedicated, prominently-labelled
   button (Art. 11a) and must not be replaced by or hidden behind a generic returns
   page. Dismissible.

#### 2.41.0

 * Improved (evidence): the tamper-evident acknowledgement receipt now uses a versioned
   hash (v2) that additionally binds the **product names** and the **predefined-
   reason code** into the SHA-256, with an explicit version marker. New acknowledgements
   use v2; acknowledgements issued by earlier versions keep verifying against the
   original (v1) hash byte-for-byte, so nothing already issued is invalidated. `
   wp bzww verify` and the admin integrity badge automatically check against the
   recorded version.

#### 2.40.0

 * New: an **approve/reject decision workflow** for withdrawal statements. Pending(
   and received) statements now have an **Approve** action alongside Reject, recorded
   with an audit trail (who decided and when). A new **“When to issue the refund”**
   setting lets you choose to refund manually (default), automatically when you 
   approve, or automatically as soon as the statement is submitted. A statutory 
   withdrawal remains effective from the moment it is submitted — this only controls
   operational handling and the refund timing, never the validity of the right.

#### Earlier versions

The changelog for versions 2.39.0 and earlier (back to 1.0.0) is available in the
readme.txt of each tagged release under https://plugins.svn.wordpress.org/beziworld-
withdrawal-for-woocommerce/tags/ .

## Meta

 *  Version **2.86.0**
 *  Last updated **3 weeks ago**
 *  Active installations **10+**
 *  WordPress version ** 6.4 or higher **
 *  Tested up to **7.0.2**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [consumer rights](https://wordpress.org/plugins/tags/consumer-rights/)[EU compliance](https://wordpress.org/plugins/tags/eu-compliance/)
   [right of withdrawal](https://wordpress.org/plugins/tags/right-of-withdrawal/)
   [withdrawal](https://wordpress.org/plugins/tags/withdrawal/)[woocommerce](https://wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://wordpress.org/plugins/beziworld-withdrawal-for-woocommerce/advanced/)

## Ratings

 5 out of 5 stars.

 *  [  1 5-star review     ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/?filter=5)
 *  [  0 4-star reviews     ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/?filter=4)
 *  [  0 3-star reviews     ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/?filter=3)
 *  [  0 2-star reviews     ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/?filter=2)
 *  [  0 1-star reviews     ](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/?filter=1)

[Your review](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/reviews/)

## Contributors

 *   [ beziworld ](https://profiles.wordpress.org/beziworld/)

## Support

Issues resolved in last two months:

     1 out of 1

 [View support forum](https://wordpress.org/support/plugin/beziworld-withdrawal-for-woocommerce/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://beziworld.eu/)