Create a custom payment form using React and Square
There are a lot of ways to accept payments online. Wouldn’t it be nice to implement a single form that could accept as many payment methods as we want at a single time? Let’s take a look at implementing a custom payment form using Square and React. This form will enable us to take credit cards online, and give us support for Apple Pay, Google Pay, and Masterpass in a single payment form.
Things required to understand this post:
Our final (payment) form:
React and Square’s Payment Form
If you’re familiar with React, then you’re accustomed to passing along
props and controlling your component via its
state. Let’s focus on how to get a basic setup up and running with Square’s payment form controlled by a React component. We’ll also demonstrate how to dynamically load the Square payment form script in case you want to simply insert the payment form component on a page. Dynamic loading the script is only relevant if you don’t want the script to only load on a checkout page (or wherever you’d like to take a payment).
At a basic level, the payment form directly captures your customer’s card details directly on Square’s servers using an
<iframe>. The payment form facilitates the generation of these
<iframe> elements and provides an API for creating a nonce (a one-time-use token) to reference those details later (all without you knowing any sensitive information!).
The main problem you hit with these
<iframe> elements replacing other elements in the DOM is that React usually likes to be in charge of managing all your DOM interactions. This requires doing a bit of extra setup on our components to be sure we render everything correctly, in the right order, and correctly handle different events generated by the Square payment form script.
Dynamically Load The Square Payment Form Script
Our base component is where we’ll actually manage dynamically loading
<script src=”https://js.squareup.com/v2/paymentform”></script> into the
<head> of the DOM and trigger our child component to render. The child component will actually be responsible for assembling, formatting, and managing our payment form. This is done to ensure the script has loaded and we can pass the
SqPaymentForm object down to our child component.
componentWillMount() to create a
<script> element and set some attributes, and then making sure that we’re updating our React component’s state to
loaded once the script has actually loaded on the page. This will trigger React to re-render and return
this.state.loaded inside our
render() method and allow our child component to render.
The other notable part of our code is how we’re passing
SqPaymentForm via the
paymentForm prop. We are passing in the SqPaymentForm object that is attached to the window, so rendering the payment form and triggering submission is easier to manage.
React Payment Form Component
To keep things simple, we’re modifying existing templates found on Square’s GitHub. For more info on customizing or setting up a Square payment form, check out our guides. We’ll focus more on the difference between those templates and wiring things into our React component.
Our render() Method
The key parts to note in the elements we have is the divs elements with the id’s:
sq-postal-code. We transformed the examples to use divs for everything instead of form components, since these are all the fields that will be targeted by Square’s payment form script to be replaced with
<iframe> elements. Also, since we’re using React, we will have our own functions for controlling submission and triggering the request of a nonce from the payment form.
Digital Wallet Payments & Methods Supported
To adjust what digital wallet options (sometimes called mobile wallet options) you want to support, just provide different key-value pairs in your
SqPaymentForm configuration object (see more on that here). You should be able to see in the
render() method that we’re controlling the display of our mobile payment options using the component’s
We are setting the state inside of the
methodsSupported() callback that the Square payment form has provided to us. Since each mobile wallet option is specific to the browser that a customer is visiting from, you need to conditionally render the buttons to match what should be available based on your customer’s browser or mobile device. We also have to make these separate conditionals since the payment form calls the
methodsSupport() function once for each method you’re choosing to support. Our example is trying to support Masterpass, Apple Pay, and Google Pay, so three calls will be made. It’s a little aggressive in our calls to
setState(), but only three calls, so no worries — just keep it in mind if you’re calling
setState() elsewhere, since every call will trigger a re-render of the component.
Linking & Controlling the Component
The main takeaway is to use
state inside of the provided callback. Using
state in the component allows us to react (so punny) to different events emitted by Square’s payment form script. You can learn more about all these events are in the docs. In our example, a key place for this tie-in would be the
inputEventReceived() callback since it’s called on every input event. In our example component, we update the brand of the card (in the top right corner) once it has been identified by the payment form.
Thoughts and Conclusions
This is only one way of approaching implementing the Square payment form in React. Initially it seemed like a good idea to try passing in the config object as a prop, but that doesn’t work too well for configuring your callback functions, unless you’re comfortable overriding them before creating your
paymentForm object (this just felt wrong).
The main place I’ve seen developers trip up is usually on not disabling
paymentform script is going to immediately look for elements with the provided element id’s on build, but the problem arises because React might not have rendered the elements to the DOM yet. It is better to control the build process by triggering it with a call to
The implementation of the form in React is fairly straight forward (if you know React) and just requires understanding of the React lifecycle in relation to the
You can find a full example of this form over at: https://github.com/mootrichard/square-react-online-payments.
If you liked this post on React + Square, but would like to see this refactored using React’s Hooks API, tweet at me, respond here on Medium, or bug me in our Slack community and I’ll follow up with a post with how to refactor this example using the React Hooks API.