Sign in
An image of the Stripe logo
Create account
Sign in
Home
Payments
Business operations
Financial services
Developer tools
No-code
All products
Home
Payments
Business operations
Home
Payments
Business operations
Financial services
Developer tools
Support
Overview
Overview
How cards work
Quickstart
Accept a payment
Add funds to your balance
Share payment links
Faster checkout with Link
More payment scenarios
U.S. and Canadian cards
Testing
Payments
·
HomePaymentsOnline payments

Accept a payment

Securely accept payments online.
Customer location
Size
Theme
Layout
The demo displays Google Pay or Apple Pay only on their corresponding platform if you have an active card associated with the account.
Complexity:

Customize with the Appearance API. Clone a sample integration from the docs or on GitHub.

If you’re looking for the individual Card Element guide, see Accept a card payment.

You can build a custom payment flow by embedding the Payment Element, which allows you to accept multiple payment methods using a single integration.

Set up Stripe
Server-side

First, you need a Stripe account. Register now.

Use our official libraries for access to the Stripe API from your application:

Command Line
# For detailed setup, see our quickstarts at https://stripe.com/docs/development/quickstart bundle add stripe

Enable payment methods

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 in the next step. Stripe enables card payments by default so you can skip this step if you want to start with cards only. 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 the Payment method integration options page for information on product and payment method support, and see our pricing page for fees.

Create a PaymentIntent
Server-side

Stripe uses a PaymentIntent object to represent your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process.

The payment methods shown to customers during the checkout process are also included on the PaymentIntent. You can let Stripe select enabled payment methods from your Dashboard or you can list them manually. Unless your integration requires that you list payment methods manually, we recommend letting Stripe select payment methods from your Dashboard. This is because Stripe evaluates the currency, payment method restrictions, and other parameters to determine the list of supported payment methods. We prioritize payment methods that help increase conversion and are most relevant to the currency and customer’s location. For example, if you pass the eur currency on the PaymentIntent and have OXXO enabled in the Dashboard, the customer won’t see OXXO because OXXO doesn’t support eur payments.

Each payment method must support the currency passed in the PaymentIntent and your business must operate in one of the countries each payment method supports. See Payment method integration options to understand which payment methods support which currencies.

If you use payment_method_types instead of automatic_payment_methods, Stripe returns an error when you specify a payment method type that is not supported in a particular currency.

Create a PaymentIntent on your server with an amount, currency, and automatic_payment_methods enabled. With automatic_payment_methods enabled, Stripe creates the PaymentIntent using the payment methods you configured in the Dashboard. If you don’t want to use the Dashboard or if you want to specify payment methods manually, you can list them using the payment_method_types attribute. 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.

Command Line
curl https://api.stripe.com/v1/payment_intents \ -u
sk_test_4eC39HqLyjWDarjtT1zdp7dc
: \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]"=true

Included in the returned PaymentIntent is a client secret, which the client side uses to securely complete the payment process instead of passing the entire PaymentIntent object. You can use different approaches to pass the client secret to the client side.

You can retrieve the client secret from an endpoint on your server using the browser’s fetch function on the client side. This approach is generally most suitable when your client side is a single-page application, particularly one built with a modern frontend framework such as React. This example shows how to create the server endpoint that serves the client secret:

main.rb
get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end

This example demonstrates how to fetch the client secret with JavaScript on the client side:

(async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })();

Collect payment details
Client-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 the payment information to Stripe over an HTTPS connection. The checkout page address must also start with https:// rather than http:// for your integration to work.

You can test your integration without using HTTPS. Enable it when you’re ready to accept live payments.

Set up Stripe.js

The Payment Element is automatically available as a feature of Stripe.js. Include the Stripe.js script on your checkout page by adding it to the head of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Do not include the script in a bundle or host a copy of it yourself.

checkout.html
<head> <title>Checkout</title> <script src="https://js.stripe.com/v3/"></script> </head>

Create an instance of Stripe with the following JavaScript on your checkout page:

checkout.js
// Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
);

Add the Payment Element to your payment page

The Payment Element needs a place to live on your payment page. Create an empty DOM node (container) with a unique ID in your payment form.

checkout.html
<form id="payment-form"> <div id="payment-element"> <!-- Elements will create form elements here --> </div> <button id="submit">Submit</button> <div id="error-message"> <!-- Display error message to your customers here --> </div> </form>

When the previous form loads, create an instance of the Payment Element and mount it to the container DOM node. Pass the client secret from the previous step into the options when you create the Elements instance.

Handle the client secret carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer.

checkout.js
const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in step 3 const elements = stripe.elements(options); // Create and mount the Payment Element const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element');

The Payment Element renders a dynamic form that allows your customer to pick a payment method. Depending on their payment method, the form automatically requests that the customer fills in all necessary payment details.

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.

By default, the Payment Element only collects necessary billing address details. In cases where you need to collect full billing address, like for calculating tax for digital goods and services, you can use the Address Element in Billing mode.

