Accept a payment
Securely accept payments online.
Build a payment form or use a prebuilt checkout page to start accepting online payments.
Build a custom payments integration by embedding UI components on your site, using Stripe Elements. See how this integration compares to Stripe’s other integration types.
The client-side and server-side code builds a checkout form that accepts various payment methods.
Integration effort
Integration type
Combine UI components into a custom payment flow
UI customization
CSS-level customization with the Appearance API
Interested in using Stripe Tax, discounts, shipping, or currency conversion?
Stripe has a Payment Element integration that manages tax, discounts, shipping, and currency conversion for you. See build a checkout page to learn more.
Set up StripeServer-side
First, create a Stripe account or sign in.
Use our official libraries to access the Stripe API from your application:
Create a PaymentIntentServer-side
Note
If you want to render the Payment Element without first creating a PaymentIntent, see Collect payment details before creating an Intent.
The PaymentIntent object represents your intent to collect payment from a customer and tracks charge attempts and state changes throughout the payment process.
Create the PaymentIntent
Create a PaymentIntent on your server with an amount and currency. 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.
Stripe uses your payment methods settings to display the payment methods you have enabled. To see how your payment methods appear to customers, enter a transaction ID or set an order amount and currency in the Dashboard. To override payment methods, manually list any that you want to enable using the payment_method_types attribute.
Note
Always decide how much to charge on the server side, a trusted environment, as opposed to the client. This prevents malicious customers from being able to choose their own prices.
Retrieve the client secret
The PaymentIntent includes a client secret that the client side uses to securely complete the payment process. You can use different approaches to pass the client secret to the client side.
Collect payment detailsClient-side
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.
If you do choose to use an iframe and want to accept Apple Pay or Google Pay, the iframe must have the allow attribute set to equal "payment *"
.
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. For each payment method, the form automatically asks the customer to fill in all necessary payment details.
Customize appearance
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.
Request Apple Pay merchant token
If you’ve configured your integration to accept Apple Pay payments, we recommend configuring the Apple Pay interface to return a merchant token to enable merchant initiated transactions (MIT). Request the relevant merchant token type in 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
When creating a PaymentIntent on your server, also create a CustomerSession 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 offering 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 client secrets for both the PaymentIntent and the CustomerSession. Then, use this Elements instance to create a Payment Element.
// Create the CustomerSession and obtain its clientSecret const res = await fetch("/create-intent-and-customer-session", { method: "POST" }); const { customer_session_client_secret: customerSessionClientSecret } = await res.json(); const elementsOptions = { clientSecret: '{{CLIENT_SECRET}}', 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 confirming the PaymentIntent, Stripe.js automatically controls setting setup_future_usage on the PaymentIntent 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_
when creating the PaymentIntent 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 } })
OptionalLink in your checkout pageClient-side
Let your customer check out faster by using Link in the Payment Element. You can autofill information for any logged-in customer already using Link, regardless of whether they initially saved their information in Link with another business. The default Payment Element integration includes a Link prompt in the card form. To manage Link in the Payment Element, go to your payment method settings.

