From 76512d07367cfea2745d0b61acd2c9422dd65adc Mon Sep 17 00:00:00 2001 From: Adam Melcher <54608117+newlinewebdesign@users.noreply.github.com> Date: Mon, 23 Mar 2026 08:52:36 -0500 Subject: [PATCH 1/4] docs(payment-methods): add Stripe, Kustom guides and move PayPal to payment-methods/ New pages: - Stripe Payment user guide (embedded/hosted modes, webhooks, saved cards, refunds) - Kustom Payment user guide (KCO/HPP modes, refunds, capture) Moved: - PayPal Payment from payment/ to payment-methods/ (consolidate all payment gateway docs) --- .../docs-v6/payment-methods/payment_kustom.md | 431 ++++++++++++++ .../docs-v6/payment-methods/payment_paypal.md | 335 +++++++++++ .../docs-v6/payment-methods/payment_stripe.md | 555 ++++++++++++++++++ 3 files changed, 1321 insertions(+) create mode 100644 website/docs-v6/payment-methods/payment_kustom.md create mode 100644 website/docs-v6/payment-methods/payment_paypal.md create mode 100644 website/docs-v6/payment-methods/payment_stripe.md diff --git a/website/docs-v6/payment-methods/payment_kustom.md b/website/docs-v6/payment-methods/payment_kustom.md new file mode 100644 index 00000000..719aa28b --- /dev/null +++ b/website/docs-v6/payment-methods/payment_kustom.md @@ -0,0 +1,431 @@ +--- +title: "Kustom Payment" +sidebar_label: "Kustom" +sidebar_position: 15 +description: "Accept payments in your J2Commerce store using Kustom's flexible payment platform with embedded or hosted checkout, multiple payment methods, and flexible authorization options." +--- + +# Kustom Payment + +The Kustom plugin lets your customers pay using credit cards, buy-now-pay-later options, direct debit, and bank transfers — all processed securely through Kustom's payment platform. + +Choose between two checkout experiences: **KCO** (Kustom Checkout embedded directly on your checkout page) or **HPP** (Hosted Payment Page redirect to Kustom's secure payment page). Both support full and partial refunds, order cancellation, and capture of authorized payments. + +## Prerequisites + +- J2Commerce installed and active on your Joomla site +- A Kustom merchant account (see the setup steps below) +- An API key from the Kustom Dashboard + +--- + +## Step 1: Set Up a Kustom Account + +If you already have a Kustom account and API key, skip ahead to [Installation & Enabling](#installation--enabling). + +### Create a Kustom Account + +1. Go to [kustom.com](https://kustom.com) and sign up for a merchant account. +2. Complete the business verification steps Kustom requires (varies by country and business type). +3. Provide your bank account details for payout. +4. Wait for Kustom to activate your account. + +### Get Your API Key + +After your account is active: + +1. Log in to the [Kustom Dashboard](https://dashboard.kustom.com). +2. Navigate to **Settings** -> **API Keys**. +3. Copy your **API Key** — this is used to authenticate API requests from your store. + + + +**Sandbox keys (for testing):** Kustom provides a sandbox environment for testing. Contact Kustom support or check your dashboard for sandbox credentials. No real money is processed in sandbox mode. + +--- + +## Installation & Enabling + +This plugin is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It does not ship with the core J2Commerce 6 component. + +1. Purchase and download the `payment_kustom.zip` package from the J2Commerce website. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload the `payment_kustom.zip` package file. +4. Go to **J2Commerce** -> **Payments** -> **Payment Methods**. +5. Find **Kustom Pay** in the list. +6. Click the toggle in the **Enabled** column to enable the plugin, or click the plugin name to open its settings first. + + + +--- + +## Configuration + +Go to **J2Commerce** -> **Payments** -> **Payment Methods** and click **Kustom Pay** to open the settings. + + + +### Display Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Display Name** | The label shown to customers at checkout | `Kustom Pay` | +| **Display Image** | Optional logo or image shown next to the payment option at checkout | Kustom logo | + +### Checkout Type + +Choose how customers interact with the payment form: + +| Field | Description | Default | +|-------|-------------|--------| +| **Checkout Type** | How the payment form is displayed | KCO (Kustom Checkout) | + +| Option | Description | +|--------|-------------| +| **KCO (Kustom Checkout)** | Payment form loads directly on your checkout page. Customers complete payment without leaving your site. **Recommended for most stores.** | +| **HPP (Hosted Payment Page)** | Customers are redirected to a Kustom-hosted payment page. After completing payment, they are redirected back to your site. Use this if you want Kustom to handle the entire payment UI. | + +### HPP Payment Methods + +This setting appears when **Checkout Type** is set to **HPP**. Select which payment methods to offer customers: + +| Method | Description | +|--------|-------------| +| **PAY_NOW** | Immediate payment via card or bank | +| **PAY_LATER** | Buy now, pay later options | +| **PAY_OVER_TIME** | Installment payment plans | +| **DIRECT_DEBIT** | Bank account direct debit | +| **DIRECT_BANK_TRANSFER** | Traditional bank transfer | + +Select multiple methods by holding Ctrl (Windows) or Cmd (Mac) while clicking. + +**Note:** Available payment methods vary by country and merchant account configuration. Contact Kustom support to enable specific methods for your account. + +### Transaction Type + +Choose when to capture payment: + +| Field | Description | Default | +|-------|-------------|--------| +| **Transaction Type** | When payment is captured from the customer's account | Auth + Capture | + +| Option | Description | +|--------|-------------| +| **Auth + Capture** | Payment is authorized and captured immediately when the customer completes checkout. The order status updates to Confirmed right away. | +| **Auth Only** | Payment is authorized but not captured. You must manually capture the payment from the order admin page within 7 days. Use this for pre-orders, backorders, or when you need to verify stock before charging. | + +### Sandbox Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Sandbox** | Switch on to use Kustom's test environment. No real money is processed. | Yes | + +Turn sandbox mode **on** while you are setting up and testing. Turn it **off** before you go live. + +When sandbox mode is active, a warning banner appears on the J2Commerce dashboard so you cannot accidentally forget. + +### Live API Credentials + +These are used when **Sandbox** is set to **No**. + +| Field | Description | +|-------|-------------| +| **API Key** | Your live API key from the Kustom Dashboard | + +### Sandbox API Credentials + +These are used when **Sandbox** is set to **Yes**. + +| Field | Description | +|-------|-------------| +| **Sandbox API Key** | Your sandbox API key for testing | + +### Subtemplate + +| Field | Description | Default | +|-------|-------------|--------| +| **Subtemplate** | Select an alternative layout template for the Kustom payment form, if any are installed | _(default)_ | + +### Order Status + +| Field | Description | Default | +|-------|-------------|--------| +| **Order Status** | The order status applied after a successful payment capture | Confirmed | + +Choose the status that fits your workflow. Most stores use **Confirmed** or **Processing** for paid orders. + +### Cancellation Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Change Status on Cancel** | Automatically change order status when an order is cancelled | No | +| **Cancel Order Status** | The status to set when an order is cancelled (shown when Change Status on Cancel is Yes) | _(none)_ | + +### Refund Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Change Status on Refund** | Automatically change order status when a refund is processed | No | +| **Refund Order Status** | The status to set when a full refund is processed (shown when Change Status on Refund is Yes) | _(none)_ | +| **Partial Refund Order Status** | The status to set when a partial refund is processed (shown when Change Status on Refund is Yes) | _(none)_ | + +### Surcharge + +Add an optional surcharge to orders paid via Kustom. This is useful if you want to pass on Kustom's processing fee to customers (check your local laws before doing this). + +| Field | Description | Default | +|-------|-------------|--------| +| **Surcharge Name** | Label shown to customers for the surcharge (e.g., "Processing Fee") | _(none)_ | +| **Surcharge Percent** | Percentage of the order subtotal added as a surcharge | _(none)_ | +| **Surcharge Fixed** | Fixed amount added as a surcharge | _(none)_ | +| **Surcharge Tax Class** | Tax profile to apply to the surcharge amount | _(none)_ | + +You can combine a percentage and a fixed amount — both will be added together. + +### Geo-Zone Restriction + +| Field | Description | Default | +|-------|-------------|--------| +| **Geo-Zone Restriction** | Limit Kustom availability to customers in a specific geo-zone | _(none — available everywhere)_ | + +Leave this empty to show Kustom to all customers regardless of location. + +### Order Amount Limits + +| Field | Description | Default | +|-------|-------------|--------| +| **Minimum Subtotal** | Hide Kustom if the cart subtotal is below this amount. Leave empty for no minimum. | _(none)_ | +| **Maximum Subtotal** | Hide Kustom if the cart subtotal exceeds this amount. Leave empty or set to `-1` for no maximum. | _(none)_ | + +### Thank You Page + +| Field | Description | +|-------|-------------| +| **Thank You Article** | Select a Joomla article to display after a successful payment. This is shown on the confirmation page in addition to the standard confirmation message. | + +### Custom Messages + +These text fields let you customize messages shown to customers at different points in the payment process. + +| Field | When it displays | +|-------|------------------| +| **On Selection** | When the customer selects Kustom as their payment method | +| **On Before Payment** | On the payment page before the customer clicks Pay | +| **On After Payment** | On the confirmation page after a successful payment | +| **On Error Payment** | When a payment error occurs | +| **On Cancel Payment** | When the customer cancels payment and returns to the cart | + +### Dashboard Icon + +| Field | Description | Default | +|-------|-------------|--------| +| **Show Dashboard Icon** | Show a shortcut icon for Kustom on the J2Commerce dashboard | No | +| **Dashboard Icon Label** | Label for the dashboard icon (only visible when Show Dashboard Icon is Yes) | _(none)_ | + +### Debug Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Debug Mode** | Write detailed Kustom API activity to `administrator/logs/payment_kustom.php` and the browser console | No | + +Enable debug mode only while troubleshooting. Disable it in production — logs can grow large quickly. + +--- + +## Checkout Experience + +### KCO (Kustom Checkout) Mode + +When Checkout Type is set to KCO: + +1. The Kustom payment form loads directly on your checkout page. +2. The customer enters payment details and clicks **Pay**. +3. Payment is processed without leaving your site. +4. The customer sees the confirmation page. + + + +### HPP (Hosted Payment Page) Mode + +When Checkout Type is set to HPP: + +1. The customer is redirected to a Kustom-hosted payment page. +2. They select their preferred payment method (if multiple are enabled). +3. They complete payment on Kustom's secure servers. +4. After payment, they are redirected back to your confirmation page. + + + +--- + +## Order Management + +Once a customer pays, J2Commerce records the transaction details: + +- **Order status** is updated to the status you configured (default: Confirmed). +- **Transaction ID** — the Kustom Order ID — is stored with the order. +- **Transaction status** — Captured, Authorized, Cancelled, or Refunded — is tracked. +- **Order history** is updated with a payment note. + +### Capture Authorized Payments (Auth Only Mode) + +If you set **Transaction Type** to **Auth Only**, payments are authorized but not captured. To capture: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. Look for the **Payment** section. +3. Click **Capture** to capture the authorized amount. +4. The order status updates to the configured payment status. + +You can also **Cancel** an authorization to release the hold on the customer's funds without charging them. + + + +### Refunds + +You can issue a full or partial refund directly from the order in the J2Commerce admin: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. Look for the **Payment** section. +3. Click **Refund**. +4. Enter the amount to refund (leave blank to refund the full amount). +5. Confirm the refund. + +The refund is sent to Kustom via the API. If you enabled **Change Status on Refund**, the order status updates automatically. + + + +### Full vs Partial Refunds + +- **Full refund:** Refunds the entire order amount. Sets transaction status to "Refunded." +- **Partial refund:** Refunds a portion of the order amount. Sets transaction status to "Partially Refunded." + +Kustom tracks the total refunded amount across all partial refunds. + +--- + +## Callbacks (Push Notifications) + +Kustom sends push notifications to your store when order status changes. These are handled automatically — no additional configuration is required. + +| Event | What happens in J2Commerce | +|-------|---------------------------| +| Order authorized | Order status updated to Pending | +| Order captured | Order status updated to Confirmed | +| Order cancelled | Order status updated to Cancelled (if enabled) | +| Order refunded | Order status updated to Refunded (if enabled) | + +The callback URL is automatically configured in the plugin. Kustom sends notifications to this URL when any status change occurs. + +--- + +## Enable Payment Methods in Kustom Dashboard + +Payment methods available in HPP mode are configured in your Kustom Dashboard: + +1. Log in to the [Kustom Dashboard](https://dashboard.kustom.com). +2. Go to **Settings** -> **Payment Methods**. +3. Enable or disable payment methods for your account. +4. Some methods may require additional verification — follow the prompts. + +**Important:** Payment methods available vary by: +- Your merchant account country +- Your customer's location +- Your account configuration + +Contact Kustom support to enable specific payment methods for your account. + + + +--- + +## Going Live Checklist + +Before accepting real payments, confirm the following: + +- [ ] **Sandbox** is set to **No** +- [ ] Your live **API Key** is entered +- [ ] You have placed a test order using a real payment method with a small amount +- [ ] **Debug Mode** is set to **No** +- [ ] Payment methods you want to offer are enabled in your Kustom Dashboard (for HPP mode) +- [ ] You have tested the capture, cancel, and refund flows + +--- + +## Troubleshooting + +### "API Key is missing or invalid" error + +**Cause:** The API key is missing or incorrect. + +**Solution:** +1. Open the Kustom plugin settings. +2. Make sure you have entered an API key for the correct mode (live or sandbox). +3. If using live mode, verify **Sandbox** is set to **No**. +4. If using sandbox mode, verify **Sandbox** is set to **Yes** and you have entered a sandbox API key. + +### Payment succeeds but order stays Pending + +**Cause:** The order status did not update correctly, possibly due to a callback failure. + +**Solution:** +1. Check that callbacks are reaching your server by enabling **Debug Mode**. +2. Verify your server is publicly accessible (Kustom cannot send callbacks to localhost). +3. Check `administrator/logs/payment_kustom.php` for callback errors. +4. Manually update the order status if needed. + +### Capture button does not appear in admin + +**Cause:** The order is not in an authorized state, or the transaction status is not "Authorized." + +**Solution:** +1. Open the order and check the **Transaction Status** field. +2. Only orders with **Transaction Type** set to **Auth Only** and **Transaction Status** of "Authorized" show the Capture button. +3. If the payment was already captured, the Capture button will not appear. + +### Refund fails with an error + +**Cause:** The order has already been fully refunded, or the Kustom Order ID is missing. + +**Solution:** +1. Open the order and check that a **Transaction ID** is recorded. +2. If the Transaction ID is empty, the payment may not have been processed correctly. Check the debug log. +3. Log in to your Kustom Dashboard and verify the transaction status there. +4. Check if the order has already been fully refunded in Kustom. + +### Dashboard shows "Kustom is in Sandbox mode" warning + +**Cause:** **Sandbox** is set to **Yes**. + +**Solution:** If you are ready to go live, open the Kustom plugin settings and switch **Sandbox** to **No**, then enter your live API key. + +### HPP payment methods not showing at checkout + +**Cause:** No payment methods are selected in the HPP Payment Methods setting, or methods are not enabled in your Kustom Dashboard. + +**Solution:** +1. Open the Kustom plugin settings. +2. Verify **Checkout Type** is set to **HPP**. +3. Check that at least one payment method is selected in **HPP Payment Methods**. +4. Log in to your Kustom Dashboard and ensure the selected methods are enabled for your account. + +### Customer sees "Payment Failed" but money was taken + +**Cause:** A communication error occurred after payment was processed but before the order was updated. + +**Solution:** +1. Check `administrator/logs/payment_kustom.php` for errors during the callback. +2. Look up the order by Transaction ID in the J2Commerce admin. +3. Manually update the order status to Confirmed. +4. Contact Kustom support if the issue persists. + +--- + +## Support + +For help with the Kustom plugin: + +- **J2Commerce documentation:** [docs.j2commerce.com](https://docs.j2commerce.com) +- **J2Commerce support:** [www.j2commerce.com](https://www.j2commerce.com) +- **Kustom Dashboard:** [dashboard.kustom.com](https://dashboard.kustom.com) +- **Kustom documentation:** [docs.kustom.com](https://docs.kustom.com) +- **Kustom support:** [support.kustom.com](https://support.kustom.com) diff --git a/website/docs-v6/payment-methods/payment_paypal.md b/website/docs-v6/payment-methods/payment_paypal.md new file mode 100644 index 00000000..09325833 --- /dev/null +++ b/website/docs-v6/payment-methods/payment_paypal.md @@ -0,0 +1,335 @@ +--- +title: "PayPal Payment" +sidebar_label: "PayPal" +sidebar_position: 10 +description: "Accept PayPal payments in your J2Commerce store using PayPal Smart Payment Buttons and the REST API v2." +--- + +# PayPal Payment + +The PayPal plugin lets your customers pay using PayPal's Smart Payment Buttons — a modern, secure checkout experience that supports PayPal accounts, credit cards, and other payment methods PayPal offers in your customers' region. + +The plugin uses PayPal's REST API v2, so no redirects are needed. Customers complete payment directly on your checkout page without leaving your site. Refunds, webhook notifications, and sandbox testing are all built in. + +## Prerequisites + +- J2Commerce installed and active on your Joomla site +- A PayPal Business account (see the setup steps below) +- REST API credentials (Client ID and Client Secret) from the PayPal Developer Dashboard + +--- + +## Step 1: Set Up a PayPal Business Account + +If you already have a PayPal Business account and REST API credentials, skip ahead to [Installation & Enabling](#installation--enabling). + +### Create a PayPal Business Account + +1. Go to [paypal.com](https://www.paypal.com) and click **Sign Up**. +2. Choose **Business Account** and click **Next**. +3. Enter your email address and create a password. +4. Fill in your business details — business name, address, and phone number. +5. Verify your email address when PayPal sends you a confirmation email. +6. Complete the identity verification steps PayPal requires (this varies by country). + +### Get Your REST API Credentials + +After your account is active: + +1. Go to [developer.paypal.com](https://developer.paypal.com) and log in with your PayPal Business account. +2. Click **Apps & Credentials** in the top navigation. +3. Make sure you are on the **Live** tab (not Sandbox). +4. Click **Create App**. +5. Give the app a name — for example, "My Store". +6. Click **Create App** to confirm. +7. On the next page you will see your **Client ID** and **Client Secret**. Copy both and keep them somewhere safe. + + + +**Sandbox credentials** (for testing): Click the **Sandbox** tab on the same Apps & Credentials page. Create a separate sandbox app or use the default one. Copy the Sandbox Client ID and Sandbox Client Secret separately. + +--- + +## Installation & Enabling + +The PayPal plugin ships with J2Commerce 6 and is available immediately after installation. Because it requires your merchant credentials before it can process payments, it is not enabled automatically during installation. + +To enable it: + +1. Go to **J2Commerce** -> **Payments** -> **Payment Methods**. +2. Find **PayPal** in the list. +3. Click the toggle in the **Enabled** column to enable the plugin, or click the plugin name to open its settings first. + + + +--- + +## Configuration + +Go to **J2Commerce** -> **Payments** -> **Payment Methods** and click **PayPal** to open the settings. + + + +### Display Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Display Name** | The label shown to customers at checkout | `PayPal` | +| **Display Image** | Optional logo or image shown next to the payment option at checkout | _(none)_ | + +### Sandbox Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Use PayPal Sandbox** | Switch this on to use PayPal's test environment. No real money is processed. | No | + +Turn sandbox mode **on** while you are setting up and testing. Turn it **off** before you go live. + +When sandbox mode is active, a warning banner appears on the J2Commerce dashboard so you cannot accidentally forget. + +### Live API Credentials + +These are used when **Use PayPal Sandbox** is set to **No**. + +| Field | Description | +|-------|-------------| +| **Client ID** | Your live REST API Client ID from [developer.paypal.com](https://developer.paypal.com) | +| **Client Secret** | Your live REST API Client Secret | + +### Sandbox API Credentials + +These are used when **Use PayPal Sandbox** is set to **Yes**. + +| Field | Description | +|-------|-------------| +| **Sandbox Client ID** | Your sandbox REST API Client ID | +| **Sandbox Client Secret** | Your sandbox REST API Client Secret | + +### Webhooks (Optional but Recommended) + +Webhooks allow PayPal to notify your store automatically when payment events occur — for example, when a payment completes, is refunded, or is disputed. Without webhooks, order status updates only happen when the customer completes checkout on your page. + +| Field | Description | +|-------|-------------| +| **Webhook ID** | The Webhook ID from your live PayPal app in the developer dashboard | +| **Sandbox Webhook ID** | The Webhook ID from your sandbox PayPal app | + +**How to create a webhook in PayPal:** + +1. In the PayPal Developer Dashboard, open your app. +2. Scroll down to **Webhooks** and click **Add Webhook**. +3. Enter your webhook URL. The URL format for J2Commerce is: `https://yoursite.com/index.php?option=com_j2commerce&task=checkout.processWebhook&payment_method=payment_paypal` +4. Select the events you want to receive. Recommended events: `PAYMENT.CAPTURE.COMPLETED`, `PAYMENT.CAPTURE.DENIED`, `PAYMENT.CAPTURE.REFUNDED`, `PAYMENT.CAPTURE.REVERSED`, `CUSTOMER.DISPUTE.CREATED`, `CUSTOMER.DISPUTE.RESOLVED`. +5. Click **Save**. Copy the **Webhook ID** shown and paste it into the plugin configuration. + + + +### Order Status + +| Field | Description | Default | +|-------|-------------|--------| +| **Order Status** | The order status applied after a successful payment capture | `Confirmed` | + +Choose the status that fits your workflow. Most stores use **Confirmed** or **Processing** for paid orders. + +### Surcharge + +Add an optional surcharge to orders paid via PayPal. This is useful if you want to pass on PayPal's processing fee to customers (check your local laws and PayPal's terms before doing this). + +| Field | Description | Default | +|-------|-------------|--------| +| **Surcharge Name** | Label shown to customers for the surcharge (e.g., "PayPal Fee") | _(none)_ | +| **Surcharge Percent** | Percentage of the order subtotal added as a surcharge | _(none)_ | +| **Surcharge Fixed** | Fixed amount added as a surcharge | _(none)_ | +| **Surcharge Tax Class** | Tax profile to apply to the surcharge amount | _(none)_ | + +You can combine a percentage and a fixed amount — both will be added together. + +### Geo-Zone Restriction + +| Field | Description | Default | +|-------|-------------|--------| +| **Geo-Zone Restriction** | Limit PayPal availability to customers in a specific geo-zone | _(none — available everywhere)_ | + +Leave this empty to show PayPal to all customers regardless of location. + +### Order Amount Limits + +| Field | Description | Default | +|-------|-------------|--------| +| **Minimum Subtotal** | Hide PayPal if the cart subtotal is below this amount. Leave empty for no minimum. | _(none)_ | +| **Maximum Subtotal** | Hide PayPal if the cart subtotal exceeds this amount. Leave empty or set to `-1` for no maximum. | _(none)_ | + +### Thank You Page + +| Field | Description | +|-------|-------------| +| **Thank You Article** | Select a Joomla article to display after a successful payment. This is shown on the confirmation page in addition to the standard confirmation message. | + +### Custom Messages + +These text fields let you customize messages shown to customers at different points in the payment process. + +| Field | When it displays | +|-------|------------------| +| **On Selection** | When the customer selects PayPal as their payment method | +| **On Before Payment** | On the payment page before the customer clicks Pay | +| **On After Payment** | On the confirmation page after a successful payment | +| **On Error Payment** | When a payment error occurs | +| **On Cancel Payment** | When the customer cancels payment and returns to the cart | + +### Dashboard Icon + +| Field | Description | Default | +|-------|-------------|--------| +| **Show Dashboard Icon** | Show a shortcut icon for PayPal on the J2Commerce dashboard | No | +| **Dashboard Icon Label** | Label for the dashboard icon (only visible when Show Dashboard Icon is Yes) | _(none)_ | + +### Subtemplate + +| Field | Description | Default | +|-------|-------------|--------| +| **Subtemplate** | Select an alternative layout template for the PayPal payment form, if any are installed | _(default)_ | + +### Debug Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Debug Mode** | Write detailed PayPal API activity to `administrator/logs/payment_paypal.php` and the browser console | No | + +Enable debug mode only while troubleshooting. Disable it in production — logs can grow large quickly. + +--- + +## Supported Currencies + +PayPal does not support every currency. If your store uses a currency not in this list, PayPal will not be available at checkout. + +Supported currencies: AUD, BRL, CAD, CNY, CZK, DKK, EUR, HKD, HUF, INR, ILS, JPY, MYR, MXN, TWD, NZD, NOK, PHP, PLN, GBP, RUB, SGD, SEK, CHF, THB, USD. + +--- + +## Checkout Experience + +When a customer selects PayPal at checkout: + +1. The PayPal Smart Payment Buttons load on the page. +2. The customer clicks their preferred option — **PayPal**, credit card, or any other method PayPal offers in their region. +3. A PayPal login window (or card form) appears. The customer completes payment. +4. The payment is captured immediately. +5. The customer is returned to your confirmation page. + + + +Payment happens without the customer leaving your site. The PayPal popup or inline experience handles authentication securely. + +If the customer clicks **Cancel** in the PayPal window, they are returned to checkout and the cart remains intact. The cancellation message you configured is displayed. + +--- + +## Order Management + +Once a customer pays, J2Commerce records the transaction details against the order: + +- **Order status** is updated to the status you configured (default: Confirmed). +- **Transaction ID** — the PayPal capture ID — is stored with the order. +- **Order history** is updated with a "Payment received via PayPal" note. + +### Refunds + +You can issue a refund directly from the order in the J2Commerce admin: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. Click the **Refund** button. +3. Enter the amount to refund (leave blank to refund the full amount). +4. Confirm the refund. + +The refund is sent to PayPal via the API. The order status is updated and a note is added to the order history. + +### Webhook-Triggered Updates + +If webhooks are configured, PayPal can update order statuses automatically for events that happen outside the normal checkout flow: + +| PayPal Event | What happens in J2Commerce | +|-------------|---------------------------| +| Payment capture completed | Order status updated to the configured "Confirmed" state | +| Payment capture pending | Order status updated to Pending | +| Payment capture denied | Order status updated to Failed | +| Payment refunded | Order status updated to Refunded | +| Payment reversed (chargeback) | Order status updated to Failed, flagged for review in order history | +| Dispute created | Warning logged in the application log | +| Dispute resolved | Resolution logged in the application log | + +Webhook events are deduplicated — if PayPal sends the same event twice, it is processed only once. + +--- + +## Going Live Checklist + +Before accepting real payments, confirm the following: + +- [ ] **Use PayPal Sandbox** is set to **No** +- [ ] Your live **Client ID** and **Client Secret** are entered +- [ ] The webhook URL is registered in your live PayPal app and the **Webhook ID** is saved +- [ ] You have placed a test order using a real PayPal account with a small amount and then refunded it +- [ ] **Debug Mode** is set to **No** + +--- + +## Troubleshooting + +### PayPal buttons do not appear at checkout + +**Cause:** The Client ID is missing or incorrect, or the plugin is not enabled. + +**Solution:** +1. Go to **J2Commerce** -> **Payments** -> **Payment Methods** and confirm PayPal is enabled. +2. Check that a Client ID (or Sandbox Client ID if in sandbox mode) is entered. +3. Enable **Debug Mode** and check the browser console for error messages. + +### "PayPal plugin is not properly configured" message + +**Cause:** The Client ID field is empty. + +**Solution:** Open the PayPal plugin settings and enter your Client ID and Client Secret. + +### Payments go through in PayPal but the order stays Pending + +**Cause:** Webhooks are not configured, so J2Commerce does not receive the payment confirmation from PayPal. + +**Solution:** +1. Set up a webhook in your PayPal app (see [Webhooks](#webhooks-optional-but-recommended) above). +2. Enter the Webhook ID in the plugin settings. +3. Alternatively, the order status is also updated during the capture step — if the customer completed checkout successfully, check whether the order status was set at that time. + +### "Currency not supported" error + +**Cause:** Your store's active currency is not in PayPal's supported currency list. + +**Solution:** Switch your store to a [supported currency](#supported-currencies) or configure a separate currency for PayPal-eligible customers. + +### Refund fails with an error + +**Cause:** The PayPal capture ID is missing from the order, or the transaction has already been refunded. + +**Solution:** +1. Open the order and check that a Transaction ID is recorded. +2. If the Transaction ID is empty, the payment may not have been captured correctly. Check the debug log. +3. Log in to your PayPal Business account and verify the transaction status there. + +### Dashboard shows "PayPal is in Sandbox mode" warning + +**Cause:** **Use PayPal Sandbox** is set to **Yes**. + +**Solution:** If you are ready to go live, open the PayPal plugin settings and switch **Use PayPal Sandbox** to **No**, then enter your live credentials. + +--- + +## Support + +For help with the PayPal plugin: + +- **J2Commerce documentation:** [docs.j2commerce.com](https://docs.j2commerce.com) +- **J2Commerce support:** [www.j2commerce.com](https://www.j2commerce.com) +- **PayPal Developer Dashboard:** [developer.paypal.com](https://developer.paypal.com) +- **PayPal Business support:** [paypal.com/support](https://www.paypal.com/support) diff --git a/website/docs-v6/payment-methods/payment_stripe.md b/website/docs-v6/payment-methods/payment_stripe.md new file mode 100644 index 00000000..bdafef6a --- /dev/null +++ b/website/docs-v6/payment-methods/payment_stripe.md @@ -0,0 +1,555 @@ +--- +title: "Stripe Payment" +sidebar_label: "Stripe" +sidebar_position: 5 +description: "Accept credit card payments and dozens of alternative payment methods in your J2Commerce store using Stripe's powerful payment platform." +--- + +# Stripe Payment + +The Stripe plugin lets your customers pay using credit cards, digital wallets, bank transfers, and buy-now-pay-later options — all processed securely through Stripe's payment platform. + +Choose between two checkout experiences: **Embedded** (payment form displayed directly on your checkout page) or **Hosted** (redirect to a Stripe-hosted payment page). Both support refunds, webhooks for automatic order updates, and saved cards for returning customers. + +## Prerequisites + +- J2Commerce installed and active on your Joomla site +- A Stripe account (see the setup steps below) +- API keys from your Stripe Dashboard (Publishable Key and Secret Key) + +--- + +## Step 1: Set Up a Stripe Account + +If you already have a Stripe account and API keys, skip ahead to [Installation & Enabling](#installation--enabling). + +### Create a Stripe Account + +1. Go to [stripe.com](https://stripe.com) and click **Sign up**. +2. Enter your email address and create a password. +3. Verify your email address when Stripe sends you a confirmation email. +4. Complete the identity verification steps Stripe requires (this varies by country). +5. Activate your account by providing business details and bank account information. + +### Get Your API Keys + +After your account is active: + +1. Log in to the [Stripe Dashboard](https://dashboard.stripe.com). +2. Click **Developers** in the left sidebar, then **API Keys**. +3. You will see your **Publishable key** and **Secret key**. +4. Copy both keys and keep them somewhere safe. + + + +**Test mode keys (for sandbox testing):** Toggle the **Test mode** switch at the top of the Stripe Dashboard. The API keys shown will be for testing — no real money is processed. Copy the test Publishable key and test Secret key separately. + +--- + +## Installation & Enabling + +This plugin is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It does not ship with the core J2Commerce 6 component. + +1. Purchase and download the `payment_stripe.zip` package from the J2Commerce website. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload the `payment_stripe.zip` package file. +4. Go to **J2Commerce** -> **Payments** -> **Payment Methods**. +5. Find **Stripe** in the list. +6. Click the toggle in the **Enabled** column to enable the plugin, or click the plugin name to open its settings first. + + + +--- + +## Configuration + +Go to **J2Commerce** -> **Payments** -> **Payment Methods** and click **Stripe** to open the settings. + + + +### Display Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Display Name** | The label shown to customers at checkout | `Credit / Debit Card` | +| **Display Image** | Optional logo or image shown next to the payment option at checkout | Stripe logo | + +### Checkout Mode + +Choose how customers interact with the payment form: + +| Field | Description | Default | +|-------|-------------|--------| +| **Checkout Mode** | How the payment form is displayed | Embedded | + +**Options:** + +| Mode | Description | +|------|-------------| +| **Embedded** | Payment form loads directly on your checkout page. Customers never leave your site. Choose between Payment Element (recommended) or Card Element. | +| **Hosted** | Customers are redirected to a Stripe-hosted payment page. After completing payment, they are redirected back to your site. | + +### Element Type (Embedded Mode Only) + +This setting appears when **Checkout Mode** is set to **Embedded**. + +| Field | Description | Default | +|-------|-------------|--------| +| **Element Type** | Which Stripe UI element to use | Payment | + +| Option | Description | +|--------|-------------| +| **Payment Element** | Full payment method selection. Stripe shows relevant payment methods based on the customer's location. **Recommended.** | +| **Card Element** | Simple card form. Use this if you want a minimalist credit card input without additional payment method options. | + +### Payment Methods (Card Element Only) + +When **Element Type** is set to **Card**, you can enable additional payment methods beyond credit cards: + +| Payment Method | Description | +|----------------|-------------| +| **Card** | Credit and debit cards (Visa, Mastercard, Amex, etc.) | +| **Amazon Pay** | Pay with Amazon account | +| **PayPal** | Pay with PayPal | +| **Link** | Stripe Link one-click checkout | +| **Cash App** | Pay with Cash App | +| **Affirm** | Buy now, pay later (US) | +| **Afterpay/Clearpay** | Buy now, pay later (varies by region) | +| **Klarna** | Buy now, pay later | +| **Zip** | Buy now, pay later | +| **Revolut Pay** | Pay with Revolut | +| **iDEAL** | Bank transfer (Netherlands) | +| **Bancontact** | Bank transfer (Belgium) | +| **SEPA Direct Debit** | Bank transfer (Europe) | +| **giropay** | Bank transfer (Germany) | +| **Sofort** | Bank transfer (Europe) | +| **EPS** | Bank transfer (Austria) | +| **Przelewy24 (P24)** | Bank transfer (Poland) | +| **BLIK** | Mobile payment (Poland) | +| **GrabPay** | Mobile wallet (Southeast Asia) | +| **FPX** | Bank transfer (Malaysia) | +| **Alipay** | Mobile wallet (China) | +| **WeChat Pay** | Mobile wallet (China) | +| **Pix** | Bank transfer (Brazil) | +| **Boleto** | Bank transfer (Brazil) | +| **OXXO** | Cash payment (Mexico) | +| **ACH Direct Debit** | Bank transfer (US) | + +**Note:** Some payment methods require activation in your Stripe Dashboard. See [Enable Payment Methods in Stripe](#enable-payment-methods-in-stripe-dashboard) below. + +### Capture Method + +Choose when to capture payment: + +| Field | Description | Default | +|-------|-------------|--------| +| **Capture Method** | When payment is captured from the customer's account | Automatic | + +| Option | Description | +|--------|-------------| +| **Automatic** | Payment is captured immediately when the customer completes checkout. The order status updates to Confirmed right away. | +| **Manual** | Payment is authorized but not captured. You must manually capture the payment from the order admin page. Use this for pre-orders, backorders, or when you need to verify stock before charging. | + +### Sandbox Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Sandbox** | Switch on to use Stripe's test environment. No real money is processed. | Yes | + +Turn sandbox mode **on** while you are setting up and testing. Turn it **off** before you go live. + +When sandbox mode is active, a warning banner appears on the J2Commerce dashboard so you cannot accidentally forget. + +### Live API Credentials + +These are used when **Sandbox** is set to **No**. + +| Field | Description | +|-------|-------------| +| **Publishable Key** | Your live Publishable key from the Stripe Dashboard | +| **Secret Key** | Your live Secret key from the Stripe Dashboard | +| **Webhook Secret** | Your live Webhook signing secret (see Webhooks below) | + +### Sandbox API Credentials + +These are used when **Sandbox** is set to **Yes**. + +| Field | Description | +|-------|-------------| +| **Sandbox Publishable Key** | Your test Publishable key | +| **Sandbox Secret Key** | Your test Secret key | +| **Sandbox Webhook Secret** | Your test Webhook signing secret | + +### Webhooks + +Webhooks allow Stripe to notify your store automatically when payment events occur — captures, refunds, disputes, and more. Without webhooks, order status updates only happen during the normal checkout flow. + +A **Webhook URL** field is displayed in the plugin settings — copy this URL and register it in your Stripe Dashboard. + +| Field | Description | +|-------|-------------| +| **Webhook URL (Live)** | The URL to register in your live Stripe Dashboard | +| **Webhook URL (Sandbox)** | The URL to register in your test Stripe Dashboard | + +**How to create a webhook in Stripe:** + +1. In the Stripe Dashboard, go to **Developers** -> **Webhooks**. +2. Click **Add endpoint**. +3. Paste the **Webhook URL** from the J2Commerce plugin settings. +4. Select the events to listen for. Recommended events: + +| Event | What happens in J2Commerce | +|-------|---------------------------| +| `payment_intent.succeeded` | Order status updated to Confirmed | +| `payment_intent.payment_failed` | Order status updated to Failed | +| `payment_intent.canceled` | Order status updated to Canceled | +| `charge.refunded` | Order status updated to Refunded | +| `charge.dispute.created` | Warning logged for review | +| `checkout.session.completed` | Order status updated (for Hosted mode) | + +5. Click **Add endpoint**. +6. On the next page, click **Reveal** next to **Signing secret**. +7. Copy the signing secret (starts with `whsec_...`). +8. Paste it into the **Webhook Secret** field in the J2Commerce plugin settings. + + + +### Saved Cards + +| Field | Description | Default | +|-------|-------------|--------| +| **Allow Saved Cards** | Let logged-in customers save cards for faster checkout on future orders | Yes | + +When enabled, customers see a **Save card for future purchases** checkbox at checkout. Saved cards appear in the customer's profile under **My Account** -> **Payment Methods**. + +### Stripe Link + +| Field | Description | Default | +|-------|-------------|--------| +| **Enable Link** | Enable Stripe Link one-click checkout for returning customers | Yes | + +Stripe Link lets customers who have saved payment details with Stripe Link pay with a single click using their email address. This requires **Allow Saved Cards** to be enabled. + +### Order Status + +| Field | Description | Default | +|-------|-------------|--------| +| **Order Status** | The order status applied after a successful payment | Confirmed | + +Choose the status that fits your workflow. Most stores use **Confirmed** or **Processing** for paid orders. + +### Refund Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Change Status on Refund** | Automatically change order status when a refund is processed | No | +| **Refund Order Status** | The status to set when a refund is processed (shown when Change Status on Refund is Yes) | _(none)_ | + +### Void Settings + +| Field | Description | Default | +|-------|-------------|--------| +| **Change Status on Void** | Automatically change order status when a void is processed | No | +| **Void Order Status** | The status to set when a void is processed (shown when Change Status on Void is Yes) | _(none)_ | + +### Surcharge + +Add an optional surcharge to orders paid via Stripe. This is useful if you want to pass on Stripe's processing fee to customers (check your local laws and Stripe's terms before doing this). + +| Field | Description | Default | +|-------|-------------|--------| +| **Surcharge Name** | Label shown to customers for the surcharge (e.g., "Processing Fee") | _(none)_ | +| **Surcharge Percent** | Percentage of the order subtotal added as a surcharge | _(none)_ | +| **Surcharge Fixed** | Fixed amount added as a surcharge | _(none)_ | +| **Surcharge Tax Class** | Tax profile to apply to the surcharge amount | _(none)_ | + +You can combine a percentage and a fixed amount — both will be added together. + +### Geo-Zone Restriction + +| Field | Description | Default | +|-------|-------------|--------| +| **Geo-Zone Restriction** | Limit Stripe availability to customers in a specific geo-zone | _(none — available everywhere)_ | + +Leave this empty to show Stripe to all customers regardless of location. + +### Order Amount Limits + +| Field | Description | Default | +|-------|-------------|--------| +| **Minimum Subtotal** | Hide Stripe if the cart subtotal is below this amount. Leave empty for no minimum. | _(none)_ | +| **Maximum Subtotal** | Hide Stripe if the cart subtotal exceeds this amount. Leave empty for `-1` for no maximum. | _(none)_ | + +### Statement Descriptor + +| Field | Description | Default | +|-------|-------------|--------| +| **Statement Descriptor** | Text that appears on your customers' bank statements (max 22 characters) | _(none)_ | + +If empty, Stripe uses your account's default statement descriptor. + +### Thank You Page + +| Field | Description | +|-------|-------------| +| **Thank You Article** | Select a Joomla article to display after a successful payment. This is shown on the confirmation page in addition to the standard confirmation message. | + +### Custom Messages + +These text fields let you customize messages shown to customers at different points in the payment process. + +| Field | When it displays | +|-------|------------------| +| **On Selection** | When the customer selects Stripe as their payment method | +| **On Before Payment** | On the payment page before the customer clicks Pay | +| **On After Payment** | On the confirmation page after a successful payment | +| **On Error Payment** | When a payment error occurs | +| **On Cancel Payment** | When the customer cancels payment and returns to the cart | + +### Dashboard Icon + +| Field | Description | Default | +|-------|-------------|--------| +| **Show Dashboard Icon** | Show a shortcut icon for Stripe on the J2Commerce dashboard | No | +| **Dashboard Icon Label** | Label for the dashboard icon (only visible when Show Dashboard Icon is Yes) | _(none)_ | + +### Subtemplate + +| Field | Description | Default | +|-------|-------------|--------| +| **Subtemplate** | Select an alternative layout template for the Stripe payment form, if any are installed | _(default)_ | + +### Debug Mode + +| Field | Description | Default | +|-------|-------------|--------| +| **Debug Mode** | Write detailed Stripe API activity to `administrator/logs/payment_stripe.php` and the browser console | No | + +Enable debug mode only while troubleshooting. Disable it in production — logs can grow large quickly. + +--- + +## Enable Payment Methods in Stripe Dashboard + +Some payment methods in Stripe require activation before they appear at checkout: + +1. Log in to the [Stripe Dashboard](https://dashboard.stripe.com). +2. Go to **Settings** -> **Payment methods**. +3. Click **Add payment methods** or enable individual methods. +4. For each payment method you want to use: + - Click the method name (e.g., **Klarna**, **Affirm**). + - Toggle **On** to enable it. + - Some methods require additional verification or configuration — follow the prompts. + +**Important:** Payment methods are shown based on the customer's location and currency. A customer in the US won't see iDEAL (Netherlands-only) even if it's enabled. + + + +--- + +## Checkout Experience + +### Embedded Mode (Payment Element) + +When a customer selects Stripe at checkout: + +1. The Payment Element loads directly on your checkout page. +2. The customer sees payment methods relevant to their location and currency. +3. They enter payment details and click **Pay**. +4. The payment is processed without leaving your site. +5. The customer sees the confirmation page. + + + +### Embedded Mode (Card Element) + +When Element Type is set to Card: + +1. A simple card form appears with optional payment method buttons. +2. The customer enters card details or clicks an alternative payment method. +3. Payment is processed without leaving your site. + +### Hosted Mode + +When Checkout Mode is set to Hosted: + +1. The customer is redirected to a Stripe-hosted payment page. +2. They complete payment on Stripe's secure servers. +3. After payment, they are redirected back to your confirmation page. + + + +--- + +## Order Management + +Once a customer pays, J2Commerce records the transaction details: + +- **Order status** is updated to the status you configured (default: Confirmed). +- **Transaction ID** — the Stripe Payment Intent ID — is stored with the order. +- **Transaction status** — Completed, Authorized, or Partially Refunded — is tracked. +- **Order history** is updated with a "Payment received via Stripe" note. + +### Capture Authorized Payments (Manual Capture) + +If you set **Capture Method** to **Manual**, payments are authorized but not captured. To capture: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. Look for the **Payment** section on the order view page. +3. Click **Capture** to capture the authorized amount. +4. The order status updates to Confirmed. + +You can also **Void** an authorization to cancel it without charging the customer. + + + +### Refunds + +You can issue a refund directly from the order in the J2Commerce admin: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. Look for the **Payment** section. +3. Click **Refund**. +4. Enter the amount to refund (leave blank to refund the full amount). +5. Confirm the refund. + +The refund is sent to Stripe via the API. If you enabled **Change Status on Refund**, the order status updates automatically. + + + +### Charge a Saved Card + +For orders placed by returning customers who have saved cards: + +1. Go to **J2Commerce** -> **Orders** and open the order. +2. If the customer has saved cards, a **Charge Card** section appears below the order summary. +3. Select a card from the dropdown. +4. Enter the amount to charge (defaults to the order total). +5. Click **Charge**. + +This is useful for manual reorders, phone orders, or collecting additional payment for shipping adjustments. + + + +### Webhook-Triggered Updates + +If webhooks are configured, Stripe can update order statuses automatically: + +| Stripe Event | What happens in J2Commerce | +|-------------|---------------------------| +| `payment_intent.succeeded` | Order status updated to Confirmed | +| `payment_intent.payment_failed` | Order status updated to Failed | +| `payment_intent.canceled` | Order status updated to Canceled | +| `charge.refunded` | Order status updated to Refunded (if enabled) | +| `charge.dispute.created` | Warning logged in the application log | + +--- + +## Saved Cards (Customer Profile) + +When **Allow Saved Cards** is enabled, customers can manage their saved cards: + +1. Log in to the frontend. +2. Go to **My Account** -> **Payment Methods** (or **Stripe Cards** tab). +3. View all saved cards with last 4 digits and expiry. +4. Delete cards they no longer want stored. + + + +--- + +## Going Live Checklist + +Before accepting real payments, confirm the following: + +- [ ] **Sandbox** is set to **No** +- [ ] Your live **Publishable Key** and **Secret Key** are entered +- [ ] The webhook URL is registered in your live Stripe Dashboard +- [ ] The **Webhook Secret** (signing secret) is saved in the plugin settings +- [ ] You have placed a test order using a real card with a small amount and then refunded it +- [ ] **Debug Mode** is set to **No** +- [ ] Payment methods you want to use are enabled in your Stripe Dashboard + +--- + +## Troubleshooting + +### "No such payment intent" error at checkout + +**Cause:** The Payment Intent was not created correctly, or the API keys are mismatched. + +**Solution:** +1. Verify that your **Publishable Key** and **Secret Key** are from the same Stripe account (both live or both test). +2. Check that you are using live keys when **Sandbox** is **No**, and test keys when **Sandbox** is **Yes**. +3. Enable **Debug Mode** and check `administrator/logs/payment_stripe.php` for the full error. + +### Payment succeeds but order stays Pending + +**Cause:** Webhooks are not configured, so J2Commerce does not receive the payment confirmation from Stripe. + +**Solution:** +1. Register the webhook URL in your Stripe Dashboard (see [Webhooks](#webhooks) above). +2. Enter the **Webhook Secret** (signing secret) in the plugin settings. +3. For Hosted mode, the order status is also updated during the redirect — check if the customer completed the redirect. + +### "Currency not supported" error + +**Cause:** Your store's active currency is not supported by the selected payment method. + +**Solution:** +1. Stripe supports 135+ currencies, but some payment methods have restrictions. +2. Check the Stripe documentation for your payment method's supported currencies. +3. Consider using a currency switcher plugin to offer multiple currencies. + +### Credit card form does not appear at checkout + +**Cause:** The Publishable Key is missing, incorrect, or the plugin is not enabled. + +**Solution:** +1. Go to **J2Commerce** -> **Payments** -> **Payment Methods** and confirm Stripe is enabled. +2. Check that a **Publishable Key** (or **Sandbox Publishable Key** if in sandbox mode) is entered. +3. Enable **Debug Mode** and check the browser console for JavaScript errors. + +### Refund fails with an error + +**Cause:** The Payment Intent ID is missing from the order, or the charge has already been fully refunded. + +**Solution:** +1. Open the order and check that a **Transaction ID** is recorded. +2. If the Transaction ID is empty, the payment may not have been captured correctly. Check the debug log. +3. Log in to your Stripe Dashboard and verify the payment status there. + +### Dashboard shows "Stripe is in Sandbox mode" warning + +**Cause:** **Sandbox** is set to **Yes**. + +**Solution:** If you are ready to go live, open the Stripe plugin settings and switch **Sandbox** to **No**, then enter your live credentials. + +### Saved cards not showing at checkout + +**Cause:** **Allow Saved Cards** is disabled, or the customer is not logged in. + +**Solution:** +1. Verify **Allow Saved Cards** is set to **Yes** in the plugin settings. +2. Saved cards require a logged-in customer with a Stripe customer ID. +3. Check that the customer has previously saved a card in their profile. + +### Stripe Link not appearing + +**Cause:** **Enable Link** is disabled, or the customer doesn't have Link enabled in their Stripe account. + +**Solution:** +1. Verify **Enable Link** is set to **Yes** in the plugin settings. +2. Stripe Link requires the customer to have previously used Link with their email address on any Stripe-powered site. + +--- + +## Support + +For help with the Stripe plugin: + +- **J2Commerce documentation:** [docs.j2commerce.com](https://docs.j2commerce.com) +- **J2Commerce support:** [www.j2commerce.com](https://www.j2commerce.com) +- **Stripe Dashboard:** [dashboard.stripe.com](https://dashboard.stripe.com) +- **Stripe documentation:** [stripe.com/docs](https://stripe.com/docs) +- **Stripe support:** [support.stripe.com](https://support.stripe.com) From 9a1089b7c22386e16f7cd29948cfb7f3d14a7dd2 Mon Sep 17 00:00:00 2001 From: Adam Melcher <54608117+newlinewebdesign@users.noreply.github.com> Date: Mon, 23 Mar 2026 08:54:16 -0500 Subject: [PATCH 2/4] docs(developer): add saved payment methods event and update payment profiles New pages: - Saved Payment Methods Event (onJ2CommerceGetSavedPaymentMethods) developer guide Updated pages: - Payment Profiles Table (added unified tab integration section) --- .../plugins/payment/payment_profiles.md | 49 ++- .../plugins/payment/saved_methods_event.md | 318 ++++++++++++++++++ 2 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 website/developer-v6/extensions/plugins/payment/saved_methods_event.md diff --git a/website/developer-v6/extensions/plugins/payment/payment_profiles.md b/website/developer-v6/extensions/plugins/payment/payment_profiles.md index 1f19e726..0c652cf1 100644 --- a/website/developer-v6/extensions/plugins/payment/payment_profiles.md +++ b/website/developer-v6/extensions/plugins/payment/payment_profiles.md @@ -56,7 +56,7 @@ The UNIQUE constraint on `(user_id, provider, environment)` enforces exactly one Use lowercase identifiers with no spaces or special characters: | Gateway | `provider` value | -|---------|-----------------| +|---------|------------------| | Authorize.Net | `authorizenet` | | Stripe | `stripe` | | Square | `square` | @@ -140,6 +140,52 @@ $db->setQuery($query)->execute(); Run this in the plugin's `onExtensionBeforeUninstall` handler only if your privacy policy requires it. The table itself must not be dropped. +## Displaying Saved Payment Methods + +J2Commerce provides a unified "Payment Methods" tab in the customer's My Account profile. Instead of each payment plugin creating its own tab, all saved payment methods appear in a single consolidated view. + +### Unified Tab Integration + +To display your saved payment methods in the unified tab, implement the `onJ2CommerceGetSavedPaymentMethods` event in your payment plugin. Return structured data about each payment method: + +```php +public function onGetSavedPaymentMethods(Event $event): void +{ + $userId = $event->getArgument('user_id', 0); + + if ($userId < 1 || !(int) $this->params->get('allow_saved_cards', 1)) { + return; + } + + $customerProfileId = $this->getCustomerProfileId($userId); + if (!$customerProfileId) { + return; + } + + $methods = $this->fetchPaymentMethodsFromGateway($customerProfileId); + $result = $event->getArgument('result', []); + + foreach ($methods as $method) { + $result[] = [ + 'id' => $method->id, + 'provider' => 'yourplugin', + 'type' => 'card', + 'display_name' => ucfirst($method->brand) . ' ending in ' . $method->last4, + 'brand' => strtolower($method->brand), + 'last4' => $method->last4, + 'exp_month' => $method->expMonth, + 'exp_year' => $method->expYear, + 'is_default' => $method->isDefault, + 'actions' => ['delete', 'set_default'], + ]; + } + + $event->setArgument('result', $result); +} +``` + +See [Saved Payment Methods Event](./saved_methods_event.md) for complete implementation details. + ## Migration from J2Store If the previous J2Store installation stored Authorize.Net profiles in `#__j2store_payment_profiles`, migrate them with: @@ -160,5 +206,6 @@ Adjust the `WHERE` clause and `provider` mapping for any other gateways stored i ## Related +- [Saved Payment Methods Event](./saved_methods_event.md) - Unified Payment Methods tab integration - [Payment Plugin Development](../index.md) - [Order Lifecycle](../../../features/payments/index.md) diff --git a/website/developer-v6/extensions/plugins/payment/saved_methods_event.md b/website/developer-v6/extensions/plugins/payment/saved_methods_event.md new file mode 100644 index 00000000..b2b5987f --- /dev/null +++ b/website/developer-v6/extensions/plugins/payment/saved_methods_event.md @@ -0,0 +1,318 @@ +--- +title: "onJ2CommerceGetSavedPaymentMethods Event" +sidebar_label: "Saved Payment Methods Event" +sidebar_position: 15 +description: "Event for payment plugins to return structured payment method data for the unified Payment Methods tab." +--- + +# onJ2CommerceGetSavedPaymentMethods Event + +## Overview + +The `onJ2CommerceGetSavedPaymentMethods` event allows payment plugins to return structured payment method data for display in the unified "Payment Methods" tab in the customer's My Account profile. + +## When to Use + +Implement this event when your payment plugin supports: +- Saved credit/debit cards +- Stored payment methods (wallets, bank accounts) +- Customer payment profiles + +Plugins that do NOT implement this event will continue using the legacy `onJ2CommerceMyProfileTab` and `onJ2CommerceMyProfileTabContent` events for separate tabs. + +## Event Registration + +Add the event to your plugin's `getSubscribedEvents()` method: + +```php +public static function getSubscribedEvents(): array +{ + return [ + // ... other events ... + 'onJ2CommerceGetSavedPaymentMethods' => 'onGetSavedPaymentMethods', + ]; +} +``` + +## Event Handler Signature + +```php +public function onGetSavedPaymentMethods(Event $event): void +{ + $userId = $event->getArgument('user_id', 0); + + // Skip if not enabled or user not logged in + if ($userId < 1 || !(int) $this->params->get('allow_saved_cards', 1)) { + return; + } + + // Get saved payment methods from your gateway + $methods = $this->getSavedMethodsFromGateway($userId); + + // Build result array + $result = $event->getArgument('result', []); + + foreach ($methods as $method) { + $result[] = [ + 'id' => $method->id, + 'provider' => 'your_plugin_name', + 'type' => 'card', + 'display_name' => 'Visa ending in 4242', + 'brand' => 'visa', + 'last4' => '4242', + 'exp_month' => 12, + 'exp_year' => 2025, + 'icon' => null, // Optional: custom icon URL + 'is_default' => true, + 'actions' => ['delete', 'set_default'], + 'metadata' => [], + ]; + } + + $event->setArgument('result', $result); +} +``` + +## PaymentMethodData Structure + +Return an array of associative arrays with these keys: + +| Key | Type | Required | Description | +|-----|------|----------|-------------| +| `id` | string | Yes | Unique payment method identifier from your gateway | +| `provider` | string | Yes | Your plugin identifier (lowercase, no spaces) | +| `type` | string | Yes | Payment type: `card`, `bank_account`, `wallet`, etc. | +| `display_name` | string | Yes | Human-readable label (e.g., "Visa ending in 4242") | +| `brand` | string | No | Card brand (visa, mastercard, amex, discover) | +| `last4` | string | No | Last 4 digits of card/account | +| `exp_month` | int | No | Expiration month (1-12) | +| `exp_year` | int | No | Expiration year (4-digit) | +| `icon` | string | No | Custom icon URL (uses default brand icon if null) | +| `is_default` | bool | Yes | Whether this is the customer's default payment method | +| `actions` | array | Yes | Available actions: `['delete']`, `['delete', 'set_default']`, etc. | +| `metadata` | array | No | Provider-specific data (not displayed to user) | + +## Brand Icon Resolution + +The core component automatically provides brand icons for common card types: + +| Brand | Icon Path | +|-------|----------| +| visa | `media/com_j2commerce/images/payment-methods/visa.svg` | +| mastercard | `media/com_j2commerce/images/payment-methods/mastercard.svg` | +| amex | `media/com_j2commerce/images/payment-methods/amex.svg` | +| discover | `media/com_j2commerce/images/payment-methods/discover.svg` | +| (default) | `media/com_j2commerce/images/payment-methods/generic-card.svg` | + +To provide a custom icon, set the `icon` key with a full URL path. + +## Provider Naming Convention + +Use consistent lowercase identifiers: + +| Gateway | `provider` value | +|---------|------------------| +| Stripe | `stripe` | +| Authorize.net | `authorizenet` | +| PayTrace | `paytrace` | +| Square | `square` | +| Braintree | `braintree` | +| PayPal | `paypal` | + +## AJAX Actions + +The unified Payment Methods tab uses your plugin's existing AJAX endpoints. Ensure these are implemented: + +### Delete Card + +``` +POST index.php?option=com_ajax&plugin={your_plugin}&task=deleteCard&format=json +``` + +Parameters: +- `{csrf_token}`: Form token value +- `payment_method_id`: The payment method ID to delete + +Response: +```json +{ + "success": true +} +// or +{ + "success": false, + "error": "Error message to display" +} +``` + +### Set Default (Optional) + +``` +POST index.php?option=com_ajax&plugin={your_plugin}&task=setDefaultCard&format=json +``` + +Parameters: +- `{csrf_token}`: Form token value +- `payment_method_id`: The payment method ID to set as default + +## Example: Complete Implementation + +```php + 'onGetPaymentPlugins', + 'onJ2CommerceGetPaymentOptions' => 'onGetPaymentOptions', + 'onJ2CommercePrePayment' => 'onPrePayment', + 'onJ2CommercePostPayment' => 'onPostPayment', + 'onJ2CommerceGetSavedPaymentMethods' => 'onGetSavedPaymentMethods', + 'onAjaxPayment_yourplugin' => 'onAjaxHandler', + ]; + } + + public function onGetSavedPaymentMethods(Event $event): void + { + $userId = $event->getArgument('user_id', 0); + + // Skip if feature disabled + if (!(int) $this->params->get('allow_saved_cards', 1)) { + return; + } + + // Must have logged-in user + if ($userId < 1) { + return; + } + + try { + // Get customer profile from your gateway + $customerProfile = $this->getCustomerProfile($userId); + + if (!$customerProfile) { + return; + } + + // Get payment methods from gateway + $paymentMethods = $this->fetchPaymentMethods($customerProfile); + + $result = $event->getArgument('result', []); + + foreach ($paymentMethods as $pm) { + $result[] = [ + 'id' => $pm->id, + 'provider' => 'yourplugin', + 'type' => 'card', + 'display_name' => ucfirst($pm->brand) . ' ending in ' . $pm->last4, + 'brand' => strtolower($pm->brand), + 'last4' => $pm->last4, + 'exp_month' => (int) $pm->expMonth, + 'exp_year' => (int) $pm->expYear, + 'icon' => null, + 'is_default' => (bool) $pm->isDefault, + 'actions' => ['delete', 'set_default'], + 'metadata' => [ + 'customer_profile_id' => $customerProfile->id, + ], + ]; + } + + $event->setArgument('result', $result); + + } catch (\Throwable $e) { + // Log error but don't throw - other plugins should still work + $this->logError('GetSavedPaymentMethods failed: ' . $e->getMessage()); + } + } + + public function onAjaxHandler(Event $event): void + { + $app = Factory::getApplication(); + $task = $app->input->getCmd('task', ''); + $user = $app->getIdentity(); + + // Authentication check + if (!$user || $user->guest) { + $event->setArgument('result', [json_encode([ + 'success' => false, + 'error' => 'Not authenticated', + ])]); + return; + } + + // CSRF check + if (!Session::checkToken('request')) { + $event->setArgument('result', [json_encode([ + 'success' => false, + 'error' => 'Invalid token', + ])]); + return; + } + + $result = match ($task) { + 'deleteCard' => $this->deletePaymentMethod($user->id, $app->input->getString('payment_method_id')), + 'setDefaultCard' => $this->setDefaultMethod($user->id, $app->input->getString('payment_method_id')), + default => ['success' => false, 'error' => 'Unknown task'], + }; + + $event->setArgument('result', [json_encode($result)]); + } + + private function deletePaymentMethod(int $userId, string $methodId): array + { + // Implementation specific to your gateway + // ... + + return ['success' => true]; + } + + private function setDefaultMethod(int $userId, string $methodId): array + { + // Implementation specific to your gateway + // ... + + return ['success' => true]; + } + + // ... other methods +} +``` + +## Backward Compatibility + +If your plugin currently uses `onJ2CommerceMyProfileTab` and `onJ2CommerceMyProfileTabContent`: + +1. Implement `onJ2CommerceGetSavedPaymentMethods` for the unified tab +2. Keep legacy handlers but have them return empty results +3. The core will use the unified tab when any plugin provides data via the new event + +```php +// Legacy handlers (empty for unified tab) +public function onMyProfileTab(Event $event): void +{ + // Return empty - using unified Payment Methods tab +} + +public function onMyProfileTabContent(Event $event): void +{ + // Return empty - using unified Payment Methods tab +} +``` + +## Related + +- [Payment Profiles Table](./payment_profiles.md) - Database table for customer profiles +- [Payment Plugin Development](./index.md) - General payment plugin guide From 2ebece467496bf472ee0dff057acb92259f2a674 Mon Sep 17 00:00:00 2001 From: Adam Melcher <54608117+newlinewebdesign@users.noreply.github.com> Date: Mon, 23 Mar 2026 08:54:41 -0500 Subject: [PATCH 3/4] docs: remove PayPal from payment/ (moved to payment-methods/) --- website/docs-v6/payment/payment_paypal.md | 335 ---------------------- 1 file changed, 335 deletions(-) delete mode 100644 website/docs-v6/payment/payment_paypal.md diff --git a/website/docs-v6/payment/payment_paypal.md b/website/docs-v6/payment/payment_paypal.md deleted file mode 100644 index 961b7613..00000000 --- a/website/docs-v6/payment/payment_paypal.md +++ /dev/null @@ -1,335 +0,0 @@ ---- -title: "PayPal Payment" -sidebar_label: "PayPal" -sidebar_position: 10 -description: "Accept PayPal payments in your J2Commerce store using PayPal Smart Payment Buttons and the REST API v2." ---- - -# PayPal Payment - -The PayPal plugin lets your customers pay using PayPal's Smart Payment Buttons — a modern, secure checkout experience that supports PayPal accounts, credit cards, and other payment methods PayPal offers in your customers' region. - -The plugin uses PayPal's REST API v2, so no redirects are needed. Customers complete payment directly on your checkout page without leaving your site. Refunds, webhook notifications, and sandbox testing are all built in. - -## Prerequisites - -- J2Commerce installed and active on your Joomla site -- A PayPal Business account (see the setup steps below) -- REST API credentials (Client ID and Client Secret) from the PayPal Developer Dashboard - ---- - -## Step 1: Set Up a PayPal Business Account - -If you already have a PayPal Business account and REST API credentials, skip ahead to [Installation & Enabling](#installation--enabling). - -### Create a PayPal Business Account - -1. Go to [paypal.com](https://www.paypal.com) and click **Sign Up**. -2. Choose **Business Account** and click **Next**. -3. Enter your email address and create a password. -4. Fill in your business details — business name, address, and phone number. -5. Verify your email address when PayPal sends you a confirmation email. -6. Complete the identity verification steps PayPal requires (this varies by country). - -### Get Your REST API Credentials - -After your account is active: - -1. Go to [developer.paypal.com](https://developer.paypal.com) and log in with your PayPal Business account. -2. Click **Apps & Credentials** in the top navigation. -3. Make sure you are on the **Live** tab (not Sandbox). -4. Click **Create App**. -5. Give the app a name — for example, "My Store". -6. Click **Create App** to confirm. -7. On the next page you will see your **Client ID** and **Client Secret**. Copy both and keep them somewhere safe. - - - -**Sandbox credentials** (for testing): Click the **Sandbox** tab on the same Apps & Credentials page. Create a separate sandbox app or use the default one. Copy the Sandbox Client ID and Sandbox Client Secret separately. - ---- - -## Installation & Enabling - -The PayPal plugin ships with J2Commerce 6 and is available immediately after installation. Because it requires your merchant credentials before it can process payments, it is not enabled automatically during installation. - -To enable it: - -1. Go to **J2Commerce** -> **Payments** -> **Payment Methods**. -2. Find **PayPal** in the list. -3. Click the toggle in the **Enabled** column to enable the plugin, or click the plugin name to open its settings first. - - - ---- - -## Configuration - -Go to **J2Commerce** -> **Payments** -> **Payment Methods** and click **PayPal** to open the settings. - - - -### Display Settings - -| Field | Description | Default | -|-------|-------------|---------| -| **Display Name** | The label shown to customers at checkout | `PayPal` | -| **Display Image** | Optional logo or image shown next to the payment option at checkout | _(none)_ | - -### Sandbox Mode - -| Field | Description | Default | -|-------|-------------|---------| -| **Use PayPal Sandbox** | Switch this on to use PayPal's test environment. No real money is processed. | No | - -Turn sandbox mode **on** while you are setting up and testing. Turn it **off** before you go live. - -When sandbox mode is active, a warning banner appears on the J2Commerce dashboard so you cannot accidentally forget. - -### Live API Credentials - -These are used when **Use PayPal Sandbox** is set to **No**. - -| Field | Description | -|-------|-------------| -| **Client ID** | Your live REST API Client ID from [developer.paypal.com](https://developer.paypal.com) | -| **Client Secret** | Your live REST API Client Secret | - -### Sandbox API Credentials - -These are used when **Use PayPal Sandbox** is set to **Yes**. - -| Field | Description | -|-------|-------------| -| **Sandbox Client ID** | Your sandbox REST API Client ID | -| **Sandbox Client Secret** | Your sandbox REST API Client Secret | - -### Webhooks (Optional but Recommended) - -Webhooks allow PayPal to notify your store automatically when payment events occur — for example, when a payment completes, is refunded, or is disputed. Without webhooks, order status updates only happen when the customer completes checkout on your page. - -| Field | Description | -|-------|-------------| -| **Webhook ID** | The Webhook ID from your live PayPal app in the developer dashboard | -| **Sandbox Webhook ID** | The Webhook ID from your sandbox PayPal app | - -**How to create a webhook in PayPal:** - -1. In the PayPal Developer Dashboard, open your app. -2. Scroll down to **Webhooks** and click **Add Webhook**. -3. Enter your webhook URL. The URL format for J2Commerce is: `https://yoursite.com/index.php?option=com_j2commerce&task=checkout.processWebhook&payment_method=payment_paypal` -4. Select the events you want to receive. Recommended events: `PAYMENT.CAPTURE.COMPLETED`, `PAYMENT.CAPTURE.DENIED`, `PAYMENT.CAPTURE.REFUNDED`, `PAYMENT.CAPTURE.REVERSED`, `CUSTOMER.DISPUTE.CREATED`, `CUSTOMER.DISPUTE.RESOLVED`. -5. Click **Save**. Copy the **Webhook ID** shown and paste it into the plugin configuration. - - - -### Order Status - -| Field | Description | Default | -|-------|-------------|---------| -| **Order Status** | The order status applied after a successful payment capture | `Confirmed` | - -Choose the status that fits your workflow. Most stores use **Confirmed** or **Processing** for paid orders. - -### Surcharge - -Add an optional surcharge to orders paid via PayPal. This is useful if you want to pass on PayPal's processing fee to customers (check your local laws and PayPal's terms before doing this). - -| Field | Description | Default | -|-------|-------------|---------| -| **Surcharge Name** | Label shown to customers for the surcharge (e.g., "PayPal Fee") | _(none)_ | -| **Surcharge Percent** | Percentage of the order subtotal added as a surcharge | _(none)_ | -| **Surcharge Fixed** | Fixed amount added as a surcharge | _(none)_ | -| **Surcharge Tax Class** | Tax profile to apply to the surcharge amount | _(none)_ | - -You can combine a percentage and a fixed amount — both will be added together. - -### Geo-Zone Restriction - -| Field | Description | Default | -|-------|-------------|---------| -| **Geo-Zone Restriction** | Limit PayPal availability to customers in a specific geo-zone | _(none — available everywhere)_ | - -Leave this empty to show PayPal to all customers regardless of location. - -### Order Amount Limits - -| Field | Description | Default | -|-------|-------------|---------| -| **Minimum Subtotal** | Hide PayPal if the cart subtotal is below this amount. Leave empty for no minimum. | _(none)_ | -| **Maximum Subtotal** | Hide PayPal if the cart subtotal exceeds this amount. Leave empty or set to `-1` for no maximum. | _(none)_ | - -### Thank You Page - -| Field | Description | -|-------|-------------| -| **Thank You Article** | Select a Joomla article to display after a successful payment. This is shown on the confirmation page in addition to the standard confirmation message. | - -### Custom Messages - -These text fields let you customize messages shown to customers at different points in the payment process. - -| Field | When it displays | -|-------|-----------------| -| **On Selection** | When the customer selects PayPal as their payment method | -| **On Before Payment** | On the payment page before the customer clicks Pay | -| **On After Payment** | On the confirmation page after a successful payment | -| **On Error Payment** | When a payment error occurs | -| **On Cancel Payment** | When the customer cancels payment and returns to the cart | - -### Dashboard Icon - -| Field | Description | Default | -|-------|-------------|---------| -| **Show Dashboard Icon** | Show a shortcut icon for PayPal on the J2Commerce dashboard | No | -| **Dashboard Icon Label** | Label for the dashboard icon (only visible when Show Dashboard Icon is Yes) | _(none)_ | - -### Subtemplate - -| Field | Description | Default | -|-------|-------------|---------| -| **Subtemplate** | Select an alternative layout template for the PayPal payment form, if any are installed | _(default)_ | - -### Debug Mode - -| Field | Description | Default | -|-------|-------------|---------| -| **Debug Mode** | Write detailed PayPal API activity to `administrator/logs/payment_paypal.php` and the browser console | No | - -Enable debug mode only while troubleshooting. Disable it in production — logs can grow large quickly. - ---- - -## Supported Currencies - -PayPal does not support every currency. If your store uses a currency not in this list, PayPal will not be available at checkout. - -Supported currencies: AUD, BRL, CAD, CNY, CZK, DKK, EUR, HKD, HUF, INR, ILS, JPY, MYR, MXN, TWD, NZD, NOK, PHP, PLN, GBP, RUB, SGD, SEK, CHF, THB, USD. - ---- - -## Checkout Experience - -When a customer selects PayPal at checkout: - -1. The PayPal Smart Payment Buttons load on the page. -2. The customer clicks their preferred option — **PayPal**, credit card, or any other method PayPal offers in their region. -3. A PayPal login window (or card form) appears. The customer completes payment. -4. The payment is captured immediately. -5. The customer is returned to your confirmation page. - - - -Payment happens without the customer leaving your site. The PayPal popup or inline experience handles authentication securely. - -If the customer clicks **Cancel** in the PayPal window, they are returned to checkout and the cart remains intact. The cancellation message you configured is displayed. - ---- - -## Order Management - -Once a customer pays, J2Commerce records the transaction details against the order: - -- **Order status** is updated to the status you configured (default: Confirmed). -- **Transaction ID** — the PayPal capture ID — is stored with the order. -- **Order history** is updated with a "Payment received via PayPal" note. - -### Refunds - -You can issue a refund directly from the order in the J2Commerce admin: - -1. Go to **J2Commerce** -> **Orders** and open the order. -2. Click the **Refund** button. -3. Enter the amount to refund (leave blank to refund the full amount). -4. Confirm the refund. - -The refund is sent to PayPal via the API. The order status is updated and a note is added to the order history. - -### Webhook-Triggered Updates - -If webhooks are configured, PayPal can update order statuses automatically for events that happen outside the normal checkout flow: - -| PayPal Event | What happens in J2Commerce | -|-------------|---------------------------| -| Payment capture completed | Order status updated to the configured "Confirmed" state | -| Payment capture pending | Order status updated to Pending | -| Payment capture denied | Order status updated to Failed | -| Payment refunded | Order status updated to Refunded | -| Payment reversed (chargeback) | Order status updated to Failed, flagged for review in order history | -| Dispute created | Warning logged in the application log | -| Dispute resolved | Resolution logged in the application log | - -Webhook events are deduplicated — if PayPal sends the same event twice, it is processed only once. - ---- - -## Going Live Checklist - -Before accepting real payments, confirm the following: - -- [ ] **Use PayPal Sandbox** is set to **No** -- [ ] Your live **Client ID** and **Client Secret** are entered -- [ ] The webhook URL is registered in your live PayPal app and the **Webhook ID** is saved -- [ ] You have placed a test order using a real PayPal account with a small amount and then refunded it -- [ ] **Debug Mode** is set to **No** - ---- - -## Troubleshooting - -### PayPal buttons do not appear at checkout - -**Cause:** The Client ID is missing or incorrect, or the plugin is not enabled. - -**Solution:** -1. Go to **J2Commerce** -> **Payments** -> **Payment Methods** and confirm PayPal is enabled. -2. Check that a Client ID (or Sandbox Client ID if in sandbox mode) is entered. -3. Enable **Debug Mode** and check the browser console for error messages. - -### "PayPal plugin is not properly configured" message - -**Cause:** The Client ID field is empty. - -**Solution:** Open the PayPal plugin settings and enter your Client ID and Client Secret. - -### Payments go through in PayPal but the order stays Pending - -**Cause:** Webhooks are not configured, so J2Commerce does not receive the payment confirmation from PayPal. - -**Solution:** -1. Set up a webhook in your PayPal app (see [Webhooks](#webhooks-optional-but-recommended) above). -2. Enter the Webhook ID in the plugin settings. -3. Alternatively, the order status is also updated during the capture step — if the customer completed checkout successfully, check whether the order status was set at that time. - -### "Currency not supported" error - -**Cause:** Your store's active currency is not in PayPal's supported currency list. - -**Solution:** Switch your store to a [supported currency](#supported-currencies) or configure a separate currency for PayPal-eligible customers. - -### Refund fails with an error - -**Cause:** The PayPal capture ID is missing from the order, or the transaction has already been refunded. - -**Solution:** -1. Open the order and check that a Transaction ID is recorded. -2. If the Transaction ID is empty, the payment may not have been captured correctly. Check the debug log. -3. Log in to your PayPal Business account and verify the transaction status there. - -### Dashboard shows "PayPal is in Sandbox mode" warning - -**Cause:** **Use PayPal Sandbox** is set to **Yes**. - -**Solution:** If you are ready to go live, open the PayPal plugin settings and switch **Use PayPal Sandbox** to **No**, then enter your live credentials. - ---- - -## Support - -For help with the PayPal plugin: - -- **J2Commerce documentation:** [docs.j2commerce.com](https://docs.j2commerce.com) -- **J2Commerce support:** [www.j2commerce.com](https://www.j2commerce.com) -- **PayPal Developer Dashboard:** [developer.paypal.com](https://developer.paypal.com) -- **PayPal Business support:** [paypal.com/support](https://www.paypal.com/support) From 54ea159438dbb4e5413ac9fcee9b1544f9c626f4 Mon Sep 17 00:00:00 2001 From: Adam Melcher Date: Fri, 3 Apr 2026 06:38:56 -0500 Subject: [PATCH 4/4] docs: add Product Reviews app user guide Adds comprehensive user guide for the app_reviews add-on plugin. Covers installation, all settings sections (basic, display, style, submission, security, email, rich snippets), review moderation, per-product overrides, CSV import, analytics, and troubleshooting. --- .../apps-and-extensions/apps/app-gdpr.md | 236 ++++++++++++ .../apps/app-profileorder.md | 161 ++++++++ .../apps-and-extensions/apps/app-reviews.md | 313 ++++++++++++++++ .../apps/app-validationrules.md | 187 ++++++++++ .../apps-and-extensions/apps/app-wishlist.md | 229 ++++++++++++ .../apps-and-extensions/apps/pdfinvoices.md | 241 ++++++++++++ .../apps/productcompare.md | 202 ++++++++++ .../apps-and-extensions/apps/quantityprice.md | 205 ++++++++++ .../apps/subscriptionproduct.md | 353 ++++++++++++++++++ .../apps-and-extensions/apps/taxrate.md | 233 ++++++++++++ .../apps-and-extensions/apps/usergroup.md | 169 +++++++++ .../mod_j2commerce_wishlist.md | 111 ++++++ 12 files changed, 2640 insertions(+) create mode 100644 website/docs-v6/apps-and-extensions/apps/app-gdpr.md create mode 100644 website/docs-v6/apps-and-extensions/apps/app-profileorder.md create mode 100644 website/docs-v6/apps-and-extensions/apps/app-reviews.md create mode 100644 website/docs-v6/apps-and-extensions/apps/app-validationrules.md create mode 100644 website/docs-v6/apps-and-extensions/apps/app-wishlist.md create mode 100644 website/docs-v6/apps-and-extensions/apps/pdfinvoices.md create mode 100644 website/docs-v6/apps-and-extensions/apps/productcompare.md create mode 100644 website/docs-v6/apps-and-extensions/apps/quantityprice.md create mode 100644 website/docs-v6/apps-and-extensions/apps/subscriptionproduct.md create mode 100644 website/docs-v6/apps-and-extensions/apps/taxrate.md create mode 100644 website/docs-v6/apps-and-extensions/apps/usergroup.md create mode 100644 website/docs-v6/apps-and-extensions/mod_j2commerce_wishlist.md diff --git a/website/docs-v6/apps-and-extensions/apps/app-gdpr.md b/website/docs-v6/apps-and-extensions/apps/app-gdpr.md new file mode 100644 index 00000000..00bae302 --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/app-gdpr.md @@ -0,0 +1,236 @@ +--- +title: "GDPR Compliance" +sidebar_label: "GDPR Compliance" +sidebar_position: 55 +description: "Give customers control over their personal data with checkout terms, activity logging, address deletion, and GDPR data request forms." +--- + +# GDPR Compliance + +The GDPR app brings data privacy compliance features to J2Commerce. It gives customers meaningful control over their personal data stored in your shop, and helps you meet obligations under GDPR and similar privacy regulations. + +Key features include: + +- Terms and conditions checkbox or link at checkout (billing or payment step) +- Customer self-service buttons to delete saved addresses and order address records +- Activity log that records every address edit and deletion +- Email notifications to store admins and customers when data changes +- Optional GDPR data request form on the My Profile page +- IP address removal from carts and orders + +## Requirements + +- PHP 8.3+ +- Joomla! 6.x +- J2Commerce 6.x + +## Purchase and Download + +The **GDPR** app is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce 6 component. + +**Step 1:** Go to the [J2Commerce website](https://www.j2commerce.com/) -> **Apps**. + +**Step 2:** Locate the **GDPR** app -> click **View Details** -> **Add to cart** -> **Checkout**. + +**Step 3:** Go to **My Downloads** under your profile menu at the top right corner and search for the app. Click **Available Versions** -> **View Files** -> **Download**. + +## Install the App + +In the Joomla Administrator, go to **System** -> **Install** -> **Extensions**. + +Upload the plugin ZIP file or use the **Install from URL** option. + +## Enable the App + +Once installed, you must enable the app. There are two ways to access it: + +**Option A:** Click the **J2Commerce** icon at the top right corner -> **Apps**. + +**Option B:** Go to the left sidebar -> **Components** -> **J2Commerce** -> **Apps**. + +Find the **GDPR** app in the list and click **Enable**. + + + +## Configuration + +Open the GDPR app settings by clicking its name in the Apps list. + + + +### Email Notifications + +| Setting | Description | Default | +|---------|-------------|---------| +| **Notify store administrators about data changes** | Send an email to the admin addresses below whenever a customer edits or deletes address data | Yes | +| **Store administrator emails** | Comma-separated list of admin email addresses to notify | *(empty)* | +| **Notify the customer about data changes** | Send a confirmation email to the customer when they change their own data | No | + +### Activity Logging + +| Setting | Description | Default | +|---------|-------------|---------| +| **Log customer edit and delete activities** | Record every address edit and deletion in the GDPR activity log | No | + +When enabled, all changes are stored in the activity log viewable from the J2Commerce Apps page. + +### IP Address Removal + +| Setting | Description | Default | +|---------|-------------|---------| +| **Remove customer IP address from cart and order** | Strip the IP address field from new cart and order records at the time they are created | No | + +:::note +IP removal only applies to **new** carts and orders created after the setting is enabled. Existing records are not retroactively modified. +::: + +### General Requirements + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable GDPR tab in My Profile** | Show a GDPR data request form as a tab on the customer My Profile page | No | +| **GDPR terms and conditions** | Show or hide terms and conditions at checkout | Yes | +| **Show terms for registered customers** | Include terms display for logged-in customers | Yes | +| **Show terms for guest customers** | Include terms display for guest checkout | Yes | +| **Terms display position** | Choose whether terms appear at the **Billing** step or the **Payment** step | Payment | +| **Terms display type** | Show terms as a **Link** (informational) or a **Checkbox** (required to proceed) | Link | +| **Terms and conditions article** | Select the Joomla article that contains your privacy policy or GDPR terms | *(none)* | + +### Terms Label Customisation + +These three fields control the text displayed around the terms link at checkout. They support Joomla language key strings or plain text. + +| Setting | Description | Default value | +|---------|-------------|---------------| +| **Terms prefix text** | Text before the clickable link | `I agree to` | +| **Terms link label** | The clickable link text | `the privacy policy` | +| **Terms suffix text** | Text after the clickable link | *(terms and conditions)* | +| **Validation error message** | Message shown when the customer does not tick the checkbox | `Please accept our GDPR terms and conditions.` | + +### Customer Buttons + +| Setting | Description | Default | +|---------|-------------|---------| +| **Show delete all addresses button** | Display a button on the My Profile page allowing customers to delete all their saved addresses | Yes | + +## Debug Mode + +| Setting | Description | Default | +|---------|-------------|---------| +| **Debug Mode** | Write detailed log entries to `administrator/logs/app_gdpr.php` | No | + +Enable Debug Mode temporarily when troubleshooting. Disable it in production to avoid filling your log directory. + +--- + +## How It Works + +### Terms and Conditions at Checkout + +When **GDPR terms and conditions** is enabled, a notice (or required checkbox) appears at the checkout step you configured — Billing or Payment. + +- **Link display type:** The terms text and link are shown as information only. The customer can click the link to read the full article in a modal window. Checkout is not blocked. +- **Checkbox display type:** The customer must tick the checkbox to continue. If they try to proceed without ticking it, an inline error message is shown. + + + +### Customer Address Deletion + +When the **Show delete all addresses button** setting is enabled, a red **Delete all my addresses** button appears on the My Profile page above the address list. When a customer clicks it: + +1. All their saved addresses are deleted from the database. +2. An activity log entry is written (if logging is enabled). +3. Admin and customer notification emails are sent (if enabled). +4. The customer is redirected back to My Profile with a confirmation message. + + + +### GDPR Data Request Tab + +When the **Enable GDPR tab in My Profile** setting is enabled, a **GDPR Request** tab appears on the My Profile page. Customers can type a free-text message and submit it to the store admin. + +The request is saved to the activity log and — if admin email notifications are enabled — sends an email to the store administrator with the customer's message. + + + +### Activity Log + +When **Log customer edit and delete activities** is enabled, the plugin records entries in a private database table. Each entry stores: + +- Date and time +- Customer email +- Whether it was an address change or order address removal +- A short description of what changed + +You can view the activity log from the J2Commerce Apps page by clicking the GDPR app name and navigating to the log view. + + + +--- + +## Setting Up Terms and Conditions + +### Step 1: Create a Privacy Policy Article + +1. In the Joomla Administrator, go to **Content** -> **Articles** -> **New**. +2. Write your GDPR privacy policy or terms and conditions. +3. Save the article and note its ID (shown in the article list). + +### Step 2: Link the Article to the Plugin + +1. Go to **J2Commerce** -> **Apps** -> **GDPR** settings. +2. In the **Terms and conditions article** field, click the **Select** button and choose your article. +3. Set **Terms display type** to **Checkbox** if you require acceptance. +4. Set **Terms display position** to where you want the terms to appear (**Billing** or **Payment**). +5. Click **Save**. + +### Step 3: Verify at Checkout + +Visit your store's checkout as a test customer and confirm the terms text and link appear at the expected step. + +--- + +## Troubleshooting + +### Terms are not appearing at checkout + +**Cause:** The **GDPR terms and conditions** setting may be disabled, or the position setting does not match the step you are checking. + +**Solution:** + +1. Open the GDPR app settings. +2. Confirm **GDPR terms and conditions** is set to **Show**. +3. Confirm **Terms display position** matches the step where you expect terms to appear. +4. If using **Checkbox** display, confirm the correct step's validation is completing without errors from other plugins. + +### The delete address button is not visible on My Profile + +**Cause:** The **Show delete all addresses button** setting may be disabled, or the customer has no saved addresses. + +**Solution:** + +1. Confirm **Show delete all addresses button** is set to **Show** in the plugin settings. +2. Log in as a test customer who has at least one saved address. The button only appears when addresses exist. + +### Admin notification emails are not arriving + +**Cause:** The admin email addresses may be missing or incorrectly formatted, or Joomla's mail settings may be misconfigured. + +**Solution:** + +1. Open the GDPR app settings and verify the **Store administrator emails** field contains valid comma-separated addresses with no spaces. +2. Go to **System** -> **Global Configuration** -> **Server** tab and confirm the mail settings are working by using the **Send Test Mail** option. + +### GDPR request form submissions are not saving + +**Cause:** The form requires a CSRF token. If the session has expired or the page was cached, the token may be invalid. + +**Solution:** Ask the customer to refresh the My Profile page and submit the form again. If the problem persists, check that Joomla page caching is not enabled for the My Profile view. + +--- + +## Related Topics + +- [Change Password](app_changepasswords.md) +- [Gift Wrapping](app-giftwrapping.md) +- [Validation Rules](app-validationrules.md) diff --git a/website/docs-v6/apps-and-extensions/apps/app-profileorder.md b/website/docs-v6/apps-and-extensions/apps/app-profileorder.md new file mode 100644 index 00000000..9a5a5a6b --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/app-profileorder.md @@ -0,0 +1,161 @@ +--- +title: "Pay Later / Pay Against Invoice" +sidebar_label: "Pay Later" +sidebar_position: 10 +description: "Allow customers to complete payment for an unpaid order after checkout by showing a Pay Now button on their order history page." +--- + +# Pay Later / Pay Against Invoice + +The **Pay Later** app adds a **Pay Now** button to the customer's order history page. When a customer places an order but does not immediately complete payment — for example, when using a bank transfer or invoice gateway — this button lets them return and pay whenever they are ready, within a time window you define. + +This is especially useful for stores that offer invoice-based purchasing, bank transfers, or any payment method that is not confirmed in real time at checkout. + +## Prerequisites + +- J2Commerce is installed and enabled +- At least one payment method plugin is installed and enabled + +## Installation + +This plugin is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce component. + +1. Purchase and download the `app_profileorder` package from the J2Commerce website. Log in, go to your account, and find the download under **My Downloads**. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload the plugin ZIP file. + + + +The plugin installs automatically. + +## Enable the Plugin + +After installation, the plugin must be enabled before it will work. + +1. Go to **J2Commerce** -> **Apps**. +2. Find **Pay Later / Pay Against Invoice** in the list. +3. Click the status toggle to enable it. The toggle turns green when the plugin is active. + + + +## Configure the Plugin + +Click the **Pay Later / Pay Against Invoice** title to open the plugin settings. + + + +### Basic Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Show Pay Button After (Seconds)** | How long to wait after an order is placed before showing the Pay Now button. This prevents the button from appearing while a gateway is still processing a callback. | `20` | +| **Pay Button Expires After (Days)** | The number of days after the order is placed when the Pay Now button stops appearing. Set to `0` for no expiry. | `10` | +| **Pay Button Text** | Custom label for the Pay Now button. Leave blank to use the default "Pay" text. | *(blank)* | +| **Order Statuses** | The Pay Now button only appears for orders with these statuses. Leave empty to show the button for orders in any status. | *(all)* | +| **Debug Mode** | Writes detailed log entries to `administrator/logs/app_profileorder.php`. Turn this off on a live store once you have finished testing. | `No` | + +### Choosing Order Statuses + +The **Order Statuses** setting is one of the most important things to configure. You almost always want to restrict the button to statuses that mean the order is genuinely unpaid — for example **Pending** or **Pending Payment** — and exclude statuses like **Completed**, **Processing**, or **Cancelled**. + +1. Click inside the **Order Statuses** field. +2. Select one or more statuses from the dropdown. +3. Save the plugin settings. + +Leaving the field empty shows the Pay Now button on orders in any status, which may not be what you want. + + + +## How It Works + +### The Customer Experience + +1. A customer places an order at checkout without completing payment — for example, they select "Bank Transfer" and close the browser, or their payment gateway session expires. +2. Later, the customer logs in and goes to **My Account** -> **My Orders** to view their order history. +3. For orders that meet the configured conditions, a **Pay** button appears next to the order. + + + +4. The customer clicks the **Pay** button. A payment selection page opens in a new browser tab. + + + +5. The customer selects a payment method and clicks **Continue**. +6. An order summary is shown, along with the payment form from the selected payment plugin (for example, a Stripe credit card form). + + + +7. The customer completes payment. The order is updated in J2Commerce exactly as if the payment had been made at checkout. + +### When the Pay Button Appears + +The Pay Now button is shown only when all three of the following conditions are met: + +1. The order's status matches one of the configured **Order Statuses** (or the setting is empty, meaning all statuses are allowed). +2. The configured **interval time** has passed since the order was placed — this prevents the button from appearing while a gateway callback may still be in flight. +3. The order was placed within the configured **expiry** window — the button will not appear for orders older than this limit. + +:::info Example + +With the default settings (20-second delay, 10-day expiry), the Pay Now button appears on orders that are at least 20 seconds old and no more than 10 days old. + +::: + +### Zero-Total Orders + +If an order has a total of zero (for example, a fully discounted order), the payment selection step is skipped. The customer is taken directly to the order confirmation page and can click **Place Order** to complete it without entering payment details. + +## Tips + +- Set a higher **interval time** if you use asynchronous payment gateways such as PayPal or Stripe Webhooks. A value of 60–300 seconds gives the gateway enough time to deliver its callback before the Pay Now button appears, reducing the risk of double payments. +- Set **Pay Button Expires After** to match your payment terms. For example, use `30` if invoices must be paid within 30 days. +- Restrict **Order Statuses** to only the statuses that represent genuinely unpaid orders. This prevents the Pay Now button appearing on orders that are already paid or cancelled. +- Pair this plugin with an offline or invoice payment method to create a full pay-by-invoice workflow: customers receive an invoice email at checkout and return to pay when they are ready. + +## Troubleshooting + +### The Pay Now button does not appear on any orders + +**Cause:** The plugin may not be enabled, or no orders match the configured conditions. + +**Solution:** + +1. Go to **J2Commerce** -> **Apps** and confirm **Pay Later / Pay Against Invoice** is enabled (green toggle). +2. Check **Order Statuses** — if specific statuses are selected, the test order must have one of those statuses. +3. Check **Show Pay Button After (Seconds)** — the button will not appear until that many seconds have elapsed since the order was placed. +4. Check **Pay Button Expires After (Days)** — the order may be older than the configured expiry window. +5. Clear the Joomla cache: **Home Dashboard** -> **Manage Cache** -> **Delete All**. + +### The payment page opens blank or shows an error + +**Cause:** The CSRF security token in the link has expired, or the order ID is invalid. + +**Solution:** + +1. Ask the customer to refresh the order history page to generate a fresh link, then click Pay again. +2. Confirm the customer is logged in — guest users cannot use this feature. +3. Enable **Debug Mode** in the plugin settings and check the log at `administrator/logs/app_profileorder.php` for a detailed error message. + +### Clicking Pay shows "Invalid order or access denied" + +**Cause:** The order does not belong to the currently logged-in user, or no order ID was passed to the page. + +**Solution:** + +1. Confirm the customer is logged in to the correct account. +2. Check that the order was originally placed by that same user account. +3. Review the debug log for more details. + +### No payment methods appear on the payment selection page + +**Cause:** No payment plugins are enabled, or all available plugins have filtered out this order. + +**Solution:** + +1. Go to **J2Commerce** -> **Payments** -> **Payment Methods** and confirm at least one payment plugin is enabled. +2. Check each payment plugin's own settings — some plugins restrict payments by order total, geozone, or customer group, which may exclude the order. + +## Related Topics + +- [Payment Methods](../../payment-methods/index.md) +- [Easy Reorder](./app_reorder.md) diff --git a/website/docs-v6/apps-and-extensions/apps/app-reviews.md b/website/docs-v6/apps-and-extensions/apps/app-reviews.md new file mode 100644 index 00000000..c4e30fc5 --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/app-reviews.md @@ -0,0 +1,313 @@ +--- +title: "Product Reviews" +sidebar_label: "Product Reviews" +sidebar_position: 60 +description: "Let customers submit star ratings and written reviews on product pages — with email review requests, image uploads, spam protection, rich snippet support, and a full admin moderation dashboard." +keywords: [j2commerce, product reviews, star ratings, customer reviews, review moderation, review emails] +--- + +# Product Reviews + +The Product Reviews app lets customers submit star ratings and written reviews directly on your product pages. Reviews appear below the product with a summary showing the average rating and star distribution. Store owners can moderate submissions, respond to reviews, and trigger automated email requests after purchase. + +Key capabilities include image uploads per review, Google reCAPTCHA spam protection, structured data (JSON-LD) for Google rich snippets, CSV import for existing reviews, review analytics, and a customizable HTML review request email. + +## Requirements + +- PHP 8.3.0+ +- Joomla! 6.x +- J2Commerce 6.x + +## Purchase and Download + +The **Product Reviews** app is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce 6 component. + +1. Go to the [J2Commerce website](https://www.j2commerce.com) -> **Apps**. +2. Locate the **Product Reviews** app -> click **View Details** -> **Add to cart** -> **Checkout**. +3. Download the `app_reviews.zip` file from your account downloads. + +## Installation + +1. Go to **System** -> **Install** -> **Extensions**. +2. Upload the `app_reviews.zip` package file. +3. The plugin installs and enables automatically. + +## Enable and Configure + +1. Go to **J2Commerce** -> **Apps**. +2. Find **Product Reviews** in the list and click its title to open settings. + + + +## Settings Reference + +### Basic Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable Reviews** | Turn review functionality on or off globally | Yes | +| **Auto-Approve Reviews** | Publish new reviews immediately without moderation | No | +| **Login Requirement** | Whether customers must be logged in to submit | Optional | +| **Prevent Duplicate Reviews** | Block the same user from reviewing the same product twice | Yes | +| **Enable Quick Icon** | Show a quick-access icon in the Joomla administrator dashboard | No | + +### Display Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Product Display Stars** | Where to show the star summary on product detail pages | After product title | +| **Category Display Stars** | Where to show the star summary in category listing views | — | +| **Show Average Rating** | Display the numeric average alongside stars in the summary | Yes | +| **Clickable Star Rating** | Make the review count a link that scrolls to the reviews section | Yes | +| **Show Rating Distribution** | Show the breakdown bar chart (5-star, 4-star, etc.) | Yes | +| **Show User Reviews Tab** | Add a tab on the customer profile page listing their submitted reviews | Yes | +| **Reviews Per Page** | Number of reviews to show per page in the list | 10 | +| **Default Sort Order** | Initial sort when the reviews list loads | Most Recent | +| **Form Display Mode** | Show the review form inline on the page or in a modal popup | Inline | + +### Style Settings + +| Setting | Description | +|---------|-------------| +| **Theme Color** | Accent color applied to buttons and interactive elements | +| **Star Color** | Color for filled star icons | +| **Custom CSS** | Additional CSS rules applied to all review output | + +### Submission Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Minimum Review Length** | Minimum characters required in review text | 10 | +| **Maximum Review Length** | Maximum characters allowed in review text | 5000 | +| **Require Review Content** | Make the text field mandatory (rating is always required) | No | +| **Enable Review Title** | Allow reviewers to add a short title to their review | Yes | +| **Enable Image Uploads** | Allow customers to attach photos to their review | No | +| **Maximum Images** | Maximum number of images per review | 3 | +| **Maximum Image Size (MB)** | Maximum file size per uploaded image | 5 | +| **Allowed File Extensions** | Comma-separated list of accepted image formats | jpg, jpeg, png, gif, webp | +| **Convert to WebP** | Automatically convert uploaded images to WebP format | Yes | +| **WebP Quality** | Quality level for WebP conversion (50–100) | 85 | +| **Maximum Image Width** | Maximum width in pixels for stored images | 1200 | +| **Maximum Image Height** | Maximum height in pixels for stored images | 1200 | +| **Thumbnail Width** | Width of generated thumbnails | 300 | +| **Thumbnail Height** | Height of generated thumbnails | 300 | + +### Security Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable reCAPTCHA** | Add Google reCAPTCHA to the review form | No | +| **reCAPTCHA Type** | Version to use: v2 (checkbox) or v3 (invisible) | v2 | +| **reCAPTCHA Site Key** | Your Google reCAPTCHA public site key | — | +| **reCAPTCHA Secret Key** | Your Google reCAPTCHA private secret key | — | +| **reCAPTCHA v3 Threshold** | Minimum score for v3 (0.0–1.0, higher = stricter) | 0.5 | +| **Rate Limit (Per Hour)** | Maximum review submissions per user per hour | 3 | +| **Enable Honeypot** | Add a hidden field to catch spam bots | Yes | +| **Disable For Logged In Users** | Skip reCAPTCHA for logged-in customers | Yes | + +### Email Settings + +The app can automatically send review request emails to customers after their order reaches a specific status. + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable Review Requests** | Send automated post-purchase review request emails | No | +| **Trigger Order Status** | Which order status triggers the email | Completed | +| **Request Delay (Days)** | Days to wait after trigger status before sending | 7 | +| **Token Expiration (Days)** | Days the one-click review link in the email remains valid | 30 | +| **Admin Notification** | Email admins when a new review is submitted | No | +| **Admin Email Addresses** | Addresses to notify (one per line) — leave blank for site admin | — | +| **Customer Approval Email** | Email customers when their review is approved | No | +| **Brand Logo** | Your store logo displayed in review request emails | — | + +#### Setting Up the Cron Job + +Emails are sent via a cron job, not immediately on order status change. + +1. In the **Email Settings** fieldset, copy the **Cron URL** displayed there. +2. Set up a cron job on your server to call that URL every 30–60 minutes: + +```bash +*/30 * * * * curl -s "https://yoursite.com/index.php?option=com_j2commerce&..." > /dev/null +``` + +The cron processes the queue and sends pending emails once the configured delay has passed. + +#### Customizing the Email + +Click the **Email Editor** tab within the plugin settings to edit the subject line and HTML body of the review request email. + +Available shortcodes you can use in the subject and body: + +| Shortcode | Replaced With | +|-----------|---------------| +| `[CUSTOMER_NAME]` | Customer full name | +| `[CUSTOMER_FNAME]` | Customer first name | +| `[PRODUCT_NAME]` | Product name | +| `[PRODUCT_SKU]` | Product SKU | +| `[PRODUCT_LINK]` | Link to the product page | +| `[REVIEW_LINK]` | Direct link to leave a review | +| `[REVIEW_LINK_1]` through `[REVIEW_LINK_5]` | Pre-filled rating links (1–5 stars) | +| `[ORDER_ID]` | Order ID | +| `[ORDER_DATE]` | Order date | +| `[STORE_NAME]` | Your store name | +| `[STORE_URL]` | Your store URL | + +Click **Send Test Email** to preview the email against a real product in your store. + +#### UTM Tracking + +Add UTM parameters to review links in emails to track campaign performance in Google Analytics: + +| Field | Example Value | +|-------|---------------| +| **UTM Source** | `j2commerce` | +| **UTM Medium** | `email` | +| **UTM Campaign** | `review_request` | +| **UTM Content** | *(optional differentiator)* | + +### Google Rich Snippets + +When enabled, the app outputs JSON-LD structured data on product pages so Google can display star ratings in search results. + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable Rich Snippets** | Output JSON-LD on product pages with reviews | No | +| **Integrate with Schema.org Ecommerce Plugin** | Inject review data into a co-installed schema plugin instead of outputting standalone schema | No | +| **Minimum Reviews** | Minimum approved reviews required before schema is added | 1 | +| **Include Individual Reviews** | Add individual review details to the structured data | Yes | +| **Maximum Individual Reviews** | Number of individual reviews to include in the schema | 10 | +| **Include Product Variants** | Add ProductGroup schema for products with variants | No | +| **Include Merchant Listing** | Add pricing and availability to the schema | No | +| **Brand Name** | Default brand for structured data (leave blank if not applicable) | — | +| **Default Currency Code** | ISO 4217 currency code for pricing in schema (e.g., USD, EUR) | — | + +## Managing Reviews + +Go to **J2Commerce** -> **Apps** -> **Product Reviews** -> **Reviews** to access the review management screen. + + + +### Review Statuses + +| Status | Meaning | +|--------|---------| +| **Pending** | Submitted but not yet reviewed by a moderator | +| **Approved** | Visible on the product page | +| **Rejected** | Hidden from the public but kept in the database | +| **Spam** | Identified as spam, hidden from public | + +### Moderating Reviews + +- Click the **Approve** or **Reject** button in the Actions column for individual reviews. +- Use the **Bulk Actions** dropdown to approve, reject, mark as spam, or delete multiple selected reviews at once. +- Filter by status, rating, or product using the toolbar dropdowns. + +### Editing a Review + +Click **Edit Review** to open the full edit form. You can: + +- Change the rating, title, and content +- Write a **Store Response** that appears publicly below the review +- Update the reviewer's name, email, and associated user +- Add or remove review images +- Toggle **Verified Purchase** status +- Change the review status + + + +## Enabling Reviews Per Product + +By default the global **Enable Reviews** setting controls all products. You can override this on individual products: + +1. Edit a product in **J2Commerce** -> **Catalog** -> **Products**. +2. Scroll to the **Reviews** tab in the product form. +3. Set **Enable Reviews for this Product** to **Yes** or **No** to override the global default. + +## Importing Reviews + +The app includes a CSV import tool to migrate reviews from another platform. + +1. Go to **J2Commerce** -> **Apps** -> **Product Reviews** -> **Import**. +2. Choose the **Product Identifier** — either **Product ID** or **SKU**. +3. Set the **Default Status** for imported reviews that have no status column. +4. Enable **Skip Duplicate Reviews** to avoid re-importing reviews by the same email for the same product. +5. Download the **Sample CSV** to see the required format. +6. Upload your CSV file and click **Start Import**. + +### Required CSV Columns + +| Column | Required | Description | Example | +|--------|----------|-------------|---------| +| `product_id` | If using Product ID | J2Commerce product ID | `42` | +| `sku` | If using SKU | Product SKU code | `SHIRT-L-BLU` | +| `reviewer_name` | Yes | Reviewer full name | `Jane Smith` | +| `reviewer_email` | Yes | Reviewer email address | `jane@example.com` | +| `rating` | Yes | Star rating 1–5 | `5` | +| `review_title` | No | Short title | `Great product!` | +| `review_content` | No | Full review text | `Arrived quickly...` | +| `status` | No | `pending`, `approved`, `rejected`, or `spam` | `approved` | +| `verified` | No | `1` for verified purchase, `0` otherwise | `1` | +| `created` | No | Date created (YYYY-MM-DD HH:MM:SS) | `2025-03-15 09:00:00` | +| `order_id` | No | Associated order ID | `1001` | +| `helpful` | No | Helpful vote count | `12` | + +## Analytics + +Go to **J2Commerce** -> **Apps** -> **Product Reviews** -> **Analytics** for a summary of review activity including: + +- Total, pending, and approved review counts +- Average rating +- Email engagement metrics (sent, engaged, pending, expired) +- Star distribution chart +- Reviews by source (product page, email, profile, backend, import) +- Device breakdown (desktop, mobile, tablet) +- User type breakdown (registered vs. guest) +- Top reviewers +- Most reviewed products +- Top rated products + + + +## Troubleshooting + +### Reviews Not Appearing on Product Pages + +**Cause:** The app is enabled but **Enable Reviews** is set to No, or the individual product has reviews disabled. + +**Solution:** +1. In the plugin settings, confirm **Enable Reviews** is set to **Yes**. +2. Edit the product and check the **Reviews** tab — if an override is set to **No**, change it to **Yes** or remove the override. + +### Review Request Emails Not Sending + +**Cause:** No cron job is configured, or the queue has not yet accumulated emails ready to send. + +**Solution:** +1. Confirm **Enable Review Requests** is turned on in **Email Settings**. +2. Verify the cron job is running and the URL is correct. +3. Check that enough days have passed since the order reached the trigger status — emails are held until the **Request Delay** period expires. +4. Enable **Debug Mode** in the plugin settings and check the Joomla log file at `administrator/logs/app_reviews.php` for error messages. + +### reCAPTCHA Not Working + +**Cause:** Invalid site key or secret key, or the domain is not registered in your Google reCAPTCHA console. + +**Solution:** +1. Verify your keys at [https://www.google.com/recaptcha/admin](https://www.google.com/recaptcha/admin). +2. Confirm the domain of your Joomla site is listed under **Domains** in the reCAPTCHA settings. +3. If using v3, try lowering the **reCAPTCHA v3 Threshold** if legitimate submissions are being blocked. + +### Rich Snippets Not Appearing in Google Search + +**Cause:** Google may take days or weeks to re-crawl and index updated structured data. + +**Solution:** +1. Test your product page in Google's [Rich Results Test tool](https://search.google.com/test/rich-results). +2. Confirm **Enable Rich Snippets** is on and the product has at least the number of approved reviews set in **Minimum Reviews**. +3. If using the Schema.org Ecommerce plugin integration, confirm that plugin is installed and active. + +## Related Topics + +- [Apps and Extensions](../index.md) +- [Products](../../catalog/index.md) diff --git a/website/docs-v6/apps-and-extensions/apps/app-validationrules.md b/website/docs-v6/apps-and-extensions/apps/app-validationrules.md new file mode 100644 index 00000000..4819b1c2 --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/app-validationrules.md @@ -0,0 +1,187 @@ +--- +title: "Data Validation" +sidebar_label: "Data Validation" +sidebar_position: 20 +description: "Configure custom validation rules for checkout fields in J2Commerce — enforce formats like email, phone, postal code, length limits, and field matching." +--- + +# Data Validation + +The Data Validation app lets you enforce custom rules on your checkout fields. You can require that customers enter a valid phone number, a correctly formatted email address, a postal code that matches their country, or that a confirmation field matches another field exactly. Rules can apply to any combination of checkout steps — Billing, Shipping, Payment, and Register. + +This app works with J2Commerce's custom checkout fields. You must have at least one enabled custom field before you can configure any rules. + +## Requirements + +- PHP 8.3.0 or higher +- Joomla! 6.x +- J2Commerce 6.x +- At least one enabled custom checkout field + +## Installation + +This plugin is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce 6 component. + +1. Purchase and download the `plg_j2commerce_app_validationrules.zip` package from the J2Commerce website. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload the ZIP file. The plugin installs and enables automatically. + + + +## Enable the Plugin + +If the plugin did not enable automatically after installation: + +1. Go to **System** -> **Manage** -> **Extensions**. +2. Search for **Data Validation**. +3. Click the status toggle to enable it (it turns green). + +You can also reach the plugin from **J2Commerce** -> **Apps**. Search for **Data Validation** and enable it there. + + + +## Open the Plugin Settings + +1. Go to **J2Commerce** -> **Apps**. +2. Find **Data Validation** in the list and click its title to open the settings. +3. Select the **Rules** tab. + + + +## Configure Validation Rules + +The **Rules** tab shows a table with one row for each of your enabled custom checkout fields. Each row has three columns: + +| Column | Purpose | +|--------|---------| +| **Custom Fields** | Shows the field name and its internal key | +| **Rules Apply For** | Which checkout steps these rules run on | +| **Rules** | The individual validation rules for this field | + +### Step 1: Choose which checkout steps the rules apply to + +In the **Rules Apply For** column, select one or more steps where you want the rules enforced: + +- **Billing** — the billing address step +- **Shipping** — the shipping address step +- **Payment** — the payment step +- **Register** — the registration step during checkout + +You must select at least one option before you can save rules for that field. If no step is selected, the rules are ignored even if they are configured. + + + +### Step 2: Add rules + +In the **Rules** column for a field, click **Add Rules**. A new row appears with two dropdowns: + +- **Rule** — select the type of validation +- **Rule Value** — provide any required value (for example, the maximum number of characters) + +You can add multiple rules to a single field. Click **Add Rules** again to add another rule row. + + + +### Step 3: Save + +Click the **Apply** button at the bottom of the form to save all rules. The rules are saved via AJAX — you do not need to leave or reload the page. + + + +## Available Rule Types + +| Rule | What it does | Requires a value? | +|------|-------------|-------------------| +| **Match Field** | Requires this field to equal another custom field (e.g., confirm email) | Yes — select the field to match | +| **Max Length** | Fails if the entered text exceeds the character limit | Yes — enter the maximum number of characters | +| **Min Length** | Fails if the entered text is shorter than the minimum | Yes — enter the minimum number of characters | +| **Numeric** | Field must contain only digits | No | +| **Alphabet** | Field must contain only letters (a–z, A–Z) | No | +| **Alphanumeric** | Field must contain only letters and digits | No | +| **Phone** | Field must match a phone number pattern (digits, spaces, `+`, `(`, `)`, `-`) | No | +| **Email** | Field must be a valid email address | No | +| **Postal/Zip Code Validation** | Validates the postal code against the format for the customer's selected country (85+ countries supported) | No | +| **Match Table Field** | Checks that the entered value exists in a column of a database table | Yes — select the table and column | + +### Match Field + +Use this rule when you want a customer to type a value twice — for example, an email address confirmation. Set the **Rule Value** to the other custom field that this field must match. + +If the values do not match, the customer sees: "Field A does not match with Field B." + +### Match Table Field + +This rule queries a database table and checks whether the entered value exists in the column you specify. After selecting the **Match Table Field** rule type, a **Table** dropdown appears. Select the table, and then select the **Column** from a second dropdown that loads automatically. + +Use this rule carefully — it allows access to any database table visible to J2Commerce. Restrict it to tables with trusted, non-sensitive data. + +## Error Messages Shown to Customers + +| Rule | Error message shown | +|------|-------------------| +| Match Field | "[Field A] does not match with [Field B]" | +| Max Length | "Maximum allowed length is [N]" | +| Min Length | "Minimum length [N] required" | +| Numeric | "Field value must be numeric" | +| Alphabet | "Field value must be alphabet" | +| Alphanumeric | "Field value must be alphanumeric" | +| Phone | "Field value must be a valid phone number" | +| Email | "Field value must be a valid email" | +| Postal/Zip Code | "Invalid Postal/Zip Code Format" | +| Match Table Field | "Enter data not available" | + +## Advanced: Debug Mode + +The plugin includes a **Debug Mode** option on the **Advanced** tab. When enabled, the plugin writes detailed log entries to the Joomla log directory. + +Turn debug mode on only when you are troubleshooting. Disable it in production to avoid unnecessary disk usage. + + + +## Tips + +- A custom field must be **enabled** in J2Commerce for it to appear in the Rules tab. If you do not see a field in the list, check that it is enabled under **J2Commerce** -> **Custom Fields**. +- The **Postal/Zip Code** rule reads the country the customer selected on the billing or shipping form. The validation pattern is chosen automatically based on the country. +- You can combine multiple rules on a single field — for example, both **Min Length** and **Alphanumeric** on a coupon code field. +- Rules only run on the checkout steps you select in **Rules Apply For**. A rule assigned only to Billing will not run on the Shipping step, even for the same field. + +## Troubleshooting + +### No fields appear in the Rules tab + +**Cause:** No enabled custom checkout fields exist in your shop. + +**Solution:** Go to **J2Commerce** -> **Custom Fields** and create or enable at least one field. Return to **J2Commerce** -> **Apps** -> **Data Validation** -> **Rules** tab and the fields will appear. + +### Rules are not running at checkout + +**Cause:** No checkout step is selected in the **Rules Apply For** column for that field, or the field is not displayed on the step being validated. + +**Solution:** +1. Open the Data Validation plugin settings and go to the **Rules** tab. +2. Check that at least one step (Billing, Shipping, Payment, or Register) is selected for the field. +3. Confirm the custom field itself is configured to display on that step — check the field's display settings in **J2Commerce** -> **Custom Fields**. +4. Click **Apply** to save. + +### Postal code validation always fails + +**Cause:** The country selected by the customer does not match the postal code format, or the billing country field was not submitted with the form. + +**Solution:** Verify that the billing country dropdown is included in your checkout form. The plugin reads the submitted `country_id` value to select the correct postal pattern. If the country is not submitted, postal validation is skipped. + +### Debug logs are not appearing + +**Cause:** Debug mode may be disabled, or the Joomla log directory is not writable. + +**Solution:** +1. Open the plugin settings and go to the **Advanced** tab. +2. Switch **Debug Mode** to **Yes**. +3. Click **Save**. +4. Complete a checkout to trigger the validation events. +5. Check the Joomla log directory (configured under **System** -> **Global Configuration** -> **Server** -> **Path to Log Folder**). + +## Related Topics + +- [Custom Fields](../../configuration/custom-fields.md) +- [Checkout Configuration](../../checkout/index.md) +- [Apps and Extensions](../index.md) diff --git a/website/docs-v6/apps-and-extensions/apps/app-wishlist.md b/website/docs-v6/apps-and-extensions/apps/app-wishlist.md new file mode 100644 index 00000000..cbd0b118 --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/app-wishlist.md @@ -0,0 +1,229 @@ +--- +title: "Wishlist" +sidebar_label: "Wishlist" +sidebar_position: 15 +description: "Let customers save products to a personal wishlist and add them to the cart later — with guest support, session migration on login, and configurable buttons." +--- + +# Wishlist + +The Wishlist app lets customers save products for later without adding them to the cart immediately. A heart icon or text button appears on product pages and product list views. Customers can view their full wishlist, add individual items or all items to the cart, and remove items they no longer want. + +Guest shoppers can build a wishlist without logging in. When they log in, their guest wishlist automatically merges with their account. + +## Requirements + +- PHP 8.3.0+ +- Joomla! 6.x +- J2Commerce 6.x + +## Purchase and Download + +The **Wishlist** app is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce 6 component. + +1. Go to the [J2Commerce website](https://www.j2commerce.com) -> **Apps**. +2. Locate the **Wishlist** app -> click **View Details** -> **Add to cart** -> **Checkout**. +3. Download the `app_wishlist.zip` file from your account downloads. + +## Installation + +1. Go to **System** -> **Install** -> **Extensions**. +2. Upload the `app_wishlist.zip` package file. +3. The plugin installs and enables automatically. + + + +## Configuration + +After installation, go to **J2Commerce** -> **Apps** and click **Wishlist** to open the plugin settings. + + + +### Settings + +| Setting | Description | Default | Notes | +|---------|-------------|---------|-------| +| **Wishlist button type** | Display the button as **Text** or **Icon** | Text | Choosing **Icon** reveals the two icon fields below | +| **Button text** | Label for the add-to-wishlist button. Accepts a plain string or a language key. | Add to Wishlist | Visible only when type is **Text** | +| **Icon CSS class** | Font Awesome class for the button (e.g., `fa-solid fa-heart`) | `fa-solid fa-heart` | Visible only when type is **Icon** | +| **Added to wishlist icon** | Font Awesome class shown when the item is already saved | `fa-solid fa-heart` | Visible only when type is **Icon** | +| **Remove after adding to cart** | Automatically remove a wishlist item when it is added to the cart | No | | +| **Link products to** | Where product links on the wishlist page lead: **Product List Layout** or **Article Layout** | Product List Layout | | +| **Thumbnail width** | Width in pixels for product images on the wishlist page | 50 | | +| **Redirect to wishlist** | Redirect the customer to the wishlist page immediately after adding an item | No | | +| **Wishlist link text** | Text for the "browse wishlist" link in the add confirmation notification | Browse wishlist | | +| **Debug Mode** | Write debug entries to the Joomla log directory. Disable in production. | No | | + +Click **Save** to apply your settings. + +## Creating the Wishlist Menu Item + +The wishlist page is displayed through a dedicated Joomla menu item. You must create this menu item before the wishlist page is accessible to customers. + +1. Go to **Menus** -> **[Your Menu]** -> **Add New Menu Item**. +2. Click **Select** next to **Menu Item Type**. +3. Choose **J2Commerce** -> **Wishlist**. +4. Set a **Menu Title** (for example, "My Wishlist"). +5. Click **Save & Close**. + + + +The plugin automatically detects this menu item to build wishlist links throughout the store. If no menu item exists, the plugin falls back to a direct URL, but product "browse wishlist" links may not be SEF. + +## Setting Up the Wishlist Module + +The companion **J2Commerce - Wishlist** module (`mod_j2commerce_wishlist`) shows the current wishlist item count and a link to the wishlist page. Place it in your header or navigation area so customers can always see how many items they have saved. + +The wishlist module is also a separate add-on and is not included in the core J2Commerce 6 package. Purchase it from the [J2Commerce Extensions Store](https://www.j2commerce.com). + +### Installing the Module + +1. Go to **System** -> **Install** -> **Extensions**. +2. Upload the `mod_j2commerce_wishlist.zip` file. +3. Go to **Content** -> **Site Modules** -> **New**. +4. Select **J2Commerce - Wishlist** from the module type list. + + + +### Module Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **Display type** | Show the counter as a plain **Link** or as a styled **Button** | Link | +| **Hide when empty** | Hide the module entirely when the wishlist has no items | No | +| **Wishlist menu item** | Select the menu item created above. Leave empty for auto-detection. | (empty) | + +### Module Position + +Assign the module to the position in your template where the header or navigation icons appear. For most Bootstrap 5 and UIkit templates, the `nav-right` or `header` position works well. + + + +### Live Count Updates + +The module updates its count automatically when a customer adds or removes a wishlist item — no page reload needed. It listens for the `j2commerce:wishlist:updated` browser event dispatched by the wishlist plugin after every change. + +## How It Works + +### Adding Products to the Wishlist + +Once the plugin is enabled, an **Add to Wishlist** button appears in two locations: + +- **Product detail page** — directly below the Add to Cart button +- **Product list views** — as a compact icon button in the cart action row + + + +Customers click the button to save the product. After adding, the button changes to an "already in wishlist" state and a short notification appears with a link to the wishlist page. + +For variable products with options (such as size or colour), the customer must select their options before adding to the wishlist. The exact options chosen are saved with the wishlist entry. + +If a customer tries to add a variable product without selecting options first, they see the message: "Please select product options before adding to wishlist." + +### Viewing the Wishlist + +Customers visit the wishlist page through the menu item you created. The page shows a table with: + +- Product thumbnail, name, and any saved options +- An **Add to Cart** button for each item +- A **Remove** (trash icon) button for each item +- A **Select All** checkbox and per-row checkboxes for bulk actions +- **Add all to cart** and **Remove all items** buttons that appear when items are checked +- A **Continue Shopping** button that returns to the previous page + + + +### Guest Customers — Save Wishlist Prompt + +Customers who are browsing as guests see a **Save wishlist** button at the bottom of their wishlist page. Clicking it takes them to the Joomla login page. Once they log in, their session wishlist automatically migrates to their account. + +This prompt only appears when the wishlist contains at least one item and the visitor is not logged in. + +### Bulk Actions + +Customers can select multiple items using the checkboxes. When any item is checked, the bulk action buttons appear: + +- **Add all to cart** — adds every checked item to the shopping cart +- **Remove all items** — removes every checked item from the wishlist + +If **Remove after adding to cart** is enabled in settings, items automatically leave the wishlist when they enter the cart. + +### Guest Wishlist and Login Migration + +Customers who are not logged in can still add products to a wishlist. The wishlist is stored against their browser session. When the customer logs in, their session wishlist automatically migrates to their account — no items are lost. + +If the logged-in account already has the same product in the wishlist, the duplicate is silently discarded so the wishlist stays clean. + +## Tips + +- Set **Wishlist button type** to **Icon** on stores with compact product list layouts to keep the cart row tidy. +- Leave **Remove after adding to cart** off (the default) if you want customers to be able to add the same wishlist item to the cart more than once. +- If your template already uses a heart icon for another purpose, change the **Icon CSS class** to something else (for example, `fa-solid fa-bookmark`) to avoid confusion. +- Enable **Redirect to wishlist** if you want customers taken to their wishlist immediately after adding an item — useful for gift registry workflows. +- Set the **Wishlist menu item** in the module settings explicitly rather than relying on auto-detection. Auto-detection scans all menu items, which adds a small overhead on every page load. +- Enable **Hide when empty** on the module to keep the header uncluttered until a customer has saved at least one item. + +## What's New in J2Commerce + +The J2Commerce Wishlist app includes several improvements over the J2Store version: + +- **Live count updates** — the wishlist module refreshes its counter instantly when items are added or removed, without any page reload. J2Store required a full page reload. +- **Icon-only mode for list views** — a dedicated icon layout keeps product list rows compact. In J2Store the same text button appeared everywhere. +- **Guest migration on login** — guest wishlist entries now migrate automatically using Joomla's standard user login events, making the flow more reliable across different authentication plugins. +- **Bootstrap 5 layout** — the wishlist page and all buttons use Bootstrap 5 markup and classes natively. J2Store used Bootstrap 3/4 markup. +- **Select All and bulk actions** — customers can check all items and add or remove them in a single click. J2Store required item-by-item actions. +- **Save wishlist login prompt** — guests see a contextual prompt to log in and save their wishlist rather than losing items at session end. + +## Troubleshooting + +### The Add to Wishlist button does not appear + +**Cause:** The plugin may not be enabled, or the product template does not fire the `AfterAddToCartButton` event. + +**Solution:** + +1. Go to **System** -> **Manage** -> **Extensions** and confirm the Wishlist plugin is enabled. +2. Check that your active template plugin (app_bootstrap5 or app_uikit) is also enabled. +3. If you have customised the product cart template (`default_cart.php`), make sure it includes the `AfterAddToCartButton` event call. + +### The wishlist page shows a blank page or "No items" + +**Cause:** The wishlist menu item has not been created, or it points to the wrong task. + +**Solution:** + +1. Confirm you have created a menu item of type **J2Commerce -> Wishlist** (see [Creating the Wishlist Menu Item](#creating-the-wishlist-menu-item)). +2. Check that the menu item is published. +3. If the page renders but shows "No items", the customer may not have added anything yet, or the plugin is not recording additions. Enable **Debug Mode** in settings and check the Joomla logs directory for `j2commerce` log entries. + +### The module count does not update after adding an item + +**Cause:** The module may be cached, or the `j2commerce:wishlist:updated` browser event is not reaching the module. + +**Solution:** + +1. Open the module settings and set **Caching** to **No Caching**. +2. Clear the Joomla cache (**System** -> **Clear Cache**). +3. Check the browser console for JavaScript errors that might prevent event listeners from running. + +### Guest wishlist items did not carry over after login + +**Cause:** The session expired before login, or browser cookies were cleared between the shopping session and the login. + +**Solution:** + +This is a normal edge case when browser cookies expire between sessions. The wishlist migration happens at the moment of login. If the browser session had already expired before the customer logged in, there is no guest wishlist left to migrate. + +### The "Add all to cart" action does nothing + +**Cause:** No items are checked, or the CSRF token has expired. + +**Solution:** + +1. Select at least one item by checking its checkbox. +2. If the page has been open for a long time, refresh it to get a fresh CSRF token, then try again. + +## Related + +- [Gift Wrapping](app-giftwrapping.md) — add gift wrapping options at checkout +- [Easy Reorder](app_reorder.md) — let customers reorder from previous orders diff --git a/website/docs-v6/apps-and-extensions/apps/pdfinvoices.md b/website/docs-v6/apps-and-extensions/apps/pdfinvoices.md new file mode 100644 index 00000000..2d4b72ab --- /dev/null +++ b/website/docs-v6/apps-and-extensions/apps/pdfinvoices.md @@ -0,0 +1,241 @@ +--- +title: "PDF Invoices" +sidebar_label: "PDF Invoices" +sidebar_position: 11 +description: "Automatically generate and email PDF invoices for J2Commerce orders, with a frontend download link for customers and an admin download button in the order detail view." +--- + +# PDF Invoices + +The **PDF Invoices** app automatically generates a PDF invoice for each order and can attach it to the notification emails sent to your customer, your store admin, or both. Customers can also download their invoice from their order history page, and store admins can download any order's invoice directly from the order detail screen. + +This app is a separate add-on available from the [J2Commerce Extensions Store](https://www.j2commerce.com). It is not included with the core J2Commerce 6 component. + +## Prerequisites + +Before installing, ensure the following are in place: + +- J2Commerce 6 is installed and enabled +- The **Dompdf Library** add-on is installed (see below) +- PHP 8.2 or higher +- Joomla 5 or 6 + +### Install the Dompdf Library + +The PDF Invoices app depends on the Dompdf library to render HTML into PDF files. This library is a separate add-on also available from the [J2Commerce Extensions Store](https://www.j2commerce.com). + +1. Download the `lib_dompdf.zip` package from the J2Commerce website. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload `lib_dompdf.zip` and click **Upload & Install**. + +The library creates a working directory at `tmp/dompdf/` inside your Joomla root. This directory must be writable by the web server. + +:::info +If you attempt to install the PDF Invoices app before the Dompdf library is present, the installer will stop and display an error with a download link for the library. +::: + +## Installation + +Once the Dompdf library is installed: + +1. Download the `plg_j2commerce_app_pdfinvoices.zip` package from the J2Commerce website. +2. Go to **System** -> **Install** -> **Extensions**. +3. Upload the ZIP file and click **Upload & Install**. + + + +After installation completes, the plugin is not yet enabled. Enable it by going to **J2Commerce** -> **Apps**, finding **PDF Invoices** in the list, and clicking its toggle to enable it. + + + +## Configuration + +Go to **J2Commerce** -> **Apps** and click **PDF Invoices** to open its settings. + +The configuration screen has two tabs: **Basic Settings** and **Advanced Settings**. + + + +### Basic Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| **File Name Prefix** | The text prepended to the PDF file name. For example, a prefix of `invoice` produces a file named `invoice_INV001.pdf`. | `invoice` | +| **Send PDF Invoice for Status** | Restrict PDF generation to specific order statuses. Select one or more statuses from the list. If nothing is selected, a PDF is generated for every order. | All statuses | +| **Additional Files** | Attach an extra PDF file alongside the invoice. Upload the file to `media/j2commerce/` first, then select it here. | None | +| **Attach Invoice To** | Choose who receives the PDF as an email attachment. Options: **None**, **Both Administrator and Customer**, **Customer Only**, **Administrator Only**. | Both Administrator and Customer | +| **Show Link in Frontend** | When enabled, a **Download PDF** button appears on the customer's order history page so they can download their invoice at any time. | No | + +#### Setting Up Order Status Filtering + +By default, PDFs are generated for orders in any status. If you only want to send invoices for confirmed or paid orders, select those statuses from the **Send PDF Invoice for Status** field. + +For example, to only send invoices for orders that have been paid: + +1. Click the **Send PDF Invoice for Status** dropdown. +2. Select **Confirmed** (or whatever status your store uses for paid orders). +3. Click **Save**. + +Orders in other statuses will not have a PDF attached to their email notification. + +#### Attaching Additional PDF Files + +You can send a static PDF file — such as a return policy or terms of service — alongside every invoice: + +1. Upload your PDF file to `media/j2commerce/` on your server using FTP or the Joomla Media Manager. +2. In the **Additional Files** field, select the uploaded file. +3. Click **Save**. + +Both the generated invoice and the additional file will be attached to matching order emails. + +### Advanced Settings + + + +| Setting | Description | Default | +|---------|-------------|---------| +| **Enable Tidy Repair** | Uses PHP's Tidy extension to clean up malformed HTML in the invoice template before passing it to the PDF renderer. Requires `ext-tidy` on your server. | Yes | +| **Enable HTML5 Parser** | Switches the Dompdf renderer to its HTML5-compatible parsing mode. Enable this if the invoice contains modern HTML5 elements that are not rendering correctly. | No | +| **Font Family CSS** | Override the body font used throughout the PDF. Enter a valid CSS `font-family` declaration, for example: `font-family: Helvetica;` | None (uses Dompdf default) | +| **Custom CSS** | Additional CSS rules applied to the entire invoice. Use this to adjust colours, spacing, borders, and layout. | None | +| **Debug Mode** | Writes detailed log entries to the Joomla log directory. Useful for diagnosing PDF generation problems. Disable this in production. | No | + +## How Invoice PDFs Are Generated + +When an order notification email is sent — either to the customer or the store admin — the plugin intercepts that email, generates a PDF from the order's invoice template, and attaches it. The PDF is saved temporarily to `media/j2commerce/invoices/` before being attached. If the same order's PDF has already been generated during the same request, the cached file is reused rather than rendering it twice. + +The invoice content is taken from the J2Commerce invoice template stored in your Joomla installation. The same template that appears when you view or print an invoice in the admin is used to produce the PDF. Images in the invoice are automatically converted to embedded data so they appear correctly in the rendered PDF. + +## Customising the Invoice Appearance + +### Changing the Font + +Dompdf supports a limited set of built-in fonts: **DejaVu Sans**, **Helvetica**, and **Courier**. Fonts outside this set may not display special characters correctly. + +To change the font, enter a CSS font-family declaration in the **Font Family CSS** field: + +``` +font-family: Helvetica; +``` + +or for a sans-serif fallback chain: + +``` +font-family: Helvetica, DejaVu Sans, sans-serif; +``` + +### Adding Custom Styles + +Use the **Custom CSS** field to override any aspect of the invoice layout. The CSS is injected into the PDF document's `