简体   繁体   中英

fill out input field in iframe with Javascript

I'm using Stripe for payment, and angular e2e for testing. I want to add the card testdata into the payment window. Stripe injects an iframe incl. form elements into #card-element (which is part of my markup), but with no form name and no ids. This is part of the markup after Stripe has injected the payment container:

<div id="card-element" class="StripeElement StripeElement--empty">
 <div class="__PrivateStripeElement">
  <iframe frameborder="0" allowtransparency="true" scrolling="no" name="__privateStripeFrame5395" allowpaymentrequest="true" src="https://js.stripe.com/v3/elements-inner-card-xxx.html" ></iframe>
 </div>
</div>

Inside the iframe is (still only showing part of the markup):

<form class="ElementsApp is-empty" dir="ltr">
 <div tabindex="-1" class="CardNumberField CardNumberField--ltr">
  <div class="CardNumberField-input-wrapper">
   <input class="InputElement is-empty Input Input--empty" autocomplete="cc-number" autocorrect="off" spellcheck="false" type="text" name="cardnumber" data-elements-stable-field-name="cardNumber" inputmode="numeric" aria-label="Kredit- eller debetkortnummer" placeholder="Kortnummer" aria-invalid="false" value="">
  </div>
 </div>
 <button tabindex="-1" aria-hidden="true" type="submit"></button>
</form>

// Full selector from inspector: //#root > form > div > div.CardField-input-wrapper.is-ready-to-slide > span.CardField-number.CardField-child > span:nth-child(2) > div > div.CardNumberField-input-wrapper > span > input

I've managed to select the card-element and the iframe:

var cont = document.getElementById('card-element');
console.log(cont); // i get the card-element markup
var iframe = cont.getElementsByTagName('iframe');
console.log(iframe); 

iframe shows this in the console:

HTMLCollection []
0: iframe
length: 1
__privateStripeFrame3085: iframe
__proto__: HTMLCollection

From here i'm kinda stuck, i'm clicking around in the iframe[0] array, but i can't find name="cardnumber" in the list, searching for it gives me 15 hits, but the dataset is not opened, so still stuck. CardNumberField-input-wrapper gives only 3 hits, but same issue, not opening...

So my question is, how do i manage to fill data into the input field called "cardnumber"?

BTW: I'm also aware of cross-domain issues, but i haven't hit those (yet) and are not sure if i will since the iframe is injected from Stripe.

Short answer is that you can't, by design. Cross domain iframes can't have their contents accessed by JavaScript for security reasons. Stripe uses this to ensure that no one can access sensitive information contained within the iframe (eg credit card numbers).

This has the dual purpose of protecting your users as well as keeping your PCI compliance level to a minimum.

This does make things tricky if you're trying to automate end to end tests. Luckily there are tools like Cypress that can get around that. Here's a good article on how to test Stripe Elements with Cypress: https://medium.com/@michabahr/testing-stripe-elements-with-cypress-5a2fc17ab27b

I have in less than 3 hours from install to successful test made a working testcase against Stripes iframe card-element solution with Cypress based on this article: https://medium.com/@michabahr/testing-stripe-elements-with-cypress-5a2fc17ab27b I had to make some modifications, these are mentioned here: Cypress: automatic tests for credit card payment

The idea of the original post was to achieve the same using vanillaJS, so you can't really say it's solved. But i'd like to say i did spend way longer trying to find a solution with vanillaJS than with Cypress, which is easy to use, so give it a go if you're in the same situation:-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM