DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Dynamic Web Forms In React For Enterprise Platforms
  • Three Best React Form Libraries
  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide

Trending

  • A Developer's Guide to Mastering Agentic AI: From Theory to Practice
  • A Guide to Container Runtimes
  • Unlocking AI Coding Assistants Part 3: Generating Diagrams, Open API Specs, And Test Data
  • Unlocking the Benefits of a Private API in AWS API Gateway
  1. DZone
  2. Coding
  3. JavaScript
  4. Online Payments With React and Square

Online Payments With React and Square

By 
Richard Moot user avatar
Richard Moot
·
Jan. 29, 20 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
8.1K Views

Join the DZone community and get the full member experience.

Join For Free

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? 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.

Requirements

  • React (simplified with create-react-app).
  • Square’s Payment Form.

Our Final (Payment) Form:

Final payment form

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. Dynamically 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).

You may also like: How to Learn React.js, Part 1: The React Road Map for Modern Web Developers.

If you’re not acquainted with Square’s payment form, head over to the docs and get familiar. There are some templates, explanations, and guides on getting the form set up using basic HTML, CSS, and JavaScript.

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 to 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 been loaded so that we can pass the SqPaymentForm object down to our child component.

JavaScript
 




x
10


 
1
import React, { Component } from 'react'; 
2
import PaymentForm from './components/PaymentForm'; 
3

          
4
class App extends Component { 
5
  constructor(props){ 
6
    super(props) 
7
      
8
    this.state = { 
9
      loaded: false 
10
    } 
11
  } 
12
  
13
  componentWillMount() { 
14
    const that = this; 
15
    let sqPaymentScript = document.createElement('script'); 
16
    
17
    sqPaymentScript.src = "https://js.squareup.com/v2/paymentform";
18
    sqPaymentScript.type = "text/javascript" sqPaymentScript.async = false;
19
    sqPaymentScript.onload = ()=>{
20
      that.setState({ 
21
        loaded: true 
22
      })
23
    }; 
24
    
25
    document.getElementsByTagName("head")[0].appendChild(sqPaymentScript); 
26
  } 
27
  
28
  render() { 
29
    return ( 
30
      this.state.loaded && <PaymentForm paymentForm={ window.SqPaymentForm } />
31
    ); 
32
  } 
33
} 
34

          
35
export default App;
36

          
30
      this.state.loaded && <PaymentForm paymentForm={ window.SqPaymentForm } />); } } export default App;



You can see we’re just using some vanilla JavaScript inside the lifecycle method componentWillMount() to create a <script> element and set some attributes. Then, we make 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 true for 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. Full code example can also be found at this repo.

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

JavaScript
 




xxxxxxxxxx
1
45


 
1
render() { 
2
  return ( 
3
    <div className="container"> 
4
        <div id="form-container"> 
5
            <div id="sq-walletbox"> 
6
                <button
7
                    style={{display: (this.state.applePay) ? 'inherit': 'none'} 
8
                    className="wallet-button" 
9
                    id="sq-apple-pay">
10
                </button> 
11
                <button 
12
                    style={{display: (this.state.masterpass) ? 'block': 'none'}}
13
                    className="wallet-button" id="sq-masterpass">
14
                </button> 
15
                <button 
16
                    style={{display: (this.state.googlePay) ? 'inherit': 'none'}}
17
                    className="wallet-button" id="sq-google-pay">
18
                </button> 
19
                <hr /> 
20
           </div> 
21
           <div id="sq-ccbox"> 
22
                <p> 
23
                    <span style={styles.leftCenter}>Enter Card Info Below </span
24
                    <span style={styles.blockRight
25
                        {this.state.cardBrand.toUpperCase()} 
26
                    </span> 
27
                </p> 
28
           <div id="cc-field-wrapper"> 
29
                <div id="sq-card-number"></div> 
30
                <input type="hidden" id="card-nonce" name="nonce" /> 
31
                <div id="sq-expiration-date"></div> 
32
                <div id="sq-cvv"></div> 
33
           </div> 
34
           <input id="name" style={styles.name} type="text" placeholder="Name" />
35
           <div id="sq-postal-code"></div> 
36
        </div> 
37
        <button 
38
            className="button-credit-card" 
39
            onClick={this.requestCardNonce}
40
        >Pay</button> 
41
    </div> 
42
    <p style={styles.center} id="error"></p> 
43
    </div> 
44
  ) 
45
}



The key parts to note in the elements we have are the divs elements with the id's: sq-apple-pay, sq-masterpass, sq-google-pay, sq-card-number, sq-cvv, sq-expiration-date, and 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 and 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 state.

JavaScript
 




xxxxxxxxxx
1
10


 
1
callbacks: { 
2
  methodsSupported: (methods) => { 
3
    if(methods.googlePay){ 
4
      this.setState(
5
        { googlePay: methods.googlePay }
6
      ) 
7
    } 
8
    
9
    if(methods.applePay){ 
10
      this.setState({ 
11
        applePay: methods.applePay 
12
      }) 
13
    } 
14
    
15
    if(methods.masterpass){ 
16
      this.setState({ 
17
        masterpass: methods.masterpass 
18
      }) 
19
    } 
20
    
21
    return; 
22
  },
23

          
13
    } 



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 and 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 autoBuild. The paymentform script is going to immediately look for elements with the provided element id’s on build, but React might not have rendered the elements to the DOM yet. (You can see how this could be an issue.) It is better to control the build process by triggering it with a call to.build().

The implementation of the form in React is fairly straight forward (if you know React) and just requires understanding React lifecycle in relation to the paymentform lifecycle.

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 DZone, 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.



Further Reading

  • A Look at React Native and React.js.
  • React.js Essentials.
React (JavaScript library) Form (document)

Published at DZone with permission of Richard Moot. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Dynamic Web Forms In React For Enterprise Platforms
  • Three Best React Form Libraries
  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!