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

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

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

Contributors & Developers

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

Contributors

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/ .