# Accept a payment with the Express Checkout Element

Use the Express Checkout Element with the Checkout Sessions API 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). |

## Integrate the Express Checkout Element 

Follow these steps to accept payments through one-click payment buttons with the Express Checkout Element and the Checkout Sessions API.

## 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 Apple Wallet.
2. Serve your application over HTTPS. This is required in development and in production. You can use a service such as [ngrok](https://ngrok.com/). Without HTTPS, wallets such as Apple Pay and Google Pay won’t appear.
3. [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).

Coding agents: [install the Stripe CLI](https://docs.stripe.com/cli/install) using the installation script for your operating system. Open a new terminal and run `stripe sandbox create --help` to provision an anonymous Stripe sandbox with working API keys. It doesn’t require account registration.

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'
```

## 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 "<<YOUR_SECRET_KEY>>:" \
  -d "line_items[0][price]={{PRICE_ID}}" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d ui_mode=elements \
  -d return_url={{RETURN_URL}}
```

Set `ui_mode` to `elements` 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
<head>
  <title>Checkout</title>
  <script src="https://js.stripe.com/endive/stripe.js"></script>
</head>
```

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('<<YOUR_PUBLISHABLE_KEY>>');
```

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.initCheckoutElementsSdk({
  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> | string` containing the client secret returned by your server.

Wrap your application with the [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider) component, passing in `clientSecret` and the `stripe` instance.

```jsx
import React from 'react';
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('<<YOUR_PUBLISHABLE_KEY>>');

const clientSecret = fetch('/create-checkout-session', {method: 'POST'})
  .then((response) => response.json())
  .then((json) => json.client_secret);

const App = () => {
  return (
    <CheckoutElementsProvider
      stripe={stripePromise}
      options={{clientSecret}}
    >
      <CheckoutForm />
    </CheckoutElementsProvider>
  );
};

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
<div id="express-checkout-element">
  <!-- Express Checkout Element will be inserted here -->
</div>
<div id="error-message">
  <!-- Display an error message to your customers here -->
</div>
```

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 {useCheckoutElements, ExpressCheckoutElement} from '@stripe/react-stripe-js/checkout';

const CheckoutForm = () => {
  const checkoutState = useCheckoutElements();

  if (checkoutState.type === 'error') {
    return <div>Error: {checkoutState.error.message}</div>;
  }

  return (
    <div id="checkout-page">
      <ExpressCheckoutElement onConfirm={handleConfirmExpressCheckout} />
    </div>
  );
};
```

## 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});
  });
}
```

#### React

### Handle payment confirmation 

Handle the `confirm` event when your customer finalizes their payment:

```jsx
import {useCheckoutElements, ExpressCheckoutElement} from '@stripe/react-stripe-js/checkout';

const CheckoutForm = () => {
  const checkoutState = useCheckoutElements();

  if (checkoutState.type === 'loading') {
    return <div>Loading...</div>;
  } else if (checkoutState.type === 'error') {
    return <div>Error: {checkoutState.error.message}</div>;
  }

  const handleConfirmExpressCheckout = (event) => {
    if (checkoutState.type === 'success') {
      checkoutState.checkout.confirm({expressCheckoutConfirmEvent: event});
    }
  };

  return (
    <div>
      {checkoutState.type === 'success' && (
        <pre>
          {JSON.stringify(checkoutState.checkout.lineItems, null, 2)}
          Total: {checkoutState.checkout.total?.amount}
        </pre>
      )}
      <ExpressCheckoutElement onConfirm={handleConfirmExpressCheckout} />
    </div>
  );
};
```

## Optional: Listen to the availablepaymentmethodschange 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 [availablepaymentmethodschange event](https://docs.stripe.com/js/elements_object/express_checkout_element_availablepaymentmethodschange_event). Inspect the `paymentMethods` 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('availablepaymentmethodschange', ({paymentMethods}) => {
  if (!paymentMethods) {
    // 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 onAvailablePaymentMethodsChange = ({paymentMethods}) => {
    if (!paymentMethods) {
      // No buttons will show
    } else {
      // Optional: Animate in the Element
      setVisibility('initial');
    }
  };

  return (
    <div id="checkout-page">
      <div id="express-checkout-element" style={{visibility}}>
        <ExpressCheckoutElement
          onConfirm={onConfirm}
          onAvailablePaymentMethodsChange={onAvailablePaymentMethodsChange}
        />
      </div>
    </div>
  );
};
```

## 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
};

<ExpressCheckoutElement
  options={expressCheckoutOptions}
  onConfirm={onConfirm}
/>
```

## 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.

Link supports credit cards, debit cards, and qualified US bank account purchases.

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 accounts based in India don’t support Google Pay. For Stripe accounts based outside India, users with IP addresses in India can test Google Pay in a sandbox, but can’t use Google Pay in live mode. Apple Pay doesn’t display for IP addresses in India in any mode.

### 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.
2. 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.
3. 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.
2. Click **Create your Amazon Account**.
3. 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.

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"="elements" \
     -d "return_url"="https://example.com/return" \
     -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}"
   ```

2. [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)
