Menu

React integration

SDK v2
Last updated January 2024

Integrate the Access Checkout Web SDK in a React application.

Integration

  1. You must add the SDK checkout.js script to your app html code and make sure this is done only once. To do this, you may want to add it in your main application or add it dynamically as part of one of your components.

  2. Before initializing the SDK, you must load the checkout.js script successfully. The reason is that this script creates an object on the window object which is required by the initialization mechanism.

  3. You must call the SDK's remove() method only once as part of your component unmounting phase but when the DOM is still available. You can do this by using the useLayoutEffect hook and by calling the remove() method in the cleanup function run by the hook.

Full integration example

Copied!
import React, {useEffect, useLayoutEffect} from "react";
import "./CheckoutIntegrationSample.css";

function scriptAlreadyLoaded(src) {
  return document.querySelector(`script[src="${src}"]`);
}

function loadCheckoutScript(src) {
  return new Promise((resolve, reject) => {
    if (scriptAlreadyLoaded(src)) {
      resolve();
      return;
    }

    let checkoutScript = document.createElement("script");
    checkoutScript.src = src;
    checkoutScript.onload = resolve;
    checkoutScript.onerror = reject;
    document.head.appendChild(checkoutScript);
  });
}

function addWorldpayCheckoutToPage() {
  return new Promise((resolve, reject) => {
    (function () {
      window.Worldpay.checkout.init(
        {
          id: "identity",
          form: "#container",
          fields: {
            pan: {
              selector: "#card-pan",
            },
            expiry: {
              selector: "#card-expiry",
            },
            cvv: {
              selector: "#card-cvv",
            },
          },
          styles: {
            "input.is-valid": {
              "color": "green",
            },
            "input.is-invalid": {
              "color": "red",
            },
            "input.is-onfocus": {
              "color": "black",
            },
          },
          enablePanFormatting: true,
        },
        function (error, checkout) {
          if (error) {
            reject(error);
          } else {
            resolve(checkout);
          }
        },
      );
    })();
  });
}

function CheckoutIntegrationSample() {
  const checkoutScriptUrl = "https://try.access.worldpay.com/access-checkout/v2/checkout.js";
  let checkout;

  function generateSession () {
    checkout.generateSessionState(
      function (error, session) {
        if (error) {
          console.warn(`Failed to generate session: ${error}`);
          return;
        }

        const infoDiv = document.querySelector(".info");
        infoDiv.innerHTML += `<div>Session retrieved is ${session}</div>`;
      });
  }

  function clearForm () {
    checkout.clearForm(() => {
      document.querySelector(".info").innerHTML = "";
    });
  }

  useEffect(() => {
    loadCheckoutScript(checkoutScriptUrl)
      .then(() => {
        addWorldpayCheckoutToPage()
          .then((checkoutInstance) => {
            checkout = checkoutInstance;
          })
          .catch(console.warn);
      })
      .catch(console.warn);
  }, []);

  useLayoutEffect(() => {
    // Make sure to call the remove method (once) in order to deallocate the SDK from memory
    return () => checkout.remove();
  },
    []);

  return (
    <section className="container" id="container">
      <section className="card">
        <section id="card-pan" className="field" />
        <section className="columns">
        <section>
        <section id="card-expiry" className="field" />
        </section>
        <section>
        <section id="card-cvv" className="field" />
        </section>
        </section>
        <section className="buttons">
          <button className="submit" type="button" onClick={generateSession}>
            Generate Session
          </button>
          <button className="clear" type="button" onClick={clearForm}>
            Clear
          </button>
        </section>
      </section>
      <div id="info" className="info" />
    </section>
  );
}

export default CheckoutIntegrationSample;
.container {
  display: flex;
  align-items: center;
  flex-direction: column;
}

.card {
  background: white;
  padding: 20px 30px;
  top: -30px;
  width: 100%;
  max-width: 300px;
  border-radius: 12px;
  box-shadow: 3px 3px 60px 0px rgba(0, 0, 0, 0.1);
}

.columns {
  display: flex;
}

.columns > * {
  margin-right: 15px;
}

.field {
  height: 40px;
  border-bottom: 1px solid lightgray;
}

.field.is-onfocus {
  border-color: black;
}

.field.is-empty {
  border-color: orange;
}

.field.is-invalid {
  border-color: red;
}

.field.is-valid {
  border-color: green;
}

#card-pan {
  margin-bottom: 30px;
}

.submit {
  background: green;
  cursor: pointer;
  width: 200px;
  margin-top:30px;
  color: white;
  outline: 0;
  font-size: 14px;
  border: 0;
  border-radius: 30px;
  text-transform: uppercase;
  font-weight: bold;
  padding: 15px 0;
  transition: background 0.3s ease;
  margin-right:20px;
}

.clear {
  background: green;
  cursor: pointer;
  width: 100px;
  margin-top:30px;
  color: white;
  outline: 0;
  font-size: 14px;
  border: 0;
  border-radius: 30px;
  text-transform: uppercase;
  font-weight: bold;
  padding: 15px 0;
  transition: background 0.3s ease;
}

.buttons {
  display: flex;
}

.info {
  width: 600px;
  word-wrap:break-word;
  margin-top: 20px;
  color: green;
}