Auto fill stripe elements during development
Blessan Mathew
Posted on December 15, 2021
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"]
}
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]()
);
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"]
}
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 }));
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.
Posted on December 15, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.