Skip to main content

Order Withdrawal (EU Compliance)

EU law gives consumers the right to withdraw from distance contracts within a statutory period — 14 days by default. Under EU Directive 2023/2673, which entered into force on 19 June 2026, online stores must provide consumers with a simple, direct mechanism to exercise that right. This plugin adds a Withdraw from Contract button to the customer's order page in J2Commerce, records each request in a dedicated dashboard, and sends legally-required confirmation emails automatically.

If your store sells to customers in the EU or EEA, this plugin is not optional — it is a legal requirement.

Prerequisites

  • J2Commerce installed and activated on Joomla 6
  • Your Joomla site email (outgoing mail) configured and working
  • Administrator access to the J2Commerce back end

Installation

This plugin is a separate add-on available from the J2Commerce Extensions Store. It is not included with the core J2Commerce component.

  1. Purchase and download the app_orderwithdrawal.zip package from the J2Commerce website.
  2. Go to System -> Install -> Extensions.
  3. Upload the app_orderwithdrawal.zip package file.
  4. The plugin installs and enables automatically. A database table (#__j2commerce_apporderwithdrawals) is created on install.

After installation, go to J2Commerce -> Apps and locate Order Withdrawal (EU Compliance). Click the plugin name to open its settings.

Configuration

The plugin settings are split across four tabs.

Basic Settings

FieldDescriptionDefaultRecommended
Enable Withdrawal FunctionMaster on/off switch. When disabled, no withdrawal button appears anywhere on the storefront.YesYes
Default Withdrawal PeriodNumber of days from the order date during which a customer may withdraw. EU standard is 14 days.1414 (or higher if your policy allows)
Eligible Order StatusesSelect which order statuses allow a withdrawal request. Orders in any other status will not show the button.(none selected — all statuses eligible)Select the statuses that represent confirmed/paid orders, such as Confirmed or Processing
Require Two-Step ConfirmationWhen enabled, the customer must complete a two-screen confirmation flow before the request is submitted. This protects against accidental withdrawals.YesYes
Allow Partial WithdrawalsWhen enabled, customers may withdraw individual items from a multi-item order rather than the entire order.NoYour business preference
Show Dashboard Quick IconDisplays a pending withdrawal count badge on the J2Commerce dashboard quick-icon panel.YesYes
Debug ModeWrites detailed log entries to administrator/logs/app_orderwithdrawal.php and the browser console. Disable in production.NoNo (only enable when troubleshooting)

Display Settings

FieldDescriptionDefault
Button PositionWhere the withdrawal button appears: Order Details Page Only, Order History Page Only, or Both Pages.Order Details Page Only
Show Days RemainingDisplays a countdown badge (e.g., "12 days remaining") next to the withdrawal button.Yes
Button Theme ColorHex color for the withdrawal button and accent elements. Accepts any valid hex color.#dc3545 (Bootstrap red)
Custom CSSPaste extra CSS rules here if you need to override the default withdrawal widget styling. Loaded on every page that renders the button.(empty)

Email Settings

FieldDescriptionDefault
Send Customer Confirmation EmailSends the legally-required written confirmation to the customer the moment their withdrawal is recorded. Required by EU law.Yes
Send Admin Notification EmailNotifies your team immediately when a new withdrawal request arrives.Yes
Admin Email AddressesComma-separated list of email addresses to receive admin notifications. Leave blank to use the Joomla site's default From address.(empty — falls back to Joomla mailfrom)
Brand Logo for EmailsSelects an image from your Joomla media library to appear at the top of both email templates.(none)
UTM SourceUTM tracking parameter appended to links inside confirmation emails.j2commerce
UTM MediumUTM medium parameter for email links.email
UTM CampaignUTM campaign parameter for email links.withdrawal

Advanced Settings

FieldDescriptionDefault
Auto-Process After DaysIf set to a number greater than 0, pending withdrawal requests are automatically marked as Processed after that many days. Set to 0 to disable.0
Extend Period if Not InformedWhen enabled, the withdrawal deadline extends to 12 months if the store has not properly informed the consumer of their withdrawal right (an EU Directive requirement). Leave this on unless you have a lawyer-reviewed alternative.Yes
Extend Deadline on WeekendsIf the withdrawal deadline falls on a Saturday or Sunday, it automatically shifts to the next Monday. Matches standard EU consumer-law practice.Yes
Enable Audit LoggingRecords every withdrawal action (created, processed, rejected) in the database for compliance tracking.Yes
Export FormatThe format used when exporting the withdrawal list. Currently CSV.CSV

Per-Product Exception Settings

Some product types are exempt from the statutory withdrawal right under EU law. The plugin adds a Withdrawal Settings tab directly on each product's edit screen so you can configure exceptions product by product.

To reach a product's withdrawal settings:

  1. Go to J2Commerce -> Catalog -> Products.
  2. Open any product and click the Withdrawal Settings tab (added by this plugin).
FieldDescription
Withdrawal AllowedToggle withdrawal on or off for this specific product. If set to No, any order containing this product is ineligible for withdrawal.
Custom Withdrawal Period (Days)Override the default period for this product. Leave blank to inherit the global default. The plugin uses the longest period among all items in an order.
Exception TypeClassifies the product under one of the eight EU-recognised statutory exceptions (see table below).
Exception ReasonA short explanation shown to the customer if they try to withdraw and this product is the reason for ineligibility.
Require Digital Content ConsentWhen set to Yes, the customer must explicitly consent before accessing digital content. This is required by EU law for digital downloads to be exempt from the withdrawal right.

Exception Types

Exception TypeEU Legal BasisExample Products
No ExceptionPhysical goods with no special status
Perishable GoodsArt. 16(d) Consumer Rights DirectiveFresh food, flowers, plants
Custom / Personalized ProductsArt. 16(c)Engraved items, made-to-order clothing
Sealed Hygiene ProductsArt. 16(e)Underwear, cosmetics opened after delivery
Sealed Audio / Video / SoftwareArt. 16(i)DVDs, games, boxed software with broken seal
Digital ContentArt. 16(m)Downloads, streaming access, software keys
Time-Sensitive ServicesArt. 16(l)Event tickets, accommodation for specific dates
Urgent RepairsArt. 16(b)Emergency repair services explicitly requested
Newspapers / MagazinesArt. 16(k)Single-issue periodicals

Setting any exception type other than No Exception blocks the withdrawal button for any order containing that product.

How the Customer-Facing Withdrawal Flow Works

When a logged-in customer views an eligible order, the plugin injects a Withdraw from Contract button (with an optional days-remaining countdown badge) into the order details page.

Clicking the button opens a two-step modal:

Step 1 — Withdrawal Form

The modal displays:

  • An EU Consumer Rights notice with the exact number of days remaining.
  • A Name field (required).
  • An Email field (required).
  • An optional Reason for Withdrawal text area.
  • An important notice explaining that goods must be returned and refunds will use the original payment method.

The customer clicks Confirm Withdrawal to proceed to Step 2.

Step 2 — Final Confirmation

The second screen shows a warning that this action cannot be undone, lists what happens next (email confirmation, review timeline, 14-day refund window, return instructions), and requires the customer to tick a confirmation checkbox before submitting.

After Submission

Once the customer clicks Confirm Withdrawal on Step 2:

  1. A withdrawal record is created in the database with status Pending.
  2. A confirmation email is sent to the customer immediately (subject: "Withdrawal Confirmation — Order [number]"). This email serves as the legally-required durable-medium receipt.
  3. An admin notification email is sent to the addresses configured in Email Settings.
  4. The button is replaced by an informational message: "Confirmed."

Admin Workflow

All withdrawal requests are managed from J2Commerce -> Apps -> Order Withdrawal Management.

The dashboard is the default view. A quick-icon badge on the J2Commerce home screen shows the count of pending requests when Show Dashboard Quick Icon is enabled.

Dashboard

The dashboard shows four summary statistics:

  • Total Requests — lifetime count
  • Pending — requests awaiting action
  • Processed This Month — withdrawals closed in the current calendar month
  • Rejection Rate — percentage of requests that were rejected

Quick links navigate to the full list, the pending-only filtered view, the analytics screen, the CSV export, and the plugin settings.

Withdrawal Requests List

Click Manage Withdrawals from the dashboard, or go to J2Commerce -> Apps -> Order Withdrawal Management and click Manage Withdrawals in the toolbar.

The list shows all withdrawal requests with columns for Order, Customer, Request Date, Status, and Days Since the request. Use the search bar to filter by order number, customer name, or email. Use the Status filter to narrow to Pending, Confirmed, Processed, or Rejected requests.

Available statuses:

StatusMeaning
PendingRequest submitted but not yet actioned by the store
ConfirmedCustomer completed the two-step form
ProcessedAdmin has processed the refund/return
RejectedAdmin has rejected the request
CancelledRequest was cancelled

Per-row actions: each row has View Details (opens the edit screen) and View Order (opens the J2Commerce order) links.

Toolbar bulk actions (select rows with checkboxes first):

  • Change Status -> Process Selected — marks selected requests as Processed
  • Change Status -> Reject Selected — marks selected requests as Rejected
  • Change Status -> Delete — permanently removes selected records (with confirmation)

Processing a Single Withdrawal

Click View Details on any row to open the withdrawal detail screen. This screen shows:

  • Order Information — order number, date, total, current status, and the ordered items
  • Customer Information — name, email, user ID, and IP address (for audit purposes)
  • Request Details — request date, confirmation date, withdrawal reason, partial items if applicable
  • Refund Information — fields to record the refund amount and a payment reference number
  • Admin Notes — a free-text field for internal notes not visible to the customer
  • Timeline — log of when the record was created and when emails were sent

To action the withdrawal:

  1. Fill in Refund Amount and Refund Reference once the refund has been issued through your payment gateway.
  2. Add any Admin Notes for your records.
  3. Click Save Changes.
  4. Use the Mark as Processed or Reject toolbar buttons to update the status.

Analytics

Click Analytics in the toolbar from the list view to access the analytics screen. It displays:

  • A line chart of withdrawals over the past 12 months
  • A pie/doughnut chart of status distribution
  • A breakdown table showing count and percentage per status, and average processing time in days

CSV Export

Click Export Data in the toolbar from the list view. The plugin streams a CSV file named withdrawals_YYYY-MM-DD.csv containing: ID, Order number, Customer name, Email, Request date, Status, Reason, Refund amount, Processed date, and Admin notes.

Emails

Customer Confirmation Email

Sent automatically when a withdrawal is confirmed. Contains:

  • Greeting with the customer's name
  • Confirmation that the withdrawal request has been received
  • Request details (order number, withdrawal ID, date and time of receipt)
  • What happens next (review, return instructions, 14-day refund)
  • A legal notice citing EU Directive 2023/2673, which serves as written confirmation on a durable medium as required by law
  • Your brand logo (if configured in Email Settings)

Admin Notification Email

Sent to each address in Admin Email Addresses (or the site's default mailfrom). Contains:

  • The order number and customer details
  • Request date and withdrawal reason
  • A direct link to the withdrawal detail screen in the admin back end

Troubleshooting

The Withdraw from Contract button does not appear

Work through the following checklist in order:

  1. Master switch disabled. Go to the plugin settings (Basic Settings tab) and confirm Enable Withdrawal Function is set to Yes.
  2. Exempt products in the order. If any product in the order has an Exception Type set (other than "No Exception") or has Withdrawal Allowed set to No, the entire order is ineligible. Check the Withdrawal Settings tab on each product in the order.
  3. Withdrawal period expired. The order is older than the configured withdrawal period. Check the order's creation date against Default Withdrawal Period. If Extend Period if Not Informed is enabled, the effective deadline is 12 months.
  4. Order status not eligible. If Eligible Order Statuses has any entries, the order's current status must be in that list. Open the order and compare its status to the selected statuses in the plugin settings.
  5. Withdrawal already submitted. If the customer already submitted a withdrawal for this order (and it was not cancelled), the button is replaced by a "Confirmed" notice. Check the Withdrawal Requests list for a record matching that order number.
  6. Customer is not the order owner. The button only appears to the logged-in user who placed the order. Administrators do not see it when viewing orders in the front end under a different account.
  7. Plugin is disabled. Go to System -> Manage -> Extensions, search for Order Withdrawal, and confirm the plugin is enabled (green tick).

Customers are not receiving confirmation emails

  1. Confirm Send Customer Confirmation Email is set to Yes in Email Settings.
  2. Confirm your Joomla outgoing mail is configured and working: System -> Global Configuration -> Server tab -> Mail Settings. Use the Send Test Mail button.
  3. Ask the customer to check their spam folder. The email is sent from your site's From address.
  4. Enable Debug Mode in Basic Settings, reproduce the withdrawal, and check administrator/logs/app_orderwithdrawal.php for any "Email send failed" entries.

The withdrawal period appears much longer than expected

Check the Extend Period if Not Informed setting in the Advanced Settings tab. When this is enabled, the plugin uses a 12-month (360-day) period if the "not informed" condition is met. Turn this off if your store correctly informs customers of their withdrawal right at the point of sale, and set your preferred period in Default Withdrawal Period.

The deadline falls on a weekend and the button disappears unexpectedly

This is by design. When Extend Deadline on Weekends is enabled (the default), a deadline that falls on Saturday is pushed to Monday, and one that falls on Sunday is pushed to the following Monday. This is standard EU practice and cannot legally disadvantage the consumer.

What's New Compared to J2Store

If your store previously used the J2Store version of this plugin, here is what changed in J2Commerce:

AreaJ2Store (v4)J2Commerce (v6)
ArchitectureFOF 2 (plgJ2StoreApp_orderwithdrawal extending F40\Plugin\Plugin)Native Joomla 6 MVC — CMSPlugin + SubscriberInterface, DI container
JavaScriptjQuery AJAXVanilla ES6+ fetch() with async/await
EmailsCalled J2Store email helper indirectlyJoomla 6 MailerFactoryInterface — emails actually send via your configured mail transport
IDOR protectionOrder ownership not always verified server-sideEvery AJAX handler verifies $order->user_id === $identity->id before processing
Admin viewsFOF-generated list / edit screensCore Joomla list layout primitives (LayoutHelper, HTMLHelper::_('searchtools.sort'), Pagination)
CSRFToken present but inconsistently checkedSession::checkToken() on every POST handler; admin actions also check core.manage ACL
Audit logFlat file onlyJoomla Log API to administrator/logs/app_orderwithdrawal.php with configurable debug/error levels
AnalyticsBasic countsChart.js line and doughnut charts with monthly trend data and per-status breakdown