How Drupal Commerce Stripe payments work on your store
Cards and wallets at checkout on a self-hosted Drupal site are handled by the contributed Commerce Stripe module from Drupal.org, installed inside your own Drupal site and running on your own servers or cloud accounts. The module connects Drupal Commerce to Stripe so that shoppers can pay on your checkout while the payment itself is processed by Stripe. Drupal Commerce keeps ownership of the order, the checkout steps, the payment gateway configuration and the local payment records, while Stripe captures the card, offers wallet buttons and runs the customer authentication steps that the card network or issuer requires.
That split shapes most of the build decisions. Your team decides which checkout pane and payment flow the shopper sees, how a Stripe payment maps to a Drupal Commerce payment and order state, and how refunds and failed attempts are recorded. Stripe decides what methods are available to a given shopper and currency, and whether an extra authentication challenge is needed. Before any build starts, confirm on the module's Drupal.org project page which release supports your Drupal and Drupal Commerce versions, which Stripe APIs it uses, and whether it supports the Payment Element. Do not assume these features from older guides or blog posts, because the Card Element and Payment Element work differently and affect your checkout design.
Ask us to document the confirmed module release, the Stripe API version and the flows you intend to offer in a written scope before development begins. This record also tells your security and compliance reviewers which card data stays with Stripe and which data passes through your Drupal site, which matters for the PCI DSS scope discussion covered later on this page.
What a Drupal Commerce Stripe build needs before work starts
Six items need to be settled before a Commerce Stripe build starts. Platform versions, the Commerce installation, Stripe credentials, a public HTTPS endpoint, the hosting stack and the state of any legacy store all shape the payment design, so they are best confirmed together in the first planning session.
Target Drupal version and PHP
Drupal 11 is the current major version. Drupal 10 requires PHP 8.1 or later, Drupal 11 requires PHP 8.3 or later and Drupal 12 requires PHP 8.5 or later. Drupal 10 reaches end of life on December 9, 2026, so a new store built on it will need an upgrade plan early. Confirm which Drupal versions the Commerce Stripe release you select supports, along with the Stripe API version it targets, on its project page before choosing a platform version.
Commerce installation and modules
Drupal Commerce is installed through Composer with its core store entities, plus Commerce Payment and the Stripe integration module. Record the exact module versions in the codebase so that Stripe, Commerce and Drupal core upgrade together. Check whether the Stripe module pulls in a Stripe PHP library version that conflicts with other payment or API modules in your stack.
Stripe account and API keys
Decide which Stripe account, test and live modes, and key sets the store will use before development begins. Publishable and secret keys belong in environment configuration, never in exported configuration or version control. Confirm who in your organization owns the account, who can rotate keys and how webhook signing secrets will be stored and recorded.
HTTPS and public webhook endpoint
Stripe sends webhook events to a publicly reachable HTTPS address, so staging and production need a valid certificate and a route that is not blocked by a VPN, IP allowlist or basic authentication. Plan the endpoint path, the firewall rules that allow Stripe to deliver events and a way to replay failed deliveries in test mode. Webhook signature checks depend on the raw request body, so confirm that no proxy rewrites it.
Database and web server
Drupal runs on Apache or Nginx with MariaDB, MySQL, PostgreSQL or SQLite as the database. Commerce stores orders, payment records and webhook-driven state transitions in this database, so choose a production engine with backups and point-in-time recovery that your team can operate. Confirm PHP extensions, cron scheduling and queue workers, since payment status updates often depend on them.
Legacy Drupal 7 stores
Drupal 6 and 7 sites cannot be updated in place to Drupal 10 or later. They are migrated into a new site with the core Migrate modules or Drush, and themes must be rebuilt. Drupal 7 security support ended on January 5, 2025, so a legacy store that cannot migrate yet needs an extended security support provider. Treat the Stripe integration as new work on the target site, and plan the migration of existing payment references and order history separately.
Configuring Commerce Stripe in the right order
This sequence takes a Drupal Commerce store from installed modules to a verified test payment, with each step confirmed before the next one depends on it. The order matters because keys, the gateway entity, webhooks and checkout configuration each rely on the one before. Your team or a partner can run it against a staging site before any live card is charged.
Confirm Commerce and Stripe module releases
Install Drupal Commerce and the Commerce Stripe module on a non-production copy of the site, using the release that your Drupal core version supports. Check the module's Drupal.org project page for its supported core versions and confirm the release against your Composer constraints before you go further. Done means the site boots, the Commerce modules and Stripe module appear as enabled in the extension list, and the status report shows no missing dependencies.
Create Stripe test and live accounts
Your organization owns the Stripe accounts, so an administrator with billing authority creates them and assigns roles to the people who will manage keys and webhooks. Keep the test and live environments separate from the start, and record which person can rotate keys. Done means you can sign in to the Stripe Dashboard in test mode and see the test API keys and webhook settings for the account.
Store API keys outside the codebase
Place the publishable and secret keys in environment variables, a secrets manager or a settings file excluded from version control, never in exported configuration or the Git repository. Confirm with your Commerce Stripe documentation which key fields the gateway form expects and how your hosting platform injects them. Done means a configuration export contains no secret key values and the test keys load on the staging site.
Create the gateway and select checkout mode
In Commerce, create a Stripe payment gateway entity under the payment gateway configuration, using the test keys first. Choose the integration type that matches your plan: Payment Element, or the legacy Card Element if you must support an existing flow, and enable the wallet or Express Checkout options you need. Done means the gateway saves in test mode, shows the chosen integration type, and the Stripe test environment is listed as active.
Register the webhook and its signing secret
In the Stripe Dashboard, add an endpoint pointing to the webhook route on your staging site, select the event types the gateway documentation requires, and copy the signing secret into the gateway configuration. Confirm the route is reachable from the public internet and not blocked by a firewall or basic authentication. Done means a test event sent from the Dashboard appears in the Stripe event log with a successful response from your site.
Add the gateway to checkout and set payment states
Enable the Stripe gateway for the store, then add it to the checkout payment step in the checkout flow configuration. Map the order and payment states so that a successful authorization, a captured payment and a failed payment each move the order to the state your fulfillment process expects. Done means the payment step lists the gateway for the target store and the state mapping matches your written order lifecycle.
Run an end-to-end test order
Place a test order using a Stripe test card through the storefront, then check the order record, the payment record in Commerce and the matching payment in the Stripe Dashboard. Repeat with a card that requires authentication and with a declined card, and confirm the webhook events for each outcome were delivered successfully. Done means each test order reaches its expected order and payment state, and the records in Commerce and Stripe agree before you switch to live keys.
Payment Element or legacy Card Element: choosing the checkout method
A new store has no existing checkout code to preserve, so the decision is mostly about which integration the installed Commerce Stripe release supports and how the team wants to maintain it over the life of the site. The Payment Element renders Stripe's payment form as a single component that can show several payment methods, so the checkout template, payment method selection and validation are handled through the Stripe integration rather than hand-built card fields. Build the checkout flow around that component from the start and avoid configuring the legacy option unless a specific requirement demands it.
- Module release check: Confirm that the Commerce Stripe release you plan to install supports the Payment Element before writing any checkout customization.
- Payment method configuration: Decide which payment methods are offered per market and currency, and confirm each one is enabled in your Stripe account.
- Webhook design: Plan the webhook endpoint and event handling, because payment status updates depend on it.
- Test coverage: Test successful payments, declined cards, abandoned checkouts and authentication challenges across each enabled method.
- Refund path: Verify full and partial refunds from the order admin before launch.
Before go-live, check the module's documentation for the Payment Element configuration keys and confirm the sandbox behavior matches your production settings.
A store already on a Card Element integration has live stored payment data, customized templates and possibly custom code that depends on the legacy form fields. Moving to the Payment Element changes how card data is collected in the browser and how the checkout step is rendered, so the change is a migration with its own risk, not a configuration toggle. Decide whether the legacy option will be kept for a transition period or retired in one release, and document the decision along with the rollback plan.
- Custom code inventory: List every template, form alteration and hook that touches the payment pane, since these will need rework.
- Stored payment data: Confirm how existing saved payment references are handled after the change, and whether customers must re-enter details.
- Legacy configuration: Determine whether the old payment method stays enabled, is disabled per store, or is removed from the codebase.
- Regression testing: Retest checkout end to end, plus refunds on orders placed before and after the change.
- Staged rollout: Run the new method in a staging copy with production-like orders before switching live traffic.
A migration between the two methods requires regression testing of checkout and refunds, so budget that testing as part of the work rather than as a final check.
Stores that want wallets or express checkout add buttons and flows that appear before or alongside the main form, which affects the layout, the cart and address handling, and the conditions under which a payment can complete. Availability depends on the payment method, the buyer's device and browser, the store's region and the Stripe account configuration, so the design must be verified per market rather than assumed. Treat express options as a scoped feature with its own acceptance criteria.
- Availability check: Confirm with Stripe and with the module documentation that Express Checkout is available for each wallet you plan to offer in each region you sell to.
- Shipping and address data: Decide which fields the express flow must collect and how shipping rates are calculated before payment.
- Device testing: Test wallet buttons on the browsers and devices your customers use, including mobile.
- Order flow: Verify that orders created through express flows get the same tax, stock and notification handling as standard checkout.
- Refund testing: Confirm refunds work for orders paid through each wallet.
Ask the module maintainers and your Stripe contact to confirm current wallet support for your specific region and currency before committing to a design.
How to test webhooks and authentication before go-live
Webhooks are what keep order state correct, so test them as a core part of the build rather than as a final check. When a shopper pays and returns to the site, the browser redirect is not a reliable signal that the payment succeeded: the shopper may close the tab, lose connectivity or never reach the return page. Stripe's webhook events are the path that tells Drupal Commerce a payment was captured, failed or needs further action, so the order transition should depend on those events. A missed event can leave an order stuck in checkout or unpaid after the customer has been charged. A repeated event can record a payment twice, send duplicate confirmations or ship an order that was already fulfilled. Plan a test for each case.
In Stripe test mode, run every outcome your store must handle: a successful card payment, a declined payment, an abandoned checkout, and a payment that triggers strong customer authentication and is completed or left unfinished on the challenge screen. Use the test cards and test events that the Commerce Stripe module documentation recommends, and confirm the exact list against that documentation for the module version you install, since test identifiers can change. Then check three controls. First, confirm that the endpoint rejects requests whose Stripe signature does not verify against the webhook signing secret. Second, replay the same event several times and confirm the order is changed once and nothing is duplicated. Third, make the endpoint fail on purpose and confirm that failed deliveries are logged with enough detail to reconcile them against the Stripe dashboard.
Keeping card data out of your Drupal servers
Card data should never sit in your Drupal database, exported configuration or logs. The controls below keep Stripe secrets and webhook traffic tightly bounded, restrict who can change payment settings, and keep the software that handles payments current. Confirm each one against your own environment and your assessor's view of PCI DSS scope before go-live.
Secret keys in environment configuration
Store the Stripe secret key and webhook signing secret in environment variables or your secrets manager, not in the exported Drupal configuration that gets committed to Git and copied between environments. A secret key in a config export is one of the most common ways credentials leak from a Drupal project. Check that test and live keys are separated, that staging never holds live keys, and that rotation has a documented owner.
Verifying webhook signatures
Stripe signs each webhook request, and the Commerce Stripe integration should reject any event whose signature does not match the signing secret for that endpoint. Without this check, anyone who finds the URL can post fake payment confirmations and mark unpaid orders as complete. Test the rejection path deliberately by sending a request with a wrong signature and confirming the order state does not change.
Restricting the webhook route
The webhook endpoint must accept only POST requests from the payment flow and should be excluded from login, caching and bot-challenge rules that would break delivery. Limit request body size, and rate-limit at the reverse proxy or web application firewall without blocking Stripe's delivery addresses by mistake. Confirm the route is reachable over HTTPS only and that access logs do not record full request bodies.
Limiting gateway and payment access
Gateway settings, refunds and payment records should sit behind dedicated Drupal permissions, separate from order editing and content administration. Review which roles can change the Stripe configuration, which can see payment method details, and which can issue refunds. Keep administrator accounts individual, enforce two-factor sign-in where your identity provider supports it, and review role assignments on a fixed schedule.
Staying on supported releases
Subscribe to Drupal Security Team advisories and track both Drupal core and the Commerce Stripe module, since a vulnerability in either can expose payment flows. Security releases are published on the third Wednesday of the month, so plan a patch window that can absorb them quickly. Check the module's compatibility with your Drupal version before upgrading, and confirm with the module maintainers which release lines receive fixes.
Logging events without card data
Log payment events such as charge created, payment requires action, refund issued and webhook rejected, using Stripe object identifiers and order numbers. Never write card numbers, full expiry dates or raw payment method payloads to Drupal logs, watchdog tables or error trackers. Check your log shipper and error tracking tool for the same rule, because logs often leave the Drupal server and reach retention systems you may not have reviewed.
Why Stripe payments fail on Drupal Commerce checkout
This table pairs common Stripe failures on Drupal Commerce checkouts with their likely causes and the fix to try first. Read each row as a symptom to check in your own environment, starting with webhook delivery and key configuration, since those cause most stuck or duplicate orders. Confirm module-specific setting names in the Commerce Stripe documentation before changing anything in production.
| Failure | Likely cause | Fix |
|---|---|---|
| Orders stay in pending after a successful charge | Stripe cannot reach the webhook endpoint, so the order never receives the payment event | Check webhook delivery attempts in the Stripe dashboard, confirm the endpoint URL is public and reachable, and replay failed events after the fix |
| Webhook signature errors after key rotation | The signing secret in the site configuration still belongs to the old webhook endpoint | Copy the current signing secret for each endpoint into the Commerce Stripe settings, clear caches, and send a test event to confirm verification passes |
| Checkout works in test mode but fails live | Live API keys or the live webhook endpoint were not entered, so requests go to the wrong account or events are never signed correctly | Create the live webhook endpoint, enter live keys and the live signing secret, and run a small live payment with a refund afterward |
| Customer sees an authentication challenge that does not complete | The payment flow does not handle required customer authentication steps, so the intent stays unconfirmed | Use the Payment Element flow that supports authentication, confirm the return URL is set, and test a card that triggers a challenge in test mode |
| Apple Pay or Google Pay buttons do not appear | The domain is not registered with the wallet provider, or the device or browser does not support the wallet | Register the live domain with Stripe for each wallet, serve the domain verification file over HTTPS, and test on a supported device |
| Duplicate orders from repeated events | Stripe retries events that were not acknowledged quickly, and the handler creates a new order each time | Make the event handler idempotent by checking the stored payment identifier before creating or completing an order, and return a success response promptly |
| Callbacks fail behind a load balancer or proxy | HTTPS is terminated upstream, so the site builds http URLs or rejects signatures because the forwarded headers are missing | Configure trusted proxy and forwarded protocol headers, confirm the site generates https links, and check the raw request body is not altered before verification |
What buyers ask before building Stripe payments in Drupal Commerce
What drives the cost and effort of a Stripe integration in Drupal Commerce?
The main drivers are the checkout method, the number of gateways, how refunds and order states are handled, whether legacy code must be replaced, and how much testing is required. A single Payment Element checkout with card and wallet options on one store is far smaller than several gateways with partial refunds, deferred capture and custom order states. Ask for a quote that lists each of these items separately, so you can see what is one-time work (configuration, custom code, testing, security review) and what recurs (Stripe fees, Stripe account administration, module updates and retesting after Drupal or module upgrades). Stripe's own fees are charged by Stripe and are not part of any implementation quote.
Can our team build Stripe payments in Drupal Commerce without outside help?
A team can do it alone when the store has one gateway, a standard checkout, and at least one developer with solid Drupal and Commerce experience. The work that usually takes longer than expected is testing across card, wallet and failure paths, verifying webhooks, and reviewing the security and PCI scope of the setup. Those steps need someone who can break the flow on purpose, and a second reviewer helps. If your team lacks that experience or cannot staff an independent review, a fixed-scope engagement can cover the build and the checks in writing before go-live.
How long does a Stripe payments project take?
Duration depends on the same drivers as cost: the checkout method, the number of payment methods, the state of the existing store, how many order and refund flows must be covered, and how quickly your staff can review test results. Stripe account setup, legal and tax decisions, and internal approvals often run in parallel with development and can become the critical path. DeployOpen does not publish timelines. We agree a schedule in writing after reviewing your scope, and the schedule states which items depend on your decisions or access.
What do we need to provide before the work starts?
Plan to provide access to the Stripe account with the roles needed to create API keys, configure webhook endpoints and view test and live data. You will also need decisions on the products to sell, currencies, tax treatment, refund policy, and which wallets or payment methods to offer. A test store or staging environment that matches production is required, along with named staff who will run checkout tests, including card declines, 3-D Secure challenges and refunds. Confirm these items in the statement of work so delays are visible early.
Should we use Stripe Payment Element or the legacy Card Element?
Choose Payment Element for new work, because it is the integration path that supports cards and many wallet and local payment methods through one component, and it handles strong customer authentication flows within the Stripe-hosted elements. The legacy Card Element only accepts card entry, so it does not offer the same range of methods, and existing sites on it should plan a migration. Confirm the current method list, supported Commerce Stripe version and any Express Checkout requirements with the module documentation and Stripe before you commit to a design.
How is PCI scope decided for a Stripe integration?
PCI scope depends on whether card data touches your servers. When Stripe Elements collects card details in the browser and your site only handles tokens or payment intent identifiers, the scope is usually smaller than a design that posts raw card numbers through Drupal. Your server configuration, logging, third-party scripts, and any custom checkout code also affect scope. Ask the assessor or your QSA to review the data flow diagram, and ask DeployOpen to document the design and controls so that your assessor can verify them. DeployOpen prepares evidence but does not issue PCI attestations.
Do Drupal 7 stores need migration before adding Stripe?
Yes, in most cases. Drupal 7 security support ended on January 5, 2025, and Drupal 6 and 7 sites cannot be updated in place to Drupal 10 or later. They must be migrated into a new site, and themes must be rebuilt. Commerce payment code written for an older stack will not carry over directly. If the migration cannot happen yet, the Drupal Association's extended security support program lists certified vendors for sites in that position, but adding new payment flows to an unsupported platform is a risk to weigh carefully before you start.
How DeployOpen works on this
DeployOpen plans, implements, customizes, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure. For Drupal Commerce payments with Stripe, the work starts with a written scope that fixes what gets built, tested and handed over before any build begins.
How we scope
- Confirm which Stripe payment methods, wallets and checkout flows your store needs before choosing the Payment Element or Express Checkout.
- Map the Commerce Stripe version, Drupal core version and PHP version to your hosting before estimating the build.
- Agree in writing which webhook events, order states and refund paths are in scope for the engagement.
How we build
- Configure the Stripe gateway, API keys and webhook endpoint in each environment, with secrets kept out of exported configuration.
- Build checkout, strong customer authentication and order-state handling against Stripe test mode before any live charges.
- Test failed payments, duplicate webhook deliveries, partial refunds and declined cards in a staging copy of your store.
How we hand over
- Deliver a written runbook covering webhook setup, key rotation, refund procedures and the steps for a failed payment.
- Document every custom module, configuration change and third-party dependency so your team can maintain the integration.
- Walk your developers and operations staff through the payment flow, logs and the test cards used during acceptance.
How we support
- Offer ongoing support, module updates and Drupal core upgrades as a retainer after the fixed-scope delivery ends.
- Track Commerce Stripe and Drupal security advisories and schedule updates in your release windows.
- Confirm with your team which monitoring alerts, reconciliation reports and support hours the retainer should cover.

