# Accept a payment with the Express Checkout Element Use a single integration to accept payments through one-click payment buttons. ![Express Checkout Element](https://b.stripecdn.com/docs-statics-srv/assets/link-in-express-checkout-element.67be6745e5a37c1c09074b0f43763cff.png) The Express Checkout Element is an integration for accepting payments through one-click payment method buttons. Supported payment methods include [Link](https://docs.stripe.com/payments/link.md), [Apple Pay](https://docs.stripe.com/apple-pay.md), [Google Pay](https://docs.stripe.com/google-pay.md), [PayPal](https://docs.stripe.com/payments/paypal.md), [Klarna](https://docs.stripe.com/payments/klarna.md), and [Amazon Pay](https://docs.stripe.com/payments/amazon-pay.md). Customers see different payment buttons depending on their device and browser. Compatible devices automatically support Google Pay and Link. You must complete additional steps to support Apple Pay and PayPal. ## Try the demo Toggle the prebuilt options in the demo to change the background color, layout, size, and shipping address collection. The demo displays Google Pay and Apple Pay only on their available platforms. Payment method buttons are only shown in their supported countries. If you don’t see the demo, try viewing this page in a [supported browser](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers). | Option | Description | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Merchant country** | Set this using the [publishable key](https://docs.stripe.com/keys.md#obtain-api-keys) that you use to [initialize Stripe.js](https://docs.stripe.com/js/initializing). To change the country, you must unmount the Express Checkout Element, update the publishable key, then re-mount the Express Checkout Element. | | **Background color** | Set colors using the [Elements Appearance API](https://docs.stripe.com/elements/appearance-api.md). Button themes are inherited from the Appearance API but you can also [define them directly when you create the Element](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-buttonTheme). | | **Desktop and mobile size** | Use the dropdown to set the max pixel width of the parent element that the Express Checkout Element is mounted to. You can set it to 750px (Desktop) or 320px (Mobile). | | **Max columns and max rows** | Set these values using the [layout](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-layout) parameter when you [Create the Express Checkout Element](https://docs.stripe.com/js/elements_object/create_express_checkout_element). | | **Overflow menu** | Set this using the [layout](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-layout) parameter when you [Create the Express Checkout Element](https://docs.stripe.com/js/elements_object/create_express_checkout_element). | | **Collect shipping address** | To collect shipping information, you must pass options when [creating](https://docs.stripe.com/js/elements_object/create_express_checkout_element) the Express Checkout Element. Learn more about [collecting customer details and displaying line items](https://docs.stripe.com/elements/express-checkout-element/accept-a-payment.md#handle-create-event). | # Checkout Sessions API > This is a Checkout Sessions API for when payment-ui is embedded-components. View the full page at https://docs.stripe.com/elements/express-checkout-element/accept-a-payment?payment-ui=embedded-components. ## Before you begin 1. Add a payment method to your browser. For example, you can add a card to your Google Pay account or to your Wallet for Safari. 1. Serve your application over HTTPS. This is required in development and in production. You can use a service such as [ngrok](https://ngrok.com/). 1. [Register your domain](https://dashboard.stripe.com/settings/payment_method_domains) in both a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) and live mode. ## Set up Stripe [Server-side] First, [create a Stripe account](https://dashboard.stripe.com/register) or [sign in](https://dashboard.stripe.com/login). Use our official libraries to access the Stripe API from your application: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` #### Python ```bash # Install through pip pip3 install --upgrade stripe ``` ```bash # Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python # Find the version you want to pin: # https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md # Specify that version in your requirements.txt file stripe>=5.0.0 ``` #### PHP ```bash # Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash # Or download the source directly: https://github.com/stripe/stripe-php/releases ``` #### Java ```java /* For Gradle, add the following dependency to your build.gradle and replace with the version number you want to use from: - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest */ implementation "com.stripe:stripe-java:31.0.0" ``` ```xml com.stripe stripe-java 31.0.0 ``` ```bash # For other environments, manually install the following JARs: # - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest # - Google Gson from https://github.com/google/gson ``` #### Node.js ```bash # Install with npm npm install stripe --save ``` #### Go ```bash # Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v83 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v83" ) ``` #### .NET ```bash # Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash # Or install with NuGet Install-Package Stripe.net ``` ## Enable payment methods By default, Stripe uses your [payment methods settings](https://dashboard.stripe.com/settings/payment_methods) to determine which payment methods the Express Checkout Element presents. You can also configure specific payment methods on your Checkout Session using the [payment_method_types](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_method_types) attribute. ### Supported payment methods The `card` payment method type automatically enables Apple Pay and Google Pay. When using Link, you must also pass the `card` payment method type. | Payment method | Payment method type | | -------------- | ------------------- | | Amazon Pay | `amazon_pay` | | Apple Pay | `card` | | Google Pay | `card` | | Link | `link`, `card` | | PayPal | `paypal` | ## Create a Checkout Session [Server-side] Create a Checkout Session on your server to control the payment flow. The Checkout Session defines your line items, shipping options, and other settings for the payment. ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "line_items[0][price]"={{PRICE_ID}} \ -d "line_items[0][quantity]"=1 \ -d mode=payment \ -d ui_mode=custom \ -d return_url={{RETURN_URL}} ``` ```cli stripe checkout sessions create \ -d "line_items[0][price]"={{PRICE_ID}} \ -d "line_items[0][quantity]"=1 \ --mode=payment \ --ui-mode=custom \ --return-url={{RETURN_URL}} ``` ```ruby client = Stripe::StripeClient.new("<>") session = client.v1.checkout.sessions.create({ line_items: [ { price: '{{PRICE_ID}}', quantity: 1, }, ], mode: 'payment', ui_mode: 'custom', return_url: '{{RETURN_URL}}', }) ``` ```python client = StripeClient("<>") # For SDK versions 12.4.0 or lower, remove '.v1' from the following line. session = client.v1.checkout.sessions.create({ "line_items": [{"price": "{{PRICE_ID}}", "quantity": 1}], "mode": "payment", "ui_mode": "custom", "return_url": "{{RETURN_URL}}", }) ``` ```php $stripe = new \Stripe\StripeClient('<>'); $session = $stripe->checkout->sessions->create([ 'line_items' => [ [ 'price' => '{{PRICE_ID}}', 'quantity' => 1, ], ], 'mode' => 'payment', 'ui_mode' => 'custom', 'return_url' => '{{RETURN_URL}}', ]); ``` ```java StripeClient client = new StripeClient("<>"); SessionCreateParams params = SessionCreateParams.builder() .addLineItem( SessionCreateParams.LineItem.builder() .setPrice("{{PRICE_ID}}") .setQuantity(1L) .build() ) .setMode(SessionCreateParams.Mode.PAYMENT) .setUiMode(SessionCreateParams.UiMode.CUSTOM) .setReturnUrl("{{RETURN_URL}}") .build(); // For SDK versions 29.4.0 or lower, remove '.v1()' from the following line. Session session = client.v1().checkout().sessions().create(params); ``` ```node const stripe = require('stripe')('<>'); const session = await stripe.checkout.sessions.create({ line_items: [ { price: '{{PRICE_ID}}', quantity: 1, }, ], mode: 'payment', ui_mode: 'custom', return_url: '{{RETURN_URL}}', }); ``` ```go sc := stripe.NewClient("<>") params := &stripe.CheckoutSessionCreateParams{ LineItems: []*stripe.CheckoutSessionCreateLineItemParams{ &stripe.CheckoutSessionCreateLineItemParams{ Price: stripe.String("{{PRICE_ID}}"), Quantity: stripe.Int64(1), }, }, Mode: stripe.String(stripe.CheckoutSessionModePayment), UIMode: stripe.String(stripe.CheckoutSessionUIModeCustom), ReturnURL: stripe.String("{{RETURN_URL}}"), } result, err := sc.V1CheckoutSessions.Create(context.TODO(), params) ``` ```dotnet var options = new Stripe.Checkout.SessionCreateOptions { LineItems = new List { new Stripe.Checkout.SessionLineItemOptions { Price = "{{PRICE_ID}}", Quantity = 1, }, }, Mode = "payment", UiMode = "custom", ReturnUrl = "{{RETURN_URL}}", }; var client = new StripeClient("<>"); var service = client.V1.Checkout.Sessions; Stripe.Checkout.Session session = service.Create(options); ``` Set `ui_mode` to `custom` to integrate with the Express Checkout Element. The returned Checkout Session includes a client secret, which the client uses to securely display the checkout interface. You can configure additional options on the Checkout Session: - [phone_number_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-phone_number_collection): Collect customer phone numbers - [shipping_address_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection): Collect shipping addresses - [shipping_options](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_options): Provide shipping rate options - [automatic_tax](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-automatic_tax): Enable automatic tax calculation ## Set up Stripe Elements [Client-side] #### HTML + JS The Express Checkout 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. Don’t include the script in a bundle or host a copy of it yourself. ```html Checkout ``` Retrieve the client secret from your server: ```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('<>'); ``` Create a `fetchClientSecret` function to retrieve the client secret from your server: ```javascript const clientSecret = fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret); ``` Create the Checkout instance: ```javascript const checkout = stripe.initCheckout({ clientSecret }); ``` #### React The Express Checkout Element is automatically available as a feature of 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 ``` Create `clientSecret` as a `Promise | string` containing the client secret returned by your server. Wrap your application with the [CheckoutProvider](https://docs.stripe.com/js/custom_checkout/react/checkout_provider) component, passing in `clientSecret` and the `stripe` instance. ```jsx import React from 'react'; import {CheckoutProvider} 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('<>'); const clientSecret = fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret); const App = () => { return ( ); }; export default App; ``` ## Create and mount the Express Checkout Element [Client-side] The Express Checkout 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. #### HTML + JS The Express Checkout 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
``` When the form has loaded, create an instance of the Express Checkout Element and mount it to the container DOM node: ```javascript // Create and mount the Express Checkout Element const expressCheckoutElement = checkout.createExpressCheckoutElement(); expressCheckoutElement.mount('#express-checkout-element'); ``` #### React Add the `ExpressCheckoutElement` component to your payment page: ```jsx import React from 'react'; import {useCheckout, ExpressCheckoutElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { const checkoutState = useCheckout(); if (checkoutState.type === 'error') { return
Error: {checkoutState.error.message}
; } return (
); }; ``` ## Collect customer details and display line items [Client-side] The Checkout Session you created on the server automatically determines the line items, total amount, and available payment methods. The Express Checkout Element uses this information to display the appropriate interface. #### HTML + JS ### Handle payment confirmation Listen to the [confirm event](https://docs.stripe.com/js/elements_object/express_checkout_element_confirm_event) when your customer finalizes their payment: ```javascript const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { expressCheckoutElement.on('confirm', (event) => { loadActionsResult.actions.confirm({expressCheckoutConfirmEvent: event}); }); } ``` ### Handle dynamic updates If you need to update the Checkout Session based on customer selections (such as shipping address or shipping rate changes), you can listen to events and update the session: ```javascript expressCheckoutElement.on('shippingaddresschange', async (event) => { const response = await fetch('/update-session-shipping', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ sessionId: checkout.session.id, shippingAddress: event.address }) }); const result = await response.json(); if (result.error) { event.reject(); } else { event.resolve(); } }); expressCheckoutElement.on('shippingratechange', async (event) => { const response = await fetch('/update-session-shipping-rate', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ sessionId: checkout.session.id, shippingRateId: event.shippingRate.id }) }); const result = await response.json(); if (result.error) { event.reject(); } else { event.resolve(); } }); ``` #### React ### Handle payment confirmation Handle the `confirm` event when your customer finalizes their payment: ```jsx import {useCheckout, ExpressCheckoutElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { const checkoutState = useCheckout(); if (checkoutState.type === 'loading') { return
Loading...
; } else if (checkoutState.type === 'error') { return
Error: {checkoutState.error.message}
; } const handleConfirmExpressCheckout = (event) => { if (checkoutState.type === 'success') { checkoutState.checkout.confirm({expressCheckoutConfirmEvent: event}); } }; return (
{checkoutState.type === 'success' && (
          {JSON.stringify(checkoutState.checkout.lineItems, null, 2)}
          Total: {checkoutState.checkout.total?.amount}
        
)}
); }; ``` ### Handle dynamic updates If you need to update the Checkout Session based on customer selections (such as shipping address or shipping rate changes), you can listen to events and update the session: ```jsx const onShippingAddressChange = async ({resolve, reject, address}) => { const response = await fetch('/update-session-shipping', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ sessionId: checkout.session.id, shippingAddress: address }) }); const result = await response.json(); if (result.error) { reject(); } else { resolve(); } }; const onShippingRateChange = async ({resolve, reject, shippingRate}) => { const response = await fetch('/update-session-shipping-rate', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ sessionId: checkout.session.id, shippingRateId: shippingRate.id }) }); const result = await response.json(); if (result.error) { reject(); } else { resolve(); } }; ``` ## Optional: Listen to the ready event [Client-side] After mounting, the Express Checkout Element won’t show buttons for a brief period. To animate the Element when buttons appear, listen to the [ready event](https://docs.stripe.com/js/element/events/on_ready). Inspect the `availablePaymentMethods` value to determine which buttons, if any, display in the Express Checkout Element. #### HTML + JS ```javascript // Optional: If you're doing custom animations, hide the Element const expressCheckoutDiv = document.getElementById('express-checkout-element'); expressCheckoutDiv.style.visibility = 'hidden'; expressCheckoutElement.on('ready', ({availablePaymentMethods}) => { if (!availablePaymentMethods) { // No buttons will show } else { // Optional: Animate in the Element expressCheckoutDiv.style.visibility = 'initial'; } }); ``` #### React ```jsx import React, {useState} from 'react'; import {ExpressCheckoutElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { // Optional: If you're doing custom animations, hide the Element const [visibility, setVisibility] = useState('hidden'); const onReady = ({availablePaymentMethods}) => { if (!availablePaymentMethods) { // No buttons will show } else { // Optional: Animate in the Element setVisibility('initial'); } }; return (
); }; ``` ## Optional: Style the button [Client-side] You can style each payment method button differently and control the overall appearance of the Express Checkout Element. #### HTML + JS ```javascript const expressCheckoutElement = checkout.createExpressCheckoutElement({ // Specify a type per payment method buttonType: { googlePay: 'checkout', applePay: 'check-out', paypal: 'buynow', }, // Specify a theme per payment method buttonTheme: { applePay: 'white-outline' }, // Height in pixels. Defaults to 44. The width is always '100%'. buttonHeight: 55 }); ``` #### React ```jsx const expressCheckoutOptions = { // Specify a type per payment method buttonType: { googlePay: 'checkout', applePay: 'check-out', paypal: 'buynow' }, // Specify a theme per payment method buttonTheme: { applePay: 'white-outline' }, // Height in pixels. Defaults to 44. The width is always '100%'. buttonHeight: 55 }; ``` ## Test the integration Before you go live, [test](https://docs.stripe.com/testing.md) each payment method integration. To determine a payment method’s browser compatibility, see [supported browsers](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers). If you use the Express Checkout Element within an iframe, the iframe must have the [allow](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allowpaymentrequest) attribute set to `payment *`. #### Link > Don’t store real user data in *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) Link accounts. Treat them as if they’re publicly available, because these test accounts are associated with your publishable key. Currently, Link only works with credit cards, debit cards, and qualified US bank account purchases. Link requires [domain registration](https://docs.stripe.com/payments/payment-methods/pmd-registration.md). You can create sandbox accounts for Link using any valid email address. The following table shows the fixed one-time passcode values that Stripe accepts for authenticating sandbox accounts: | Value | Outcome | | ----------------------------------- | ---------------------------- | | Any other 6 digits not listed below | Success | | 000001 | Error, code invalid | | 000002 | Error, code expired | | 000003 | Error, max attempts exceeded | #### Wallets > #### Regional testing > > 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. ### Apple Pay You can’t save Stripe test card information to Apple Pay. Instead, Stripe recognizes when you’re using your test [API keys](https://docs.stripe.com/keys.md) and returns a successful test card token for you to use. This allows you to make test payments using a live card without charging it. Make sure you’re on a [registered domain](https://docs.stripe.com/payments/payment-methods/pmd-registration.md), [supported browser](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers), and have an active card saved to your Apple Pay wallet. ### Google Pay You can’t save Stripe test card information to Google Pay. Instead, Stripe recognizes when you’re using your test API keys and returns a successful test card token for you to use. This allows you to make test payments using a live card without charging it. You can also use Google Pay’s [test card suite](https://developers.google.com/pay/api/web/guides/resources/test-card-suite) to test your integration. Make sure you’re on a [registered domain](https://docs.stripe.com/payments/payment-methods/pmd-registration.md) and [supported browser](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers), and have an active card saved to your Google Pay wallet. ### PayPal To test your PayPal integration: 1. Create a [sandbox test account](https://developer.paypal.com/dashboard/accounts), ensuring you’re in sandbox mode. 1. Click the **PayPal** button in the Express Checkout Element and use the generated email and password from the sandbox account to log in. You can’t use a personal PayPal account in a sandbox. 1. If you haven’t yet, [register](https://dashboard.stripe.com/settings/payment_method_domains) your domain. #### Amazon Pay To create a sandbox test account for Amazon Pay: 1. Click the **Amazon Pay** button in sandbox mode. 1. Click **Create your Amazon Account**. 1. Use your sandbox account to test your integration using your test [API keys](https://docs.stripe.com/keys.md). Use the following cards to simulate payments in the Amazon Pay sandbox: | Card | Outcome | | ----------------------- | --------- | | Discover ending in 9424 | Success | | Visa ending in 1111 | Success | | Visa ending in 0701 | 3D Secure | | Amex ending in 0005 | Decline | | JCB ending in 0000 | Decline | ## Optional: Use the Express Checkout Element with Stripe Connect *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) platforms can use the Express Checkout Element with Checkout Sessions by including the connected account in the session. > #### Compare Customers v1 and Accounts v2 references > > If your customer is an Accounts v2 entity, use our [guide](https://docs.stripe.com/billing/v1-v2-customer-map.md) to replace `Customer` and event references in your code with the equivalent Accounts v2 API references. 1. When creating the Checkout Session on your server, include the connected account: ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u sk_test_...: \ -d "line_items[0][price]"="price_..." \ -d "line_items[0][quantity]"=1 \ -d "mode"="payment" \ -d "ui_mode"="custom" \ -d "return_url"="https://example.com/return" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" ``` 1. [Register all of the domains](https://docs.stripe.com/payments/payment-methods/pmd-registration.md?dashboard-or-api=api#register-your-domain-while-using-connect) where you plan to show the Express Checkout Element. ## 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](https://stripe.com/legal/privacy-center#as-a-business-user-what-notice-do-i-provide-to-my-end-customers-about-stripe). ## See also - [Stripe Elements](https://docs.stripe.com/payments/elements.md) - [Checkout Sessions](https://docs.stripe.com/payments/checkout.md) - [Finalize payments on the server](https://docs.stripe.com/payments/finalize-payments-on-the-server.md) # Payment Intents API > This is a Payment Intents API for when payment-ui is elements. View the full page at https://docs.stripe.com/elements/express-checkout-element/accept-a-payment?payment-ui=elements. We recommend that you collect payment details before creating an Intent when using the Express Checkout Element. If you previously integrated with the [Payment Element](https://docs.stripe.com/payments/payment-element.md), you might need to [update your integration](https://docs.stripe.com/payments/accept-a-payment-deferred.md) to this preferred approach. ## Before you begin - Add a payment method to your browser. For example, you can add a card to your Google Pay account or to your Wallet for Safari. - Serve your application over HTTPS. This is required in development and in production. You can use a service such as [ngrok](https://ngrok.com/). - [Register your domain](https://dashboard.stripe.com/settings/payment_method_domains) in both a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) and live mode. ## Set up Stripe [Server-side] First, [create a Stripe account](https://dashboard.stripe.com/register) or [sign in](https://dashboard.stripe.com/login). Use our official libraries to access the Stripe API from your application: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` #### Python ```bash # Install through pip pip3 install --upgrade stripe ``` ```bash # Or find the Stripe package on http://pypi.python.org/pypi/stripe/ ``` ```python # Find the version you want to pin: # https://github.com/stripe/stripe-python/blob/master/CHANGELOG.md # Specify that version in your requirements.txt file stripe>=5.0.0 ``` #### PHP ```bash # Install the PHP library with Composer composer require stripe/stripe-php ``` ```bash # Or download the source directly: https://github.com/stripe/stripe-php/releases ``` #### Java ```java /* For Gradle, add the following dependency to your build.gradle and replace with the version number you want to use from: - https://mvnrepository.com/artifact/com.stripe/stripe-java or - https://github.com/stripe/stripe-java/releases/latest */ implementation "com.stripe:stripe-java:31.0.0" ``` ```xml com.stripe stripe-java 31.0.0 ``` ```bash # For other environments, manually install the following JARs: # - The Stripe JAR from https://github.com/stripe/stripe-java/releases/latest # - Google Gson from https://github.com/google/gson ``` #### Node.js ```bash # Install with npm npm install stripe --save ``` #### Go ```bash # Make sure your project is using Go Modules go mod init # Install stripe-go go get -u github.com/stripe/stripe-go/v83 ``` ```go // Then import the package import ( "github.com/stripe/stripe-go/v83" ) ``` #### .NET ```bash # Install with dotnet dotnet add package Stripe.net dotnet restore ``` ```bash # Or install with NuGet Install-Package Stripe.net ``` ## Enable payment methods By default, Stripe uses your [payment methods settings](https://dashboard.stripe.com/settings/payment_methods) to determine which payment methods are enabled in the Express Checkout Element. To manually override which payment methods are enabled, list any that you want to enable using the `payment_method_types` attribute. - If you collect payments before creating an intent, then list payment methods in the [`paymentMethodTypes` attribute on your Elements provider options](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-paymentMethodTypes). - If you create an intent before rendering Elements, then list payment methods in the [`payment_method_types` attribute on your Intent](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-payment_method_types). ### Supported payment methods Apple Pay and Google Pay are automatically enabled when using `card` payment method type. When using Link, you must also pass the `card` payment method type. | Payment method name | Payment method API parameters | | ------------------- | ----------------------------- | | Apple Pay | `card` | | Google Pay | `card` | | Link | `link, card` | | PayPal | `paypal` | | Amazon Pay | `amazon_pay` | | Klarna | `klarna` | ## Set up Stripe Elements [Client-side] #### HTML + JS The Express Checkout 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. 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('<>'); ``` Then, create an instance of Elements with the [mode](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-mode) (payment, setup, or subscription), [amount](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-amount), and [currency](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-currency). These values determine which payment methods to show to your customer. See the next step for more configurable Elements options. ```javascript const options = { mode: 'payment', amount: 1099, currency: 'usd', // Customizable by using the Appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form. const elements = stripe.elements(options); ``` #### React The Express Checkout Element is automatically available as a feature of 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 ``` To use the Express Checkout Element component, wrap your checkout page component in an [Elements provider](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Call `loadStripe` with your publishable key, and pass the returned `Promise` to the `Elements` provider. The `Elements` provider also accepts the mode (payment, setup, or subscription), amount, and currency. Many payment methods, including Apple Pay and Google Pay, use these values within their UI. See the next step for more configurable Elements options. ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutPage from './CheckoutPage'; // 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 options = {mode: 'payment', amount: 1099, currency: 'usd', // Customizable with appearance API. appearance: {/*...*/}, }; return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` ## Optional: Additional Elements options [Client-side] The [Elements object](https://docs.stripe.com/js/elements_object/create_without_intent) accepts additional options that influence payment collection. Based on the options provided, the Express Checkout Element displays available payment methods from those you’ve enabled. Learn more about [payment method support](https://docs.stripe.com/payments/payment-methods/payment-method-support.md). | Property | Type | Description | Required | | ---------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------- | | `mode` | - `payment` - `setup` - `subscription` | Indicates whether the Express Checkout Element is used with a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods), *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method), or *Subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis). | Yes | | `currency` | `string` | The currency of the amount to charge the customer. | Yes | | `amount` | `number` | The amount to charge the customer, shown in Apple Pay, Google Pay, or BNPL UIs. | For `payment` and `subscription` mode | | `setupFutureUsage` | - `off_session` - `on_session` | Indicates that you intend to make future payments with the payment details collected by the Express Checkout Element. Not supported for Klarna using the Express Checkout Element. | No | | `captureMethod` | - `automatic` - `automatic_async` - `manual` | Controls when to capture the funds from the customer’s account. | No | | `onBehalfOf` | `string` | Connect only. The Stripe account ID, which is the business of record. See [use cases](https://docs.stripe.com/connect/charges.md) to determine if this option is relevant for your integration. | No | | `paymentMethodTypes` | `string[]` | A list of payment method types to render. You can omit this attribute to manage your payment methods in the [Stripe Dashboard](https://dashboard.stripe.com/settings/payment_methods). | No | | `paymentMethodConfiguration` | `string` | The [payment method configuration](https://docs.stripe.com/api/payment_method_configurations.md) to use when managing your payment methods in the [Stripe Dashboard](https://dashboard.stripe.com/settings/payment_methods). If not specified, your default configuration is used. | No | | `paymentMethodCreation` | `manual` | Allows PaymentMethods to be created from the Elements instance using [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method_elements). | No | | `paymentMethodOptions` | `{us_bank_account: {verification_method: string}}` | Verification options for the `us_bank_account` payment method. Accepts the same verification methods as [Payment Intents](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-us_bank_account-verification_method). | No | | `paymentMethodOptions` | `{card: {installments: {enabled: boolean}}}` | Allows manually enabling the card installment plan selection UI if applicable when you aren’t managing your payment methods in the [Stripe Dashboard](https://dashboard.stripe.com/settings/payment_methods). You must set `mode='payment'` *and* explicitly specify `paymentMethodTypes`. Otherwise an error is raised. Incompatible with `paymentMethodCreation='manual'`. | No | ## Create and mount the Express Checkout Element [Client-side] The Express Checkout 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. #### HTML + JS The Express Checkout 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
``` When the form has loaded, create an instance of the Express Checkout Element and mount it to the container DOM node: ```javascript // Create and mount the Express Checkout Element const expressCheckoutElement = elements.create('expressCheckout'); expressCheckoutElement.mount('#express-checkout-element'); ``` #### React Add the `ExpressCheckoutElement` component to your payment page: ```jsx import React from 'react'; import {ExpressCheckoutElement} from '@stripe/react-stripe-js'; const CheckoutPage = () => { return (
); }; ``` ## Collect customer details and display line items [Client-side] Pass options when [creating](https://docs.stripe.com/js/elements_object/create_express_checkout_element) the Express Checkout Element. #### HTML + JS ### Collect payer information Set `emailRequired: true` to collect emails, and `phoneNumberRequired: true` to collect phone numbers. The `billingAddressRequired` default depends on your integration: - If you pass `allowedShippingCountries`, `phoneNumberRequired`, `shippingAddressRequired`, `emailRequired`, `applePay`, `lineItems`, or `business` when creating the Express Checkout Element, `billingAddressRequired` defaults to false. - Otherwise, `billingAddressRequired` defaults to true. ```javascript elements.create('expressCheckout', { emailRequired: true, phoneNumberRequired: true }); ``` > #### PayPal customer information > > PayPal normally doesn’t provide the customer’s billing address (except for the country) or phone number. If they aren’t provided, the confirm event has empty strings for those properties. If you require the customer’s billing address or phone number, then the Express Checkout Element doesn’t display the PayPal button unless that information is available. ### Collect shipping information Set `shippingAddressRequired: true` and pass an array of [shippingRates](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-shippingRates). ```javascript elements.create('expressCheckout', { shippingAddressRequired: true, allowedShippingCountries: ['US'], shippingRates: [ { id: 'free-shipping', displayName: 'Free shipping', amount: 0, deliveryEstimate: { maximum: {unit: 'day', value: 7}, minimum: {unit: 'day', value: 5} } }, ] }); ``` Listen to the [shippingaddresschange event](https://docs.stripe.com/js/elements_object/express_checkout_element_shippingaddresschange_event) to detect when a customer selects a shipping address. You must call either `resolve` or `reject` if you choose to handle this event. > To maintain privacy, browsers might anonymize the shipping address by removing sensitive information that isn’t necessary to calculate shipping costs. Depending on the country, some fields can be missing or partially redacted. For example, the shipping address in the US can only contain a city, state, and postal code. The full shipping address appears in the [confirm event](https://docs.stripe.com/js/elements_object/express_checkout_element_confirm_event#express_checkout_element_on_confirm-handler-shippingAddress) object after the purchase is confirmed in the browser’s payment interface. ```javascript expressCheckoutElement.on('shippingaddresschange', async (event) => { const response = await fetch('/calculate-shipping', { data: JSON.stringify({ shippingAddress: event.address }) }); const result = await response.json(); event.resolve({ lineItems: result.updatedLineItems, }); }); ``` Listen to the [shippingratechange event](https://docs.stripe.com/js/elements_object/express_checkout_element_shippingratechange_event) to detect when a customer selects a shipping rate. You must call either `resolve` or `reject` if you choose to handle this event. ```javascript expressCheckoutElement.on('shippingratechange', async (event) => { const response = await fetch('/calculate-and-update-amount', { data: JSON.stringify({ shippingRate: event.shippingRate }) }); const result = await response.json(); elements.update({amount: result.amount}) event.resolve({ lineItems: result.updatedLineItems, }); }); ``` Listen to the [cancel event](https://docs.stripe.com/js/elements_object/express_checkout_element_cancel_event) to detect when a customer dismisses the payment interface. Reset the amount to the initial amount. ```javascript expressCheckoutElement.on('cancel', () => { elements.update({amount: 1099}) }); ``` ### Display line items Pass in an array of [lineItems](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-lineItems): ```javascript elements.create('expressCheckout', { lineItems: [ { name: 'Sample item', amount: 1000 }, { name: 'Tax', amount: 100 }, { name: 'Shipping cost', amount: 1000 } ] }); ``` ### Configure the Apple Pay interface Learn how to configure the Apple Pay interface. ### Merchant initiated transactions (MIT) You can set up recurring payments, deferred payments, or automatic reload payments when a user checks out with Apple Pay by requesting the relevant [merchant token type](https://docs.stripe.com/apple-pay/merchant-tokens.md?pay-element=ece&mpan=auto-reload#merchant-token-types) in the Express Checkout Element `click` event. We recommend implementing Apple Pay merchant tokens to align with Apple Pay’s latest guidelines and to future proof your integration. #### React ### Collect payer information Set `emailRequired: true` to collect emails, and `phoneNumberRequired: true` to collect phone numbers. The `billingAddressRequired` default depends on your integration: - If you pass `allowedShippingCountries`, `phoneNumberRequired`, `shippingAddressRequired`, `emailRequired`, `applePay`, `lineItems`, or `business` when creating the Express Checkout Element, `billingAddressRequired` defaults to false. - Otherwise, `billingAddressRequired` defaults to true. ```jsx const options = { emailRequired: true, phoneNumberRequired: true }; ``` ### Collect shipping information Set `shippingAddressRequired: true` and pass an array of [shippingRates](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-shippingRates): ```jsx const options = { emailRequired: true, phoneNumberRequired: true, shippingAddressRequired: true, allowedShippingCountries: ['US'], shippingRates: [ { id: 'free-shipping', displayName: 'Free shipping', amount: 0, deliveryEstimate: { maximum: {unit: 'day', value: 7}, minimum: {unit: 'day', value: 5} } }, ] }; ``` Listen to the [shippingaddresschange event](https://docs.stripe.com/js/elements_object/express_checkout_element_shippingaddresschange_event) to detect when a customer selects a shipping address. You must call either `resolve` or `reject` if you choose to handle this event. ```jsx const onShippingAddressChange = async ({resolve, address}) => { const response = await fetch('/calculate-shipping', { data: JSON.stringify({ shippingAddress: address }) }); const result = await response.json(); resolve({ lineItems: result.updatedLineItems, }); }; ``` Listen to the [shippingratechange event](https://docs.stripe.com/js/elements_object/express_checkout_element_shippingratechange_event) to detect when a customer selects a shipping rate. You must call either `resolve` or `reject` if you choose to handle this event. ```jsx const onShippingRateChange = async ({resolve, shippingRate}) => { const response = await fetch('/calculate-and-update-amount', { data: JSON.stringify({ shippingRate: shippingRate }) }); const result = await response.json(); elements.update({amount: result.amount}) resolve({ lineItems: result.updatedLineItems, }); }; ``` Listen to the [cancel event](https://docs.stripe.com/js/elements_object/express_checkout_element_cancel_event) to detect when a customer dismisses the payment interface. Reset the amount to the initial amount. ```jsx const onCancel = () => { elements.update({amount: 1099}) }; ``` Add the event handlers when creating the Element. ```jsx ``` ### Display line items Pass in an array of [lineItems](https://docs.stripe.com/js/elements_object/express_checkout_element_click_event#express_checkout_element_on_click-handler-resolve-lineItems). ```jsx const options = { lineItems: [ { name: 'Sample item', amount: 1000 }, { name: 'Tax', amount: 100 }, { name: 'Shipping cost', amount: 1000 } ] }; ``` ### Configure the Apple Pay interface Learn how to configure the Apple Pay interface. ### Merchant initiated transactions (MIT) We provide specific options to configure for Apple Pay. Set the `applePay.recurringPaymentRequest` [option](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-applePay-recurringPaymentRequest) to specify a request to set up a recurring payment. When specified, Apple Pay issues a [merchant token](https://developer.apple.com/apple-pay/merchant-tokens/) and provides the customer with a way to manage payment methods for a recurring payment. ```jsx const options = { applePay: { recurringPaymentRequest: { paymentDescription: 'My subscription', managementURL: 'https://example.com/billing', regularBilling: { amount: 2500, label: 'Monthly subscription fee', recurringPaymentIntervalUnit: 'month', recurringPaymentIntervalCount: 1, }, } } }; ``` ## Optional: Listen to the ready event [Client-side] After mounting, the Express Checkout Element won’t show buttons for a brief period. To animate the Element when buttons appear, listen to the [ready event](https://docs.stripe.com/js/element/events/on_ready). Inspect the `availablePaymentMethods` value to determine which buttons, if any, display in the Express Checkout Element. #### HTML + JS ```javascript // Optional: If you're doing custom animations, hide the Element const expressCheckoutDiv = document.getElementById('express-checkout-element'); expressCheckoutDiv.style.visibility = 'hidden'; expressCheckoutElement.on('ready', ({availablePaymentMethods}) => { if (!availablePaymentMethods) { // No buttons will show } else { // Optional: Animate in the Element expressCheckoutDiv.style.visibility = 'initial'; } }); ``` #### React ```jsx import React, {useState} from 'react'; import {ExpressCheckoutElement} from '@stripe/react-stripe-js'; import {onConfirm} from './confirmHandler'; const CheckoutPage = () => { // Optional: If you're doing custom animations, hide the Element const [visibility, setVisibility] = useState('hidden'); const onReady = ({availablePaymentMethods}) => { if (!availablePaymentMethods) { // No buttons will show } else { // Optional: Animate in the Element setVisibility('initial'); } }; return (
); }; ``` ## Optional: Control when to show payment buttons [Client-side] You can manage the payment methods that appear in the Express Checkout Element in several ways: - In the Stripe Dashboard’s [payment methods settings](https://dashboard.stripe.com/settings/payment_methods). - By using the [paymentMethods property](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-paymentMethods) to disable payment buttons. Using this property gives you finer control over what your customers see. The Express Checkout Element displays Apple Pay or Google Pay when the customer is on a supported platform and has an active card. If you want to always display Apple Pay and Google Pay even when the customer doesn’t have an active card, you can also configure this with `paymentMethods`. ## Optional: Style the button [Client-side] You can [style](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-buttonTheme) each payment method button differently. For examples of button themes and types, see [Google’s](https://developers.google.com/pay/api/web/guides/resources/customize) and [Apple’s](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Using-Apple-Pay-buttons) resources. You can also use the `borderRadius` variable in the [Appearance API](https://docs.stripe.com/elements/appearance-api.md?platform=web#commonly-used-variables): #### HTML + JS ```javascript const appearance = { variables: { // This controls the border-radius of the rendered Express Checkout Element borderRadius: '4px', } }; // Pass the appearance object to the Elements instance const elements = stripe.elements({clientSecret, appearance}); elements.create('expressCheckout', { // Specify a type per payment method // Defaults to 'buy' for Google, 'plain' for Apple, and 'paypal' for PayPal buttonType: { googlePay: 'checkout', applePay: 'check-out', paypal: 'buynow', }, // Specify a theme per payment method // Default theme is based on appearance API settings buttonTheme: { applePay: 'white-outline' }, // Height in pixels. Defaults to 44. The width is always '100%'. buttonHeight: 55 }); ``` #### React ```jsx const options = { mode: 'payment', amount: 1099, currency: 'usd',appearance: { variables: { // This controls the border-radius of the rendered Express Checkout Element borderRadius: '4px' } } }; const expressCheckoutOptions = { // Specify a type per payment method // Defaults to 'buy' for Google and 'plain' for Apple buttonType: { googlePay: 'checkout', applePay: 'check-out' }, // Specify a theme per payment method // Default theme is based on appearance API settings buttonTheme: { applePay: 'white-outline' }, // Height in pixels. Defaults to 44. The width is always '100%'. buttonHeight: 55 }; ``` Pass in these `options` while creating the Element and `Elements` provider. ```jsx ``` ## Optional: Create a ConfirmationToken [Client-side] When the customer authorizes a payment, you can create a *ConfirmationToken* (ConfirmationTokens help capture data from your client, such as your customer's payment instruments and shipping address, and are used to confirm a PaymentIntent or SetupIntent) to send to your server for additional validation or business logic prior to confirmation. You must immediately use the created ConfirmationToken to confirm a PaymentIntent or SetupIntent. #### HTML + JS ```javascript const handleError = (error) => { const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } expressCheckoutElement.on('confirm', async (event) => { ... const {error: submitError} = await elements.submit(); if (submitError) { handleError(submitError); return; } // Create a ConfirmationToken using the details collected by the Express Checkout Element const {error, confirmationToken} = await stripe.createConfirmationToken({ elements, params: { payment_method_data: { billing_details: { name: 'Jenny Rosen', } }, return_url: 'https://example.com/order/123/complete' } }); if (error) { // This point is only reached if there's an immediate error when // confirming the payment. Show the error to your customer (for example, payment details incomplete) handleError(error); return; } // Send the ConfirmationToken ID to your server for additional logic and attach the ConfirmationToken const res = await fetch('/create-intent', { method: 'POST', body: confirmationToken.id }); const {client_secret: clientSecret} = await res.json(); // Confirm the PaymentIntent const {error: confirmError} = await stripe.confirmPayment({ clientSecret, confirmParams: { confirmation_token: confirmationToken.id }, }); if (confirmError) { // This point is only reached if there's an immediate error when // confirming the payment. Show the error to your customer (for example, payment details incomplete) handleError(confirmError); } else { // The payment UI automatically closes with a success animation. // Your customer is redirected to your `return_url`. } }); ``` #### React ```jsx import React from 'react'; import {useStripe, useElements, ExpressCheckoutElement} from '@stripe/react-stripe-js'; const CheckoutPage = () => { const stripe = useStripe(); const elements = useElements(); const [errorMessage, setErrorMessage] = useState(); const onConfirm = async (event) => { if (!stripe) { // Stripe.js hasn't loaded yet. // Make sure to disable form submission until Stripe.js has loaded. return; } const {error: submitError} = await elements.submit(); if (submitError) { setErrorMessage(submitError.message); return; } // Create a ConfirmationToken using the details collected by the Express Checkout Element const {error, confirmationToken} = await stripe.createConfirmationToken({ elements, params: { payment_method_data: { billing_details: { name: 'Jenny Rosen', }, }, return_url: 'https://example.com/order/123/complete', } }); if (error) { // This point is only reached if there's an immediate error when // creating the ConfirmationToken. Show the error to your customer (for example, payment details incomplete) setErrorMessage(error.message); } // Send the ConfirmationToken ID to your server for additional logic and attach the ConfirmationToken const res = await fetch('/create-intent', { method: 'POST', body: confirmationToken.id }); const {client_secret: clientSecret} = await res.json(); // Confirm the PaymentIntent const {error: confirmError} = await stripe.confirmPayment({ clientSecret, confirmParams: { confirmation_token: confirmationToken.id }, }); if (confirmError) { // This point is only reached if there's an immediate error when // confirming the payment. Show the error to your customer (for example, payment details incomplete) setErrorMessage(confirmError.message); } else { // The payment UI automatically closes with a success animation. // Your customer is redirected to your `return_url`. } }; return (
{errorMessage &&
{errorMessage}
}
); }; ``` ## Create a PaymentIntent [Server-side] Stripe uses a *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods) object to represent your intent to collect payment from a customer, tracking charge attempts and payment state changes throughout the process. Create a PaymentIntent on your server with an amount and currency. This must match what you set on the `stripe.elements` instance in [step 3](https://docs.stripe.com/elements/express-checkout-element/accept-a-payment.md#set-up-elements). Always decide how much to charge on the server-side, a trusted environment, as opposed to the client-side. This prevents malicious customers from choosing their own prices. #### Ruby ```ruby require 'stripe' Stripe.api_key = '<>' post '/create-intent' do # If you used a Tax Calculation, optionally recalculate taxes # confirmation_token = Stripe::ConfirmationToken.retrieve(params[:confirmation_token_id]) # summarized_payment_details = summarize_payment_details(confirmation_token) intent = Stripe::PaymentIntent.create({ # To allow saving and retrieving payment methods, provide the Customer ID. customer: customer.id, # If you used a Tax Calculation, use its `amount_total`. # amount: summarized_payment_details.amount_total, amount: 1099, currency: 'usd', # Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, # If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. # hooks: { # inputs: { # tax: { # calculation: tax_calculation.id # } # } #} }, #{ # stripe_version: '2025-09-30.preview' } ) {client_secret: intent.client_secret}.to_json end ``` #### Python ```python import stripe from flask import Flask, jsonify, request app = Flask(__name__) stripe.api_key = "<>" @app.route('/create-intent', methods=['POST']) def createIntent(): # If you used a Tax Calculation, optionally recalculate taxes #confirmation_token = stripe.ConfirmationToken.retrieve(request.json['confirmation_token_id']) #summarized_payment_details = summarize_payment_details(confirmation_token) intent = stripe.PaymentIntent.create( # To allow saving and retrieving payment methods, provide the Customer ID. customer=customer['id'], # If you used a Tax Calculation, use its `amount_total`. #amount=summarized_payment_details.amount_total, amount=1099, currency='usd', # Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods={ 'enabled': True, }, # If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. #hooks={ # 'inputs': { # 'tax': { # 'calculation': tax_calculation.id # } # } #}, #stripe_version='2025-09-30.preview' ) return jsonify(client_secret=intent.client_secret) ``` #### PHP ```php >"); //$confirmationToken = $stripe->confirmationTokens->retrieve($_POST['confirmation_token_id']); //$summarizedPaymentDetails = summarizePaymentDetails($confirmationToken); $intent = $stripe->paymentIntents->create( [ // To allow saving and retrieving payment methods, provide the Customer ID. 'customer' => $customer->id, // If you used a Tax Calculation, use its `amount_total`. //'amount' => $summarizedPaymentDetails->amount_total, 'amount' => 1099, 'currency' => 'usd', // Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. 'automatic_payment_methods' => ['enabled' => true], // If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. //'hooks' => [ // 'inputs' => [ // 'tax' => [ // 'calculation' => $tax_calculation->id // ] // ] //] ], //[ // 'stripe_version' => '2025-09-30.preview' //] ); echo json_encode(array('client_secret' => $intent->client_secret)); ?> ``` #### Node.js ```javascript const stripe = require("stripe")("<>"); const express = require('express'); const app = express(); app.use(express.static(".")); app.post('/create-intent', async (req, res) => { // If you used a Tax Calculation, optionally recalculate taxes //const confirmationToken = await stripe.confirmationTokens.retrieve(req.body.confirmation_token_id) //const summarizePaymentDetails = summarizePaymentDetails(confirmationToken) const intent = await stripe.paymentIntents.create( { // To allow saving and retrieving payment methods, provide the Customer ID. customer: customer.id, // If you used a Tax Calculation, use its `amount_total`. //amount: summarizePaymentDetails.amount_total, amount: 1099, currency: 'usd', // Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, // If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. //hooks: { // inputs: { // tax: { // calculation: tax_calculation.id // } // } //} }, //{ // stripe_version: '2025-09-30.preview' //} } ); res.json({client_secret: intent.client_secret}); }); app.listen(3000, () => { console.log('Running on port 3000'); }); ``` #### Java ```java import java.util.HashMap; import java.util.Map; import com.stripe.Stripe; import com.stripe.model.PaymentIntent; import com.stripe.model.ConfirmationToken; import com.stripe.param.PaymentIntentCreateParams; import com.stripe.param.RequestOptions; import com.google.gson.Gson; import static spark.Spark.post; public class StripeJavaQuickStart { public static void main(String[] args) { Gson gson = new Gson(); Stripe.apiKey = "<>"; post("/create-intent", (request, response) -> { // If you used a Tax Calculation, optionally recalculate taxes //ConfirmationToken confirmationToken = ConfirmationToken.retrieve(request.body()); //PaymentDetails summarizedPaymentDetails = summarizePaymentDetails(confirmationToken); //RequestOptions requestOptions = RequestOptions.builder() // .setStripeVersion("2025-09-30.preview") // .build(); PaymentIntentCreateParams params = PaymentIntentCreateParams .builder() // To allow saving and retrieving payment methods, provide the Customer ID. .setCustomer(customer.getId()) // If you used a Tax Calculation, use its `amount_total`. //.setAmount(summarizedPaymentDetails.getAmountTotal()) .setAmount(1099L) .setCurrency("usd") // Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. .setAutomaticPaymentMethods( PaymentIntentCreateParams.AutomaticPaymentMethods.builder().setEnabled(true).build() ) // If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. //.setHooks( // PaymentIntentCreateParams.Hooks.builder() // .setInputs( // PaymentIntentCreateParams.Hooks.Inputs.builder() // .setTax( // PaymentIntentCreateParams.Hooks.Inputs.Tax.builder() // .setCalculation(taxCalculation.getId()) // .build() // ) // .build() // ) // .build() //) .build(); PaymentIntent paymentIntent = PaymentIntent.create(params, requestOptions); Map map = new HashMap(); map.put("client_secret", paymentIntent.getClientSecret()); return map; }, gson::toJson); } } ``` #### Go ```go package main import ( "encoding/json" "net/http" "github.com/stripe/stripe-go/v76.0.0" "github.com/stripe/stripe-go/v76.0.0/paymentintent" //"github.com/stripe/stripe-go/v76.0.0/confirmationtoken" ) type CheckoutData struct { ClientSecret string `json:"client_secret"` } func main() { stripe.Key = "<>" http.HandleFunc("/create-intent", func(w http.ResponseWriter, r *http.Request) { // If you used a Tax Calculation, optionally recalculate taxes //confirmationToken, _ := confirmationtoken.Get(r.FormValue("confirmation_token_id"), nil) //summarizedPaymentDetails := summarizePaymentDetails(confirmationToken) params := &stripe.PaymentIntentParams{ // To allow saving and retrieving payment methods, provide the Customer ID. Customer: stripe.String(c.ID), // If you used a Tax Calculation, use its `amount_total`. //Amount: stripe.Int64(summarizedPaymentDetails.AmountTotal), Amount: stripe.Int64(1099), Currency: stripe.String(string(stripe.CurrencyUSD)), // Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. AutomaticPaymentMethods: &stripe.PaymentIntentAutomaticPaymentMethodsParams{ Enabled: stripe.Bool(true), }, // If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. //Hooks: &stripe.PaymentIntentHooksParams{ // Inputs: &stripe.PaymentIntentHooksInputsParams{ // Tax: &stripe.PaymentIntentHooksInputsTaxParams{ // Calculation: stripe.String(taxCalculation.ID), // }, // }, //}, } //params.SetStripeVersion("2025-09-30.preview") intent, _ := paymentintent.New(params) data := CheckoutData{ ClientSecret: intent.ClientSecret, } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(data) }) http.ListenAndServe(":3000", nil) } ``` #### .NET ```csharp using System; using Microsoft.AspNetCore.Mvc; using Stripe; namespace StripeExampleApi.Controllers { [Route("create-intent")] [ApiController] public class CheckoutApiController : Controller { public CheckoutApiController() { StripeConfiguration.ApiKey = "<>"; } [HttpPost] public ActionResult Post([FromBody] dynamic request) { // If you used a Tax Calculation, optionally recalculate taxes //var requestOptions = new RequestOptions //{ // StripeVersion = "2025-09-30.preview" //}; //var confirmationTokenService = new ConfirmationTokenService(); //var confirmationToken = confirmationTokenService.Get(request.confirmation_token_id); //var summarizedPaymentDetails = SummarizePaymentDetails(confirmationToken); var options = new PaymentIntentCreateOptions { // To allow saving and retrieving payment methods, provide the Customer ID. Customer = customer.Id, // If you used a Tax Calculation, use its `amount_total`. // Amount = summarizedPaymentDetails.AmountTotal, Amount = 1099, Currency = "usd", // Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default. AutomaticPaymentMethods = new PaymentIntentAutomaticPaymentMethodsOptions { Enabled = true, }, // If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax. //Hooks = new PaymentIntentHooksOptions //{ // Inputs = new PaymentIntentHooksInputsOptions // { // Tax = new PaymentIntentHooksInputsTaxOptions // { // Calculation = taxCalculation.Id // } // } //} }; var service = new PaymentIntentService(); PaymentIntent intent = service.Create(options, requestOptions); return Json(new {client_secret = intent.ClientSecret}); } } } ``` The returned PaymentIntent includes a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)), 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. ## Submit the payment to Stripe [Client-side] Use [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) to complete the payment using details from the Express Checkout Element. > For Amazon Pay, Klarna, and PayPal, the amount you confirm in the PaymentIntent must match the amount the buyer pre-authorized. If the amounts don’t match, the payment is declined. Provide a [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) to this function to indicate where Stripe should redirect the user after they complete the payment. Your user might be initially redirected to an intermediate site before being redirected to the `return_url`. Payments immediately redirect to the `return_url` when a payment is successful. If you don’t want to redirect after payment completion, set [redirect](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect) to `if_required`. This only redirects customers that check out with redirect-based payment methods. #### HTML + JS ```javascript const handleError = (error) => { const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } expressCheckoutElement.on('confirm', async (event) => { const {error: submitError} = await elements.submit(); if (submitError) { handleError(submitError); return; } // Create the PaymentIntent and obtain clientSecret const res = await fetch('/create-intent', { method: 'POST', }); const {client_secret: clientSecret} = await res.json(); const {error} = await stripe.confirmPayment({ // `elements` instance used to create the Express Checkout Element elements, // `clientSecret` from the created PaymentIntent clientSecret, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point is only reached if there's an immediate error when // confirming the payment. Show the error to your customer (for example, payment details incomplete) handleError(error); } else { // The payment UI automatically closes with a success animation. // Your customer is redirected to your `return_url`. } }); ``` #### React ```jsx import React from 'react'; import {useStripe, useElements, ExpressCheckoutElement} from '@stripe/react-stripe-js'; const CheckoutPage = () => { const stripe = useStripe(); const elements = useElements(); const [errorMessage, setErrorMessage] = useState(); const onConfirm = async (event) => { if (!stripe) { // Stripe.js hasn't loaded yet. // Make sure to disable form submission until Stripe.js has loaded. return; } const {error: submitError} = await elements.submit(); if (submitError) { setErrorMessage(submitError.message); return; } // Create the PaymentIntent and obtain clientSecret const res = await fetch('/create-intent', { method: 'POST', }); const {client_secret: clientSecret} = await res.json(); // Confirm the PaymentIntent using the details collected by the Express Checkout Element const {error} = await stripe.confirmPayment({ // `elements` instance used to create the Express Checkout Element elements, // `clientSecret` from the created PaymentIntent clientSecret, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point is only reached if there's an immediate error when // confirming the payment. Show the error to your customer (for example, payment details incomplete) setErrorMessage(error.message); } else { // The payment UI automatically closes with a success animation. // Your customer is redirected to your `return_url`. } }; return (
{errorMessage &&
{errorMessage}
}
); }; ``` ## Test the integration Before you go live, [test](https://docs.stripe.com/testing.md) each payment method integration. To determine a payment method’s browser compatibility, see [supported browsers](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers). If you use the Express Checkout Element within an iframe, the iframe must have the [allow](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allowpaymentrequest) attribute set to `payment *`. #### Link > Don’t store real user data in *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) Link accounts. Treat them as if they’re publicly available, because these test accounts are associated with your publishable key. Currently, Link only works with credit cards, debit cards, and qualified US bank account purchases. Link requires [domain registration](https://docs.stripe.com/payments/payment-methods/pmd-registration.md). You can create sandbox accounts for Link using any valid email address. The following table shows the fixed one-time passcode values that Stripe accepts for authenticating sandbox accounts: | Value | Outcome | | ----------------------------------- | ---------------------------- | | Any other 6 digits not listed below | Success | | 000001 | Error, code invalid | | 000002 | Error, code expired | | 000003 | Error, max attempts exceeded | #### Wallets > #### Regional testing > > 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. ### Apple Pay You can’t save Stripe test card information to Apple Pay. Instead, Stripe recognizes when you’re using your test [API keys](https://docs.stripe.com/keys.md) and returns a successful test card token for you to use. This allows you to make test payments using a live card without charging it. Make sure you’re on a [registered domain](https://docs.stripe.com/payments/payment-methods/pmd-registration.md), [supported browser](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers), and have an active card saved to your Apple Pay wallet. Alternatively, set the [paymentMethods](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-paymentMethods) `applePay` option to `always` to remove the requirement for an active saved card. ### Google Pay You can’t save Stripe test card information to Google Pay. Instead, Stripe recognizes when you’re using your test API keys and returns a successful test card token for you to use. This allows you to make test payments using a live card without charging it. You can also use Google Pay’s [test card suite](https://developers.google.com/pay/api/web/guides/resources/test-card-suite) to test your integration. Make sure you’re on a [registered domain](https://docs.stripe.com/payments/payment-methods/pmd-registration.md), [supported browser](https://docs.stripe.com/elements/express-checkout-element.md#supported-browsers) and have an active card saved to your Google Pay wallet. Alternatively, set the [paymentMethods](https://docs.stripe.com/js/elements_object/create_express_checkout_element#express_checkout_element_create-options-paymentMethods) `googlePay` option to `always` to remove the requirement for an active saved card. ### PayPal To test your PayPal integration: 1. Create a [sandbox test account](https://developer.paypal.com/dashboard/accounts), ensuring you’re in sandbox mode. 1. Click the **PayPal** button in the Express Checkout Element and use the generated email and password from the sandbox account to log in. You can’t use a personal PayPal account in a sandbox. 1. If you haven’t yet, [register](https://docs.stripe.com/payments/payment-methods/pmd-registration.md) your domain. #### Amazon Pay To create a sandbox test account for Amazon Pay: 1. Click the Amazon Pay button in sandbox mode. 1. Click **Create your Amazon Account**. 1. Use your sandbox account to test your integration using your test [API keys](https://docs.stripe.com/keys.md). Use the following cards to simulate payments in Amazon Pay Sandbox: | Card | Outcome | | ----------------------- | --------- | | Discover ending in 9424 | Success | | Visa ending in 1111 | Success | | Visa ending in 0701 | 3D Secure | | Amex ending in 0005 | Decline | | JCB ending in 0000 | Decline | #### Klarna Klarna requires [domain registration](https://docs.stripe.com/payments/payment-methods/pmd-registration.md). Below, we have specially selected test data for the currently supported customer countries. In a sandbox, Klarna approves or denies a transaction based on the supplied email address. #### Australia | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1970 | 03-05-1994 | | First Name | Test | John | | Last Name | Person-au | snow | | Street | Wharf St | Silverwater Rd | | House number | 4 | 1-5 | | Postal Code | 4877 | 2128 | | City | Port Douglas | Silverwater | | Region | QLD | NSW | | Phone | +61473752244 | +61473763254 | | Email | customer@email.au | customer+denied@email.au | #### Austria | | Approved | Denied | | ------------- | ------------------ | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-at | Person-at | | Email | customer@email.at | customer+denied@email.at | | Street | Mariahilfer Straße | Mariahilfer Straße | | House number | 47 | 47 | | City | Wien | Wien | | Postal code | 1060 | 1060 | | Phone | +4306762600456 | +4306762600745 | #### Belgium | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-be | Person-be | | Email | customer@email.be | customer+denied@email.be | | Street | Grote Markt | Grote Markt | | House number | 1 | 1 | | City | Brussel | Brussel | | Postal code | 1000 | 1000 | | Phone | +32485121291 | +32485212123 | #### Canada | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-ca | Person-ca | | Street | 2693 Byron Rd | 2693 Byron Rd | | Postal Code | V7H 1L9 | V7H 1L9 | | City | North Vancouver | North Vancouver | | Region | BC | BC | | Phone | +15197438620 | +15197308624 | | Email | customer@email.ca | customer+denied@email.ca | #### Czechia | | Approved | Denied | | ------------- | ------------------ | ------------------------ | | Date of Birth | 01-01-1970 | 27-06-1992 | | First Name | Test | Test | | Last Name | Person-cz | Person-cz | | Email | customer@email.cz | customer+denied@email.cz | | Street | Zazvorkova 1480/11 | Zázvorkova 1480/11 | | Postal code | 155 00 | 155 00 | | City | Praha | PRAHA 13 | | Phone | +420771613715 | +420771623691 | #### Denmark | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 01-01-1980 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-dk | Person-dk | | Email | customer@email.dk | customer+denied@email.dk | | Street | Dantes Plads | Nygårdsvej | | House number | 7 | 65 | | City | København Ø | København Ø | | Postal code | 1556 | 2100 | | Phone | +4542555628 | +4552555348 | #### Finland | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 01-01-1999 | 01-01-1999 | | First Name | Test | Person FI | | Last Name | Person-fi | Test | | Email | customer@email.fi | customer+denied@email.fi | | Street | Mannerheimintie | Mannerheimintie | | House number | 34 | 34 | | City | Helsinki | Helsinki | | Postal code | 00100 | 00100 | | Phone | +358401234567 | +358401234568 | #### France | | Approved | Denied | | -------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1990 | 10-07-1990 | | Place of Birth | Paris | Paris | | First Name | Test | Test | | Last Name | Person-fr | Person-fr | | Email | customer@email.fr | customer+denied@email.fr | | Street | rue La Fayette | rue La Fayette | | House number | 33 | 33 | | City | Paris | Paris | | Postal code | 75009 | 75009 | | Phone | +33689854321 | +33687984322 | #### Germany | | Approved | Denied | | ------------- | --------------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Mock | Test | | Last Name | Mock | Person-de | | Email | customer@email.de | customer+denied@email.de | | Street | Neue Schönhauser Str. | Neue Schönhauser Str. | | House number | 2 | 2 | | City | Berlin | Berlin | | Postal code | 10178 | 10178 | | Phone | +49017614284340 | +49017610927312 | #### Greece | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Tax number | 090000045 | 090000045 | | Date of Birth | 01-01-1960 | 11-11-1970 | | First Name | Test | Test | | Last Name | Person-gr | Test-gr | | Email | customer@email.gr | customer+denied@email.gr | | Street | Kephisias | Baralo | | House number | 37 | 56 | | Postal code | 151 23 | 123 67 | | City | Athina | Athina | | Phone | +306945553624 | +306945553625 | #### Ireland | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-ie | Person-ie | | Email | customer@email.ie | customer+denied@email.ie | | Street | King Street South | King Street South | | House Number | 30 | 30 | | City | Dublin | Dublin | | EIR Code | D02 C838 | D02 C838 | | Phone | +353855351400 | +353855351401 | #### Italy | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 01-01-1980 | 01-01-1980 | | First Name | Test | Test | | Last Name | Person-it | Person-it | | Email | customer@email.it | customer+denied@email.it | | Fiscal code | RSSBNC80A41H501B | RSSBNC80A41H501B | | Street | Via Enrico Fermi | Via Enrico Fermi | | House number | 150 | 150 | | City | Roma | Roma | | Postal code | 00146 | 00146 | | Phone | +393339741231 | +393312232389 | #### Netherlands | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-nl | Person-nl | | Email | customer@email.nl | customer+denied@email.nl | | Street | Osdorpplein | Osdorpplein | | House number | 137 | 137 | | City | Amsterdam | Amsterdam | | Postal code | 1068 SR | 1068 SR | | Phone | +31689124321 | +31632167678 | #### New Zealand | | Approved | Denied | | ------------- | ------------------------ | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-nz | Person-nz | | Street | Mount Wellington Highway | Mount Wellington Highway | | House number | 286 | 286 | | Postal Code | 6011 | 6011 | | City | Auckland | Wellington | | Phone | +6427555290 | +642993007712 | | Email | customer@email.nz | customer+denied@email.nz | #### Norway | | Approved | Denied | | --------------- | ------------------- | ------------------------ | | Date of Birth | 01-08-1970 | 01-08-1970 | | First Name | Jane | Test | | Last Name | Test | Person-no | | Email | customer@email.no | customer+denied@email.no | | Personal number | NO1087000571 | NO1087000148 | | Street | Edvard Munchs Plass | Sæffleberggate | | House Number | 1 | 56 | | City | Oslo | Oslo | | Postal code | 0194 | 0563 | | Phone | +4740123456 | +4740123457 | #### Poland | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 05-05-1967 | 05-05-1967 | | First Name | Test | Test | | Last Name | Person-pl | Person-pl | | Street | Ul. Górczewska | Ul. Górczewska | | House number | 124 | 124 | | Postal Code | 01-460 | 01-460 | | City | Warszawa | Warszawa | | Phone | +48795222223 | +48795223325 | | Email | customer@email.pl | customer+denied@email.pl | #### Portugal | | Approved | Denied | | ------------- | ------------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-pt | Person-pt | | Street | Avenida Dom João II | Avenida Dom João II | | House number | 40 | 40 | | Postal Code | 1990-094 | 1990-094 | | City | Lisboa | Lisboa | | Phone | +351935556731 | +351915593837 | | Email | customer@email.pt | customer+denied@email.pt | #### Romania | | Approved | Denied | | ------------------------------------ | ----------------- | ------------------------ | | Date of Birth | 25-12-1970 | 25-12-1970 | | First Name | Test | Test | | Last Name | Person-ro | Person-ro | | Email | customer@email.ro | customer+denied@email.ro | | Street | Drumul Taberei | Drumul Taberei | | House number | 35 | 35 | | City | București | București | | Sector | Sectorul 6 | Sectorul 6 | | Postal code | 061357 | 061357 | | Phone | +40741209876 | +40707127444 | | Personal Identification Number (CNP) | 1701225193558 | | #### Spain | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | DNI/NIE | 99999999R | 99999999R | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-es | Person-es | | Email | customer@email.es | customer+denied@email.es | | Street | C. de Atocha | C. de Atocha | | House number | 27 | 27 | | City | Madrid | Madrid | | Postal code | 28012 | 28012 | | Phone | +34672563009 | +34682425101 | #### Sweden | | Approved | Denied | | ------------- | ----------------------- | ------------------------ | | Date of Birth | 21-03-1941 | 28-10-1941 | | First Name | Alice | Test | | Last Name | Test | Person-se | | Email | customer@email.se | customer+denied@email.se | | Street | Södra Blasieholmshamnen | Karlaplan | | House number | 2 | 3 | | City | Stockholm | Stockholm | | Postal code | 11 148 | 11 460 | | Phone | +46701740615 | +46701740620 | #### Switzerland | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 01-01-1990 | 01-01-2000 | | First Name | Accepted | Customer | | Last Name | Person-ch | Person-ch | | Street | Augustinergasse | Bahnhofstrasse | | House number | 2 | 77 | | Postal Code | 4051 | 8001 | | City | Basel | Zürich | | Phone | +41758680000 | +41758680001 | | Email | customer@email.ch | customer+denied@email.ch | #### United Kingdom | | Approved | Denied | | ------------- | --------------------- | ------------------------ | | Date of Birth | 10-07-1970 | 10-07-1970 | | First Name | Test | Test | | Last Name | Person-uk | Person-uk | | Email | customer@email.uk | customer+denied@email.uk | | Street | New Burlington Street | New Burlington Street | | House number | 10 | 10 | | Apartment | Apt 214 | Apt 214 | | Postal code | W1S 3BE | W1S 3BE | | City | London | London | | Phone | +447755564318 | +447355505530 | #### United States | | Approved | Denied | | ------------- | ----------------- | ------------------------ | | Date of Birth | 07-10-1970 | 07-10-1970 | | First Name | Test | Test | | Last Name | Person-us | Person-us | | Email | customer@email.us | customer+denied@email.us | | Street | Amsterdam Ave | Amsterdam Ave | | House number | 509 | 509 | | City | New York | New York | | State | New York | New York | | Postal code | 10024-3941 | 10024-3941 | | Phone | +13106683312 | +13106354386 | ### Two-step authentication Any six digit number is a valid two-step authentication code. Use `999999` for authentication to fail. ### Repayment method Inside the Klarna flow, you can use the following test values to try various repayment types: | Type | Value | | ------------- | --------------------------------------------------------------------------------------- | | Direct Debit | DE11520513735120710131 | | Bank transfer | Demo Bank | | Credit Card | - Number: 4111 1111 1111 1111 - CVV: 123 - Expiration: any valid date in the future | | Debit Card | - Number: 4012 8888 8888 1881 - CVV: 123 - Expiration: any valid date in the future | ## Optional: Use the Express Checkout Element with Stripe Connect *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) platforms that either create direct charges or add the token to a `Customer` on the connected account must take additional steps. > #### Compare Customers v1 and Accounts v2 references > > If your customer is an Accounts v2 entity, use our [guide](https://docs.stripe.com/billing/v1-v2-customer-map.md) to replace `Customer` and event references in your code with the equivalent Accounts v2 API references. 1. On your frontend, before creating the `ExpressCheckoutElement`, set the `stripeAccount` option on the Stripe instance: ```javascript const stripe = Stripe('<>', { apiVersion: "2025-11-17.clover", stripeAccount: '{{CONNECTED_ACCOUNT_ID}}', }); ``` 1. [Register all of the domains](https://docs.stripe.com/payments/payment-methods/pmd-registration.md?dashboard-or-api=api#register-your-domain-while-using-connect) where you plan to show the Express Checkout Element. ## 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](https://stripe.com/legal/privacy-center#as-a-business-user-what-notice-do-i-provide-to-my-end-customers-about-stripe). ## See also - [Stripe Elements](https://docs.stripe.com/payments/elements.md) - [Collect payment details before creating an Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md) - [Finalize payments on the server](https://docs.stripe.com/payments/finalize-payments-on-the-server.md)