BeziWorld Withdrawal for WooCommerce

Changelog

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.

2.39.0

  • New: a single Admin email recipients setting (WooCommerce → Withdrawal Settings → Integrations) controls who receives the merchant-facing emails — the new-submission notification and the refund-deadline alert digest. Enter several comma-separated addresses (e.g. the shop owner plus a support inbox); leave blank to use the store admin address. The per-email recipient field in WooCommerce → Settings → Emails still takes precedence when set.
  • Fix: the predefined reason dropdown again appears on the withdrawal form whenever reasons are configured. A regression in 2.19.0 could keep it hidden if the settings had been saved before any reasons were added; its visibility is now governed by the reasons list itself.

2.38.0

  • New (opt-in, GDPR): data-retention enforcement. A daily job anonymises closed statements once they pass a configurable retention horizon (default 6 years; per-country hints) and clears the IP/user-agent from any record past a technical-log horizon (default 90 days). Conservative by design — records are anonymised, never hard-deleted, and a statement with a refund still in progress is never touched. Preview or run on demand with wp bzww retention –preview.

2.37.0

  • Security: outbound notification webhooks can now be HMAC-signed. Set a signing secret and each request carries X-BZWW-Timestamp and X-BZWW-Signature: sha256=… (over the timestamp and body), so your endpoint can verify authenticity and reject replays. Webhook delivery now also uses wp_safe_remote_post for extra SSRF protection. Optional and off unless a secret is set.

2.36.0

  • Compatibility: the plugin now also declares Cart & Checkout Blocks compatibility (in addition to HPOS / custom order tables), reflecting the block-checkout integrations. All order data is accessed through the WooCommerce CRUD API, so it is safe with HPOS and sync-on-read disabled.
  • Internal: added a CI matrix (PHP 7.4–8.4) that lints every file, runs the regression suite and the translation check, plus a PHP 7.4 compatibility scan, so the supported floor is enforced automatically.

2.35.0

  • New: French (fr_FR) and Italian (it_IT) starter translations for the core consumer-facing strings (form, buttons, status timeline, confirmation), plus a generic locale builder for future languages. The statutory Annex texts are deliberately left in English until a native legal review is available, since a wrong legal translation is worse than an English one; the in-force withdrawal/confirmation button wording is already applied verbatim per locale.

2.34.0

  • Internal (i18n): the plugin now pins its own bundled translation for a locale above the community (translate.wordpress.org) file when one is shipped. This protects the legally-reviewed wording (statutory labels, Annex texts) from drifting if a community translation changes them. The bundled Polish translation is author-maintained; a full German bundle will follow once its statutory texts have had native legal review. The in-force statutory button labels are already applied verbatim per locale regardless of the translation files.

2.33.0

  • New: an acknowledgement integrity verifier. The stored SHA-256 acknowledgement can now be re-checked against the statement content with wp bzww verify <id> (reports MATCH / ALTERED / UNKNOWN), and the admin detail screen shows an integrity badge. This proves the durable-medium acknowledgement has not been tampered with. (A record anonymised by a GDPR erasure intentionally shows as ALTERED.)

2.32.0

  • New (compliance): a refund-correctness guardrail. The default remains a full refund to the original payment method; if an administrator enters a refund amount below the calculated value, a reason is now required (Art. 14(2) — the consumer is liable only for diminished value) and the reduction is recorded in the order notes. The wording also makes clear that statutory withdrawal does not permit restocking fees.

2.31.0

  • New: an Article 16 exemption taxonomy. Classify a product — or a whole product category — as standard, service fully performed (16a), custom-made (16c), perishable (16d), sealed health/hygiene (16e), sealed audio/video/software (16i) or digital content (16m), instead of relying only on the blunt “virtual + downloadable” rule. Non-destructive: a virtual + downloadable product still resolves to 16(m) until you classify it, so existing behaviour is unchanged; you can also mark such a product “standard” to allow withdrawal. Each exemption carries a clear consumer-facing reason.

2.30.0

  • New (compliance): the checkout withdrawal notice now also renders on the WooCommerce block (Store API) checkout, via the checkout slot-fill — previously it appeared only on the classic checkout, so on a default modern store the pre-contractual reminder was missing. The same configured notice text is reused. The script is dependency-guarded (loads only where the block checkout is present, no build step, no remote assets), so the classic checkout is unaffected and the notice never renders twice.