OptionalCustomize the layout
Client-side

OptionalCollect address details
Client-side

OptionalCustomize the appearance
Client-side

OptionalFetch updates from the server
Client-side

Submit the payment to Stripe
Client-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_url. Card payments immediately redirect to the return_url when a payment is successful.

If you don’t want to redirect for card payments after payment completion, you can set redirect to if_required. This only redirects customers that check out with redirect-based payment methods.

checkout.js
const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } });

Make sure the return_url corresponds to a page on your website that provides the status of the payment. When Stripe redirects the customer to the return_url, we provide the following URL query parameters:

ParameterDescription
payment_intentThe unique identifier for the PaymentIntent.
payment_intent_client_secretThe client secret of the PaymentIntent object.

If you have tooling that tracks the customer’s browser session, you might need to add the stripe.com 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_url, which persist through the redirect process.

status.js
// Initialize Stripe.js using your publishable key const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => { const message = document.querySelector('#message') // Inspect the PaymentIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (paymentIntent.status) { case 'succeeded': message.innerText = 'Success! Payment received.'; break; case 'processing': message.innerText = "Payment processing. We'll update you when payment is received."; break; case 'requires_payment_method': message.innerText = 'Payment failed. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; default: message.innerText = 'Something went wrong.'; break; } });

Handle post-payment events
Server-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_intent.succeeded event, we recommend handling two other events when collecting payments with the Payment Element:

EventDescriptionAction
payment_intent.succeededSent when a customer has successfully completed a payment.Send the customer an order confirmation and fulfill their order.
payment_intent.processingSent when a customer successfully initiated a payment, but the payment has yet to complete. This event is most commonly sent when a bank debit is initiated. It’s followed by either a payment_intent.succeeded or payment_intent.payment_failed event in the future.Send the customer an order confirmation that indicates their payment is pending. For digital goods, you may want to fulfill the order before waiting for payment to complete.
payment_intent.payment_failedSent when a customer attempted a payment, but the payment failed.If a payment transitioned from processing to payment_failed, offer the customer another attempt to pay.

Test the integration

Use test payment details and the test redirect page to verify your integration. Click the tabs below to view details for each payment method.

Payment methodScenarioHow to test
Credit cardThe card payment succeeds and doesn’t require authentication.Fill out the credit card form using the credit card number 4242 4242 4242 4242 with any expiration, CVC, and postal code.
Credit cardThe card payment requires authentication.Fill out the credit card form using the credit card number 4000 0025 0000 3155 with any expiration, CVC, and postal code.
Credit cardThe card is declined with a decline code like insufficient_funds.Fill out the credit card form using the credit card number 4000 0000 0000 9995 with any expiration, CVC, and postal code.

OptionalAffirm
Client-side

OptionalAfterpay / Clearpay
Server-side

OptionalApple Pay and Google Pay
Client-side

OptionalACH Direct Debit
Client-side
Server-side

OptionalBLIK
Server-side

OptionalQR Code payment methods
Client-side
Server-side

See also

Now that you’ve finished your integration, you might want to check out these other resources.

  • Set up future payments
  • Save payment details during payment
  • The Elements Appearance API
Was this page helpful?
Questions? Contact us.
Watch our developer tutorials.
Check out our product changelog.
Powered by Markdoc
You can unsubscribe at any time. Read our privacy policy.
Code quickstart
On this page
Set up Stripe
Enable payment methods
Create a PaymentIntent
Collect payment details
Customize the layout
Collect address details
Customize the appearance
Fetch updates from the server
Submit the payment to Stripe
Handle post-payment events
Test the integration
Affirm
Afterpay / Clearpay
Apple Pay and Google Pay
ACH Direct Debit
BLIK
QR Code payment methods
See also
Related Guides
More Payment Scenarios
How Cards Work
Stripe Shell
Test mode
▗▄ ▄▟█ █▀▀ ▗▟████▙▖ ██████ ███▗▟█ ███ ███▗▟██▙▖ ▗▟█████▙▖ ███▖ ▀▀ ███ ███▀▀▀ ███ ███▀ ███ ███ ███ ▝▜████▙▖ ███ ███ ███ ███ ███ █████████ ▄▄ ▝███ ███ ▄ ███ ███ ███▄ ███ ███ ▄▄ ▝▜████▛▘ ▝▜███▛ ███ ███ ███▝▜██▛▘ ▝▜█████▛▘ ███ ▀▘
Welcome to the Stripe Shell! Stripe Shell is a browser-based shell with the Stripe CLI pre-installed. Login to Stripe docs and press Control + Backtick on your keyboard to start managing your Stripe resources in test mode. - View supported commands: - Find webhook events: - Listen for webhook events: - Call Stripe APIs: stripe [api resource] [operation] (e.g. )
The Stripe Shell is best experienced on desktop.
$