Finalize payments on the server
Build an integration where you render the Payment Element before you create a PaymentIntent or SetupIntent, then confirm the Intent from your server.
The Payment Element allows you to accept multiple payment methods using a single integration. This integration builds a custom payment flow where you render the Payment Element, create the PaymentIntent, and confirm the payment from your server.
Set up StripeServer-side
First, create a Stripe account or sign in.
Use our official libraries to access the Stripe API from your application:
Enable payment methods
Caution
This integration path doesn’t support BLIK or pre-authorized debits that use the Automated Clearing Settlement System (ACSS).
View your payment methods settings and enable the payment methods you want to support. You need at least one payment method enabled to create a PaymentIntent.
By default, Stripe enables cards and other prevalent payment methods that can help you reach more customers, but we recommend turning on additional payment methods that are relevant for your business and customers. See Payment method support for product and payment method support, and our pricing page for fees.
Collect payment detailsClient-side
You’re ready to collect payment details on the client with the Payment Element. The Payment Element is a prebuilt UI component that simplifies collecting payment details for a variety of payment methods.
The Payment Element contains an iframe that securely sends payment information to Stripe over an HTTPS connection. Avoid placing the Payment Element within another iframe because some payment methods require redirecting to another page for payment confirmation.
The checkout page address must start with https://
rather than http://
for your integration to work. You can test your integration without using HTTPS, but remember to enable it when you’re ready to accept live payments.
The Payment Element renders a dynamic form that allows your customer to pick a payment method. The form automatically collects all necessary payments details for the payment method selected by the customer.
You can customize the Payment Element to match the design of your site by passing the appearance object into options
when creating the Elements
provider.
Collect addresses
By default, the Payment Element only collects the necessary billing address details. To collect a customer’s full billing address (to calculate the tax for digital goods and services, for example) or shipping address, use the Address Element.
OptionalCustomize the layoutClient-side
You can customize the Payment Element’s layout (accordion or tabs) to fit your checkout interface. For more information about each of the properties, see elements.create.
The following image is the same Payment Element rendered using different layout configurations:

Payment Element layouts
OptionalCustomize the appearanceClient-side
Now that you’ve added the Payment Element to your page, you can customize its appearance to make it fit your design. To learn more about customizing the Payment Element, see Elements Appearance API.

Customize the Payment Element
OptionalSave and retrieve customer payment methods
You can configure the Payment Element to save your customer’s payment methods for future use. This section shows you how to integrate the saved payment methods feature, which enables the Payment Element to:
- Prompt buyers for consent to save a payment method
- Save payment methods when buyers provide consent
- Display saved payment methods to buyers for future purchases
- Automatically update lost or expired cards when buyers replace them

Save payment methods.

