1

I have a Stripe payment form on my page but I only want to load it when the user presses a button to show the form.

I've used this code without the dynamic loading and it works 100%, but with dynamic loading it doesn't seem to do anything as far as I can tell..

I put my code into JSFiddle, because StackOverflow's code snippet wasn't working correctly.. https://jsfiddle.net/4zc1uuas/

Here is my JS code:

I'm using a loadFiles function to load the stripe.js file, and then 500 milliseconds later loading the Stripe code from their examples.

var oLink = document.getElementById('showBtn');
oLink.addEventListener('click', loadFiles);

function loadFiles() {
  document.getElementById("payment").style.display = "block";
  loadScript('https://js.stripe.com/v3/');
  setTimeout(function() {
    loadStripe();
  }, 500);
}

function loadScript(url, type, charset) {
  if (type === undefined) type = 'text/javascript';
  if (url) {
    var script = document.querySelector("script[src*='" + url + "']");
    if (!script) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          script = document.createElement('script');
          script.setAttribute('src', url);
          script.setAttribute('type', type);
          if (charset) script.setAttribute('charset', charset);
          head.appendChild(script);
        }
      }
    }
    return script;
  }
};

loadStripe = function() {
  var stripe = Stripe('pk_test_rWG7KN6nzFjUj5D0EkbdevdS');
  var elements = stripe.elements();

  var card = elements.create('card', {
    style: {
      base: {
        iconColor: '#666EE8',
        color: '#31325F',
        lineHeight: '40px',
        fontWeight: 400,
        fontFamily: '"Proxima Nova", "Montserrat", Arial, sans-serif',
        fontSize: '15px',

        '::placeholder': {
          color: '#CFD7E0',
        },
      },
    }
  });
  card.mount('#card-element');

  function setOutcome(result) {
    var successElement = document.querySelector('.success');
    var errorElement = document.querySelector('.error');
    successElement.classList.remove('visible');
    errorElement.classList.remove('visible');

    if (result.token) {
      // Use the token to create a charge or a customer
      // https://stripe.com/docs/charges

      successElement.querySelector('.token').textContent = result.token.id;
      successElement.classList.add('visible');
      self.confetti();
    } else if (result.error) {
      errorElement.textContent = result.error.message;
      errorElement.classList.add('visible');
    }
  }

  card.on('change', function(event) {
    setOutcome(event);
  });

  document.querySelector('form').addEventListener('submit', function(e) {
    e.preventDefault();
    var form = document.querySelector('form');
    var extraDetails = {
      name: form.querySelector('input[name=cardholder-name]').value,
    };
    stripe.createToken(card, extraDetails).then(setOutcome);
  });
}

Does anyone have an idea how I can load the Stripe code dynamically as loading the v3 script without having the html form within the dom, returns an error.

For the full example please look at the jsfiddle!

Any help would be great!

Simon
  • 2,498
  • 3
  • 34
  • 77
  • Your JSFiddle seems to work -- there's an issue in the `setOutcome` function (the `success` element doesn't have a `token` sub-element, and `confetti()` is not defined), but Stripe.js does load and the card element is mounted successfully. – Ywain Oct 09 '17 at 08:34
  • @Ywain so strange... you're right. it works now. im not sure why i was having problems... – Simon Oct 09 '17 at 13:06

0 Answers0