28

I am trying to use Stripe.js following https://stripe.com/docs/stripe-js/elements/quickstart

I made html, css, javascript just same as sample of that url.

But when I click 'Submit Payment' Button, it always shows console error and not working.

(index):1 Uncaught (in promise) Error: We could not retrieve data from the specified Element.
              Please make sure the Element you are attempting to use is still mounted.
    at new t ((index):1)
    at e._handleMessage ((index):1)
    at e._handleMessage ((index):1)
    at (index):1

Please let me know why this happens.

LarAng
  • 959
  • 15
  • 23

7 Answers7

5

Please try this. It works.

<html>
    <head>
        <style>
            /**
            * The CSS shown here will not be introduced in the Quickstart guide, but shows
            * how you can use CSS to style your Element's container.
            */
            .StripeElement {
            box-sizing: border-box;

            height: 40px;

            padding: 10px 12px;

            border: 1px solid transparent;
            border-radius: 4px;
            background-color: white;

            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;
            }
        </style>
    </head>
    <body>
        <script src="https://js.stripe.com/v3/"></script>

        <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" role="alert"></div>
            </div>

            <button>Submit Payment</button>
        </form>

        <script>
            // Create a Stripe client.
            var stripe = Stripe('pk_test_XzLQCcuHS0Qc5xPIARiG8aNU');

            // 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',
                    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);
                    }
                });
            });

            // Submit the form with the token ID.
            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', 'text');
                // hiddenInput.setAttribute('name', 'stripeToken');
                // hiddenInput.setAttribute('value', token.id);
                // form.appendChild(hiddenInput);
                alert('Success! Got token: ' + token.id);

                // Submit the form
                // form.submit();
            }
        </script>
    </body>
</html>
LarAng
  • 959
  • 15
  • 23
  • 4
    This answer could really do with one additional line of explanation - bare minimum to explain which lines of your solution are additional. However it worked, so I've upvoted as well. – goose Nov 26 '19 at 07:25
  • I am having a similar issue except I am nesting an angular component that does the tokenization of credit card info inside of a Nebular Stepper UI component. Here's a link to my question (https://stackoverflow.com/questions/61448168/angular-8-stripe-elements-nested-inside-nebular-components). I am getting the same exception above and unfortunately haven't found a solution yet. – Scott Apr 26 '20 at 22:04
4

I've had this problem when switching between mobile and desktop screen sizes - the cutoff size where Stripe only displays the last 4 digits of the card number. If I refresh the page in the new resolution it works.

If this description fits your problem you might be able to mount the element again after the size change, or you'll have to recreate it.

T Pringle
  • 41
  • 2
2

If you're seeing this in React code, these links might help: https://github.com/stripe/react-stripe-elements/issues/55#issuecomment-326707827 https://github.com/stripe/react-stripe-elements#troubleshooting

Essentially the stripe elements in react use the higher order component pattern. If a HOC that uses shouldComponentUpdate wraps the injectStripe function, create token won't be able to find the ref to stripe elements. Make injectStripe the outer most HOC

Example:

  connect()(injectStripe(YourComponent))
  Becomes
  injectStripe(connect()(YourComponent))
William Chou
  • 632
  • 4
  • 15
1

If you work in your local dev environment and your HTTP connection is not secure (not HTTPS), then you need to include Stripe JS without https:

Stanislav
  • 855
  • 2
  • 9
  • 13
0

Disclaimer: I know this question has been answered, but I had the same issue with duplicate scripts inclusions due to merging. Since this is the first page I got when looking up my problem I felt that this would be a good place to leave this information.

A) If it is functioning and the token is created (console.log or check stripe dashboard), please be sure to check that Stripe.js was not included twice.

B) If you are using Angular (an analogy probably exists for React), I had a very easy time implementing stripe through the use of the ngx-stripe module.

Feel free to ask more specific questions. I've had to implement the base one from quick-start which was overall hell.

Ilia
  • 82
  • 5
0

Took me a few days to figure out, but in my case I was displaying the Stripe credit card element in a modal (Angular 11) that was using the Angular Shadow DOM encapsulation. Removing the Shadow DOM encapsulation solved this problem.

Russ
  • 449
  • 5
  • 10
-2

This should work

JS Code

 constructor(paymentInfo) {
    this.paymentInfo = paymentInfo;
    this.paymentInfo.amount = 25;
   this.loadStripe();
}

afterLoadingStripe() {
    this.stripe = Stripe(this.publicKey);
    var elements = this.stripe.elements();
    this.card = elements.create('card', {
        style: {
            base: {
                iconColor: '#666EE8',
                color: '#31325F',
                lineHeight: '40px',
                fontWeight: 300,
                fontFamily: 'Helvetica Neue',
                fontSize: '15px',

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

getToken() {
    let context = this;
    this.stripe.createToken(this.card).then(function (result) {
        if (result.error) {
        } else {
            context.paymentInfo.token = result;
            context.submitPaymentInfo();
        }
    });
}
submitPaymentInfo() {
    //submit here
    return;
}

loadStripe() {
    var script = document.createElement('script');
    let context = this;
    script.onload = function () {
        context.afterLoadingStripe();
    };
    script.src = "https://js.stripe.com/v3/";
    document.getElementsByTagName('head')[0].appendChild(script);
}

}

HTML

<script src="https://js.stripe.com/v3/"></script>
<div class="modal-dialog modal-lg">
    <require from="../../../css/stylesheet.css"></require>
    <div class="modal-content">
        <div class="modal-header">
            <h4>Payment</h4>
            <button type="button" id="stripe-modal-close" class="close" data-dismiss="modal">×</button>
        </div>
        <div class="modal-body">
            <form class="stripe-form" submit.delegate="getToken()">
                <div class="group">
                    <label class="stripe-label">
                        <span>Title</span>
                        <input id="name" class="stripe-field" placeholder="Jane Doe" />
                    </label>
                    <label class="stripe-label">
                        <span>Card</span>
                        <div id="card-element" class="stripe-field"></div>
                    </label>
                </div>
                <button class="btn btn-outline-dark my-3" type="submit">Pay $25</button>
                <div class="stripe-outcome">
                    <div class="stripe-error"></div>
                </div>
            </form>
        </div>
    </div>
</div>

CSS

.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;
}

.stripe-label {
  position: relative;
  color: #8898AA;
  font-weight: 300;
  height: 40px;
  line-height: 40px;
  margin-left: 20px;
  display: flex;
  flex-direction: row;
}

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

.stripe-label > span {
  width: 80px;
  text-align: right;
  margin-right: 30px;
}

.stripe-field {
  background: transparent;
  font-weight: 300;
  border: 0;
  color: #31325F;
  outline: none;
  flex: 1;
  padding-right: 10px;
  padding-left: 10px;
  cursor: text;
}

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

.stripe-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;
}

.stripe-button:focus {
  background: #555ABF;
}

.stripe-button:active {
  background: #43458B;
}

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

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

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

.stripe-error {
  color: #E4584C;
}

.stripe-success {
  color: #666EE8;
}

.stripe-success .stripe-token {
  font-weight: 500;
  font-size: 13px;
}
Ali Riaz
  • 1
  • 1