The PayPal Checkout plugin (plg_solidshoppayment_paypal) adds PayPal Smart Payment Buttons to your Solidshop checkout. Customers can pay with their PayPal balance, debit or credit cards (no PayPal account required), Pay Later instalments, and Venmo — all surfaced automatically by the official PayPal JavaScript SDK based on the visitor’s region, currency, and order amount.

The plugin is free forever, ships under GPL-3, and is built on PayPal’s modern Orders v2 REST API via the official PayPal PHP Server SDK. See the PayPal extension page for the high-level feature overview.

Requirements

  • Joomla 6.x or later
  • PHP 8.4 or later
  • Solidshop 1.0 or later (core component installed and configured)
  • A PayPal Business account — sign up here if you don’t have one yet
  • A store currency in PayPal’s supported set (see Supported currencies below)

Installation

Download the plugin

Download plg_solidshoppayment_paypal.zip from the Downloads page. No licence key is required — the PayPal plugin is free.

Install via the Extension Manager

In your Joomla admin, go to System → Install → Extensions. Drag the ZIP file into the upload area or click “Browse for file” and select it. Joomla installs the plugin, registers the solidshoppayment group entry, and bundles the PayPal PHP Server SDK — no Composer step required.

Enable the plugin

Go to System → Manage → Plugins, filter by the solidshoppayment type, and enable Solidshop Payment — PayPal. The plugin is disabled by default after install — until you enable it, the PayPal button won’t appear at checkout.

Get your PayPal API credentials

PayPal authenticates the plugin using a client ID and secret pair, generated per-app inside your PayPal developer portal. You’ll need two pairs — one for sandbox testing and one for live production — and you can store both simultaneously.

Sign in to the PayPal Developer Dashboard

Go to developer.paypal.com → Apps & Credentials and log in with the PayPal Business account that will receive your payouts.

Create a REST API app

Switch to the Sandbox tab and click Create App. Give it a name (e.g. “My Solidshop Store — Sandbox”) and choose the Merchant account type. PayPal creates the app and shows you a Client ID and Secret. Copy both.

Repeat under the Live tab to generate the production credential pair. The live tab is only available once your PayPal Business account is verified.

Configure the plugin

PayPal configuration lives at the store level — each store has its own credentials, so you can run a separate PayPal account per storefront in a multi-store install.

Open your store’s Payments tab

Go to Solidshop → Stores, open the store you want to configure, and switch to the Payments tab. Tick the PayPal row to enable it for this store.

Pick test mode or live

The Test mode switch defaults to Yes so accidental charges aren’t possible on a fresh install. Leave it on Yes while you run sandbox checkouts; flip it to No when you’re ready to accept real payments.

Both credential pairs are stored in parallel — the plugin reads the sandbox pair while test mode is on, and the live pair when it’s off. No need to rotate keys to run a test order.

Paste your credentials

In test mode, fill the Sandbox Client ID and Sandbox Secret fields. Outside test mode, fill the Live Client ID and Live Secret fields. Both are required when the matching mode is active — Solidshop refuses to save the form otherwise.

Optional — set a surcharge fee

If you want to pass PayPal’s processing cost to the customer, enter a flat amount in the Fee field. It appears as a separate line in the cart total when PayPal is selected at checkout. Leave it at 0 to absorb the fee yourself.

Save and reload your checkout

Save the store. Visit your storefront, add a product to the cart, and go to checkout — the PayPal Smart Button row should now render. If it doesn’t, see Troubleshooting.

Webhooks & payment reconciliation

Some payment outcomes are decided after the shopper leaves your checkout — an eCheck capture that clears (or is declined) hours later, or a refund you issue straight from the PayPal dashboard. PayPal reports those back through webhooks, and the plugin uses them to keep each order’s payment status in step with PayPal, so it never silently drifts from what actually happened. The plugin subscribes to three events:

  • PAYMENT.CAPTURE.COMPLETED — an asynchronous capture cleared; the order is marked Paid and its confirmation email is queued.
  • PAYMENT.CAPTURE.DENIED — a pending capture failed; the order is left Unpaid.
  • PAYMENT.CAPTURE.REFUNDED — a refund was issued at PayPal (including one made in the PayPal dashboard); the order moves to Refunded or Partially refunded.

