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 0000000..719aa28 --- /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 0000000..0932583 --- /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 0000000..bdafef6 --- /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 1f19e72..0c652cf 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 0000000..b2b5987 --- /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 961b761..0000000 --- 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 380d25a5ba37b07f3516bab5be3f56ed72afbb19 Mon Sep 17 00:00:00 2001 From: Adam Melcher Date: Sat, 4 Apr 2026 13:36:34 -0500 Subject: [PATCH 4/4] docs: update Getting Started ## Summary **1 new documentation page(s)** added. ### New Pages - `website/docs-v6/getting-started/product-category-wizard.md` ## Documentation Areas --- _Auto-generated by J2Commerce documentation sync script._ --- .../product-category-wizard.md | 314 ++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 website/docs-v6/getting-started/product-category-wizard.md diff --git a/website/docs-v6/getting-started/product-category-wizard.md b/website/docs-v6/getting-started/product-category-wizard.md new file mode 100644 index 0000000..eb7a51c --- /dev/null +++ b/website/docs-v6/getting-started/product-category-wizard.md @@ -0,0 +1,314 @@ +--- +title: "Product Category Setup Wizard" +sidebar_label: "Product Category Wizard" +sidebar_position: 4 +description: "Use the J2Commerce Product Category Setup Wizard to quickly create product categories, a first product, and a menu item so customers can find your store." +--- + +# Product Category Setup Wizard + +The Product Category Setup Wizard is a step-by-step modal that helps new store owners create everything they need to make their products accessible on the frontend — all in under two minutes. It creates a Joomla category, a product, an article, and a published menu item pointing to your store. + +The wizard is designed to be completed once at the start of your store setup. You can run it again at any time if you want to add more categories or products quickly. + +--- + +## Prerequisites + +- J2Commerce 6 installed and the required system and content plugins enabled. +- You are logged in to the Joomla administrator as a Super Administrator. + +--- + +## How to Open the Wizard + +The wizard can be launched from two places: + +**From the Setup Guide:** + +1. Click the purple **Setup Wizard** button in the J2Commerce dashboard toolbar. +2. Expand the **Catalog** section. +3. Click the **Shop / Category Menu Item** check. +4. Click **Run Setup Wizard**. + + + +**From the dashboard directly:** + +The wizard modal is embedded on the dashboard page. Any button or link that opens `#j2commerceCategoryWizardModal` will launch it. + +:::info +The wizard requires Super Administrator access. If you do not have `core.admin` permission on `com_j2commerce`, the AJAX calls will return a 403 error. +::: + +--- + +## Wizard Flows + +The wizard adapts to your situation. On the first step you choose how many products you plan to sell, and the wizard branches into one of two flows: + +| Your Answer | Flow | What Gets Created | +|---|---|---| +| **Just 1 product** | Single Product | Category, article, product, menu item | +| **2 – 10, 11 – 50, or 50+ products** | Multi Category | Root category, subcategories, menu item(s) | + +--- + +## Single Product Flow + +Use this flow when you have one product to sell and want a menu item that links directly to its product page. + +### Step 1: How many products? + +Select **Just 1 product** and click **Next**. + + + +### Step 2: Product name + +Type the name of your product (for example, "Handmade Ceramic Mug"). Click **Next**. + + + +### Step 3: Product type + +Choose the type that best describes your product: + +| Type | When to use | +|---|---| +| **Digital Download** | E-books, software, music, or any file the customer downloads after purchase | +| **Physical Product (no variants)** | A single item without size or color options — e.g., a book or a candle | +| **Physical Product with Options** | An item with variants like size or color — e.g., a t-shirt | + +Click **Next**. + + + +### Step 3b: Define options (variable products only) + +If you chose **Physical Product with Options**, the wizard asks you to name the options your product has (for example, "Size" or "Color"). Each option title you enter becomes a separate option set. + +- Click **Add another option** to add a second option (for example, both Size and Color). +- Click the **×** button to remove an option row. + +Click **Next** when all option titles are filled in. + + + +### Step 3c: Add option values (variable products only) + +For each option title you defined, enter the specific values customers will choose from: + +- Type each value (for example, "Small", "Medium", "Large" for a Size option). +- Click **Add value** to add more values in the same option. +- Click the **×** button to remove a value. + +Click **Next** when all options have at least one value. + + + +:::tip +Option names and values are saved globally and reused across products. If a "Size" option with matching values already exists in your catalog, the wizard will reuse it rather than create a duplicate. +::: + +### Template step (YOOtheme sites only) + +If YOOtheme is your active frontend template and the J2Commerce UIkit app plugin is installed and enabled, an extra step asks which layout to use: + +| Choice | When to choose | +|---|---| +| **UIkit layout** | Your theme is YOOtheme and you want the layout optimized for UIkit components | +| **Bootstrap 5 layout** | All other situations (default) | + +Click **Next**. + +### Confirm + +A summary lists everything the wizard will create. Review it and click **Create My Store** when you are ready. + + + +### Success + +The wizard displays a success screen with direct links: + +- **Edit your product** (or **Edit Product & Configure Variants** for variable products) — takes you directly to the product edit form. +- **Add more products** — opens the Products list. + + + +For variable products, a note reminds you to open the product editor to set pricing, inventory, and images for each variant combination. + +Click **Done** to close the wizard. + +--- + +## Multi Category Flow + +Use this flow when you have multiple products organized into categories. + +### Step 1: How many products? + +Select **2 – 10 products**, **11 – 50 products**, or **50+ products**, then click **Next**. + +### Step 2: How many categories? + +Choose how many product categories you need: + +| Choice | What happens | +|---|---| +| **Just 1 category** | The wizard creates one root "Shop" category and skips the subcategory steps | +| **2 – 5 categories** | You will name 2 categories by default (and can add more) | +| **6 – 10 categories** | You will name 3 categories by default (and can add more) | +| **More than 10** | A single root "Shop" category is created; you add subcategories later from the admin | + +Click **Next**. + +### Step 3: Display settings (2+ categories only) + +Choose how you want the categories to appear in your site navigation: + +| Choice | Result | +|---|---| +| **All categories on the same page** | One "Product Categories" menu item showing all categories at once | +| **Each category on its own page** | A separate menu item for each subcategory | + +Click **Next**. + +### Category naming + +Name your categories. For "Just 1 category" or "More than 10", you name the root category only. For other choices, a row of text inputs appears — one per category. + +- Click **Add another category** to add more name rows. +- Click the **×** button to remove a row. + +Click **Next**. + + + +### Template step (YOOtheme sites only) + +Same as described in the single-product flow above. + +### Confirm + +Review the summary and click **Create My Store**. + +### Success + +The success screen shows: + +- Root category created +- Number of subcategories created +- Number of menu items created +- **Add products** button — opens the Products list +- **Manage categories** button — opens the Joomla Categories admin for `com_content` + +Click **Done** to close the wizard. + +--- + +## What the Wizard Creates + +### Single Product Flow + +| Item | Details | +|---|---| +| **Joomla category** | Title: "Shop" (or custom name), published, under the Joomla root category, extension `com_content` | +| **Joomla article** | Title: your product name, published, assigned to the "Shop" category | +| **J2Commerce product** | Linked to the article, product type as selected, master variant with SKU `PROD-[id]` | +| **Product options** | One option per title you entered, with values linked to the product | +| **Menu item** | Type: component, link: product page, published in a "J2Commerce" menu type | + +### Multi Category Flow + +| Item | Details | +|---|---| +| **Root category** | Title: first category name you entered, published under the Joomla root | +| **Subcategories** | One per additional name you entered, published as children of the root | +| **Menu item(s)** | Either one "categories" menu item pointing at the root, or one "products" menu item per subcategory, depending on your display choice | + +:::note +The wizard does **not** create products in the multi-category flow. After the wizard finishes, go to **J2Commerce → Catalog → Products** and add products to each category. +::: + +--- + +## After the Wizard + +### For single-product stores + +1. Open the product using the **Edit your product** link on the success screen. +2. Set the price on the **Prices** tab. +3. For variable products, use the **Variants** tab to configure each size/color combination's price, stock, and images. +4. Upload product images on the **Images** tab. +5. Preview the frontend using the menu item the wizard created. + +### For multi-category stores + +1. Go to **J2Commerce → Catalog → Products → New** and create your first product. +2. Assign it to one of the categories the wizard created. +3. Repeat for each product. +4. (Optional) Assign the menu item(s) to your site's main navigation menu in **Menus → Main Menu**. + +--- + +## Tips + +- The wizard creates menu items in a hidden "J2Commerce" menu type, not your main navigation menu. To show your shop in the site header, copy or recreate the menu item in **Menus → Main Menu**. +- If YOOtheme is detected but the UIkit app plugin is not installed, the template step is skipped and Bootstrap 5 is used automatically. +- Running the wizard a second time creates additional items — it does not overwrite anything created previously. +- Option names are case-insensitive. Entering "size" when a "Size" option already exists reuses the existing option. + +--- + +## Troubleshooting + +### The wizard shows "Setup failed. Please try again." + +**Cause:** An error occurred on the server while creating one of the items (category, article, product, or menu item). + +**Solution:** + +1. Check the Joomla error log at **System → Manage → System Information → PHP Error Log** or in `administrator/logs/com_j2commerce.php`. +2. Verify your database user has `INSERT` permissions on the `#__categories`, `#__content`, `#__j2commerce_products`, and `#__menu` tables. +3. Try again. If the root category or option already exists from a previous run, the wizard reuses it rather than duplicating it. + +### The wizard modal does not open + +**Cause:** The wizard JavaScript did not load, or the modal HTML is missing from the page. + +**Solution:** + +1. Open the browser developer console (F12) and check for JavaScript errors. +2. Ensure you are a **Super Administrator** — lower permission levels prevent the AJAX calls from succeeding. +3. Hard-refresh the page (Ctrl+Shift+R) to clear the browser asset cache. + +### The menu item was created but the frontend page shows a 404 error + +**Cause:** The menu item was created in the "J2Commerce" menu type, which is not assigned to any module position in your template. + +**Solution:** + +1. Go to **Menus → J2Commerce** in the Joomla administrator. +2. Copy the menu item to your main site navigation menu (typically **Main Menu**), or create a new menu item there manually using the same link the wizard used. +3. Make sure the menu module is published and assigned to your site's header position. + +### No template/UIkit step appeared, but I have YOOtheme installed + +**Cause:** The J2Commerce UIkit app plugin (`app_uikit`) is not installed or not enabled. + +**Solution:** + +1. Go to **System → Manage → Extensions** and search for `app_uikit`. +2. Enable the plugin if it is disabled. +3. Run the wizard again — the template step will now appear. + +--- + +## Related Topics + +- [Store Setup](store-setup.mdx) +- [Dashboard](dashboard.md) +- [Creating Products](../catalog/products) +- [Creating Options](../catalog/creating-options.mdx)