Last reviewed June 2026, the Stripe module requirements (Payment Intents API, webhook events, order-state sync), the test card numbers, SCA/3DS2 behaviour and Apple Pay domain-verification step described here are current for PrestaShop 1.7, 8.x and 9.x. Stripe's test cards and event names are taken from its current documentation; confirm anything pricing-related in your own Stripe dashboard.

Most Stripe-for-PrestaShop guides stop at "paste your API keys and you're done." That's the part that never breaks. What breaks (quietly, days after you've gone live and stopped watching) is the webhook that never fired, the order stuck in limbo with the money already taken, the 3D Secure challenge that sent a paying customer back to the cart. Getting Stripe working on PrestaShop is a ten-minute job. Getting it to reconcile every payment, refund and dispute back into your order list, on the right currency, surviving the next core upgrade. That's the integration this guide is actually about.

This is the implementation walkthrough: choosing a module that fits PrestaShop's architecture, wiring keys and webhooks correctly, satisfying European SCA rules, turning on Apple Pay and Google Pay, and the specific failure modes that strand PrestaShop orders. If you're still deciding whether Stripe is the right processor for you, that's a separate question, we compare it head-to-head with PayPal in Stripe vs PayPal, and weigh it against the wider field in best payment modules for PrestaShop. Here we assume the decision is made: you want Stripe, and you want it integrated properly.

Choosing a Stripe module that fits PrestaShop

A modern contactless card payment terminal on a counter with a blank chip card resting beside it
A good Stripe integration should feel as effortless at checkout as a tap on a card terminal - the complexity lives in the setup, not the customer's experience.

Stripe itself is just an API. The thing that turns it into a working checkout button, syncs order statuses, and stores customer data in PrestaShop's tables is the module, and the module choice matters more than anything you'll do in the Stripe dashboard. Two technical requirements decide whether a module is worth installing at all:

  • It must use the Payment Intents API, not the legacy Charges API. Payment Intents is Stripe's current required architecture for SCA-ready modules, and it's what makes Strong Customer Authentication work automatically. Modules built on the old Charges (or Sources) flow are deprecated and a poor fit for SCA, avoid them. If a module's description still talks about "Charges" or "tokens" without mentioning Payment Intents, walk away.
  • It must reconcile back into PrestaShop's order statuses. A payment succeeding in Stripe is only half the job. The module has to map that success onto a PrestaShop order state (Payment accepted), handle refunds issued from your back office, and write the Stripe transaction ID back against the order. Modules that skip this leave you cross-referencing two systems by hand every time a customer queries a charge.

The official free Stripe module covers the basics for a simple catalogue. Premium modules add saved cards, express wallet buttons, real-time voucher validation and a dispute/refund view inside PrestaShop itself. We laid out the full field, free versus premium, what each tier actually gives you, in the payment modules comparison, so we won't re-run it here. The point for this guide: confirm Payment Intents and order-state sync before you install anything, because retrofitting either is painful.

Step 1. Set up and verify your Stripe account

Sign up at stripe.com and complete business verification before you touch PrestaShop. Stripe reviews your live site and account approval can take a day or two, so start it early. You'll need business registration documents (or personal ID for sole traders), bank details for payouts, and your live store URL.

Once you're in, go to Developers → API keys. You'll see two key sets: test mode and live mode. Do all your setup in test mode first, test keys process fake payments without moving real money, and you do not want to discover a broken webhook with a real customer's card.

Step 2, Install the module and enter your keys

Upload the module under Modules → Module Manager → Upload a module, then open its configuration. Every Stripe module asks for the same three credentials, and it's worth understanding what each one is so you can tell when one is wrong:

  • Publishable key (pk_test_… / pk_live_…): used in the browser to render the card field. It's designed to be public. Exposing it is not a security problem.
  • Secret key (sk_test_… / sk_live_…): authenticates server-side calls to Stripe. This must never appear in client-side code or theme files. The module stores it server-side; if you ever see an sk_ key in page source, stop and rotate it in the Stripe dashboard immediately.
  • Webhook signing secret (whsec_…): set up in the next step. The module uses it to prove that incoming webhook calls genuinely came from Stripe and weren't forged.

The single most common mistake here is mixing test and live keys, a pk_live_ publishable key with an sk_test_ secret key produces confusing "no such payment intent" errors. Keep both keys in the same mode.

Step 3. Configure webhooks (this is where PrestaShop integrations fail)