Automatic registration (the default)

You normally don’t have to do anything. When you save a store that has valid PayPal credentials for the active mode, Solidshop registers the webhook for you — against the PayPal app those credentials belong to — points it at this store’s Webhook URL, and writes the resulting Webhook ID into the store’s PayPal settings. You’ll see a confirmation notice with the ID. Sandbox (test mode) and live each get their own webhook, so save the store once in each mode.

Re-save after a credential change. A Webhook ID only verifies events from the app its credentials belong to. If you swap the Client ID or Secret, save the store again so the webhook is re-registered against the new app — otherwise PayPal delivers no events for it.

Manual registration (when automatic can’t run)

Automatic registration is skipped on a local or development site (PayPal can’t reach a localhost URL), and it can fail on a restricted PayPal account or a transient API error. In those cases Solidshop shows a warning and leaves the manual path open:

Copy the Webhook URL

In Solidshop → Stores, open your store, go to Payments → PayPal, and copy the read-only Webhook URL field. It looks like https://your-site.example/index.php?option=com_solidshop&task=payment.callback&payment=paypal&store_id=1 and is unique per store. The field only appears once the store is saved — the URL carries the store ID.

Create the webhook in PayPal

In the PayPal Developer Dashboard, open the same app whose Client ID and Secret you pasted into the store — the Sandbox app for test mode, the Live app for production — find its Webhooks section, and click Add Webhook. Paste the Webhook URL, then subscribe to exactly these three events: PAYMENT.CAPTURE.COMPLETED, PAYMENT.CAPTURE.DENIED, and PAYMENT.CAPTURE.REFUNDED. Save.

Paste the Webhook ID back

PayPal shows a Webhook ID for the new webhook. Copy it into the Webhook ID field in the store’s PayPal settings (that field shows for whichever mode — sandbox or live — is active) and save. The plugin uses it to verify the signature on every incoming event.

The webhook must belong to the same PayPal app as your credentials. A Webhook ID from a different app verifies nothing and receives no events. If reconciliation isn’t working, that mismatch is the first thing to check — and a store with no Webhook ID on file rejects every incoming event, because it can’t verify the signature.

Test with sandbox accounts

PayPal provides personal “buyer” sandbox accounts you can use to place test orders against your sandbox merchant credentials. They behave like real PayPal accounts but use play money — no real funds move.

Find your sandbox buyer

Go to developer.paypal.com → Sandbox → Accounts. PayPal pre-creates a default personal account — copy the email address and click View / edit account to see (or reset) the password.

Place a test checkout

With test mode on, run a checkout on your storefront. When the PayPal button opens the PayPal login window, sign in with the sandbox buyer email and password. PayPal returns to your checkout, the plugin captures the order via the Orders v2 API, and the order status flips to Paid.

You can also pay with a test card — PayPal’s sandbox card testing guide lists card numbers that succeed, fail, and trigger 3-D Secure prompts.

Verify the order

Open Solidshop → Orders and check the new order: payment status should be Paid, the payment method should be PayPal, and the order timeline should show the PayPal transaction ID returned by the capture call. Solidshop also queues the confirmation email at this point — provided your email queue task is running, you’ll see it arrive within the next minute.

Don’t skip the test order. Run at least one complete sandbox checkout end-to-end before flipping test mode off — it catches misconfigured credentials, currency mismatches, and missing webhooks before any real customer money is involved.

Supported currencies

PayPal accepts payments in 24 currencies. The plugin reads your store’s currency and forwards it to PayPal verbatim — no conversion happens inside Solidshop. If your store currency isn’t in PayPal’s list, the PayPal button is automatically hidden at checkout.

Supported codes: AUD, BRL, CAD, CHF, CNY, CZK, DKK, EUR, GBP, HKD, HUF, ILS, JPY, MXN, MYR, NOK, NZD, PHP, PLN, SEK, SGD, THB, TWD, USD.

