Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
OverviewExplore 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
Sample projects
About the APIs
Build with LLMs
Use Stripe without code
Set up Stripe
Create an account
Web Dashboard
Mobile Dashboard
Migrate to Stripe
Manage fraud risk
Understand fraud
Radar fraud protection
Manage disputes
Verify identities
HomeGet startedStart developing

Accept a payment

Securely accept payments online.

Copy page

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

Build a checkout page on your website using Stripe Elements and Checkout Sessions, an integration that manages tax, discounts, shipping rates, and more.

Customer location
Size
Theme
Layout
This demo only displays Google Pay or Apple Pay if you have an active card with either wallet.

Set up the server
Server-side

Before you begin, you need to register for a Stripe account.

Use the official Stripe libraries to access the API from your application.

Command Line
Node
npm install stripe@18.0.0 --save

Set the SDK to use at least the 2025-03-31.basil API version.

TypeScript
// Set your secret key. Remember to switch to your live secret key in production. // See your keys here: https://dashboard.stripe.com/apikeys import Stripe from 'stripe'; const stripe = new Stripe(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, { apiVersion: '2025-03-31.basil' as any, });

Create a Checkout Session
Server-side

Add an endpoint on your server that creates a Checkout Session and returns its client secret to your front end. A Checkout Session represents your customer’s session as they pay for one-time purchases or subscriptions. Checkout Sessions expire 24 hours after creation.

server.ts
TypeScript
import express, {Express} from 'express'; const app: Express = express(); app.post('/create-checkout-session', async (req: Express.Request, res: Express.Response) => { const session = await stripe.checkout.sessions.create({ line_items: [ { price_data: { currency: 'usd', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }, ], mode: 'payment', ui_mode: 'custom', // The URL of your payment completion page return_url: 'https://example.com/return?session_id={CHECKOUT_SESSION_ID}' }); res.json({checkoutSessionClientSecret: session.client_secret}); }); app.listen(3000, () => { console.log('Running on port 3000'); });

Set up the front end
Client-side

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. Don’t include the script in a bundle or host a copy of it yourself.

You’ll need to update Stripe.js to basil from v3 by including the following script tag <script src="https://js.stripe.com/basil/stripe.js"></script>. Learn more about Stripe.js versioning.

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

Note

Stripe provides an npm package that you can use to load Stripe.js as a module. See the project on GitHub. Version 7.0.0 or later is required.

Initialize stripe.js.

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'
, );

Initialize Checkout
Client-side

Create a fetchClientSecret function. This function retrieves the client secret from your server and returns a promise that resolves with the client secret. Call initCheckout, passing in fetchClientSecret. initCheckout returns a promise resolving to a checkout instance.

The checkout object acts as the foundation of your checkout page, containing data from the Checkout Session and methods to update the Session.

The object returned by checkout.session() contains your pricing information. We recommend reading and displaying the total, and lineItems from the session in your UI.

This lets you turn on new features with minimal code changes. For example, adding manual currency prices requires no UI changes if you display the total.

checkout.js
const fetchClientSecret = () => { return fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.checkoutSessionClientSecret); }; stripe.initCheckout({fetchClientSecret}) .then((checkout) => { const checkoutContainer = document.getElementById('checkout-container'); checkoutContainer.append(JSON.stringify(checkout.lineItems, null, 2)); checkoutContainer.append(document.createElement('br')); checkoutContainer.append(`Total: ${checkout.session().total.total.amount}`); });
index.html
<div id="checkout-container"></div>

Collect customer email
Client-side

If you already pass in an existing customer_email or Customer with a valid email set when creating the Checkout Session, you can skip this step.

If you implement your own email validation, you can pass in the validated email on checkout.confirm and skip this step.

Create an email input to collect your customer’s email address. Call updateEmail when your customer finishes the input to validate and save the email address.

Depending on the design of your checkout form, you can call updateEmail in the following ways:

  • Directly before submitting the payment. You can also call updateEmail to validate earlier, such as on input blur.
  • Before transitioning to the next step, such as clicking a Save button, if your form includes multiple steps.
index.html
<input type="text" id="email" /> <div id="email-errors"></div>
checkout.js
stripe.initCheckout({fetchClientSecret}).then((checkout) => { const emailInput = document.getElementById('email'); const emailErrors = document.getElementById('email-errors'); emailInput.addEventListener('input', () => { // Clear any validation errors emailErrors.textContent = ''; }); emailInput.addEventListener('blur', () => { const newEmail = emailInput.value; checkout.updateEmail(newEmail).then((result) => { if (result.error) { emailErrors.textContent = result.error.message; } }); }); });

Collect payment details
Client-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.

First, create a container DOM element to mount the Payment Element. Then create an instance of the Payment Element using checkout.createPaymentElement and mount it by calling element.mount, providing either a CSS selector or the container DOM element.

index.html
<div id="payment-element"></div>
checkout.js
const paymentElement = checkout.createPaymentElement(); paymentElement.mount('#payment-element');

See the Stripe.js docs to view what options are supported.

You can customize the appearance of all Elements by passing elementsOptions.appearance when initializing Checkout on the front end.

Submit the payment
Client-side

Render a “pay” button that calls confirm from the checkout instance to submit the payment.

index.html
<button id="pay-button">Pay</button> <div id="confirm-errors"></div>
checkout.js
stripe.initCheckout({fetchClientSecret}).then((checkout) => { const button = document.getElementById('pay-button'); const errors = document.getElementById('confirm-errors'); button.addEventListener('click', () => { // Clear any validation errors errors.textContent = ''; checkout.confirm().then((result) => { if (result.type === 'error') { errors.textContent = result.error.message; } }); }); });

Test your integration

  1. Navigate to your checkout page.
  2. Fill out the payment details with a payment method from the following table. For card payments:
    • Enter any future date for card expiry.
    • Enter any 3-digit number for CVC.
    • Enter any billing postal code.
  3. Submit the payment to Stripe.
  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 billing information and the list of purchased items. You can use this information to fulfill the order.
Card numberScenarioHow to test
The card payment succeeds and doesn’t require authentication.Fill out the credit card form using the credit card number with any expiration, CVC, and postal code.
The card payment requires authentication.Fill out the credit card form using the credit card number with any expiration, CVC, and postal code.
The card is declined with a decline code like insufficient_funds.Fill out the credit card form using the credit card number with any expiration, CVC, and postal code.
The UnionPay card has a variable length of 13-19 digits.Fill out the credit card form using the credit card number with any expiration, CVC, and postal code.

See Testing for additional information to test your integration.

OptionalCreate products and prices

OptionalPrefill customer data
Server-side

OptionalSave payment method details

OptionalCollect billing and shipping addresses

OptionalSeparate authorization and capture
Server-side

OptionalCustomer account management
No code

OptionalOrder fulfillment

See also

  • Add discounts for one-time payments
  • Collect taxes
  • Enable adjustable line item quantities
  • Add one-click buttons
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access program.
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
Products Used
Payments
Elements
Checkout