Configuration
This module takes full advantage of the Nuxt Runtime Configuration so you don't have to configure anything.
Just add your Stripe keys and you are good to go!
# Publishable Key is prefixed with `pk_`
NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_<...>"
# Secret Key is prefixed with `sk_`
NUXT_STRIPE_SECRET="sk_"
# Webhook Secret is prefixed with `whsec_`
NUXT_STRIPE_WEBHOOK_SECRET="whsec_"
That's it! You can now use the Stripe client-side and server-side with no additional configuration!
Configuration
If you want to customize the module, you can do so by adding a stripe
section to your nuxt.config
, belows is an example:
export default defineNuxtConfig({
stripe: {
client: {
options: {
locale: 'en'
}
},
server: {
options: {
apiVersion: '...'
}
},
webhook: {
/**
* Default to `/api/stripe/webhook`
*/
listener: false // Disable the Stripe CLI listener
},
}
})
publishableKey
The publishable key is used client-side to initialize the Stripe client.
export default defineNuxtConfig({
stripe: {
publishableKey: '',
}
})
You typically want to set this value in the NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
environment variables.
NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_<...>"
client
The client options are passed directly to the Stripe client, you can use it to customize the locale for example.
export default defineNuxtConfig({
stripe: {
client: {
locale: 'en'
}
}
})
Head over the official Stripe documentation to learn more about the available options.
You can override the default in the createClient
method:
<script setup lang="ts">
const { createClient: createStripeClient } = useStripe()
const stripe = await createStripeClient({
stripeAccount: 'acct_',
locale: 'en'
})
</script>
createClient
is a thin wrapper around the window.Stripe
constructor, you can pass any option you want, they will be passed directly to the Stripe client.
webhookPath
useRuntimeConfig()
as it's only needed in development. If you need access the webhook path location at runtime, here's how you can do it.
The webhook path is mainly used for local testing, in production it generally does not matter where your webhook endpoint is located.
export default defineNuxtConfig({
stripe: {
webhookPath: 'api/stripe-webhook-path'
}
})
And make sure your endpoint actually exists:
export default stripeWebhookHandler((event) => {
// ...
})
Expose the Webhook Path to useRuntimeConfig()
To access the webhook path at runtime, add it to the runtimeConfig
in the nuxt.config
:
export default defineNuxtConfig({
runtimeConfig: {
stripe: {
webhookPath: 'api/stripe-webhook-path'
},
// If you need it on the client
public: {
stripe: {
webhookPath: 'api/stripe-webhook-path'
}
}
}
})
With T3 env
T3 env is a convenience tool to check and validate environment variables on dev and built, it helps forgetting to set env variables.
Install the @t3-oss/env-nuxt
package along with zod
:
pnpm add @t3-oss/env-nuxt zod
Create the env.ts
file, you can choose any name you want.
import { createEnv } from '@t3-oss/env-nuxt'
import { z } from 'zod'
export const env = createEnv({
// Don't trigger validation on `$ nuxt prepare`
skipValidation: process.env.npm_lifecycle_event === 'postinstall',
emptyStringAsUndefined: true,
client: {
NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().min(1),
},
server: {
NUXT_STRIPE_SECRET: z.string().min(1),
NUXT_STRIPE_WEBHOOK_SECRET: z.string().min(1),
}
})
Then in your nuxt.config.ts
:
import './env'
export default defineNuxtConfig({
})
That's it, importing the file will trigger the validation when you run either build
or dev
.
import { env } from './env'
in your code, it is strongly recoomended you create two files,
env.server.ts
and env.client.ts
othrwhise, you gonna expose the zod schema to the client. The schema contains your env variables names, types and default values.
Read the alert note here on the T3-env official doc
Webhook
This module comes with a built-in webhook handler, you can use it to receive webhook events from Stripe.
Create the file api/stripe/webhook.ts
:
export default stripeWebhookHandler((event, context) => {
switch (stripeEvent.type) {
case 'payment_intent.succeeded': {
return {
customEventCode: 123,
result: 'This message is available in the Stripe dashboard!'
}
}
}
// You can access the default Stripe instance
// and the original H3 event from the context
const h3event = context.$event
const stripe = context.stripe
})
Any value you return will be available in the Stripe dashboard:
{
"ok": true,
"data": {
"customEventCode": 123,
"result": "This message is available in the Stripe dashboard!"
}
}
The module always return { ok: true }
field, followed by the data
you return.
When no value is returned, the payload will only contains { ok: true }
.
event
when you are using the build in event handler.
If you absolutely need a cutting-edge custom behavior, handle the webhook manually.Error Handling
Unhandled exception will be handled by Nuxt itself, this module do not attempt to catch an exception.
export default stripeWebhookHandler(() => {
throw new Error('This error will be returned to Stripe!')
})
Event Handling
The event
is a Stripe.Event object, you can use it to access the event type and data.
We have setup a little example on how to handle the different event types in TypeScript:
export default stripeWebhookHandler((event) => {
switch (stripeEvent.type) {
case 'payment_intent.succeeded': {
const paymentIntent = stripeEvent.data.object as Stripe.PaymentIntent
break
}
case 'checkout.session.expired': {
const session = stripeEvent.data.object as Stripe.Checkout.Session
break
}
case 'customer.created' : {
const customer = stripeEvent.data.object as Stripe.Customer
break
}
}
})
Webhook Path
By now surely you have notice we have use the webhook path /api/stripe/webhook
quite alot as that's the default path this module uses,
you can customize it in the module options:
export default defineNuxtConfig({
stripe: {
webhook: {
listener: '/api/stripe/webhook'
}
}
})
However, this settings is important only if you want to use this module local testing functionality as this module need to know where to proxy the webhook requests.
You can turn off the local testing by setting webhook.listener
to false
:
export default defineNuxtConfig({
stripe: {
webhook: {
listener: false
}
}
})
And that's pretty much it, head over the Stripe CLI section to start testing your webhook locally!