├── .editorconfig ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .npmrc ├── .nuxtrc ├── .vscode ├── launch.json └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENCE ├── README.md ├── commitlint.config.js ├── eslint.config.js ├── package.json ├── playground ├── .env.example ├── app.vue ├── components │ ├── OtherComponent.vue │ └── OtherOverride.vue ├── nuxt.config.ts ├── server │ ├── api │ │ ├── create-payment-intent.get.ts │ │ └── stripe.ts │ └── tsconfig.json └── tsconfig.json ├── pnpm-lock.yaml ├── src ├── module.ts └── runtime │ ├── composables │ └── useClientStripe.ts │ └── server │ └── services │ ├── index.ts │ └── useServerStripe.ts ├── test ├── basic.test.ts └── fixtures │ └── basic │ ├── app.vue │ ├── components │ └── OtherComponent.vue │ ├── nuxt.config.ts │ ├── package.json │ └── server │ └── api │ └── stripe.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Types of changes 4 | 5 | - [ ] Bug fix (a non-breaking change which fixes an issue) 6 | - [ ] New feature (a non-breaking change which adds functionality) 7 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 8 | 9 | 10 | ## Description 11 | 12 | 13 | 14 | 15 | 16 | ## Checklist: 17 | 18 | 19 | 20 | - [ ] My change requires a change to the documentation. 21 | - [ ] I have updated the documentation accordingly. 22 | - [ ] I have added tests to cover my changes (if not applicable, please state why) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Logs 5 | *.log* 6 | 7 | # Temp directories 8 | .temp 9 | .tmp 10 | .cache 11 | 12 | # Yarn 13 | **/.yarn/cache 14 | **/.yarn/*state* 15 | 16 | # Generated dirs 17 | dist 18 | 19 | # Nuxt 20 | .nuxt 21 | .output 22 | .vercel_build_output 23 | .build-* 24 | .env 25 | .netlify 26 | 27 | # Env 28 | .env 29 | 30 | # Testing 31 | reports 32 | coverage 33 | *.lcov 34 | .nyc_output 35 | 36 | # VSCode 37 | .vscode/* 38 | !.vscode/settings.json 39 | !.vscode/tasks.json 40 | !.vscode/launch.json 41 | !.vscode/extensions.json 42 | !.vscode/*.code-snippets 43 | 44 | # Intellij idea 45 | *.iml 46 | .idea 47 | 48 | # OSX 49 | .DS_Store 50 | .AppleDouble 51 | .LSOverride 52 | .AppleDB 53 | .AppleDesktop 54 | Network Trash Folder 55 | Temporary Items 56 | .apdisk 57 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | pnpm commitlint --edit $1 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm test 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /.nuxtrc: -------------------------------------------------------------------------------- 1 | imports.autoImport=false 2 | typescript.includeWorkspace=true 3 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "node", 7 | "request": "launch", 8 | "name": "Test debug", 9 | "autoAttachChildProcesses": true, 10 | "skipFiles": ["/**", "**/node_modules/**"], 11 | "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", 12 | "args": ["run", "${relativeFile}"], 13 | "smartStep": true, 14 | "console": "integratedTerminal" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.experimental.useFlatConfig": true 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v5.0.0 4 | 5 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v4.0.2...v5.0.0) 6 | 7 | ### 🚀 Enhancements 8 | 9 | - ⚠️ Upgrade stripe.js major version ([#48](https://github.com/fuentesloic/nuxt-stripe/pull/48)) 10 | 11 | ### 🏡 Chore 12 | 13 | - **release:** V4.0.2 ([bb3b217](https://github.com/fuentesloic/nuxt-stripe/commit/bb3b217)) 14 | - **deps-dev:** Bump vitest ([#44](https://github.com/fuentesloic/nuxt-stripe/pull/44)) 15 | - Upgrade package definition ([c20f9b0](https://github.com/fuentesloic/nuxt-stripe/commit/c20f9b0)) 16 | 17 | #### ⚠️ Breaking Changes 18 | 19 | - ⚠️ Upgrade stripe.js major version ([#48](https://github.com/fuentesloic/nuxt-stripe/pull/48)) 20 | 21 | ### ❤️ Contributors 22 | 23 | - Flozero ([@flozero](https://github.com/flozero)) 24 | - Florent Giraud ([@flozero](https://github.com/flozero)) 25 | 26 | ## v4.0.2 27 | 28 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v4.0.1...v4.0.2) 29 | 30 | ### 🏡 Chore 31 | 32 | - Fix security issue for cross spawn ([#42](https://github.com/fuentesloic/nuxt-stripe/pull/42)) 33 | 34 | ### ❤️ Contributors 35 | 36 | - Florent Giraud ([@flozero](http://github.com/flozero)) 37 | 38 | ## v4.0.1 39 | 40 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v4.0.0...v4.0.1) 41 | 42 | ## v4.0.0 43 | 44 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v3.0.0...v4.0.0) 45 | 46 | ### 🚀 Enhancements 47 | 48 | - **stripe:** ⚠️ Major version about for stripe ([#39](https://github.com/fuentesloic/nuxt-stripe/pull/39)) 49 | 50 | ### 📖 Documentation 51 | 52 | - Add Runtime Config section ([#37](https://github.com/fuentesloic/nuxt-stripe/pull/37)) 53 | 54 | ### 🏡 Chore 55 | 56 | - **release:** V3.0.0 ([8f1b88c](https://github.com/fuentesloic/nuxt-stripe/commit/8f1b88c)) 57 | - Migrate to eslint v9 ([#33](https://github.com/fuentesloic/nuxt-stripe/pull/33)) 58 | - Indicate compatibility with new v4 major ([#36](https://github.com/fuentesloic/nuxt-stripe/pull/36)) 59 | 60 | #### ⚠️ Breaking Changes 61 | 62 | - **stripe:** ⚠️ Major version about for stripe ([#39](https://github.com/fuentesloic/nuxt-stripe/pull/39)) 63 | 64 | ### ❤️ Contributors 65 | 66 | - Florent Giraud ([@flozero](http://github.com/flozero)) 67 | - Nicolas Chaintron 68 | - Daniel Roe ([@danielroe](http://github.com/danielroe)) 69 | 70 | ## v3.0.0 71 | 72 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v2.1.0...v3.0.0) 73 | 74 | ### 🚀 Enhancements 75 | 76 | - ⚠️ Update version to major release ([e044376](https://github.com/fuentesloic/nuxt-stripe/commit/e044376)) 77 | 78 | #### ⚠️ Breaking Changes 79 | 80 | - ⚠️ Update version to major release ([e044376](https://github.com/fuentesloic/nuxt-stripe/commit/e044376)) 81 | 82 | ### ❤️ Contributors 83 | 84 | - Florent Giraud ([@flozero](http://github.com/flozero)) 85 | 86 | ## v2.1.0 87 | 88 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v2.0.0...v2.1.0) 89 | 90 | ### 🚀 Enhancements 91 | 92 | - Upgrade general versions of all stripe dependencies and others ([#29](https://github.com/fuentesloic/nuxt-stripe/pull/29)) 93 | 94 | ### 📖 Documentation 95 | 96 | - Use new `nuxi module add` command in installation ([#28](https://github.com/fuentesloic/nuxt-stripe/pull/28)) 97 | 98 | ### 🏡 Chore 99 | 100 | - **release:** V2.0.0 ([41bd7a4](https://github.com/fuentesloic/nuxt-stripe/commit/41bd7a4)) 101 | - **release:** V3.0.0 ([78032fc](https://github.com/fuentesloic/nuxt-stripe/commit/78032fc)) 102 | - Update package version to correct version ([229f26a](https://github.com/fuentesloic/nuxt-stripe/commit/229f26a)) 103 | - Fix changelog ([658c69a](https://github.com/fuentesloic/nuxt-stripe/commit/658c69a)) 104 | 105 | ### ❤️ Contributors 106 | 107 | - Florent Giraud ([@flozero](http://github.com/flozero)) 108 | - Daniel Roe ([@danielroe](http://github.com/danielroe)) 109 | - Giraud Florent 110 | 111 | ## v2.0.0 112 | 113 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v1.1.2...v2.0.0) 114 | 115 | 116 | ### 🏡 Chore 117 | 118 | - Lint files ([fabb627](https://github.com/fuentesloic/nuxt-stripe/commit/fabb627)) 119 | 120 | ### ❤️ Contributors 121 | 122 | - Giraud Florent 123 | 124 | ## v1.1.2 125 | 126 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v1.2.1...v1.1.2) 127 | 128 | 129 | ### 🩹 Fixes 130 | 131 | - Hydration issue ([e68ff2a](https://github.com/fuentesloic/nuxt-stripe/commit/e68ff2a)) 132 | 133 | ### 💅 Refactors 134 | 135 | - Remove plugin for only composable ([1a38280](https://github.com/fuentesloic/nuxt-stripe/commit/1a38280)) 136 | 137 | ### 🏡 Chore 138 | 139 | - Remove useless flag ([998ee2f](https://github.com/fuentesloic/nuxt-stripe/commit/998ee2f)) 140 | - Resolve conflict ([206fef3](https://github.com/fuentesloic/nuxt-stripe/commit/206fef3)) 141 | - Use onMounted instead of beforeMount ([226959f](https://github.com/fuentesloic/nuxt-stripe/commit/226959f)) 142 | 143 | ### ❤️ Contributors 144 | 145 | - Giraud Florent 146 | 147 | ## v1.1.1 148 | 149 | [compare changes](https://github.com/fuentesloic/nuxt-stripe/compare/v1.1.0...v1.1.1) 150 | 151 | 152 | ### 🩹 Fixes 153 | 154 | - Contributors in changelog ([f30914b](https://github.com/fuentesloic/nuxt-stripe/commit/f30914b)) 155 | 156 | ### 🏡 Chore 157 | 158 | - Package naming as no ownership in @nuxtjs ([81b710d](https://github.com/fuentesloic/nuxt-stripe/commit/81b710d)) 159 | 160 | ### ❤️ Contributors 161 | 162 | - Loic Fuentes ([@fuentesloic](http://github.com/fuentesloic)) 163 | 164 | ## v1.1.0 165 | 166 | 167 | ### 🚀 Enhancements 168 | 169 | - Adding typing for server side ([bc6ec38](https://github.com/fuentesloic/nuxt-stripe/commit/bc6ec38)) 170 | - Adding license ([e267906](https://github.com/fuentesloic/nuxt-stripe/commit/e267906)) 171 | - Remove locale ([#8](https://github.com/fuentesloic/nuxt-stripe/pull/8)) 172 | - Client playground UI ([#10](https://github.com/fuentesloic/nuxt-stripe/pull/10)) 173 | 174 | ### 🩹 Fixes 175 | 176 | - Add alias via tsConfig paths ([#9](https://github.com/fuentesloic/nuxt-stripe/pull/9)) 177 | 178 | ### 💅 Refactors 179 | 180 | - Use template dst to define the final path ([a1584df](https://github.com/fuentesloic/nuxt-stripe/commit/a1584df)) 181 | 182 | ### 📖 Documentation 183 | 184 | - Update documentation ([1e5c0aa](https://github.com/fuentesloic/nuxt-stripe/commit/1e5c0aa)) 185 | 186 | ### 🏡 Chore 187 | 188 | - Initial commit ([f1cee19](https://github.com/fuentesloic/nuxt-stripe/commit/f1cee19)) 189 | - Adding code of conduct ([873d054](https://github.com/fuentesloic/nuxt-stripe/commit/873d054)) 190 | - Adding runtime transpilationg ([757a586](https://github.com/fuentesloic/nuxt-stripe/commit/757a586)) 191 | - Updating path and runtime folders ([6d4fa8d](https://github.com/fuentesloic/nuxt-stripe/commit/6d4fa8d)) 192 | - Fix path of import ([926d239](https://github.com/fuentesloic/nuxt-stripe/commit/926d239)) 193 | - Clean imports ([bc3a877](https://github.com/fuentesloic/nuxt-stripe/commit/bc3a877)) 194 | - Cleanup defu ([204483d](https://github.com/fuentesloic/nuxt-stripe/commit/204483d)) 195 | - Updating type definition with add template ([0c80308](https://github.com/fuentesloic/nuxt-stripe/commit/0c80308)) 196 | - Update package name ([b93dea5](https://github.com/fuentesloic/nuxt-stripe/commit/b93dea5)) 197 | 198 | ### ❤️ Contributors 199 | 200 | - Loic Fuentes ([@fuentesloic](http://github.com/fuentesloic)) 201 | - Florent Giraud ([@flozero](https://github.com/flozero)) 202 | - Daniel Roe ([@danielroe](https://github.com/danielroe)) 203 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at oss@nuxtjs.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Nuxt Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt module for Stripe 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![License][license-src]][license-href] 6 | 7 | Nuxt module for application using stripe. 8 | 9 | - [✨  Release Notes](/CHANGELOG.md) 10 | - [🏀 Online playground](https://stackblitz.com/github/fuentesloic/nuxt-stripe?file=playground%2Fapp.vue) 11 | 12 | ## Features 13 | 14 | This Nuxt module provides an easy way to integrate Stripe in your Nuxt application, both on the client-side and server-side. It utilizes the official [stripe](https://www.npmjs.com/package/stripe) package for server-side usage and [@stripe/stripe-js](https://www.npmjs.com/package/@stripe/stripe-js) for the client-side. 15 | 16 | ## Installation 17 | 18 | 1. Add `@unlok-co/nuxt-stripe` dependency to your project 19 | 20 | ```bash 21 | npx nuxi@latest module add stripe-next 22 | ``` 23 | 24 | 2. Add `@unlok-co/nuxt-stripe` to the `modules` section of `nuxt.config.ts` 25 | 26 | ```ts 27 | export default defineNuxtConfig({ 28 | modules: ["@unlok-co/nuxt-stripe"], 29 | }); 30 | ``` 31 | 32 | ## Configuration 33 | 34 | For all available `serverConfig` options take a look at the [official repo README](https://github.com/stripe/stripe-node#configuration). While for the `clientConfig` options take a look at the [official docs](https://stripe.com/docs/js/initializing#init_stripe_js-options). 35 | 36 | ### Using Options 37 | 38 | ```ts 39 | export default defineNuxtConfig({ 40 | modules: ["@unlok-co/nuxt-stripe"], 41 | stripe: { 42 | // Server 43 | server: { 44 | key: process.env.STRIPE_SECRET_KEY, 45 | options: { 46 | // your api options override for stripe server side 47 | // https://github.com/stripe/stripe-node?tab=readme-ov-file#configuration 48 | }, 49 | }, 50 | // Client 51 | client: { 52 | key: process.env.STRIPE_PUBLIC_KEY, 53 | // manualClientLoad: true, // if you want to have control where you are going to load the client 54 | // your api options override for stripe client side https://stripe.com/docs/js/initializing#init_stripe_js-options 55 | options: {}, 56 | }, 57 | }, 58 | }); 59 | ``` 60 | 61 | ### Alternatively using [Runtime Config](https://nuxt.com/docs/guide/going-further/runtime-config) 62 | 63 | ```ts 64 | export default defineNuxtConfig({ 65 | modules: ["@unlok-co/nuxt-stripe"], 66 | runtimeConfig: { 67 | // Server 68 | stripe: { 69 | key: process.env.STRIPE_SECRET_KEY, 70 | options: {}, 71 | }, 72 | // Client 73 | public: { 74 | stripe: { 75 | key: process.env.STRIPE_PUBLIC_KEY, 76 | options: {}, 77 | }, 78 | }, 79 | }, 80 | }); 81 | ``` 82 | 83 | ## Usage 84 | 85 | ### Server-side 86 | 87 | The module provides a `useServerStripe` function to create a Stripe instance on the server-side. 88 | This instance can be used to interact with the Stripe API. 89 | 90 | #### Minimum example 91 | 92 | ```ts 93 | import { defineEventHandler } from "h3"; 94 | import { useServerStripe } from "#stripe/server"; 95 | 96 | export default defineEventHandler(async (event) => { 97 | const stripe = await useServerStripe(event); 98 | console.info("Stripe instance:", stripe); 99 | 100 | return { 101 | version: stripe.VERSION, 102 | }; 103 | }); 104 | ``` 105 | 106 | #### generate payment intent for stripe elements 107 | 108 | At any time you can find a full code at `playground/server/api/create-payment-intent.get.ts` for the server side and `playground/components/OtherComponent.vue` 109 | for the client side. 110 | 111 | Server side example: 112 | 113 | ```ts 114 | export default defineEventHandler(async (event) => { 115 | const stripe = await useServerStripe(event); 116 | const orderAmount = 1400; 117 | let paymentIntent; 118 | 119 | try { 120 | paymentIntent = await stripe.paymentIntents.create({ 121 | currency: "usd", 122 | amount: orderAmount, 123 | automatic_payment_methods: { enabled: true }, 124 | }); 125 | 126 | return { 127 | clientSecret: paymentIntent.client_secret, 128 | error: null, 129 | }; 130 | } catch (e) { 131 | return { 132 | clientSecret: null, 133 | error: e, 134 | }; 135 | } 136 | }); 137 | ``` 138 | 139 | Client side example: 140 | 141 | ```ts 142 | const { stripe } = useClientStripe(); 143 | 144 | watch( 145 | stripe, 146 | async () => { 147 | if (stripe.value) { 148 | // https://github.com/stripe-samples/accept-a-payment/blob/main/payment-element/client/vue-cva/src/components/SrCheckoutForm.vue 149 | const { clientSecret, error } = await $fetch( 150 | "/api/create-payment-intent" 151 | ); 152 | if (error) { 153 | console.error(error); 154 | return; 155 | } 156 | 157 | const elements = stripe.value.elements({ 158 | clientSecret: clientSecret as string, 159 | }); 160 | const linkAuthenticationElement = elements.create("linkAuthentication"); 161 | linkAuthenticationElement.mount("#linkAuthenticationElement"); 162 | } 163 | }, 164 | { 165 | immediate: true, 166 | } 167 | ); 168 | ``` 169 | 170 | ### Client-side usage 171 | 172 | On the client-side, you can use the `useClientStripe`. This is going to expose to you an object with 173 | 174 | ```ts 175 | { 176 | stripe, // This composable is a wrap around the [`loadStripe`](https://github.com/stripe/stripe-js#loadstripe) and can be used in pages or plugins. 177 | isLoading, // You don't really need this in practice but we did expose it 178 | loadStipe; // you can also manually loadStripe if you have disabled auto load for stripe 179 | } 180 | ``` 181 | 182 | You can see the actual code used inside `playground/app.vue` file. 183 | 184 | #### Automated load of stripe client side 185 | 186 | ```vue 187 | 193 | 194 | 199 | ``` 200 | 201 | #### Manually load client side stripe 202 | 203 | nuxt.config.ts 204 | 205 | ```ts 206 | stripe: { 207 | client: { 208 | // ... 209 | manualClientLoad: true, // this is the part you want 210 | }, 211 | // ... 212 | }, 213 | ``` 214 | 215 | App.vue 216 | 217 | ```ts 218 | import { useNuxtApp, useClientStripe } from "#imports"; 219 | 220 | const { loadStripe, stripe } = useClientStripe(); 221 | const nuxtApp = useNuxtApp(); 222 | 223 | // you can leave it empty if you already have defined the keys in the config or override like in this example 224 | stripe.value = await loadStripe(nuxtApp.$config.public.stripe.key); 225 | ``` 226 | 227 | ## Development 228 | 229 | Initial step: Clone this repository 230 | 231 | ```bash 232 | # Install dependencies 233 | yarn install 234 | npm install 235 | 236 | # Generate type stubs 237 | yarn dev:prepare 238 | npm run dev:prepare 239 | 240 | # Develop with the playground 241 | yarn dev 242 | npm run dev 243 | 244 | # Build the playground 245 | yarn dev:build 246 | npm run dev:build 247 | 248 | # Run ESLint 249 | yarn lint 250 | npm run lint 251 | 252 | # Run Vitest 253 | yarn test 254 | yarn test:watch 255 | npm run test 256 | npm run test:watch 257 | 258 | # Release new version 259 | yarn release 260 | npm run release 261 | ``` 262 | 263 | 264 | 265 | [npm-version-src]: https://img.shields.io/npm/v/@unlok-co/nuxt-stripe/latest.svg?style=flat&colorA=18181B&colorB=28CF8D 266 | [npm-version-href]: https://npmjs.com/package/@unlok-co/nuxt-stripe 267 | [npm-downloads-src]: https://img.shields.io/npm/dm/@unlok-co/nuxt-stripe.svg?style=flat&colorA=18181B&colorB=28CF8D 268 | [npm-downloads-href]: https://npmjs.com/package/@unlok-co/nuxt-stripe 269 | [license-src]: https://img.shields.io/npm/l/@unlok-co/nuxt-stripe.svg?style=flat&colorA=18181B&colorB=28CF8D 270 | [license-href]: https://npmjs.com/package/@unlok-co/nuxt-stripe 271 | [nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js 272 | [nuxt-href]: https://nuxt.com 273 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ['@commitlint/config-conventional'], 3 | } 4 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { createConfigForNuxt } from "@nuxt/eslint-config/flat"; 3 | 4 | export default createConfigForNuxt({ 5 | features: { 6 | tooling: true, 7 | // stylistic: true, 8 | }, 9 | dirs: { 10 | src: ["./playground"], 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@unlok-co/nuxt-stripe", 3 | "version": "5.0.0", 4 | "description": "Nuxt module for stripe", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/fuentesloic/nuxt-stripe.git" 8 | }, 9 | "license": "MIT", 10 | "type": "module", 11 | "exports": { 12 | ".": { 13 | "types": "./dist/types.d.mts", 14 | "import": "./dist/module.mjs" 15 | } 16 | }, 17 | "main": "./dist/module.mjs", 18 | "typesVersions": { 19 | "*": { 20 | ".": [ 21 | "./dist/types.d.mts" 22 | ] 23 | } 24 | }, 25 | "files": [ 26 | "dist" 27 | ], 28 | "scripts": { 29 | "prepack": "nuxt-module-build build", 30 | "dev": "nuxi dev playground", 31 | "dev:build": "nuxi build playground", 32 | "dev:prepare": "nuxt-module-build --stub && nuxi prepare playground", 33 | "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags", 34 | "lint": "eslint .", 35 | "test": "vitest run", 36 | "test:watch": "vitest watch", 37 | "prepare": "husky", 38 | "commit": "commit" 39 | }, 40 | "dependencies": { 41 | "@jest/globals": "^29.7.0", 42 | "@nuxt/kit": "^3.16.2", 43 | "@stripe/stripe-js": "^7.2.0", 44 | "defu": "^6.1.4", 45 | "stripe": "^18.0.0" 46 | }, 47 | "devDependencies": { 48 | "@commitlint/cli": "^19.8.0", 49 | "@commitlint/config-conventional": "^19.8.0", 50 | "@commitlint/prompt-cli": "^19.8.0", 51 | "@nuxt/eslint-config": "^1.3.0", 52 | "@nuxt/module-builder": "^1.0.1", 53 | "@nuxt/schema": "^3.16.2", 54 | "@nuxt/test-utils": "^3.17.2", 55 | "@types/node": "^22.14.1", 56 | "changelogen": "^0.6.1", 57 | "eslint": "^9.17.0", 58 | "husky": "^9.1.7", 59 | "nuxt": "^3.16.2", 60 | "typescript": "^5.8.3", 61 | "vitest": "^3.1.2" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /playground/.env.example: -------------------------------------------------------------------------------- 1 | STRIPE_SECRET_KEY="yourstripsecretkey" 2 | STRIPE_PUBLIC_KEY="yourstripepublickey" 3 | -------------------------------------------------------------------------------- /playground/app.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 27 | 28 | 50 | -------------------------------------------------------------------------------- /playground/components/OtherComponent.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 50 | -------------------------------------------------------------------------------- /playground/components/OtherOverride.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | -------------------------------------------------------------------------------- /playground/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | modules: ["../src/module"], 3 | 4 | stripe: { 5 | client: { 6 | key: process.env.STRIPE_PUBLIC_KEY, 7 | manualClientLoad: true, 8 | }, 9 | server: { 10 | key: process.env.STRIPE_SECRET_KEY, 11 | }, 12 | }, 13 | compatibilityDate: "2024-10-07", 14 | }); 15 | -------------------------------------------------------------------------------- /playground/server/api/create-payment-intent.get.ts: -------------------------------------------------------------------------------- 1 | import { defineEventHandler } from "h3"; 2 | import { useServerStripe } from "#stripe/server"; 3 | 4 | export default defineEventHandler(async (event) => { 5 | // Create a PaymentIntent with the amount, currency, and a payment method type. 6 | // 7 | // See the documentation [0] for the full list of supported parameters. 8 | // 9 | // [0] https://stripe.com/docs/api/payment_intents/create 10 | const stripe = await useServerStripe(event); 11 | const orderAmount = 1400; 12 | let paymentIntent; 13 | 14 | try { 15 | paymentIntent = await stripe.paymentIntents.create({ 16 | currency: "usd", 17 | amount: orderAmount, 18 | automatic_payment_methods: { enabled: true }, 19 | }); 20 | return { 21 | clientSecret: paymentIntent.client_secret, 22 | error: null, 23 | }; 24 | } catch (e) { 25 | return { 26 | clientSecret: null, 27 | error: e, 28 | }; 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /playground/server/api/stripe.ts: -------------------------------------------------------------------------------- 1 | import { defineEventHandler } from 'h3' 2 | import { useServerStripe } from '#stripe/server' 3 | 4 | export default defineEventHandler(async (event) => { 5 | const stripe = await useServerStripe(event) 6 | console.info('Stripe instance:', stripe) 7 | 8 | return { 9 | message: 'Inspect your terminal to see stripe server object', 10 | } 11 | }) 12 | -------------------------------------------------------------------------------- /playground/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/module.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from "node:url"; 2 | import { defineNuxtModule, createResolver } from "@nuxt/kit"; 3 | import defu from "defu"; 4 | import type Stripe from "stripe"; 5 | 6 | import type { StripeConstructorOptions } from "@stripe/stripe-js"; 7 | 8 | export interface ServerStripeOptions { 9 | key?: string | null; 10 | options?: Stripe.StripeConfig; 11 | } 12 | 13 | export interface ClientStripeOptions { 14 | key?: string | null; 15 | options?: StripeConstructorOptions; 16 | } 17 | 18 | export interface ModuleOptions { 19 | server: ServerStripeOptions; 20 | client: ClientStripeOptions & { manualClientLoad?: boolean }; 21 | } 22 | 23 | export default defineNuxtModule({ 24 | meta: { 25 | name: "@unlok-co/nuxt-stripe", 26 | configKey: "stripe", 27 | compatibility: { 28 | nuxt: ">=3.0.0", 29 | }, 30 | }, 31 | defaults: { 32 | server: { 33 | key: null, 34 | options: {}, 35 | }, 36 | client: { 37 | manualClientLoad: false, 38 | key: null, 39 | options: {}, 40 | }, 41 | }, 42 | setup(options, nuxt) { 43 | const { resolve } = createResolver(import.meta.url); 44 | 45 | // Public runtimeConfig 46 | nuxt.options.runtimeConfig.public.stripe = defu( 47 | nuxt.options.runtimeConfig.public.stripe, 48 | options.client 49 | ); 50 | 51 | // Private runtimeConfig 52 | nuxt.options.runtimeConfig.stripe = defu( 53 | nuxt.options.runtimeConfig.stripe, 54 | options.server 55 | ); 56 | 57 | // Transpile runtime 58 | const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url)); 59 | nuxt.options.build.transpile.push(runtimeDir); 60 | 61 | nuxt.hook("imports:dirs", (dirs) => { 62 | dirs.push(resolve(runtimeDir, "composables")); 63 | }); 64 | 65 | nuxt.hook("nitro:config", (nitroConfig) => { 66 | nitroConfig.alias = nitroConfig.alias || {}; 67 | 68 | // Inline module runtime in Nitro bundle 69 | nitroConfig.externals = defu( 70 | typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, 71 | { 72 | inline: [resolve("./runtime")], 73 | } 74 | ); 75 | nitroConfig.alias["#stripe/server"] = resolve( 76 | runtimeDir, 77 | "./server/services" 78 | ); 79 | }); 80 | 81 | nuxt.hook("prepare:types", (options) => { 82 | options.tsConfig.compilerOptions.paths["#stripe/server"] = [ 83 | resolve(runtimeDir, "./server/services"), 84 | ]; 85 | }); 86 | }, 87 | }); 88 | -------------------------------------------------------------------------------- /src/runtime/composables/useClientStripe.ts: -------------------------------------------------------------------------------- 1 | import { loadStripe } from "@stripe/stripe-js"; 2 | 3 | import type { Stripe } from "@stripe/stripe-js"; 4 | import { onMounted, useNuxtApp, useState } from "#imports"; 5 | import type { ModuleOptions } from "nuxt/schema"; 6 | 7 | /** 8 | * useClientStripe function 9 | * 10 | * This function is a helper to easily access the Stripe instance provided by the Nuxt plugin. 11 | * It can be used in components or pages to interact with the Stripe.js library. 12 | * 13 | */ 14 | export default function useClientStripe() { 15 | const nuxtApp = useNuxtApp(); 16 | const stripe = useState("stripe-client", () => null); 17 | const isLoading = useState("stripe-client-loading", () => false); 18 | 19 | async function _loadStripe( 20 | key: string | undefined = undefined, 21 | options: ModuleOptions["client"]["options"] | undefined = undefined 22 | ): Promise { 23 | const _key = key ?? nuxtApp.$config.public.stripe.key; 24 | const _options = options ?? nuxtApp.$config.public.stripe.options; 25 | 26 | if (stripe.value && !nuxtApp.$config.public.stripe.manualClientLoad) { 27 | return stripe.value; 28 | } 29 | 30 | isLoading.value = true; 31 | 32 | if (!nuxtApp.$config.public.stripe.key && !key) 33 | console.warn("no key given for Stripe client service"); 34 | 35 | const _stripe = await loadStripe(_key, _options); 36 | 37 | isLoading.value = false; 38 | if (!nuxtApp.$config.public.stripe.manualClientLoad) { 39 | stripe.value = _stripe; 40 | } 41 | return _stripe; 42 | } 43 | 44 | onMounted(async () => { 45 | if (nuxtApp.$config.public.stripe.manualClientLoad) return; 46 | if (!isLoading.value) { 47 | await _loadStripe(undefined, undefined); 48 | } 49 | }); 50 | 51 | return { 52 | loadStripe: _loadStripe, 53 | stripe, 54 | isLoading, 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/runtime/server/services/index.ts: -------------------------------------------------------------------------------- 1 | export { useServerStripe } from './useServerStripe' 2 | -------------------------------------------------------------------------------- /src/runtime/server/services/useServerStripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe' 2 | import type { H3Event } from 'h3' 3 | import { useRuntimeConfig } from '#imports' 4 | 5 | /** 6 | * useServerStripe is a utility function that initializes and returns a Stripe instance 7 | * for server-side usage in Nuxt. It ensures that only one instance of Stripe is created 8 | * per event context, avoiding unnecessary re-initializations. 9 | * 10 | * @param {H3Event} event - The event object passed to the Nuxt event handler 11 | * @return {Promise} - A Promise that resolves to the Stripe server instance for the event context 12 | */ 13 | export const useServerStripe = async (event: H3Event): Promise => { 14 | const { stripe: { key, options } } = useRuntimeConfig() 15 | 16 | // Return Stripe's instance if already initialized in event context 17 | if (event.context._stripe) return event.context._stripe 18 | 19 | if (!key) console.warn('no key given for server service') 20 | 21 | // @docs — https://stripe.com/docs/api/versioning 22 | const stripe = new Stripe(key, options) 23 | 24 | // Store the initialized Stripe instance in the event context for future use 25 | event.context._stripe = stripe 26 | 27 | return event.context._stripe 28 | } 29 | -------------------------------------------------------------------------------- /test/basic.test.ts: -------------------------------------------------------------------------------- 1 | // https://vitest.dev/guide/debugging.html#vscode to debug tests 2 | 3 | import { fileURLToPath } from "node:url"; 4 | import { describe, it, expect } from "vitest"; 5 | import { setup, $fetch } from "@nuxt/test-utils"; 6 | 7 | describe("ssr", async () => { 8 | const rootDir = fileURLToPath(new URL("./fixtures/basic", import.meta.url)); 9 | 10 | await setup({ rootDir }); 11 | 12 | it("renders the index page", async () => { 13 | const html = await $fetch("/"); 14 | expect(html).toContain("

