Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
OverviewSee all products
Start building
Start developing
    Set up your development environment
    Send your first API request
    Accept a payment
    Build and test new features
    Go-live checklist
About the APIs
Build with an LLM
Use Stripe without code
Set up Stripe
Create an account
Stripe Dashboard
Migrate to Stripe
HomeGet startedStart developing

Accept a payment

Securely accept payments online.

Build a payment form or use a prebuilt checkout page to start accepting online payments.

Embed a pre-built payment form on your site using Stripe Checkout. See how this integration compares to Stripe’s other integration types.

Embedded Checkout previewEmbedded Checkout preview
powdur.me

Integration effort

Low code

Integration type

Embed pre-built payment form on your site

UI customisation

Limited customization

Use the branding settings in the Stripe Dashboard to match Checkout to your site design.

Set up Stripe
Server-side

First, you need a Stripe account. Register now.

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

Command Line
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
# Available as a gem sudo gem install stripe
Gemfile
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
# If you use bundler, you can add this line to your Gemfile gem 'stripe'

Create a Checkout Session
Server-side

From your server, create a Checkout Session and set the ui_mode to embedded. You can configure the Checkout Session with line items to include and options such as currency.

You can also create a Checkout Session for an existing customer, allowing you to pre-fill Checkout fields with known contact information and unify your purchase history for that customer.

To return customers to a custom page that you host on your website, specify that page’s URL in the return_url parameter. Include the {CHECKOUT_SESSION_ID} template variable in the URL to retrieve the session’s status on the return page. Checkout automatically substitutes the variable with the Checkout Session ID before redirecting.

Read more about configuring the return page and other options for customising redirect behaviour.

