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.