Stripe payment example is not displaying

34,341

Solution 1

Don't add the script in the head, instead, add it right before you close the body.

<html lang= "en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>test</title>
    </head>
    <body>
        <form action="/charge" method="post" id="payment-form">
            <div class="form-row">
                <label for="card-element">
                    Credit or debit card
                </label>
                <div id="card-element">
                <!-- a Stripe Element will be inserted here. -->
                </div>
                <!-- Used to display form errors -->
                <div id="card-errors"></div>
            </div>
            <button>Submit Payment</button>
        </form>
        <script src="https://js.stripe.com/v3/"></script>
    </body>
</html>

Putting your script at the bottom ensures that the DOM is rendered prior to executing the script, so that'll do the trick!

Solution 2

Put your script after the html from,

 <form></form>
 //after your stripe form put stripe script 
 <script></script>

As below

<style type="text/css">
    * {
  font-family: "Helvetica Neue", Helvetica;
  font-size: 15px;
  font-variant: normal;
  padding: 0;
  margin: 0;
}

html {
  height: 100%;
}

body {
  background: #E6EBF1;
  align-items: center;
  min-height: 100%;
  display: flex;
  width: 100%;
}

form {
  width: 480px;
  margin: 20px auto;
}

.group {
  background: white;
  box-shadow: 0 7px 14px 0 rgba(49,49,93,0.10),
              0 3px 6px 0 rgba(0,0,0,0.08);
  border-radius: 4px;
  margin-bottom: 20px;
}

label {
  position: relative;
  color: #8898AA;
  font-weight: 300;
  height: 40px;
  line-height: 40px;
  margin-left: 20px;
  display: block;
}

.group label:not(:last-child) {
  border-bottom: 1px solid #F0F5FA;
}

label > span {
  width: 20%;
  text-align: right;
  float: left;
}

.field {
  background: transparent;
  font-weight: 300;
  border: 0;
  color: #31325F;
  outline: none;
  padding-right: 10px;
  padding-left: 10px;
  cursor: text;
  width: 70%;
  height: 40px;
  float: right;
}

