Developer/React Sdk

React SDK - Overview

Version 2.1.7 or later required

Fat Zebra is updating its 3D Secure integration. Merchants using this SDK must be on @fat-zebra/sdk 2.1.7 or later for 3DS to keep working. See the Upgrade Notice for details.

Introduction

Fat Zebra provides a JavaScript package called @fat-zebra/sdk that enables merchants to access features including:

  • 3DS2
  • Card tokenization

Authentication

Each feature accessible via the SDK requires OAuth authentication whereby merchants obtain an OAuth access token for each payment session required. Refer to Obtain an OAuth token for more details.

Usage

First, install the package (version 2.1.7 or later):

bash
npm install @fat-zebra/sdk@^2.1.7

Or add it to your package.json as a dependency:

json
"dependencies": {
   "@fat-zebra/sdk": "^2.1.7"
}

Card verification

The processes for new card and existing card verification are separate. Each process is detailed below.

Verify a new card

To use this package, you can import the relevant parts we need from the SDK. To then verify a card, we can use the VerifyCard component along with the verification hash.

Calculation of the verification hash

The new card verification hash is calculated using reference, amount and currency.
This part needs to be done server side to protect the FATZEBRA_SHARED_SECRET variable

javascript
// server side
import { createHmac } from "crypto";

const payment = {
  reference: "payment-001",
  amount: 100,
  currency: "AUD",
};

const newCardVerificationHash = createHmac("md5", process.env.FATZEBRA_SHARED_SECRET)
  .update(`${payment.reference}:${payment.amount}:${payment.currency}`)
  .digest("hex");

From this action of this component, we can pull out the token from the card tokenization event, and (if required) wait until the PublicEvent.SCA_SUCCESS event has happened before continuing with a customer's purchase.

The reference, amount and currency passed to the component must match the values used to calculate the hash.

Example code
tsx
// app.tsx
import VerifyNewCard from "./VerifyNewCard";

export default function Main() {
  // These are typically sourced from your backend
  const REFERENCE = "payment-001";
  const ACCESS_TOKEN = "<oauth access token goes here>"; // see: Obtain an OAuth token
  const NEW_CARD_VERIFICATION_HASH = "<calculated server side as shown above using your shared secret>";

  return (
  
  );
}
tsx
// VerifyNewCard.tsx
import { useState } from "react";
import {
  Environment,
  Payment,
  PaymentIntent,
  PublicEvent,
  PaymentConfig,
  Handlers,
} from "@fat-zebra/sdk/dist";
import { VerifyCard } from "@fat-zebra/sdk/dist/react";

type Props = {
  verification: string;
  accessToken: string;
  reference: string;
};

export default function VerifyNewCard({ verification, accessToken, reference }: Props) {
  const [events, setEvents] = useState([]);

  const addEvent = (event: CustomEvent) => {
  setEvents((prev) => [...prev, event]);
  };

  const payment: Payment = {
  reference,
  amount: 100,
  currency: "AUD",
  };

  const paymentIntent: PaymentIntent = {
  payment,
  verification,
  };

  const config: PaymentConfig = {
  username: "your-username-here",
  environment: Environment.sandbox, // or Environment.production
  accessToken,
  paymentIntent,
  options: {
    sca_enabled: true,
  },
  };

  const tokenizationSuccessful = (event: CustomEvent) => {
  // event.detail contains the card token: send it to your backend
  addEvent(event);
  };

  const scaSuccess = (event: CustomEvent) => {
  // event.detail contains the 3DS result fields to include in your purchase call
  addEvent(event);
  };

  const scaError = (event: CustomEvent) => {
  addEvent(event);
  };

  // Subscribe to the particular events you wish to handle
  const handlers: Handlers = {
  [PublicEvent.FORM_VALIDATION_ERROR]: addEvent,
  [PublicEvent.FORM_VALIDATION_SUCCESS]: addEvent,
  [PublicEvent.TOKENIZATION_SUCCESS]: tokenizationSuccessful,
  [PublicEvent.SCA_SUCCESS]: scaSuccess,
  [PublicEvent.SCA_ERROR]: scaError,
  };

  return (
  <div className="App flex gap-8 mx-8">
    <div className="w-1/2">
    
    </div>
  </div>
  );
}

Verify Existing Card

To then verify an existing card, we can use the VerifyExistingCard component.

From the action of this component, the successful or failed tokenised credit card event will fire. Indicating whether or not a card has been previously tokenised.

This component will return either: “Could not find card on file” or “fz.tokenization.success” status and run sca on each verification.

Calculation of the verification hash

The verification hash for verify an existing card is calculated by hashing the card token. This is to be done server-side as an example:

javascript
// server side
import { createHmac } from "crypto";

const CARD_TOKEN = "fdsde3yx";

// Never expose FATZEBRA_SHARED_SECRET to the client
const existingCardVerificationHash = createHmac("md5", process.env.FATZEBRA_SHARED_SECRET)
  .update(CARD_TOKEN)
  .digest("hex");
Example code
tsx
// app.tsx
import VerifyOurCard from "./VerifyOurCard";

export default function Main() {
  // These are typically sourced from your backend
  const REFERENCE = "payment-001";
  const ACCESS_TOKEN = "<oauth access token goes here>";
  const CARD_TOKEN = "fdsde3yx";
  const EXISTING_CARD_VERIFICATION_HASH = "<calculated server side as shown above using your shared secret>";

  return (
  
  );
}
tsx
// VerifyOurCard.tsx
import { useState } from "react";
import {
  Environment,
  PaymentConfig,
  PublicEvent,
  Handlers,
} from "@fat-zebra/sdk/dist";
import { VerifyExistingCard } from "@fat-zebra/sdk/dist/react";

type Props = {
  verification: string;
  accessToken: string;
  reference: string;
  cardToken: string;
};

export default function VerifyOurCard({ verification, accessToken, reference, cardToken }: Props) {
  const [events, setEvents] = useState<string[]>([]);

  const config: PaymentConfig = {
  username: "your-username-here",
  environment: Environment.sandbox, // or Environment.production
  accessToken,
  paymentIntent: {
    payment: {
    reference,
    amount: 100,
    currency: "AUD",
    },
    verification,
  },
  options: {
    sca_enabled: true, // if you are enabled for 3D Secure
  },
  };

  const handleEvent = (event: CustomEvent) => {
  setEvents((prev) => [...prev, event.type]);
  };

  // Subscribe to the particular events you wish to handle
  const handlers: Handlers = {
  [PublicEvent.TOKENIZATION_SUCCESS]: handleEvent,
  [PublicEvent.TOKENIZATION_ERROR]: handleEvent,
  [PublicEvent.SCA_SUCCESS]: handleEvent,
  [PublicEvent.SCA_ERROR]: handleEvent,
  };

  return (
  <>
    
    <ol>
    {events.map((event, index) => (
      <li key={index}>{event}</li>
    ))}
    </ol>
  </>
  );
}

Creating a payment

There's currently no form support for taking a payment with this SDK.

Instead, we would recommend passing the token from a TOKENIZATION_SUCCESS event back to your backend, and then processing a payment from there using the FatZebra API.