2.29.0

  • New: a customer-facing status timeline (Submitted → In review → Refund issued) on the on-screen confirmation, for both logged-in and guest submitters, built from the record’s own timestamps. While a statement is open it shows the date the refund is due by. The acknowledgement-of-receipt step is kept visually distinct from the refund step.

2.28.0

  • New (opt-in): proactive refund-deadline email alerts. A daily Action Scheduler job emails the store admin a digest when open withdrawals are approaching (within three days of) or past the 14-day statutory reimbursement deadline, so a refund is never missed. Off by default; the digest goes only to your own admin address (no third party), and is sent at most once a day.

2.27.0

  • New: a Germany §356a strict mode (enabled automatically by the Germany country preset, or manually). It reduces the withdrawal form to the statutory minimum (item selection, name, contact email — every optional and custom field is suppressed), locks the German button wording, and forces the two-step confirmation, in line with §356a BGB. A reminder is shown to keep the withdrawal button separate from any §312k cancellation button.

2.26.0

  • New: a Jurisdiction tab with one-click country presets (DE, FR, IT, NL, PL, ES, DK, SE). Each preset applies sensible structural defaults for that market and is fully reversible. A status panel states, with a dated legal citation, whether the dedicated withdrawal function is actually in force there — including that Poland had not transposed it (so it is voluntary for now), so you are never told something is mandatory where it is not.

2.25.0

  • New: the withdrawal/confirmation button wording is now resolved from the order’s contract language when known (via order language meta or a bzww/statutory_labels/order_lang filter for WPML/Polylang), falling back to the site language — never from the visitor’s IP.
  • New: an optional “Lock to statutory wording” setting forces the exact statutory labels and ignores custom wording. German and Italian are always locked, because their transpositions mandate the exact wording (e.g. §356a BGB).
  • New: a non-blocking wording check warns on save if a custom button label drops the core withdrawal verb for the language or uses wording that suggests a generic return/cancellation rather than a statutory withdrawal.
  • New: a read-only reference table on the settings screen shows the verbatim statutory wording for every supported language.

2.24.0

  • Improved (compliance): the site-wide withdrawal access entry point in the footer is now rendered as a prominent, high-contrast button rather than a muted link, so it is clearly distinguishable from the surrounding footer and legal links (the “prominent and easily accessible” requirement, and the German footer-contrast reading). The button colour meets WCAG AA contrast.

2.23.0

  • Accessibility (EAA / WCAG 2.1 & 2.2 AA): the withdrawal form now sets autocomplete on the name and email fields, fixes the per-item quantity control so its accessible name matches its visible label and includes the product name (2.5.3 Label in Name), adds a visible “required fields” note plus screen-reader “(required)” text, enforces a 24×24px minimum target size (2.5.8), keeps focused controls clear of the sticky access bar via scroll padding (2.4.11), and strengthens text and focus-indicator contrast. The form remains fully usable without JavaScript.

2.22.0

  • New (compliance): the optional Article 16(m) digital-content consent is now also captured on the WooCommerce block (Store API) checkout — the default checkout since WooCommerce 8.3 — using the Additional Checkout Fields API (WooCommerce 8.9+). Previously the consent was captured only on the classic checkout, so on a default modern store it was never recorded. The same order meta and order note are written on both checkouts, and when you require the acknowledgement it is enforced for digital orders on the block checkout too. If the API is unavailable the checkout is left untouched.

2.21.0

  • Improved (compliance): the acknowledgement of receipt is now shown as a clearly separated, highlighted block in the confirmation email and on the on-screen success pages, with explicit wording that it confirms receipt of the declaration only and is not a confirmation that a refund has been made. This keeps the durable-medium acknowledgement (Article 11a(4)) visually and textually distinct from any refund — important because refunds may be issued automatically. The submission date and time (with timezone) and the SHA-256 verification code remain part of the acknowledgement.

2.20.0

  • New: a verbatim statutory-label dictionary. The withdrawal and confirmation button labels now default to the exact wording mandated by Article 11a of Directive (EU) 2023/2673 for the site language — for example “Vertrag widerrufen” / “Widerruf bestätigen” (DE, §356a BGB), “Renoncer au contrat ici” / “Confirmer la rétractation” (FR), “Recedere dal contratto qui” / “Conferma di recesso” (IT, infinitive form), “Odstąp od umowy tutaj” (PL), as well as ES and NL. Your own custom button labels are always respected; the dictionary only fills in an empty label. Each entry is documented with its legal source and a filter (bzww/statutory_labels/dictionary) allows adjustment.