.field::-webkit-input-placeholder { color: #CFD7E0; }
.field::-moz-placeholder { color: #CFD7E0; }
.field:-ms-input-placeholder { color: #CFD7E0; }

button {
  float: left;
  display: block;
  background: #666EE8;
  color: white;
  box-shadow: 0 7px 14px 0 rgba(49,49,93,0.10),
              0 3px 6px 0 rgba(0,0,0,0.08);
  border-radius: 4px;
  border: 0;
  margin-top: 20px;
  font-size: 15px;
  font-weight: 400;
  width: 100%;
  height: 40px;
  line-height: 38px;
  outline: none;
}

button:focus {
  background: #555ABF;
}

button:active {
  background: #43458B;
}

.outcome {
  float: left;
  width: 100%;
  padding-top: 8px;
  min-height: 24px;
  text-align: center;
}

.success, .error {
  display: none;
  font-size: 13px;
}

.success.visible, .error.visible {
  display: inline;
}

.error {
  color: #E4584C;
}

.success {
  color: #666EE8;
}

.success .token {
  font-weight: 500;
  font-size: 13px;
}
</style>

<form action="subscription.php" method="post">
  <div class="group">
    <label>
      <span>Name</span>
      <input name="cardholder-name" class="field" placeholder="Jane Doe" />
    </label>
    <label>
      <span>Phone</span>
      <input class="field" placeholder="(123) 456-7890" type="tel" />
    </label>
  </div>
  <div class="group">
    <label>
      <span>Card</span>
      <div id="card-element" class="field"></div>
    </label>
  </div>
  <button type="submit">Pay $25</button>
  <div class="outcome">
    <div class="error" role="alert"></div>
    <div class="success">
      Success! Your Stripe token is <span class="token"></span>
    </div>
  </div>
</form>
<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">

    var stripe = Stripe('YOUR_PUBLIC_KEY');
    var elements = stripe.elements();

var card = elements.create('card', {
  style: {
    base: {
      iconColor: '#666EE8',
      color: '#31325F',
      lineHeight: '40px',
      fontWeight: 300,
      fontFamily: '"Helvetica Neue", Helvetica, 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');
  } 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);
});
</script>

Solution 3

For anyone else with this same problem - the code snippet in Stripe's docs is incomplete. So the suggested fixes above may in fact be necessary to ensure proper order of operations, but the whole thing won't work unless you define a stripeTokenHandler method.

Stripe's docs define the method (further down the page) as:

function stripeTokenHandler(token) {
  // Insert the token ID into the form so it gets submitted to the server
  var form = document.getElementById('payment-form');
  var hiddenInput = document.createElement('input');
  hiddenInput.setAttribute('type', 'hidden');
  hiddenInput.setAttribute('name', 'stripeToken');
  hiddenInput.setAttribute('value', token.id);
  form.appendChild(hiddenInput);

  // Submit the form
  form.submit();
}

Solution 4

Stripe.js renders the inputs for credit card number, expiration, CVC in iFrames. You cannot create these or get at them with JavaScript. You can however style the containers as you want which will enable you to get pretty close matching to the UI of your website - Bootstrap, MDC-Web, or whatever.

If your elements are not displaying, try the below to get started.

<div class="stripe-custom-element">
    <label for="stripe-card">Card Number</label>
    <div class="" id="stripe-card"></div>
</div>
<div class="stripe-custom-element">
    <label for="stripe-exp">Expiration</label>
    <div class="" id="stripe-exp"></div>
</div>
<div class="stripe-custom-element">
    <label for="stripe-cvc">CVC</label>
    <div class="" id="stripe-cvc"></div>
</div>

var cardNumberElement = doc.getElementById("stripe-card");
var cardExpiryElement = doc.getElementById("stripe-exp");
var cardCvcElement = doc.getElementById("stripe-cvc");

var cardNumber = elements.create('cardNumber', {});
var cardExpiry = elements.create('cardExpiry', {});
var cardCvc = elements.create('cardCvc', {});

cardNumber.mount(cardNumberElement);
cardExpiry.mount(cardExpiryElement);
cardCvc.mount(cardCvcElement);        

registerElements([cardNumber, cardExpiry, cardCvc]);
Share:
34,341
daniel8x
Author by

daniel8x

Updated on November 16, 2021

Comments

  • daniel8x
    daniel8x over 2 years

    I am trying to create a really simple example of using Stripe payments.

    This is my code:

    // Create a Stripe client
    var stripe = Stripe('pk_test_XSHE4IYLLy9qCPe7lW7pK4ZE');
    
    // Create an instance of Elements
    var elements = stripe.elements();
    
    // Custom styling can be passed to options when creating an Element.
    // (Note that this demo uses a wider set of styles than the guide below.)
    var style = {
    base: {
      color: '#32325d',
      lineHeight: '24px',
      fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSmoothing: 'antialiased',
      fontSize: '16px',
      '::placeholder': {
        color: '#aab7c4'
      }
    },
    invalid: {
      color: '#fa755a',
      iconColor: '#fa755a'
    }
    };
    
    // Create an instance of the card Element
    var card = elements.create('card', {style: style});
    
    // Add an instance of the card Element into the `card-element` <div>
    card.mount('#card-element');
    
    // Handle real-time validation errors from the card Element.
    card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
    });
    
    // Handle form submission
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
    event.preventDefault();
    
    stripe.createToken(card).then(function(result) {
      if (result.error) {
        // Inform the user if there was an error
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        // Send the token to your server
        stripeTokenHandler(result.token);
      }
    });
    });
    .StripeElement {
    background-color: white;
    padding: 8px 12px;
    border-radius: 4px;
    border: 1px solid transparent;
    box-shadow: 0 1px 3px 0 #e6ebf1;
    -webkit-transition: box-shadow 150ms ease;
    transition: box-shadow 150ms ease;
    }
    
    .StripeElement--focus {
    box-shadow: 0 1px 3px 0 #cfd7df;
    }
    
    .StripeElement--invalid {
    border-color: #fa755a;
    }
    
    .StripeElement--webkit-autofill {
    background-color: #fefde5 !important;
    }
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://js.stripe.com/v3/"></script>
        <title>test</title>
      </head>
      <body>
        <form action="/charge" method="post" id="payment-form">
          <div class="form-row">
            <label for="card-element">
              Credit or debit card
            </label>
            <div id="card-element">
              <!-- a Stripe Element will be inserted here. -->
            </div>
    
            <!-- Used to display form errors -->
            <div id="card-errors"></div>
          </div>
    
          <button>Submit Payment</button>
        </form>
    
      </body>
    </html>

    I followed the example from Stripe.

    This is the error that I got from the Javascript console:

    Uncaught Error: The selector you specified (#card-element) applies to no DOM elements that are currently on the page.
    Make sure the element exists on the page before calling mount().
         at new t (js.stripe.com/:1)
         at t.value (js.stripe.com/:1)
    

    Based on the error, I think the Stripe JavaScript could not find any #card-element, but it is there.

    This could be a dumb question, but this is my first time using Stripe, so it would be great if someone could help me. Thank you so much.

  • Shiv
    Shiv over 4 years
    var form = document.getElementById('payment-form'); is returning 'undefined'
  • Gojira
    Gojira over 4 years
    What does your form tag look like? In the Stripe doc (and OP's code) it is: <form action="/charge" method="post" id="payment-form">
  • Shiv
    Shiv over 4 years
    yes. <form action="/charge" method="post" id="payment-form">
  • Daniyal dehleh
    Daniyal dehleh over 2 years
    Once I move it to body, I run into Stripe is not defined for the rest of my JS Code