# Payments for existing customers Learn how to charge an existing payment method while a customer is on-session. # Elements A Checkout Session allows buyers to enter their payment details. If the buyer is an existing customer, you can configure the Checkout Session to prefill the details with one of the customer’s [saved cards](https://docs.stripe.com/payments/checkout/save-during-payment.md?payment-ui=embedded-components). The Checkout Session displays up to 50 saved cards that a customer can choose to pay with. ![Payment Element with one saved card](https://b.stripecdn.com/docs-statics-srv/assets/saved_card.9ae121fe039c6d963f3c9831eb92172f.png) ## Create a Checkout Session [Client-side] [Server-side] Checkout Sessions supports reusing existing customer-configured `Account` objects with the [customer_account](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_account) parameter or `Customer` objects with the [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer) parameter. When reusing existing customers, all objects created by Checkout, such as `PaymentIntents` and `Subscriptions`, are associated with the object that represents that customer. > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is generally available for Connect users, and in public preview for other Stripe users. If you’re part of the Accounts v2 preview, you need to specify a [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) in your code. > > To request access to the Accounts v2 preview, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d ui_mode=elements \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ --data-urlencode "return_url=https://example.com/return?session_id={CHECKOUT_SESSION_ID}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d ui_mode=elements \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "customer={{CUSTOMER_ID}}" \ --data-urlencode "return_url=https://example.com/return?session_id={CHECKOUT_SESSION_ID}" ``` ## Optional: Display additional saved payment methods [Server-side] > #### Compliance > > You’re responsible for your compliance with all applicable laws, regulations, and network rules when saving a customer’s payment details. When rendering past payment methods to a customer for future purchases, make sure you’ve collected consent to save the payment method details for this specific future use. By default, we only show payment methods set to [always allow redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay). You can’t reuse Apple Pay and Google Pay during a Checkout Session, so these payment methods don’t appear in the list of saved options. You must display the Google Pay and Apple Pay UI, and the payment request button UI, each time the Checkout Session is active. You can display other previously saved payment methods by including other redisplay values in the Checkout Session, or by updating a payment method’s `allow_redisplay` setting to `always`. - Use the `allow_redisplay_filters` [parameter](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-allow_redisplay_filters) to specify which saved payment methods to show in Checkout. You can set any of the valid values: `limited`, `unspecified` and `always`. If you specify redisplay filtering in your Checkout Session, it overrides the default behavior, so you must include the `always` value to see those saved payment methods. #### Accounts v2 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d ui_mode=elements \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ --data-urlencode "return_url=https://example.com/return?session_id={CHECKOUT_SESSION_ID}" \ -d "saved_payment_method_options[allow_redisplay_filters][0]=always" \ -d "saved_payment_method_options[allow_redisplay_filters][1]=limited" \ -d "saved_payment_method_options[allow_redisplay_filters][2]=unspecified" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d ui_mode=elements \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d "customer={{CUSTOMER_ID}}" \ --data-urlencode "return_url=https://example.com/return?session_id={CHECKOUT_SESSION_ID}" \ -d "saved_payment_method_options[allow_redisplay_filters][0]=always" \ -d "saved_payment_method_options[allow_redisplay_filters][1]=limited" \ -d "saved_payment_method_options[allow_redisplay_filters][2]=unspecified" ``` - [Update the Payment Method](https://docs.stripe.com/api/payment_methods/update.md) to set the `allow_redisplay` value on individual payment methods. ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}} \ -u "<>:" \ -d allow_redisplay=always ``` ## Display the Payment Element [Client-side] #### HTML + JS ### Set up 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. Don’t include the script in a bundle or host a copy of it yourself. ```html Checkout ``` Create an instance of Stripe with the following JavaScript on your checkout page: ```javascript // 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('<>'); ``` ### 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: ```html
``` Fetch the Checkout Session `client_secret` from the previous step to initialize the `Checkout` object. Then create and mount the Payment Element. ```javascript const promise = fetch("/create-checkout-session", { method: "POST", headers: { "Content-Type": "application/json" }, }) .then((r) => r.json()) .then((r) => r.clientSecret); // Initialize Checkout const checkout = stripe.initCheckoutElementsSdk({ clientSecret: promise, }); // Create and mount the Payment Element const paymentElement = checkout.createPaymentElement(); paymentElement.mount('#payment-element'); ``` #### React ### Set up Stripe.js Install [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) and the [Stripe.js loader](https://www.npmjs.com/package/@stripe/stripe-js) from the npm public registry: ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` ### Add and configure the CheckoutElementsProvider to your payment page Fetch the Checkout Session `client_secret` from the previous step to initialize the [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider). Then render the `CheckoutForm` component that contains the payment form. ```jsx import React, {useMemo} from 'react'; import ReactDOM from 'react-dom'; import {CheckoutElementsProvider} from '@stripe/react-stripe-js/checkout'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './CheckoutForm'; // Make sure to call `loadStripe` outside of a component's render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('<>'); function App() { const promise = useMemo(() => { return fetch('/create-checkout-session', { method: 'POST', }) .then((res) => res.json()) .then((data) => data.clientSecret); }, []); return (
); }; ReactDOM.render(, document.getElementById('root')); ``` ### Add the Payment Element component Use the `PaymentElement` component to display the payment form. ```jsx import React from 'react'; import {PaymentElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { return (
); }; export default CheckoutForm; ``` ## Prefill fields on payment page If all the following conditions are true, the [Session object](https://docs.stripe.com/js/custom_checkout/session_object) contains the **email**, **name**, **card**, and **billing address** using details from the customer’s saved card for you to display on your payment page, and the Payment Element to display the saved card: - Checkout is in `payment` or `subscription` mode; `setup` mode doesn’t support prefilling fields. - The customer has a saved card. Checkout only supports prefilling card payment methods. - The saved card has `allow_redisplay` set to `always` or you adjusted the [default display setting](https://docs.stripe.com/payments/existing-customers.md#display-additional-saved-payment-methods). - The payment method includes [`billing_details`](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-billing_details) required by the Checkout Session’s [`billing_address_collection`](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-billing_address_collection) value: - `auto` requires values for `email`, `name`, and `address[country]`. US, CA, and GB billing addresses also require `address[postal_code]`. - `required` requires values for `email`, `name`, and all `address` fields. If your customer has multiple saved cards, the Payment Element displays the saved card matching the following prioritization: - In `payment` mode, Stripe prefills the fields using the customer’s newest saved card. - In `subscription` mode, Stripe prefills the customer’s default payment method if it’s a card. Otherwise, Stripe prefills the newest saved card. When [collecting a shipping address](https://docs.stripe.com/payments/collect-addresses.md), the [Session object](https://docs.stripe.com/js/custom_checkout/session_object) contains the shipping address fields if the Customer’s [shipping.address](https://docs.stripe.com/api/customers/object.md#customer_object-shipping-address) meets the Checkout Session’s [supported countries](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection-allowed_countries). To let your customers remove saved cards during a Checkout Session, set [save_payment_method_options[payment_method_remove]](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_remove) to `enabled`. > #### Prefill timeout > > The prefilled payment method displays for 30 minutes following Checkout Session creation. After it expires, loading the same Checkout Session doesn’t prefill the payment method anymore for security reasons. ## Submit the payment to Stripe [Client-side] #### HTML + JS Render a **Pay** button that calls [confirm](https://docs.stripe.com/js/custom_checkout/confirm) from the `Checkout` instance to submit the payment. ```html
``` ```js const checkout = stripe.initCheckoutElementsSdk({clientSecret}); checkout.on('change', (session) => { document.getElementById('pay-button').disabled = !session.canConfirm; }); const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { const {actions} = loadActionsResult; const button = document.getElementById('pay-button'); const errors = document.getElementById('confirm-errors'); button.addEventListener('click', () => { // Clear any validation errors errors.textContent = ''; actions.confirm().then((result) => { if (result.type === 'error') { errors.textContent = result.error.message; } }); }); } ``` #### React Render a **Pay** button that calls [confirm](https://docs.stripe.com/js/custom_checkout/confirm) from [useCheckoutElements](https://docs.stripe.com/js/react_stripe_js/checkout/use_checkout_elements) to submit the payment. ```jsx import React from 'react'; import {useCheckoutElements} from '@stripe/react-stripe-js/checkout'; const PayButton = () => { const checkoutState = useCheckoutElements(); const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(null); if (checkoutState.type !== "success") { return null; } const handleClick = () => { setLoading(true);checkoutState.checkout.confirm().then((result) => { if (result.type === 'error') { setError(result.error) } setLoading(false); }) }; return (
{error &&
{error.message}
}
) }; export default PayButton; ``` ## Handle post-payment events [Server-side] Stripe sends a [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) event when a customer completes a Checkout Session payment. Use the [Dashboard webhook tool](https://dashboard.stripe.com/webhooks) or follow the [webhook guide](https://docs.stripe.com/webhooks/quickstart.md) 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 fulfillment 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](https://stripe.com/payments/payment-methods-guide) with a single integration. Learn more in our [fulfillment guide for Checkout](https://docs.stripe.com/checkout/fulfillment.md). Handle the following events when collecting payments with the Checkout: | Event | Description | Action | | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | Sent when a customer successfully completes a Checkout Session. | Send the customer an order confirmation and *fulfill* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) their order. | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | Sent when a payment made with a delayed payment method, such as ACH direct debt, succeeds. | Send the customer an order confirmation and *fulfill* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) their order. | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | Sent 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. |