Reuse a previously saved payment method.
Enable saving the payment method in the Payment Element
Create a CustomerSession on your server by providing the Customer ID and enabling the payment_element component for your session. Configure which saved payment method features you want to enable. For instance, enabling payment_method_save displays a checkbox that allows customers to save their payment details for future use.
You can specify setup_
on a PaymentIntent or Checkout Session to override the default behavior for saving payment methods. This ensures that you automatically save the payment method for future use, even if the customer doesn’t explicitly choose to save it.
Caution
Allowing buyers to remove their saved payment methods by enabling payment_method_remove impacts subscriptions that depend on that payment method. Removing the payment method detaches the PaymentMethod from that Customer.
Your Elements instance uses the CustomerSession’s client secret to access that customer’s saved payment methods. Handle errors properly when you create the CustomerSession. If an error occurs, you don’t need to provide the CustomerSession client secret to the Elements instance, as it’s optional.
Create the Elements instance using the CustomerSession client secret. Then, use the Elements instance to create a Payment Element.
// Create the CustomerSession and obtain its clientSecret const res = await fetch("/create-customer-session", { method: "POST" }); const { customer_session_client_secret: customerSessionClientSecret } = await res.json(); const elementsOptions = { mode: 'payment', amount: 1099, currency: 'usd', customerSessionClientSecret, // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret // and CustomerSession's client secret obtained in a previous step const elements = stripe.elements(elementsOptions); // Create and mount the Payment Element const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element');
When creating the ConfirmationToken, Stripe.js automatically controls setting setup_future_usage on the ConfirmationToken and allow_redisplay on the PaymentMethod, depending on whether the customer checked the box to save their payment details.
Enforce CVC recollection
Optionally, specify require_
both when creating the PaymentIntent and when creating Elements to enforce CVC recollection when a customer is paying with a card.
Detect the selection of a saved payment method
To control dynamic content when a saved payment method is selected, listen to the Payment Element change
event, which is populated with the selected payment method.
paymentElement.on('change', function(event) { if (event.value.payment_method) { // Control dynamic content if a saved payment method is selected } })
OptionalDynamically update payment detailsClient-side
As the customer performs actions that change the payment details (for example, applying a discount code), update the Elements instance to reflect the new values. Some payment methods, like Apple Pay and Google Pay, show the amount in the UI, so make sure it’s always accurate and up to date.
OptionalAdditional Elements optionsClient-side
The Elements object accepts additional options that influence payment collection. Based on the options provided, the Payment Element displays available payment methods from those you’ve enabled. Learn more about payment method support.
Property | Type | Description | Required |
---|---|---|---|
mode |
| Indicates whether the Payment Element is used with a PaymentIntent, SetupIntent, or Subscription. | Yes |
currency | string | The currency of the amount to charge the customer. | Yes |
amount | number | The amount to charge the customer, shown in Apple Pay, Google Pay, or BNPL UIs. | For payment and subscription mode |
setupFutureUsage |
| Indicates that you intend to make future payments with the payment details collected by the Payment Element. | No |
captureMethod |
| Controls when to capture the funds from the customer’s account. | No |
onBehalfOf | string | Connect only. The Stripe account ID, which is the business of record. See use cases to determine if this option is relevant for your integration. | No |
paymentMethodTypes | string[] | A list of payment method types to render. You can omit this attribute to manage your payment methods in the Stripe Dashboard. | No |
paymentMethodConfiguration | string | The payment method configuration to use when managing your payment methods in the Stripe Dashboard. If not specified, your default configuration is used. | No |
paymentMethodCreation | manual | Allows PaymentMethods to be created from the Elements instance using stripe.createPaymentMethod. | No |
paymentMethodOptions | {us_ | Verification options for the us_ payment method. Accepts the same verification methods as Payment Intents. | No |
paymentMethodOptions | {card: {installments: {enabled: boolean}}} | Allows manually enabling the card installment plan selection UI if applicable when you aren’t managing your payment methods in the Stripe Dashboard. You must set mode='payment' and explicitly specify paymentMethodTypes . Otherwise an error is raised. Incompatible with paymentMethodCreation='manual' . | No |
Create the ConfirmationTokenClient-side
Use createPaymentMethod through a legacy implementation
If you’re using a legacy implementation, you might be using the information from stripe.
to finalize payments on the server. While we encourage you to follow this guide to Migrate to Confirmation Tokens you can still access our old documentation to Finalize payments on the server
When the customer submits your payment form, call stripe.createConfirmationToken to create a ConfirmationToken to send to your server for additional validation or business logic before payment confirmation.
Confirming the PaymentIntent generates a PaymentMethod. You can read the payment_method ID off the PaymentIntent confirmation response.
Caution
You must immediately use the created ConfirmationToken to confirm a PaymentIntent; if unused, it expires after 12 hours.
OptionalInsert custom business logicServer-side
Before creating and confirming the payment, you can run your custom business logic. Information about the customer’s payment details is available by looking at the ConfirmationToken you created. If you’re using the Stripe SDK, make sure your SDK is up-to-date to these versions:
stripe-php v13.
15. 0 stripe-go v76.
22. 0 stripe-ruby v10.
13. 0 stripe-java v24.
21. 0 stripe-node v14.
22. 0 stripe-python v8.
8. 0 stripe-dotnet v43.
20. 0
Create and submit the payment to StripeServer-side
When the customer submits your payment form, use a PaymentIntent to facilitate the confirmation and payment process. Create a PaymentIntent on your server with an amount
and currency
specified. In the latest version of the API, specifying the automatic_
parameter is optional because Stripe enables its functionality by default. You can manage payment methods from the Dashboard. Stripe handles the return of eligible payment methods based on factors such as the transaction’s amount, currency, and payment flow. To prevent malicious customers from choosing their own prices, always decide how much to charge on the server-side (a trusted environment) and not the client.
You can use the ConfirmationToken sent by your client to create and confirm the PaymentIntent in a single request.
const stripe = require("stripe")(
); const express = require('express'); const app = express(); app.set('trust proxy', true); app.use(express.json()); app.use(express.static(".")); app.post('/create-confirm-intent', async (req, res) => { try { const intent = await stripe.paymentIntents.create({ confirm: true, amount: 1099, currency: 'usd', // In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, confirmation_token: req.body.confirmationTokenId, // the ConfirmationToken ID sent by your client }); res.json({ client_secret: intent.client_secret, status: intent.status }); } catch (err) { res.json({ error: err }) } }); app.listen(3000, () => { console.log('Running on port 3000'); });"sk_test_BQokikJOvBiI2HlWgH4olfQ2"
Handle any next actionsClient-side
When the PaymentIntent requires additional action from the customer, such as authenticating with 3D Secure or redirecting to a different site, you need to trigger those actions. Use stripe.
to trigger the UI for handling customer action and completing the payment.
OptionalHandle post-payment events
Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.
Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also helps you accept more payment methods in the future. Learn about the differences between all supported payment methods.
Handle events manually in the Dashboard
Use the Dashboard to View your test payments in the Dashboard, send email receipts, handle payouts, or retry failed payments.
Build a custom webhook
Build a custom webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.
Integrate a prebuilt app
Handle common business events, such as automation or marketing and sales, by integrating a partner application.