Webhooks are how Stripe tells your store about anything that happens outside the live checkout window: a delayed payment finally clearing, a dispute opening, a refund processed from Stripe's side, a subscription renewing. Without a working webhook, your store simply never finds out. Which is why the classic symptom of a broken Stripe integration is "the money's in Stripe but the PrestaShop order is still pending."

In the Stripe dashboard go to Developers → Webhooks → Add endpoint. Point it at your module's webhook controller, for our Stripe Express Checkout module the URL follows PrestaShop's front-controller pattern, which you'll find printed in the module's configuration page so you can copy it exactly rather than guessing. Subscribe to at least these events:

  • payment_intent.succeeded, confirms a payment completed; drives the order into Payment accepted.
  • payment_intent.payment_failed. Lets the store react to declines instead of leaving a ghost order.
  • charge.dispute.created, surfaces a chargeback the moment it opens, while you still have time to respond.
  • charge.refunded. Keeps a refund issued from the Stripe side in sync with the PrestaShop order.
  • checkout.session.completed, needed if you use Stripe's hosted Checkout rather than an embedded form.

Copy the endpoint's signing secret (whsec_…) back into the module config. A well-built module verifies that signature on every call (ours rejects any request whose signature doesn't validate with an HTTP 400 before it touches your database) so a forged "payment succeeded" can't conjure a free order. After saving, send a test event from the Stripe dashboard and confirm the module logged it. If the webhook never arrives, the usual culprits are a firewall or CDN (Cloudflare in particular) blocking the request, an .htaccess rule shadowing the front-controller URL, or a stale signing secret, check Developers → Webhooks for failed delivery attempts and your server's PHP error log.

[SCREENSHOT: The Stripe dashboard Add endpoint screen with the PrestaShop webhook URL entered and the five payment_intent / charge / checkout events selected in the event picker]

Step 4. Test every scenario before going live

Stripe ships test card numbers that force each outcome, so you can exercise the whole flow without real money:

Test cardWhat it simulatesWhat to verify in PrestaShop
4242 4242 4242 4242Successful paymentOrder moves to Payment accepted; confirmation email sent; stock decremented
4000 0000 0000 3220Forces 3D Secure 2 challengeCustomer is returned to the order, not the cart, after authenticating
4000 0000 0000 9995Declined, insufficient fundsNo order created, or order marked as payment error; cart preserved
4000 0000 0000 0069Expired cardClear inline error; customer can retry without losing the cart

Run each one and watch what PrestaShop does, not just what Stripe reports. The order status, the confirmation email, the inventory adjustment and the back-office transaction record all have to land correctly. This is the step people skip, and it's exactly the step that catches the webhook problem above before a customer does.

SCA and 3D Secure 2: handled, if you chose the right module

Strong Customer Authentication came into force across the European Economic Area on 14 September 2019, though regulators granted a migration period that phased real enforcement through the end of 2020 (and into March 2021 in the UK). It is fully in effect now, which in practice means many European card payments may require 3D Secure 2 two-factor authentication, while Stripe and the issuer decide when exemptions or frictionless flows apply. The reassuring part: if your module uses the Payment Intents API (the requirement we opened with), Stripe decides when a challenge is needed and runs the authentication flow itself. Your store's job is just to handle the response. Which is why testing card 4000 0000 0000 3220 above matters so much.

Three behaviours worth knowing so they don't surprise you:

  • Low-value exemptions. Small transactions can qualify to skip the challenge; Stripe requests the exemption automatically, but the customer's bank has the final say, so you can't rely on it.
  • Recurring and saved-card payments. The first payment is authenticated interactively; later merchant-initiated charges against a stored card don't re-prompt, important if you sell subscriptions.
  • Abandonment at the challenge. A share of customers drop out when the 3DS2 popup appears. You can't eliminate it, but a fast, native-feeling authentication UI minimises it, another reason the module's frontend quality matters.

Turning on Apple Pay and Google Pay

Apple Pay and Google Pay aren't separate Stripe integrations, they ride on Stripe's Payment Request / Express Checkout buttons. Switch that on and eligible shoppers see a native wallet button that completes the order with a fingerprint or face scan instead of typing a card. For mobile customers especially, that removes the single most painful part of checkout. (Our Stripe Express Checkout module is built specifically around this: it can place the wallet button on product, cart and checkout pages, so a returning customer pays in seconds without ever entering the traditional flow.)

Apple Pay needs one extra step Google Pay doesn't, domain verification:

  • Register your domain under Settings → Payments → Payment methods → Apple Pay in the Stripe dashboard.
  • Upload Stripe's verification file to yourstore.com/.well-known/apple-developer-merchantid-domain-association (well-behaved modules handle this for you; confirm the file is reachable over HTTPS).
  • Enable the Payment Request / wallet button in the module settings.

