The Payment Element allows you to collect payment details securely. This implementation follows the deferred payment pattern:
- Wrap
StripeElement inside StripeElements. - Use
StripeElements to manage the lifecycle and configuration (mode, amount, currency). - Use
StripeElement with type="payment" to render the UI. - Access the underlying Stripe instance and elements via component refs (
elementsComponent.value.instance and elementsComponent.value.elements) to call confirmPayment.
<template>
<form v-if="stripeLoaded" @submit.prevent="handleSubmit">
<StripeElements
:stripe-key="stripeKey"
:instance-options="stripeOptions"
:elements-options="elementsOptions"
ref="elementsComponent"
>
<StripeElement
type="payment"
:options="paymentElementOptions"
ref="paymentComponent"
/>
</StripeElements>
<button type="submit">Submit</button>
</form>
</template>
<script setup lang="ts">
import { onBeforeMount, ref } from "vue"
import { loadStripe } from "@stripe/stripe-js"
import { StripeElements, StripeElement } from "vue-stripe-js"
import type { StripeElementsOptionsMode, StripePaymentElementOptions } from "@stripe/stripe-js"
const stripeKey = "pk_test_..."
const stripeOptions = ref({})
const elementsOptions = ref<StripeElementsOptionsMode>({
mode: "payment",
amount: 1099,
currency: "usd",
appearance: { theme: "flat" },
})
const paymentElementOptions = ref<StripePaymentElementOptions>({})
const stripeLoaded = ref(false)
const clientSecret = ref("")
const elementsComponent = ref()
const paymentComponent = ref()
onBeforeMount(() => {
loadStripe(stripeKey).then(() => {
stripeLoaded.value = true
})
})
async function handleSubmit() {
const stripeInstance = elementsComponent.value?.instance
const elements = elementsComponent.value?.elements
if (stripeInstance) {
const { error } = await stripeInstance.confirmPayment({
elements,
clientSecret: clientSecret.value,
confirmParams: {
return_url: "https://example.com/order/123/complete",
},
})
if (error) {
console.log(error)
}
}
}
</script>