2.19.0

  • New: a withdrawal form field manager. Under WooCommerce → Withdrawal Settings → Form, you can now choose which optional fields the customer fills in (reason, additional details, phone, IBAN), set their order, mark an optional field required, and add your own custom fields (single line, paragraph, checkbox or dropdown). The item selection, full name and email stay required as mandated by Directive (EU) 2023/2673, and the screen warns against adding friction beyond the statutory minimum. Custom answers appear in the admin detail view, the CSV export and the personal-data export.
  • New: optional phone number field on the withdrawal form, pre-filled from the order’s billing phone when available.
  • Improved: the settings screen has been redesigned into a clean, responsive, tabbed layout with a sticky save bar. With JavaScript disabled every section still renders stacked, so the screen remains fully usable.
  • Note: the previous standalone “Offer an IBAN field” toggle is now part of the form field manager (your current setting is preserved).

2.18.0

  • Clarity: the description and FAQ now state plainly that the plugin is a technical tool, does not provide legal advice, does not by itself guarantee compliance, and that the obligation depends on each country’s transposition of the directive (in force in DE/FR/IT/NL; not transposed in Poland at the time of writing). Added an explicit “not affiliated with WooCommerce/Automattic” note.
  • Privacy: the plugin now contributes suggested text to the WordPress Privacy Policy Guide (Settings → Privacy), describing the personal data stored for each withdrawal and the data sent by the optional notification webhook when one is configured.
  • Compatibility: added the WooCommerce version headers (WC requires at least, WC tested up to) so the WooCommerce compatibility checks read the supported range directly.
  • Internal: the release build can now run the official Plugin Check against the staged package before zipping.

2.17.0

  • New: a merchant notification email is sent when a customer submits a withdrawal. Enable it and set the recipient(s) under WooCommerce → Settings → Emails → Withdrawal — new submission (merchant); it is on by default and goes to the store admin address.
  • New: the body of every withdrawal email (the four customer emails plus the new merchant email) can be edited in a visual editor under WooCommerce → Withdrawal Settings → Email content. Each editor is pre-filled with the legally compliant default; placeholders such as {withdrawal_id} are supported. The statutory acknowledgement of receipt is always appended to the confirmation email and cannot be removed.
  • New: the wording of the withdrawal form the customer fills in (heading, optional intro, field labels and hints) is now editable under WooCommerce → Withdrawal Settings → Withdrawal form texts, with legally compliant defaults. The item selection, full name and email remain required.

2.16.0

  • New: optional expiry for the guest withdrawal link. Set WooCommerce → Withdrawal Settings → Guest link validity (days) to a positive number to have the emailed link stop working after that many days (an expired link sends the consumer back to the lookup form). Default is 0 = no expiry, so existing behaviour is unchanged.
  • Internal: the guest-token issuing and verification logic is now centralised in one place across the form, REST API and My Account flows.

2.15.5

  • Improved: the compliance-readiness panel on the Withdrawal Settings screen now spans the full content width with a cleaner, WordPress-native two-column layout (styling moved into the admin stylesheet).

2.15.4

  • Fix: shop managers can now save the plugin settings. The settings save was previously gated by the administrator-only capability even though the screen is available to shop managers, so their changes were silently rejected.

2.15.3

  • Privacy: the personal-data eraser no longer deletes withdrawal statements whose withdrawal or refund is still in progress (pending/received); these are retained until finalised so a pending reimbursement is never stranded, with only non-essential request metadata removed. Anonymising a retained (refunded) statement now also clears the free-text reason. The personal-data export now includes the received/refunded timestamps and the confirmation channel.

2.15.2

  • Fix: when an explicit delivery date is recorded for an order, it is now normalised to the shop timezone before the withdrawal deadline is computed, so the final day boundary is correct regardless of the timezone the date was stored in.

2.15.1

  • Security: the post-submission confirmation page now shows the acknowledgement verification code and certificate link only to the order owner or to a request that carries the matching receipt code, so the code can no longer be revealed by guessing a withdrawal reference number. Affects only the acknowledgement-certificate feature; refund and submission flows are unchanged.

2.15.0

  • Documentation: the readme now lists the main developer filters and actions inline (eligibility, refunds, lifecycle, security, presentation and integration), instead of linking out for the hook reference.

2.14.0

  • The wp bzww stats command and the /wp-json/bzww/v1/stats REST endpoint now report the number of open statements past the reimbursement deadline (overdue_refunds), so external monitoring and alerting can track compliance risk.
  • Fix: the “All” counter on the Withdrawals list now matches every row the list can display.
  • Internal: the bundled translation compiler now byte-sorts the compiled .mo string table for full gettext conformance.

