Vue Stripe offers three checkout integrations.
CheckoutProvider was removed in v3. See the migration guide.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, TermsElement, and
LinkSignupElement.
LinkSignupElement requires beta access. Contact
Stripe support to request it. Import it from
vue-stripe/checkout and render it inside CheckoutElementsProvider. It does
not work inside CheckoutFormProvider.
<script setup>
import { LinkSignupElement } from 'vue-stripe/checkout'
function onReady(element) {
console.log('Link Signup Element ready', element)
}
</script>
<template>
<LinkSignupElement
:options="{
defaultValues: {
email: 'customer@example.com',
name: 'Jenny Rosen',
phone: '+15555555555',
},
}"
@ready="onReady"
/>
</template>
Every field in defaultValues is optional. The element emits ready with the
element instance, plus focus, blur, escape, loaderstart, and
loaderror. It has no change event.
Appearance and font options are nested under elementsOptions.
const options = {
clientSecret: 'cs_test_xxx',
elementsOptions: {
appearance: { theme: 'night' },
},
}
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() 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.
<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>