Zero-decimal currencies. PayPal requires whole-number amounts for HUF, JPY, and TWD — no decimal point. The plugin handles this automatically: a 1500.50 JPY order is sent to PayPal as 1501. Display formatting in your storefront isn’t affected.

How the payment flow works

For developers and integrators, the high-level sequence at checkout looks like this:

  1. The plugin registers its asset on the checkout page and the PayPal JavaScript SDK renders the Smart Button row.
  2. When the customer clicks the button, the SDK calls back to com_ajax?plugin=paypal&group=solidshoppayment&step=createOrder. The plugin creates the Solidshop order in a pending state, then calls PayPal’s Orders v2 Create endpoint and returns the PayPal order ID to the SDK.
  3. The SDK opens the PayPal approval window. The customer logs in (or enters a card) and confirms.
  4. On approval, the SDK calls back to the same endpoint with step=approveOrder. The plugin calls PayPal’s Capture endpoint, marks the order Paid, enqueues the confirmation email, and returns the customer to the order confirmation page.

Order creation and capture both happen server-side, so the client never sees your secret or makes a direct API call to PayPal — only the public client ID is exposed to the browser.

Beyond this synchronous flow, PayPal also calls the store back through webhooks for outcomes that land later — an eCheck capture completing, a pending capture being denied, or a refund issued from the PayPal dashboard — so the recorded payment status always catches up with PayPal.

Seller Protection & billing address

The plugin forwards the customer’s billing-address snapshot (name, address lines, city, state, ISO country code) to PayPal with every order. This lets eligible transactions qualify for PayPal Seller Protection — you don’t need to do anything beyond entering an address at checkout.

Troubleshooting

PayPal button doesn’t render at checkout

  • Confirm the plugin is Enabled under System → Plugins.
  • Confirm PayPal is ticked in the Store → Payments tab.
  • Confirm the store currency is one of the 24 supported codes above.
  • Check the browser console for an SDK load error — a missing or invalid client ID will surface here.

“Can’t create the PayPal order” error

  • Verify the client ID and secret match the current Test mode selection — sandbox creds with test mode off (or vice versa) is the most common cause.
  • Check the response’s debug_id (logged in the error message) against your PayPal Developer Dashboard activity log.
  • If your account was recently created, ensure it’s fully verified — some endpoints reject unverified merchants.

Order confirmation email doesn’t arrive

The plugin enqueues the confirmation email after PayPal confirms the capture, using the standard Solidshop email queue. If emails aren’t sending, the scheduler task is the most likely culprit — see Set up the email queue in the installation guide.

Payment status doesn’t update after checkout (or dashboard refunds don’t show)

  • Confirm a Webhook ID is present in the store’s PayPal settings for the active mode. Without it, Solidshop can’t verify incoming events and rejects them, so reconciliation never runs. Re-save the store with valid credentials to auto-register it, or paste one in by hand — see Webhooks & payment reconciliation.
  • Make sure the webhook belongs to the same PayPal app as the configured credentials — a Webhook ID from another app receives no events.
  • On a development or localhost site, webhooks can’t be delivered at all — PayPal needs a publicly reachable URL.
  • Check the Solidshop payment log for rejected-webhook entries (missing Webhook ID, signature failure, or no matching order).

Going live

When you’re ready to accept real payments:

  1. Flip Test mode to No in the store’s Payments tab.
  2. Confirm the Live Client ID and Live Secret fields are filled and saved.
  3. Saving the store in live mode registers the live webhook — look for the confirmation notice with the webhook ID (or, if you registered it manually, that the live Webhook ID field is filled). See Webhooks & payment reconciliation.
  4. Place one final low-value real order with your own PayPal account — you can refund it from your PayPal dashboard immediately.
  5. Watch the first few real orders for unexpected currency or address issues; the PayPal Developer Dashboard’s activity log is the fastest place to spot problems.

That’s it — PayPal Checkout is live on your Solidshop storefront.