Google Pay needs no file. It activates as soon as the wallet button is enabled. Wallet buttons are one of the clearer mobile-conversion wins available to a PrestaShop store, though the size of the gain depends entirely on how much of your traffic is mobile and how rough your current checkout is, measure it on your own store rather than trusting a headline percentage.

Disputes and chargebacks

Accepting cards means accepting the occasional dispute; the goal is to make responding to one a five-minute task, not a scavenger hunt across two systems. Three habits do most of the work:

  • Respond inside Stripe's evidence window. You get a fixed number of days to submit evidence, order confirmation, shipping tracking, delivery confirmation, any customer correspondence. Miss it and the dispute is lost by default.
  • Use Stripe Radar. Radar scores every transaction for fraud and can block or queue the risky ones before they become disputes; the baseline version is included, and you can add custom rules at the higher tier.
  • Keep the evidence where you can reach it. A module that records the Stripe transaction against the PrestaShop order, and exposes refunds and dispute status in the back office, means you're not logging into Stripe and cross-referencing order numbers under a deadline. (This is one of the things our Express Checkout module pulls into PrestaShop's own admin: charges, refunds and payment data sit against the order, so the evidence is already assembled.)

Keeping the Stripe checkout fast

A careless Stripe integration can add seconds to your checkout, which is the last place you can afford to be slow. Three rules keep it tight:

  • Load Stripe.js asynchronously so it never blocks the page from rendering.
  • Initialise the payment form only when it's needed, at the payment step, not on the cart or every product page.
  • Use Stripe's Payment Element, its current unified component, instead of the older Card Element. One integration then surfaces whatever payment methods are relevant to the shopper's country, cards, wallets, and local methods, without separate code paths.

That last point is where Stripe quietly earns its place for cross-border stores: the same Payment Element can present local methods that European shoppers expect and trust. If your customers are in markets with strong local habits, that's worth leaning into, see what those expectations look like in payment methods for European e-commerce, the conversion case for offering them in BLIK, iDEAL and Bancontact, and the buy-now-pay-later angle (Klarna and friends, which Stripe can surface too) in buy now, pay later. For Polish stores in particular, if you need full native P24 coverage or Polish-market features, it's worth comparing Stripe's Przelewy24 support with a dedicated Przelewy24 module, which we walk through in Przelewy24 for PrestaShop.

Where the Payment Element meets your checkout layout

Wiring Stripe correctly gets the payment to clear; how the payment step looks decides how many customers reach it. If you want Stripe's card field, the Apple Pay / Google Pay wallet button and any local methods to appear inside one clean, single-page payment step, rather than scattered across a multi-step default checkout, that's a checkout-layer decision that sits alongside the Stripe wiring, not inside it. Our Checkout Revolution module is built for exactly that single-step presentation, and our Stripe Express Checkout module is what handles the Stripe side underneath it. Used together, the customer sees one streamlined payment step with the wallet button up top and cards below, while everything you set up in this guide (webhooks, order-state sync, SCA) keeps reconciling cleanly behind it.

Troubleshooting the PrestaShop-specific failures

Money in Stripe, order still pending

Almost always a webhook problem: the endpoint is unreachable, blocked, or signed with the wrong secret. Check Developers → Webhooks for failed deliveries, confirm the signing secret in the module matches the endpoint, and make sure no CDN or firewall is intercepting the call. This is the number-one Stripe support ticket on PrestaShop, and it's the reason Step 3 exists.

Duplicate orders

Two paths create the same order, the webhook and the customer's return-from-payment redirect, or the customer double-clicks pay. A correctly built module uses idempotency keys and checks for an existing order keyed on the payment intent before creating a new one. If you're seeing duplicates, the module isn't deduplicating, and that's a module problem, not a configuration one.

Currency mismatches

Stripe charges in the currency you tell it to. If PrestaShop displays a price in EUR but the module creates the payment intent in USD, the customer is billed a different amount than they saw. The module must read the cart's active currency and pass that exact ISO code to Stripe. Verify this if you run a multi-currency store.

The going-live checklist