2.13.0

  • The dashboard widget now highlights, at the top, when open statements have passed the statutory reimbursement deadline — so the compliance risk is visible on login, not only on the Withdrawals screen.

2.12.0

  • Fix: Polish translations now use the correct grammatical plural forms for counts (e.g. processed-statement notices and the admin status counters), instead of falling back to English. The translation build tooling now compiles plural forms into the .mo file.

2.11.0

  • New: the Withdrawals admin screen now shows a warning when open statements have passed the 14-day statutory reimbursement deadline (EU Directive Art. 13(3)), so refunds are not missed. The deadline is filterable via bzww/refund/deadline_days.

2.10.0

  • The Withdrawals admin list now shows a count next to each status filter (All, Pending, Received, Refunded, Rejected, Trash), so you can see your queue at a glance without opening each view.

2.9.0

  • New read-only REST endpoint GET /wp-json/bzww/v1/stats (requires the manage_woocommerce capability) returning withdrawal counts by status, the total, the refunded amount and the shop currency — for headless dashboards and monitoring.

2.8.0

  • The selected predefined withdrawal reason is now stored separately, and the dashboard widget shows the most common reasons over the last 30 days — helping you spot and reduce avoidable returns.
  • Security: the CSV export now neutralises spreadsheet formula injection in consumer-supplied fields (name, email, reason).
  • Fix: automatic order-status transition on submission now works for all statuses (a prefix-handling bug previously skipped statuses such as “completed” and “cancelled”).
  • Hardening: outbound webhook requests no longer follow redirects and reject unsafe (internal) URLs; the Polish holiday preset is now generated algorithmically so it never expires; when a consumer requests a refund to a specific IBAN, automatic reversal to the card is disabled so it can be settled to that account.

2.7.0

  • New WP-CLI command wp bzww stats — prints withdrawal counts by status and the total refunded, for scripting and monitoring.

2.6.0

  • The dashboard widget now shows the withdrawal rate — the share of recent orders that resulted in a withdrawal — computed efficiently and cached.

2.5.0

  • The dashboard widget now also shows the average refund amount and the average time from submission to refund over the last 30 days, alongside the existing status counts and total refunded.

2.4.0

  • New: a “Record delivery date” order action. From the order screen you can stamp the delivery date that starts the 14-day withdrawal clock — useful for marking the last parcel of a multi-shipment order without a separate tracking plugin. The recorded date takes priority over the configured deadline basis.

2.3.0

  • New: configurable basis for the withdrawal deadline — start the 14-day clock from the order completed date (default), the order date, or the payment date — plus an optional “grace days” buffer. A delivery date recorded on the order (meta _bzww_delivered_at, e.g. by a tracking/shipping plugin) still takes priority, so multi-shipment deadlines remain accurate.

2.2.0

  • New (opt-in): outbound webhook notifications. Set a Slack, Discord or generic webhook URL and the plugin posts a small JSON payload when a withdrawal is submitted. Off by default; nothing is sent unless a URL is configured (see Notifications in the settings, and the External services section).

2.1.0

  • New (opt-in): capture the consumer’s Article 16(m) consent at checkout for carts containing immediately-supplied digital content (virtual + downloadable). The acknowledgement is stored on the order with its text and timestamp and recorded as an order note; it can be shown for the record only or required to complete checkout. Applied to the classic checkout; block (Store API) checkout support is planned.

2.0.0

  • Milestone release consolidating the compliance toolkit built across the 1.x series: verifiable SHA-256 acknowledgement receipt, printable certificate, always-visible footer/sticky access, Annex I.A/I.B page generator, optional two-step confirmation, optional IBAN field, honeypot + rate limiting, WCAG 2.1 AA forms, and a compliance readiness panel.
  • New: a contextual Help tab on the settings screen with a quick-start guide and compliance pointers.
  • Documentation: the plugin description now reflects the full feature set.
  • No breaking changes — this is a safe upgrade from any 1.x version; settings and existing withdrawal records are preserved.

1.5.0

  • New: a compliance readiness panel on the settings screen — an at-a-glance checklist (public page published, guest form available, prominent access, withdrawal period, pre-purchase notice, Annex I.A/I.B pages) so you can see what is set up for the directive and what still needs attention.
  • UI: frontend form controls now inherit the active theme’s typography, with clearer keyboard-focus styles and reduced-motion support, for a cleaner look on default block themes (Twenty Twenty-*) and Storefront.

