Core Concepts

Checkout

CheckoutElementsProvider, CheckoutFormProvider, and EmbeddedCheckout

Checkout

Vue Stripe offers three checkout integrations.

  1. CheckoutElementsProvider, for building a checkout out of individual Elements
  2. CheckoutFormProvider, for Stripe's single prebuilt Checkout form
  3. EmbeddedCheckout, for Stripe's fully hosted UI embedded in your page
CheckoutProvider was removed in v3. See the migration guide.

CheckoutElementsProvider

Use this when you want to lay out your own checkout from individual Elements.

<script setup>
import { loadStripe } from '@stripe/stripe-js'
import {
  CheckoutElementsProvider,
  PaymentElement,
  useCheckoutElements,
} from 'vue-stripe/checkout'

const stripePromise = loadStripe('pk_test_xxx')

const options = {
  clientSecret: 'cs_test_xxx',
}
</script>

<template>
  <CheckoutElementsProvider :stripe="stripePromise" :options="options">
    <PaymentElement />
  </CheckoutElementsProvider>
</template>

Inside the provider, read the session with useCheckoutElements(). It returns a computed ref holding a loading, success, or error result.

<script setup>
import { useCheckoutElements } from 'vue-stripe/checkout'

const checkout = useCheckoutElements()

async function pay() {
  if (checkout.value.type !== 'success') {
    return
  }

  await checkout.value.checkout.confirm()
}
</script>

<template>
  <p v-if="checkout.type === 'loading'">
    Loading
  </p>
  <p v-else-if="checkout.type === 'error'">
    {{ checkout.error.message }}
  </p>
  <button v-else @click="pay">
    Pay {{ checkout.checkout.total.total.amount }}
  </button>
</template>

Supported children are PaymentElement, BillingAddressElement, ShippingAddressElement, ExpressCheckoutElement, CurrencySelectorElement, TaxIdElement, ContactDetailsElement, and TermsElement.

Appearance and font options are nested under elementsOptions.

const options = {
  clientSecret: 'cs_test_xxx',
  elementsOptions: {
    appearance: { theme: 'night' },
  },
}

CheckoutFormProvider

Use this when you want Stripe's prebuilt Checkout form as a single component.

<script setup>
import { loadStripe } from '@stripe/stripe-js'
import { CheckoutForm, CheckoutFormProvider } from 'vue-stripe/checkout'

const stripePromise = loadStripe('pk_test_xxx')

const options = {
  clientSecret: 'cs_test_xxx',
  appearance: { theme: 'stripe' },
}
</script>

<template>
  <CheckoutFormProvider :stripe="stripePromise" :options="options">
    <CheckoutForm />
  </CheckoutFormProvider>
</template>

Read the session with useCheckoutForm(), which has the same result shape as useCheckoutElements().

CheckoutFormProvider supports only <CheckoutForm> and <CurrencySelectorElement> as children. The underlying form SDK cannot create the other Elements. Use CheckoutElementsProvider if you need them.

Unlike CheckoutElementsProvider, appearance and fonts are top-level options here, not nested under elementsOptions.

useCheckout

useCheckout() still works under either provider and returns the Elements shaped result, but it is deprecated. Prefer useCheckoutElements() or useCheckoutForm(), which return the exact action surface their SDK exposes.

EmbeddedCheckout

<script setup>
import { loadStripe } from '@stripe/stripe-js'
import { EmbeddedCheckout, EmbeddedCheckoutProvider } from 'vue-stripe'

const stripePromise = loadStripe('pk_test_xxx')

async function fetchClientSecret() {
  const res = await fetch('/api/checkout-session', { method: 'POST' })
  const { clientSecret } = await res.json()
  return clientSecret
}

const options = { fetchClientSecret }
</script>

<template>
  <EmbeddedCheckoutProvider :stripe="stripePromise" :options="options">
    <EmbeddedCheckout />
  </EmbeddedCheckoutProvider>
</template>