Nuxt Stripe module test

"); 15 | }); 16 | 17 | it("overrides the default config exposing only public key", async () => { 18 | const html = await $fetch("/"); 19 | expect(html).toContain(`key:"pk_test123"`); 20 | }); 21 | 22 | it("validates ssr config", async () => { 23 | const serverResponse = await $fetch("/"); 24 | const serverRenderedHtml = serverResponse.data; 25 | 26 | const clientResponse = await $fetch("/client-rendered"); 27 | const clientRenderedHtml = clientResponse.data; 28 | 29 | expect(serverRenderedHtml).toEqual(clientRenderedHtml); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/fixtures/basic/app.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /test/fixtures/basic/components/OtherComponent.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /test/fixtures/basic/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | ssr: true, 3 | modules: [ 4 | '../../../src/module', 5 | ], 6 | stripe: { 7 | client: { 8 | key: 'pk_test123', 9 | }, 10 | server: { 11 | key: 'pk_test123', 12 | }, 13 | }, 14 | }) 15 | -------------------------------------------------------------------------------- /test/fixtures/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "basic", 4 | "type": "module" 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/basic/server/api/stripe.ts: -------------------------------------------------------------------------------- 1 | import { defineEventHandler } from 'h3' 2 | import { useServerStripe } from '#stripe/server' 3 | 4 | export default defineEventHandler(async (event) => { 5 | const stripe = await useServerStripe(event) 6 | 7 | return { 8 | status: 200, 9 | // @ts-expect-error VERSION is not typed 10 | version: stripe.VERSION, 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./playground/.nuxt/tsconfig.json", 3 | "compilerOptions": { 4 | "strictNullChecks": false 5 | } 6 | } 7 | --------------------------------------------------------------------------------