Before you swap test keys for live keys, confirm every line:

  • All four test-card scenarios pass, success, decline, 3DS2 challenge, refund.
  • Webhooks are configured and you've seen a test event arrive and process.
  • Order-state mapping is correct (payment_intent.succeeded → Payment accepted).
  • Confirmation emails send after a successful payment.
  • A refund issued from the PrestaShop back office reaches Stripe and updates the order.
  • Apple Pay domain verification is complete and the wallet button renders on mobile.
  • Stripe Radar has at least a baseline rule (e.g. block countries you don't ship to).
  • The whole flow works on a real phone, not just a desktop browser.

Stripe is a strong default for PrestaShop because the hard parts, SCA, wallets, dozens of payment methods from one integration, are handled by the platform once the wiring is right. The wiring is the work, and it's almost entirely about webhooks and order-state sync, which is where a PrestaShop-native module pays for itself: our mypresta.rocks Stripe Express Checkout module verifies webhook signatures, syncs charges and refunds straight onto your orders, and puts the Apple Pay / Google Pay button on the pages where customers are ready to buy, so the integration you set up today keeps reconciling cleanly long after you've stopped watching it. And since offering the methods your customers actually reach for is itself a conversion lever, it's worth remembering why more payment options means more sales when you decide which to switch on.

Frequently asked questions

The payment shows as succeeded in Stripe but the PrestaShop order is still pending, what's wrong?

The webhook isn't reaching your store. Stripe confirms anything that happens outside the live checkout window (a delayed clear, a refund, a dispute) by calling your module's webhook endpoint, if that endpoint is unreachable, blocked by Cloudflare or a firewall, shadowed by an .htaccess rule, or signed with a stale whsec_ secret, PrestaShop never learns the payment cleared. Open Developers → Webhooks in Stripe and look for failed delivery attempts, confirm the signing secret in the module matches the endpoint, and check your PHP error log. This is the number-one Stripe support ticket on PrestaShop.

Which Stripe events does the PrestaShop module need to subscribe to?

At minimum: payment_intent.succeeded (drives the order to Payment accepted), payment_intent.payment_failed (handles declines), charge.dispute.created (surfaces chargebacks early), and charge.refunded (keeps Stripe-side refunds in sync). Add checkout.session.completed if you use Stripe's hosted Checkout rather than an embedded form. Subscribe to those, copy the endpoint's whsec_ signing secret into the module, then send a test event from the dashboard to confirm it processes.

Do I need to do anything special for SCA / 3D Secure 2?

Not if your module uses the Payment Intents API. Stripe decides when a 3D Secure 2 challenge is required and runs the authentication flow itself, your store just handles the response. That's why the Payment Intents requirement is the first thing to confirm before installing a module; a module still built on the legacy Charges API can mishandle European SCA. Test it with card 4000 0000 0000 3220, which forces a 3DS2 challenge, and verify the customer lands back on the order rather than the cart after authenticating.

Why are some customers getting "no such payment intent" errors?

Almost always mixed test and live keys. A pk_live_ publishable key paired with an sk_test_ secret key (or the reverse) makes Stripe look for a payment intent in the wrong environment, which surfaces as that error. Both keys must be in the same mode. Re-check the publishable and secret keys in the module config and make sure they're both test or both live, matching the mode you intend to run in.

Do I need separate setup for Apple Pay and Google Pay?

They both ride on Stripe's Payment Request / Express Checkout button, so enabling that button turns on both. The one extra step is for Apple Pay only: domain verification. Register your domain under Settings → Payments → Payment methods → Apple Pay in Stripe and make sure the verification file at yourstore.com/.well-known/apple-developer-merchantid-domain-association is reachable over HTTPS (good modules place it for you). Google Pay needs no file. It activates as soon as the wallet button is enabled.

Share this post:
David Miller

David Miller

Founder, mypresta.rocks

David Miller is a PrestaShop specialist with over a decade of hands-on experience and the founder of mypresta.rocks, a software studio in Tychy, Poland. He builds and maintains a catalogue of 152 PrestaShop modules, including 21 "Revolution" suites spanning SEO, checkout, security, performance, marketing, search, support, and warehouse operations, that improve real stores every day, all tested against PrestaShop 1.7.8, 8.x, and 9.x. He also acts as caretaker for production stores turning over millions in annual sales, so his work is judged on live revenue, not demos. His experience runs the full breadth of ecommerce, performance, security, SEO, and marketing, and reaches beyond PrestaShop to WooCommerce, Shopify, and custom-built systems. On the blog he writes about the code-aware side of PrestaShop: what the platform really does under the hood, what breaks in production, and which fixes hold up.

Comments

No comments yet. Be the first!
Enjoyed this article?

Get our latest tips, guides and module updates delivered to your inbox.

You may unsubscribe at any moment. For that purpose, please find our contact info in the legal notice.

Loading...
Back to top