After you create the Checkout Session, use the client_secret returned in the response to mount Checkout.

Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
# This example sets up an endpoint using the Sinatra framework. # To learn more about Sinatra, watch this video: https://youtu.be/8aA9Enb8NVc. require 'json' require 'sinatra' require 'stripe' # Set your secret key. Remember to switch to your live secret key in production. # See your keys here: https://dashboard.stripe.com/apikeys Stripe.api_key =
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
post '/create-checkout-session' do session = Stripe::Checkout::Session.create({ line_items: [{ price_data: { currency: 'usd', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], mode: 'payment', ui_mode: 'embedded', return_url: 'https://example.com/checkout/return?session_id={CHECKOUT_SESSION_ID}' }) {clientSecret: session.client_secret}.to_json end

Mount Checkout
Client-side

Checkout is available as part of Stripe.js. Include the Stripe.js script on your page by adding it to the head of your HTML file. Next, create an empty DOM node (container) to use for mounting.

index.html
<head> <script src="https://js.stripe.com/basil/stripe.js"></script> </head> <body> <div id="checkout"> <!-- Checkout will insert the payment form here --> </div> </body>

Initialise Stripe.js with your publishable API key.

Create an asynchronous fetchClientSecret function that makes a request to your server to create the Checkout Session and retrieve the client secret. Pass this function into options when you create the Checkout instance:

index.js
// Initialize Stripe.js const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); initialize(); // Fetch Checkout Session and retrieve the client secret async function initialize() { const fetchClientSecret = async () => { const response = await fetch("/create-checkout-session", { method: "POST", }); const { clientSecret } = await response.json(); return clientSecret; }; // Initialize Checkout const checkout = await stripe.initEmbeddedCheckout({ fetchClientSecret, }); // Mount Checkout checkout.mount('#checkout'); }

Checkout renders in an iframe that securely sends payment information to Stripe over an HTTPS connection.

Common mistake

Avoid placing Checkout within another iframe because some payment methods require redirecting to another page for payment confirmation.

Customize appearance

Customise Checkout to match the design of your site by setting the background colour, button colour, border radius, and fonts in your account’s branding settings.

By default, Checkout renders with no external padding or margin. We recommend using a container element such as a div to apply your desired margin (for example, 16px on all sides).

Show a return page

After your customer attempts payment, Stripe redirects them to a return page that you host on your site. When you created the Checkout Session, you specified the URL of the return page in the return_url parameter. Read more about other options for customising redirect behaviour.

When rendering your return page, retrieve the Checkout Session status using the Checkout Session ID in the URL. Handle the result according to the session status as follows:

  • complete: The payment succeeded. Use the information from the Checkout Session to render a success page.
  • open: The payment failed or was cancelled. Remount Checkout so that your customer can try again.
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
get '/session-status' do session = Stripe::Checkout::Session.retrieve(params[:session_id]) {status: session.status, customer_email: session.customer_details.email}.to_json end
client.js
const session = await fetch(`/session_status?session_id=${session_id}`) if (session.status == 'open') { // Remount embedded Checkout } else if (session.status == 'complete') { // Show success page // Optionally use session.payment_status or session.customer_email // to customize the success page }

Redirect-based payment methods

During payment, some payment methods redirect the customer to an intermediate page, such as a bank authorisation page. When they complete that page, Stripe redirects them to your return page.

Learn more about redirect-based payment methods and redirect behaviour.

Handle post-payment events

Stripe sends a checkout.session.completed event when a customer completes a Checkout Session payment. Use the Dashboard webhook tool or follow the webhook guide to receive and handle these events, which might trigger you to:

  • Send an order confirmation email to your customer.
  • Log the sale in a database.
  • Start a shipping workflow.

Listen for these events rather than waiting for your customer to be redirected back to your website. Triggering fulfilment only from your Checkout landing page is unreliable. Setting up your integration to listen for asynchronous events allows you to accept different types of payment methods with a single integration.

Learn more in our fulfilment guide for Checkout.

Handle the following events when collecting payments with the Checkout:

EventDescriptionAction
checkout.session.completedSent when a customer successfully completes a Checkout Session.Send the customer an order confirmation and fulfill their order.
checkout.session.async_payment_succeededSent when a payment made with a delayed payment method, such as ACH direct debt, succeeds.Send the customer an order confirmation and fulfill their order.
checkout.session.async_payment_failedSent when a payment made with a delayed payment method, such as ACH direct debt, fails.Notify the customer of the failure and bring them back on-session to attempt payment again.

Test your integration

To test your embedded payment form integration:

  1. Create an embedded Checkout Session and mount Checkout on your page.
  2. Fill out the payment details with a method from the table below.
    • Enter any future date for card expiry.
    • Enter any 3-digit number for CVC.
    • Enter any billing postal code.
  3. Click Pay. You’re redirected to your return_url.
  4. Go to the Dashboard and look for the payment on the Transactions page. If your payment succeeded, you’ll see it in that list.
  5. Click your payment to see more details, like a Checkout summary with billing information and the list of purchased items. You can use this information to fulfil the order.

Learn more about testing your integration.

Card numberScenarioHow to test
The card payment succeeds and doesn’t require authentication.Fill in the credit card form using the credit card number with any expiry date, CVC, and postal code.
The card payment requires authentication.Fill in the credit card form using the credit card number with any expiry date, CVC, and postal code.
The card is declined with a decline code like insufficient_funds.Fill in the credit card form using the credit card number with any expiry date, CVC, and postal code.
The UnionPay card has a variable length of 13-19 digits.Fill in the credit card form using the credit card number with any expiry date, CVC, and postal code.

See Testing for additional information to test your integration.

OptionalAdd more payment methods

By default, Checkout supports many payment methods. You have to take additional steps to enable and display some methods, like Apple Pay, Google Pay, and buy now, pay later methods.

Apple Pay and Google Pay

To accept payments from Apple Pay and Google Pay, you must:

  • 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.
  • Serve your application over HTTPS in development and production. You can use a service like ngrok to serve your application for local testing.

In addition, a Checkout Session only displays the Apple Pay button to customers when all of the following conditions are true:

  • The customer’s device is running macOS version 17 or later or iOS version 17 or later.
  • The customer is using the Safari browser.
  • The customer has a valid card registered with Apple Pay.

A Checkout Session only displays the Google Pay button to customers when all of the following conditions are true:

  • The customer’s device is running Chrome 61 or newer.
  • The customer has a valid card registered with Google Pay.

Regional testing
India

Stripe Checkout doesn’t support Apple Pay or Google Pay for Stripe accounts or customers in India. If your IP address is in India, you can’t test your Apple Pay or Google Pay integration, even if the Stripe account is outside India.

OptionalCreate products and prices

Let customers decide what to pay

You can set up your Checkout Session to accept tips and donations, or sell pay-what-you-want products and services.

Before you create a Checkout Session, you can create Products and Prices upfront. Use products to represent different physical goods or levels of service, and Prices to represent each product’s pricing.

For example, you can create a T-shirt as a product with a price of 20 USD. This allows you to update and add prices without needing to change the details of your underlying products. You can either create products and prices with the Stripe Dashboard or API. Learn more about how products and prices work.

The API only requires a name to create a Product. Checkout displays the product name, description, and images that you supply.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/products \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d name=T-shirt

Next, create a Price to define how much to charge for your product. This includes how much the product costs and what currency to use.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/prices \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d product=
{{PRODUCT_ID}}
\ -d unit_amount=2000 \ -d currency=usd

Each price you create has an ID. When you create a Checkout Session, reference the price ID and quantity. If you’re selling in multiple currencies, make your Price multi-currency. Checkout automatically determines the customer’s local currency and presents that currency if the Price supports it.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d mode=payment \ -d "line_items[0][price]"={{PRICE_ID}} \ -d "line_items[0][quantity]"=1 \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return"

OptionalPrefill customer data
Server-side

If you’ve already collected your customer’s email and want to pre-fill it in the Checkout Session for them, pass customer_email when creating a Checkout Session.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ --data-urlencode customer_email="customer@example.com" \ -d "line_items[0][price]"=
{{PRICE_ID}}
\ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return"

OptionalSave payment method details
Server-side

By default, payment methods used to make a one-off payment with Checkout aren’t available for future use.

Save payment methods to charge them off-session

You can set Checkout to save payment methods used to make a one-off payment by passing the payment_intent_data.setup_future_usage argument. This is useful if you need to capture a payment method on-file to use for future fees, such as cancellation or no-show fees.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d customer_creation=always \ -d "line_items[0][price_data][currency]"=usd \ -d "line_items[0][price_data][product_data][name]"=T-shirt \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return" \ -d "payment_intent_data[setup_future_usage]"=off_session

If you use Checkout in subscription mode, Stripe automatically saves the payment method to charge it for subsequent payments. Card payment methods saved to customers using either setup_future_usage or subscription mode don’t appear for return purchases in Checkout (more on this below). We recommend using custom text to link out to any relevant terms regarding the usage of saved payment information.

Caution

Global privacy laws are complicated and nuanced. We recommend contacting your legal and privacy team prior to implementing setup_future_usage because it might implicate your existing privacy compliance framework. Refer to the guidance issued by the European Protection Board to learn more about saving payment details.

Save payment methods to prefill them in Checkout

By default, Checkout uses Link to provide your customers with the option to securely save and reuse their payment information. If you prefer to manage payment methods yourself, use saved_payment_method_options.payment_method_save when creating a Checkout Session to let your customers save their payment methods for future purchases in Checkout.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d customer_creation=always \ -d "line_items[0][price_data][currency]"=usd \ -d "line_items[0][price_data][product_data][name]"=T-shirt \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return" \ -d "saved_payment_method_options[payment_method_save]"=enabled

Passing this parameter in either payment or subscription mode displays an optional tickbox to let customers explicitly save their payment method for future purchases. When customers tick this tickbox, Checkout saves the payment method with allow_redisplay: always. Checkout uses this parameter to determine whether a payment method can be pre-filled on future purchases. When using saved_payment_method_options.payment_method_save, you don’t need to pass in setup_future_usage to save the payment method.

Using saved_payment_method_options.payment_method_save requires a Customer. To save a new customer, set the Checkout Session’s customer_creation to always. Otherwise, the session doesn’t save the customer or the payment method.

If payment_method_save isn’t passed in or if the customer doesn’t agree to save the payment method, Checkout still saves payment methods created in subscription mode or using setup_future_usage. These payment methods have an allow_redisplay value of limited, which prevents them from being pre-filled for returning purchases and allows you to comply with card network rules and data protection regulations. Learn how to change the default behaviour enabled by these modes and how to change or override allow_redisplay behaviour.

Note

You can use Checkout to save cards and other payment methods to charge them off-session, but Checkout only pre-fills saved cards. Learn how to pre-fill saved cards. To save a payment method without an initial payment, use Checkout in setup mode.

Let customers remove saved payment methods

To let your customers remove a saved payment method so it doesn’t resurface for future payments, use saved_payment_method_options.payment_method_remove when creating a Checkout Session.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d customer={{CUSTOMER_ID}} \ -d "line_items[0][price_data][currency]"=usd \ -d "line_items[0][price_data][product_data][name]"=T-shirt \ -d "line_items[0][price_data][unit_amount]"=2000 \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return" \ -d "saved_payment_method_options[payment_method_remove]"=enabled

The customer can’t remove a payment method if it’s tied to an active subscription and the customer doesn’t have a default payment method saved for invoice and subscription payments.

OptionalCustomer account management
No code

Let your customers manage their own accounts by sharing a link to your customer portal. The customer portal lets customers log in with their email address to manage subscriptions, update payment methods, and so on.

OptionalSeparate authorisation and capture
Server-side

Stripe supports two-step card payments so you can first authorise a card, then capture funds later. When Stripe authorises a payment, the card issuer guarantees the funds and places a hold for the payment amount on the customer’s card. You then have a certain amount of time to capture the funds, depending on the card). If you don’t capture the payment before the authorisation expires, the payment is cancelled and the issuer releases the held funds.

Separating authorisation and capture is useful if you need to take additional actions between confirming that a customer is able to pay and collecting their payment. For example, if you’re selling stock-limited items, you may need to confirm that an item purchased by your customer using Checkout is still available before capturing their payment and fulfilling the purchase. Accomplish this using the following workflow:

  1. Confirm that Stripe authorised the customer’s payment method.
  2. Consult your inventory management system to confirm that the item is still available.
  3. Update your inventory management system to indicate that a customer has purchased the item.
  4. Capture the customer’s payment.
  5. Inform your customer whether their purchase was successful on your confirmation page.

To indicate that you want to separate authorisation and capture, you must set the value of payment_intent_data.capture_method to manual when creating the Checkout Session. This instructs Stripe to only authorise the amount on the customer’s card.

Command Line
cURL
Stripe CLI
Ruby
Python
PHP
Java
Node.js
Go
.NET
No results
curl https://api.stripe.com/v1/checkout/sessions \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d "line_items[0][price]"={{PRICE_ID}} \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d "payment_intent_data[capture_method]"=manual \ -d ui_mode=embedded \ --data-urlencode return_url="https://example.com/return"

To capture an uncaptured payment, you can use either the Dashboard or the capture endpoint. Programmatically capturing payments requires access to the PaymentIntent created during the Checkout Session, which you can get from the Session object.

OptionalOrder fulfilment

Learn how to programmatically get a notification whenever a customer pays.

See also

  • Add discounts
  • Collect taxes
  • Collect tax IDs
  • Add shipping
  • Customise your branding
Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Join our early access programme.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc
Code quickstart
Related Guides
Elements Appearance API
More payment scenarios
How cards work