The Stripe plugin (plg_solidshoppayment_stripe) adds Stripe’s
Payment Element to your Solidshop checkout. One integration
surfaces every payment method you have enabled in your Stripe account —
cards with 3-D Secure, Apple Pay and Google Pay, Klarna, Affirm,
Afterpay/Clearpay, iDEAL, SEPA Direct Debit, ACH, and more — picked
automatically for each visitor based on their region, currency, and device.
The plugin ships under GPL-3 and talks to Stripe’s PaymentIntents API server-side; the browser only ever sees your publishable key. Stripe Connect (charging on behalf of a connected account) is supported out of the box. See the Stripe extension page for the high-level feature overview.
Requirements
- Joomla 6.x or later
- PHP 8.4 or later
- Solidshop 1.3.1 or later — the installer refuses to run against an older core, so update Solidshop first if you are behind. 1.3.1 is what ships the Webhook URL field and the payment entries the plugin writes to the order’s Activity Timeline
- A Stripe account — sign up here if you don’t have one yet
- HTTPS on your storefront — Stripe requires it for live payments
Installation
Download plg_solidshoppayment_stripe.zip from the
Downloads page — it’s available while
your Stripe plugin subscription is active, and updates arrive through the
standard Joomla updater.
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 and registers the
solidshoppayment group entry — no Composer step required.
Go to System → Manage → Plugins, filter by the
solidshoppayment type, and enable
Solidshop Payment — Stripe. The plugin is
disabled by default after install — until you enable it,
Stripe won’t appear at checkout.
Get your Stripe API keys
Stripe authenticates the plugin with a publishable key and a secret key pair. You’ll need two pairs — one for test mode and one for live — and you can store both simultaneously.
Go to dashboard.stripe.com → Developers → API keys and log in with the Stripe account that will receive your payouts.
With the dashboard’s Test mode toggle on, copy the
test Publishable key (pk_test_…) and
Secret key (sk_test_…). Toggle test
mode off and copy the live pair (pk_live_… /
sk_live_…) the same way.
Configure the plugin
Stripe configuration lives at the store level — each store has its own keys, so you can run a separate Stripe account per storefront in a multi-store install.
Go to Solidshop → Stores, open the store you want to configure, and switch to the Payments tab. Tick the Stripe row to enable it for this store.
The Test mode switch defaults to Yes so accidental charges aren’t possible on a fresh install. Leave it on Yes while you run test checkouts; flip it to No when you’re ready to accept real payments.
Both key pairs are stored in parallel — the plugin reads the test pair while test mode is on, and the live pair when it’s off. If the pair for the active mode is missing, Stripe is automatically hidden at checkout.
In test mode, fill the test Publishable Key and Secret Key fields. Outside test mode, fill the live pair. Both are required when the matching mode is active — Solidshop refuses to save the form otherwise.
If you charge on behalf of a Stripe Connect account, enter
its account ID (acct_…) in the optional
Connected Account ID field. Leave it empty to charge your
own account directly.
If you want to pass Stripe’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 Stripe is selected at checkout. Leave it at
0 to absorb the fee yourself.
Save the store, then continue with Webhooks & payment reconciliation below — the webhook is not optional for Stripe: redirect-based methods (Klarna, iDEAL, …) and bank debits are only confirmed through it.
Webhooks & payment reconciliation
Card payments are usually confirmed inline, before the shopper leaves your checkout. Everything else is decided after they leave — a Klarna or iDEAL approval that happens on the provider’s site, or a SEPA/ACH bank debit that clears days later. Stripe reports those outcomes through webhooks. The plugin verifies each event’s signature and reconciles two of them:
-
payment_intent.succeeded— the payment cleared; the plugin checks the captured amount and currency against the order, marks it Paid, queues the confirmation email, and records the capture on the order’s Activity Timeline together with the PaymentIntent id. Every payment is logged there — the entry names the webhook when reconciliation happened after checkout, so you can tell the two apart at a glance. -
charge.refunded— a refund was issued at Stripe (including one made in the Stripe dashboard); the order moves to Refunded or Partially refunded.
In Solidshop → Stores, open your store, go to
Payments → Stripe, and copy the read-only
Webhook URL field. It looks like
https://your-site.example/index.php?option=com_solidshop&task=payment.callback&payment=stripe&store_id=1
and is unique per store. The field only appears once the store is saved
— the URL carries the store ID.
In the Stripe dashboard → Developers → Webhooks,
click Add endpoint, paste the Webhook URL, and subscribe it
to the payment_intent.succeeded and
charge.refunded events. Create the endpoint in the mode
you’re configuring — test and live each need their own endpoint
and secret.
Stripe also asks you to pick an API version for the endpoint. Any current version works — take the default your account is already on. The version only shapes the event payload Stripe sends, and the plugin reads just the long-stable fields (the payment intent’s id, amount and metadata; the charge’s payment intent, currency and cumulative refunded amount). It pins its own version independently for the API calls it makes, so the two never have to match.
Stripe shows a signing secret (whsec_…)
for the new endpoint. Copy it into the store’s
Webhook Signing Secret field for the matching mode and
save. The plugin uses it to verify the signature on every incoming event
— a store with no signing secret on file rejects all of them.
Testing webhooks on a local site. Stripe can’t reach a
localhost URL. For development, use the
Stripe CLI:
stripe listen --forward-to your Webhook URL prints a temporary
signing secret — paste that into the store while you test.
Test with Stripe test cards
With test mode on, run a checkout on your storefront and pick
Stripe. The Payment Element opens in a dialog — pay
with the classic test card 4242 4242 4242 4242
(any future expiry, any CVC). Stripe’s
testing guide
lists numbers that decline, trigger 3-D Secure, and simulate every other
payment method.
Open Solidshop → Orders and check the new order:
payment status should be Paid, the payment method should be
Stripe, and the recorded transaction ID
(pi_…) should match the PaymentIntent in your Stripe
dashboard. Solidshop queues the confirmation email at this point —
provided your email queue
task is running, you’ll see it arrive within the next minute.
Test a redirect method too. If you plan to offer Klarna, iDEAL, or another redirect-based method, run one test checkout with it — it exercises the webhook path end-to-end and catches a missing or mismatched signing secret before real money is involved.
Supported currencies
Stripe processes payments in 135+ currencies. The plugin reads your store’s currency and forwards it to Stripe verbatim — no conversion happens inside Solidshop. Which payment methods appear in the Payment Element depends on the currency; cards work with all of them.
Zero-decimal currencies. Stripe counts
JPY, KRW, VND and other zero-decimal
currencies in whole units, and KWD, BHD and other
three-decimal currencies in thousandths. The plugin converts amounts
automatically in both directions — a ¥1,500 order is
sent to Stripe as 1500, not 150000. 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:
- The customer places the order; Solidshop creates it in a pending state and the plugin opens a dialog, loading Stripe.js from Stripe’s CDN.
-
The plugin calls back to
com_ajax?plugin=stripe&group=solidshoppayment&step=createPaymentIntent. The server creates a Stripe PaymentIntent for the order total and returns its client secret; the Payment Element renders in the dialog. - The customer confirms. Card payments resolve inline; redirect methods (Klarna, iDEAL, …) send the browser to the provider and return through a signed, token-protected return URL.
-
For inline payments, the plugin calls back with
step=confirmPayment. The server re-fetches the PaymentIntent from Stripe’s API — never trusting the browser — validates its status, amount, and currency, marks the order Paid, and enqueues the confirmation email. Bank debits that resolve as processing leave the order pending until the webhook confirms the money moved. -
For redirect and asynchronous payments, the
payment_intent.succeededwebhook performs the same validation and marks the order Paid.
PaymentIntent creation and confirmation both happen server-side, so the client never sees your secret key or decides the payment outcome — only the publishable key is exposed to the browser.
Finding an order in the Stripe dashboard
Every charge the plugin creates carries the store name and the order reference
as its Description — for example
My store 5 — order 821b7a65 — so the Stripe
Payments list is readable without opening each row. The same
payment also carries order_id and order_reference
under Metadata on the payment page, which is what you search
when reconciling a Stripe payout against Solidshop orders.
Refunds
Refund orders without leaving Joomla: open the order in Solidshop → Orders and use the Refund action — full or partial, with an optional reason that is stored on the Stripe refund. The money moves at Stripe first; only a refund Stripe accepted is recorded locally, and the order moves to Refunded or Partially refunded automatically. Bank-debit refunds that Stripe reports as pending are recorded the same way — the money is on its way.
Refunds issued directly from the Stripe dashboard are picked up too: the
charge.refunded webhook reconciles them into
the order’s refund history, so the order in Solidshop and the charge in
Stripe never drift apart. The refunded amount always matches Stripe exactly; on
recent API versions Stripe omits the individual refund
from the event, so a dashboard refund is filed without its refund id or reason
— refund from Joomla when you want those recorded on the order.
Troubleshooting
Stripe doesn’t appear at checkout
- Confirm the plugin is Enabled under System → Plugins.
- Confirm Stripe is ticked in the Store → Payments tab.
- Confirm the publishable and secret key are saved for the active mode — the plugin hides itself when either is missing, so a store switched to live with only test keys shows no Stripe option.
The payment dialog shows a loading error
- An ad blocker or strict privacy proxy can block
js.stripe.com— the plugin shows a “Could not load Stripe” message instead of a payment form. Whitelisting the domain fixes it. - Check the browser console — an invalid publishable key surfaces here.
Shoppers are asked to create a Link account
- Stripe’s Link offers to save a shopper’s details whenever the Payment Element collects an email and phone number — which Klarna and the bank-debit methods require. The notice comes from Stripe, not Solidshop, and no Elements option suppresses it.
- Turn Link off per account under Stripe → Settings → Payment methods. Weigh it up first: Link gives returning shoppers one-click checkout, but a buyer who chose Klarna being asked to open a different account mid-payment is a conversion risk.
Klarna / iDEAL / bank-debit orders stay Pending
- These methods are confirmed only by the webhook. Confirm the endpoint
exists in the Stripe dashboard for the active mode, points at this store’s
Webhook URL, and subscribes to
payment_intent.succeeded. - Confirm the Webhook Signing Secret for the active mode matches that endpoint — a wrong or missing secret makes the store reject every delivery (Stripe’s dashboard shows the failed attempts).
- On a development or
localhostsite, webhooks can’t be delivered at all — use the Stripe CLI as described above. - Check the Solidshop payment log (
solidshoppayment_stripe.phpin your Joomla log directory) for rejected-webhook entries.
Order confirmation email doesn’t arrive
The plugin enqueues the confirmation email after Stripe confirms the payment, 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.
Going live
When you’re ready to accept real payments:
- Flip Test mode to No in the store’s Payments tab.
- Confirm the live Publishable Key and Secret Key fields are filled and saved.
- Create a live webhook endpoint in the Stripe dashboard and paste its signing secret into the live Webhook Signing Secret field — the test endpoint doesn’t carry over. See Webhooks & payment reconciliation.
- Place one final low-value real order with your own card — you can refund it from the Stripe dashboard immediately.
- Watch the first few real orders for unexpected currency or method issues; the Stripe dashboard’s Events log is the fastest place to spot problems.
That’s it — Stripe is live on your Solidshop storefront.