4

I'm trying to get Stripe working with my Vue.js 2 application. For PCI-DSS reasons, Stripe requires that their Javascript is always loaded from js.stripe.com. I've followed the instructions in:

but I get a 'Stripe' is not defined error when I try to use the library. These solutions seemed to be aimed at merely getting a <script> tag into the output HTML (e.g. for analytics), not actually consuming the functions and objects in that script.

Here's what my component Javascript looks like:

<script>
    export default {
        name: "PaymentPage",
        mounted() {
            let stripeScript = document.createElement('script');
            stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
            document.head.appendChild(stripeScript);

            let s = Stripe('pk_test_Fooo');
            console.log(s);
        }
    }
</script>

I also tried adding the script tag to my public/index.html file instead, but I get the same outcome. This would probably be my preferred route, since Stripe encourages developers to import their script on all pages on the site.

<!DOCTYPE html>
<html lang="en">
  <head>
    // ...
    <script src="https://js.stripe.com/v3/"></script>
  </head>

How can I pull a script from an external CDN and use it within my component's Javascript?

I'm aware of some libraries to integrate Vue.js with Stripe (e.g. matfish2/vue-stripe and jofftiquez/vue-stripe-checkout), but the former doesn't import properly for me (I'm hitting issue #24) and the latter is built against the older Stripe API and the new version is still in beta.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • Do you need this to be specifically inside a script tag or can you also bring in the object from a component or the store? – Michael Sep 08 '19 at 09:08
  • Is the Stripe script being fetched correctly? Check the Network tab. I have created a new project and have tried the `index.html` & `createElement` ways, and they do work. The only issue I had was that the `createElement` way doesn't wait for script to fetch/execute, so you have to add a `onload` listener. – yuriy636 Sep 08 '19 at 09:12
  • Also with a SPA you are always on the same page, `index.html`, so I think there is no need to worry for including the script on "all pages". – yuriy636 Sep 08 '19 at 09:15
  • @yuriy636 I think part of my issue was paying attention to IDE errors (from Webstorm) and the output of `npm run serve` rather than looking to see what's happening in the browser and Javascript console. – Duncan Jones Sep 08 '19 at 09:19
  • Hello I'm the author of vue-stripe-checkout. The latest version is out now. Kindly check. Thanks. – jofftiquez Mar 02 '20 at 12:47

4 Answers4

5

You aren't giving the script time to load before checking if Stripe is there. What you need is something like this:

<script>
    export default {
        name: "PaymentPage",
        mounted() {
            let stripeScript = document.createElement('script');
            stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
            stripeScript.onload = () => {
              let s = Stripe('pk_test_Fooo');
              console.log(s);
            };

            document.head.appendChild(stripeScript);
        }
    }
</script>
kshetline
  • 12,547
  • 4
  • 37
  • 73
4

Thanks to yuriy636's comment, I realised that errors were only from the linter, which presumably can't statically figure out what I'm up to.

I opted to put the script into index.html, then ensured I squashed linter errors with:

// eslint-disable-next-line no-undef
let s = Stripe('pk_test_Fooo');
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • I am still curious why the Stripe object needs to be used in your app via a script tag – Michael Sep 08 '19 at 11:10
  • @Michael The main thing is it needs to be served, live, from their website. There may be other ways to achieve that with Vue that I'm not familiar with. – Duncan Jones Sep 08 '19 at 15:07
0

In my case, I still had errors calling functions of the specific script. So it was required to specify the ¨window¨ scope. Also, if you need to access any Vue element inside the ¨onload¨function, you need a new variable for the ¨this¨ instance.

<script>
export default {
    name: "PaymentPage",
    mounted() {
        let stripeScript = document.createElement('script');
        // new variable for Vue elements.
        let self = this;

        stripeScript.onload = () => {
          // call a script function using 'window' scope.
          window.Stripe('pk_test_Fooo');
          // call other Vue elements
          self.otherVueMethod();
          
        };
        stripeScript.setAttribute('src', 'https://js.stripe.com/v3/');
        document.head.appendChild(stripeScript);
    }
}

I worked with this on Vue 2.6.

Alex
  • 428
  • 5
  • 8
0

Just install the npm package npm install @stripe/stripe-js and use it like a regular import

import { loadStripe } from "@stripe/stripe-js";

export default {
  async mounted() {
    // init stripe
    const stripe = await loadStripe('your_stripe_key_here');
    this.stripe = stripe; // store the stripe instance
    // access the stripe instance in your methods or where you want to use them
  },
}

It's working as of 6th Jan 2022.

Huzaifa
  • 345
  • 4
  • 15