Collect a customer email address for Link authentication or enrollment
Integration options 
There are two ways you can integrate Link with the Payment Element. Of these, Stripe recommends passing a customer email address to the Payment Element if available. Remember to consider how your checkout flow works when deciding between these options:
Integration option | Checkout flow | Description |
---|---|---|
Pass a customer email address to the Payment Element Recommended |
| Programmatically pass a customer email address to the Payment Element. In this scenario, a customer authenticates to Link directly in the payment form instead of a separate UI component. |
Collect a customer email address in the Payment Element | Your customers enter their email and authenticate or enroll with Link directly in the Payment Element during checkout. | If a customer hasn’t enrolled with Link and they choose a supported payment method in the Payment Element, they’re prompted to save their details using Link. For those who have already enrolled, Link automatically populates their payment information. |
OptionalFetch updates from the serverClient-side
You might want to update attributes on the PaymentIntent after the Payment Element renders, such as the amount (for example, discount codes or shipping costs). You can update the PaymentIntent on your server, then call elements.fetchUpdates to see the new amount reflected in the Payment Element. This example shows you how to create the server endpoint that updates the amount on the PaymentIntent:
This example demonstrates how to update the UI to reflect these changes on the client side:
(async () => { const response = await fetch('/update'); if (response.status === 'requires_payment_method') { const {error} = await elements.fetchUpdates(); } })();
Submit the payment to StripeClient-side
Use stripe.confirmPayment to complete the payment using details from the Payment Element. Provide a return_url to this function to indicate where Stripe should redirect the user after they complete the payment. Your user may be first redirected to an intermediate site, like a bank authorization page, before being redirected to the return_
. Card payments immediately redirect to the return_
when a payment is successful.
If you don’t want to redirect for card payments after payment completion, you can set redirect to if_
. This only redirects customers that check out with redirect-based payment methods.
Make sure the return_
corresponds to a page on your website that provides the status of the payment. When Stripe redirects the customer to the return_
, we provide the following URL query parameters:
Parameter | Description |
---|---|
payment_ | The unique identifier for the PaymentIntent . |
payment_ | The client secret of the PaymentIntent object. |
Caution
If you have tooling that tracks the customer’s browser session, you might need to add the stripe.
domain to the referrer exclude list. Redirects cause some tools to create new sessions, which prevents you from tracking the complete session.
Use one of the query parameters to retrieve the PaymentIntent. Inspect the status of the PaymentIntent to decide what to show your customers. You can also append your own query parameters when providing the return_
, which persist through the redirect process.
Handle post-payment eventsServer-side
Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard webhook tool or follow the webhook guide to receive these events and run actions, such as 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 is what enables you to accept different types of payment methods with a single integration.
In addition to handling the payment_
event, we recommend handling these other events when collecting payments with the Payment Element:
Event | Description | Action |
---|---|---|
payment_intent.succeeded | Sent when a customer successfully completes a payment. | Send the customer an order confirmation and fulfill their order. |
payment_intent.processing | Sent when a customer successfully initiates a payment, but the payment has yet to complete. This event is most commonly sent when the customer initiates a bank debit. It’s followed by either a payment_ or payment_ event in the future. | Send the customer an order confirmation that indicates their payment is pending. For digital goods, you might want to fulfill the order before waiting for payment to complete. |
payment_intent.payment_failed | Sent when a customer attempts a payment, but the payment fails. | If a payment transitions from processing to payment_ , offer the customer another attempt to pay. |
Test your integration
To test your custom payments integration:
- Create a Payment Intent and retrieve the client secret.
- Fill out the payment details with a method from the following table.
- Enter any future date for card expiry.
- Enter any 3-digit number for CVC.
- Enter any billing postal code.
- Submit the payment to Stripe. You’re redirected to your
return_
.url - Go to the Dashboard and look for the payment on the Transactions page. If your payment succeeded, you’ll see it in that list.
- Click your payment to see more details, like billing information and the list of purchased items. You can use this information to fulfill the order.
Learn more about testing your integration.
See Testing for additional information to test your integration.
OptionalAdd more payment methods
The Payment Element supports many payment methods by default. You have to take additional steps to enable and display some payment methods.
Affirm 
To begin using Affirm, you must enable it in the Dashboard. When you create a PaymentIntent with the Affirm payment method, you need to include a shipping address. This example suggests passing the shipping information on the client after the customer selects their payment method. Learn more about using Affirm with Stripe.
Test Affirm 
Learn how to test different scenarios using the following table:
Scenario | How to test |
---|---|
Your customer successfully pays with Affirm. | Fill out the form (make sure to include a shipping address) and authenticate the payment. |
Your customer fails to authenticate on the Affirm redirect page. | Fill out the form and click Fail test payment on the redirect page. |
Afterpay (Clearpay) 
When you create a PaymentIntent with the Afterpay payment method, you need to include a shipping address. Learn more about using Afterpay with Stripe.
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. The example below uses the automatic_payment_methods attribute but you can list afterpay_
with payment method types. In the latest version of the API, specifying the automatic_
parameter is optional because Stripe enables its functionality by default. Regardless of which option you choose, make sure that you enable Afterpay Clearpay in the Dashboard.
Test Afterpay (Clearpay) 
Learn how to test different scenarios using the following table:
Scenario | How to test |
---|---|
Your customer successfully pays with Afterpay. | Fill out the form (make sure to include a shipping address) and authenticate the payment. |
Your customer fails to authenticate on the Afterpay redirect page. | Fill out the form and click Fail test payment on the redirect page. |
Apple Pay and Google Pay 
When you enable card payments, we display Apple Pay and Google Pay for customers whose environment meets the wallet display conditions. To accept payments from these wallets, you must also:
- Enable them in your payment methods settings. Apple Pay is enabled by default.
- Serve your application over HTTPS in development and production.
- Register your domain.
- Fetch updates from the server if you update the amount of a PaymentIntent to keep the wallet’s payment modal in sync.
Regional TestingIndia
Stripe Elements doesn’t support Google Pay or Apple Pay for Stripe accounts and customers in India. Therefore, you can’t test your Google Pay or Apple Pay integration if the tester’s IP address is in India, even if the Stripe account is based outside India.
Learn more about using Apple Pay and Google Pay with Stripe.
ACH Direct Debit 
When using the Payment Element with the ACH Direct Debit payment method, follow these steps:
Create a Customer object.
Specify the customer ID when creating the
PaymentIntent
.Select a verification method.
When using the ACH Direct Debit payment method with the Payment Element, you can only select automatic
or instant
.
Learn more about using ACH Direct Debit with Stripe.
Test ACH Direct Debit 
Scenario | How to test |
---|---|
Your customer successfully pays with a US bank account using instant verification. | Select US bank account and fill out the form. Click the test institution. Follow the instructions on the modal to link your bank account. Click your payment button. |
Your customer successfully pays with a US bank account using microdeposits. | Select US bank account and fill out the form. Click Enter bank details manually instead. Follow the instructions on the modal to link your bank account. You may use these test account numbers. Click your payment button. |
Your customer fails to complete the bank account linking process. | Select US bank account and click the test institution or Enter bank details manually instead. Close the modal without completing it. |
BLIK 
When using the Payment Element with BLIK, the user can close the modal prompting them to authorize the payment in their banking app. This triggers a redirect to your return_
and doesn’t return the user to the checkout page. Learn more about using BLIK with Stripe.
To handle users closing the modal, in the server-side handler for your return_
, inspect the Payment Intent’s status
to see if it’s succeeded
or still requires_
(meaning the user has closed the modal without authorizing), dealing with each case as needed.
QR code payment methods 
When using the Payment Element with a QR code based payment method (WeChat Pay, PayNow, Pix, PromptPay, Cash App Pay), the user can close the QR code modal. This triggers a redirect to your return_
and doesn’t return the user to the checkout page.
To handle users closing QR code modals, at the server-side handler for your return_
, inspect the Payment Intent’s status
to see if it’s succeeded
or still requires_
(meaning the user has closed the modal without paying), dealing with each case as needed.
Alternatively, prevent the automatic redirect to your return_
by passing the advanced optional parameter redirect=if_
, which prevents the redirect when closing a QR code modal.
Cash App Pay 
The Payment Element renders a dynamic form differently in desktop web or mobile web since it uses different customer authentication methods. Learn more about using Cash App Pay with Stripe.
PayPal 
To use PayPal, make sure you’re on a registered domain.
Disclose Stripe to your customers 
Stripe collects information on customer interactions with Elements to provide services to you, prevent fraud, and improve its services. This includes using cookies and IP addresses to identify which Elements a customer saw during a single checkout session. You’re responsible for disclosing and obtaining all rights and consents necessary for Stripe to use data in these ways. For more information, visit our privacy center.