1
votes

I am currently attempting to configure the client side portion of stripe.js so I can use its elements api source creation feature to collect user payment information. However the client side package is only available via script tag. I’ve tried bringing it in via the index.template.html (this doesn't work with quasar) however it always errors as soon as I go to initialize a Stripe client with;

vue.stripe = Stripe(‘pk_live_dMLr0hShLxaZmXesv1buhndd’)

the error is;

Error Stripe is not defined.

I’ve tried a variety of alternative methods for importing in the package, scriptjs, hand mounting it to the dom in register.vue, all to no avail as it can’t find the Stripe variable and instantiate a client. Or if I set Stripe equal to the script tag then I get a Stripe is not a function error. here’s the tutorial I’m following;

https://stripe.com/docs/stripe-js

and my code;

https://github.com/Screen-Art-Studios/TimeCrunch/blob/master/src/pages/Register.vue (Line 74-76 & 142-203 The register page where I would like to call the elements api)

https://github.com/Screen-Art-Studios/TimeCrunch/blob/master/src/plugins/stripe.js (The quasar plugin that I used to import the package)

Any help would be a life saver as this is all that is preventing the completion of this app.

*Update I still am having issues with understanding exactly what is going on but its no longer throwing a Stripe is not defined error once I changed it over to ‘this.$Stripe()’ vs ‘Stripe()’ thinking that would reference the plugin Quasar generated and it did compile. However now its throwing a stripe.elements is not a function error when; var stripe = this.$Stripe(‘pk_test_EUZwPeinKym4DDl0d9kMbrOw’) var elements = stripe.elements() which is almost exactly what the tutorial prescribes [The only difference being the change from Stripe() to this.$Stripe()]. I’m gonna keep banging my head about this, any clarification on the whole Quasar package thing and / or insight into solving this problem would be a lifesaver.

1
did you try window.Stripe('pk_stripe')? It works for me. - musicformellons

1 Answers

0
votes

I use Quasar with Typescript (and vue-property-decorators), and the below works great.

You could easily adapt it for plain JS if preferred.

template part

<div>
  <p>Card</p>
  <div id="card-element"></div>
</div>

script part

// Includes Stripe.js dynamically
  includeStripe(URL: string, callback: any) {
    let documentTag = document
    let tag = 'script'
    let object = documentTag.createElement(tag)
    let scriptTag = documentTag.getElementsByTagName(tag)[0]
    object.setAttribute('src', `//${URL}`)

    if (callback) {
      object.addEventListener(
        'load',
        function(e) {
          callback(null, e)
        },
        false
      )
    }
    scriptTag.parentNode!.insertBefore(object, scriptTag)
  }

  stripe: any
  elements: any
  card: any

  async configureStripe() {
    const pubKey = await getStripePubKey()
    this.stripe = (window as any).Stripe(pubKey)
    this.elements = this.stripe.elements()
    this.card = this.elements.create('card')

    this.card.mount('#card-element')
  }

  created() {
    // checks that Stripe is not loaded already, useful when hot-reloading in localhost
    const stripeComponents = document.getElementById('card-element')
    if (!stripeComponents)
      this.includeStripe('js.stripe.com/v3/', this.configureStripe)
  }
}

Note that I get the pubKey via a custom API function call (retrieved from a server), so as to be able to dynamically change it later on if needed.

You could also skip the check -- whether Stripe.js was already loaded-- though it is useful when developing to not have the warning in console all the time....

And you could also go for the "manual", non-dynamically inserted version of adding <script src="https://js.stripe.com/v3/"></script> yourself in Quasar's index.template.html; not sure that's the best idea though, as it would keep it loaded throughout the entire app unnecessarily.