DEV Community

Blessan Mathew
Blessan Mathew

Posted on

Auto fill stripe elements during development

tl:dr - Link to the repo.

My job involves creating different customer payment flows for different scenarios. So I have to deal with a lot of forms on a daily basis. Filling out forms to test a flow and especially during development can become very repetitive. So to solve this issue we created a chrome extention. We simply call it the dev-tools.

Out dev tools can autofill forms with a simple short key ⌥ + enter. Its a pretty simple setup if you have some idea about chrome extensions. Please refer their documentation if you are not familiar with chrome extensions.

We utilize their content scripts feature which basically allows us to inject javascript into any url patterns we list in the manifest file.

{
  "name": "dev-tools",
  ...
  "content_scripts": [
    {
      "matches": [
        "https://js.stripe.com/v3/elements-inner-card*"
      ],
      "js": ["content-script.js"]
    }
  ],
  "permissions": ["tabs", "storage"]
}
Enter fullscreen mode Exit fullscreen mode

Below you can see how content-script.js looks like,

const formFillers = {
  directSales() {
    const fields = [
      { name: "firstName", value: "John" },
      { name: "lastName", value: "Doe" },
      { name: "postalCode", value: "12345" },
    ];
    fields.forEach(({ name, value }) => {
      document.getElementsByName(name)[0].value = value;
      document
        .getElementsByName(name)[0]
        .dispatchEvent(
          new Event("input", { bubbles: true })
        );
    });

    document.getElementById("terms").checked = true;
    document
      .getElementById("terms")
      .dispatchEvent(new Event("click", { bubbles: true }));
  },
};

Array.from(document.forms).forEach((form) =>
  formFillers[form.name]()
);
Enter fullscreen mode Exit fullscreen mode

The code is pretty simple, it loops through all the forms in the page and invokes a form filler function we have mapped to the form name.

This will not work with stripe elements!

Each stripe elements is an iframe. We cannot simply manipulate a HTML element in an iframe from the outer frame.

all_frames for the win

In the manifest of the extension you can specify an option called all_frames for a content script. Be default chrome will only inject your content script to the top most frame of the page. All the inner frames will be ignored. If you enable all_frames:true for your content script, it will be injected into every frame in the page.

{
  "matches": [
    "https://js.stripe.com/v3/elements-inner-card*"
  ],
  "all_frames": true,
  "js": ["content-script.js"]
}
Enter fullscreen mode Exit fullscreen mode

So now that we can inject javascript into the frame, we use the following code to fill the elements.

const params = new URLSearchParams(window.location.href);
const name = params.get("componentName");

const values = {
  cardNumber: "4242424242424242",
  cardExpiry: "12/25",
  cardCvc: "123",
};

document.querySelector(
  `[data-elements-stable-field-name="${name}"]`
).value = values[name];
document
  .querySelector(
    `[data-elements-stable-field-name="${name}"]`
  )
  .dispatchEvent(new Event("input", { bubbles: true }));
Enter fullscreen mode Exit fullscreen mode

By parsing the url we get an idea of what element is being renderred and then we just find the input field and set the value.

That's it. I hope this helps.

Top comments (1)

Collapse
 
mreduar profile image
Eduar Bastidas

Greetings, I was trying to do it without an extension but a button in my application itself. But it gives me a cors error because as you say in the publication is an iframe where are the stripe elements to be modified, for security the browser does not let manipulate and gives a cors error. Do you know if it is possible to do it with a button inside my application itself?