1.4.0

  • New: a printable acknowledgement certificate — a clean, self-contained document of the withdrawal declaration (content, submission time and SHA-256 verification code) that the consumer can save as a PDF with the browser print function. Linked from the confirmation email, the on-screen confirmation, and the admin detail screen. No third-party PDF library is bundled.

1.3.0

  • New: one-click generator for the statutory Annex I texts — a withdrawal-information page (Annex I.A) and a model withdrawal form (Annex I.B), populated from your store details. Available as the shortcodes [bzww_withdrawal_policy] and [bzww_model_form] and as ready-made pages from the settings screen.
  • New: optional two-step confirmation — a read-only review screen with a separate confirmation control before a withdrawal is recorded (off by default; works without JavaScript).
  • Frontend styling refined for readability on default block themes (Twenty Twenty-*) and Storefront, inheriting the theme’s typography.

1.2.0

  • Always-visible access: an optional site-wide footer link (on by default) and an optional dismissible sticky bar make the withdrawal function reachable from every page, in line with the Directive’s “prominent and easily accessible” requirement — no longer only inside the My Account tab.
  • Added an optional IBAN field to the withdrawal form (off by default) for consumers who ask to be refunded to a specific bank account. It is never mandatory; entries are validated with the IBAN checksum, surfaced in the confirmation email and admin detail, and included in the privacy exporter/eraser.
  • Accessibility: error messages now use a focus-managed alert region, required fields are explicitly marked, and the sticky bar has a keyboard-accessible dismiss control (WCAG 2.1 AA).
  • New settings section “Withdrawal access (visibility)” plus an “Offer an IBAN field” toggle.

1.1.0

  • Acknowledgement of receipt now carries a verifiable SHA-256 code derived from the declaration content, so the confirmation can be checked for tampering — strengthening the durable-medium record required by Directive (EU) 2023/2673.
  • Confirmation wording now states clearly that it acknowledges receipt only and does not by itself decide whether the withdrawal is effective or accepted, keeping the receipt distinct from any automatic refund.
  • The verification code is also shown on the on-screen confirmation in My Account and on the public guest page.
  • Added honeypot spam protection and per-IP rate limiting to the public lookup and guest submission endpoints, hardening them against bots and order-number enumeration.
  • Internal: centralised client IP / user-agent retrieval used by the audit trail and the new rate limiter.

1.0.2

  • Pre-escape attribute and label arguments passed to wp_dropdown_pages() on the settings page so the PHPCS escape-output rule no longer flags the call.

1.0.1

  • Move inline checkbox-toggle script on the admin list screen to an enqueued asset (assets/js/admin-list.js).
  • Escape the return value of the the_title filter and the WooCommerce endpoint-title filter.
  • Register the Gutenberg block through a PHP render callback that returns a string, replacing the file-based render that echoed shortcode output.
  • Document and lint-mark the trust boundary on the Elementor widget’s shortcode echo.

1.0.0

  • Initial release.
  • Full EU 2023/2673 compliance: dedicated withdrawal function, immediate confirmation, 14-day refund.
  • Item-level partial withdrawals with per-line quantity.
  • Public lookup page (order number + email) — guests submit without an account.
  • Automatic refund through the original payment gateway when supported.
  • Admin can override the calculated refund amount per statement.
  • Configurable withdrawal period (7-60 days).
  • Deadline calculator with weekend & Polish public-holiday rollover.
  • Rule engine for excluding products, categories, roles and gateways.
  • Storefront notices on product / cart / checkout / thank-you with WYSIWYG text.
  • Four customer status emails (confirmation, received, refunded, rejected) — theme-overridable.
  • Customer self-service cancellation.
  • Trash / restore / delete workflow for withdrawal records.
  • Audit trail with IP, user-agent, timestamps.
  • WordPress privacy tools integration (exporter + eraser).
  • WP-CLI commands.
  • REST API.
  • CSV export.
  • Gutenberg block + Elementor widget.
  • WooCommerce HPOS compatible.
  • Polish translation included (253 strings).

Plugin Website
Visit website

Author
beziworld
Version:
2.44.0
Last Updated
June 25, 2026
Requires
WordPress 6.4
Tested Up To
WordPress 7.0
Requires PHP
7.4

Share Post

Join our newsletter.

Get insights into what’s happening at ChangelogWP right in your inbox. We don’t believe in spam.