Home / Clientside & SDKs

Card Viewer SDK

Render Card Details

The Highnote Card Viewer SDK allows you to embed sensitive card data in your UI seamlessly using iframes. This allows you to avoid PCI-scoped data flowing through your servers or being accessible to scripts running on your page.

Note: Secure Inputs uses client tokens to make requests to the Highnote GraphQL API on your behalf. Learn how to generate client tokens using the generatePaymentCardClientToken mutation (docs).

Requirements

  • A Highnote account
  • A server-side integration using an API Key
  • Payment Card ID(s) (for the Card Viewer)

Installation

The Card Viewer library follows semver and can be installed from npm or a cdn.

via NPM

You can install the Card Viewer library with the following

With npm: npm i @highnoteplatform/card-viewer

With yarn: yarn add @highnoteplatform/card-viewer

With pnpm: pnpm add @highnoteplatform/card-viewer

Note: This package ships with TypeScript definitions installed.

via CDN

You can install the Card Viewer library for use on your page directly from a CDN such as JSDelivr. This is helpful when exploring the SDK or for use in tools such as CodeSandbox.

It is recommended you select a specific version of the library to use. You can replace @latest with your chosen version (for example, @1.0.0).

Usage

To render card details in your UI, you will need to set up elements to hold each field (card number, cvv, and expiration date). You can then initialize the JavaScript library to populate those fields with the proper values via iframes.

Fetch a Client Token

First, you will need to obtain a client token from your server using the generatePaymentCardClientToken mutation (docs). When generating the client token, you will need to provide the Payment Card ID of the card you will render.

The resulting token can be safely provided to your client and passed to the Highnote JavaScript SDK. It is only valid for 10 minutes but can be used multiple times within that period. Once the token has expired, you will need to generate a new one if you wish to re-render the payment card details.

Prepare Your HTML

You will need to provide the Card Viewer with the elements you want to render iframes into for each field.

  • Card Number
  • CVV
  • Expiration date
Prepare HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Payment Card</title>
  </head>
  <body>
    <p>Card Number</p>
    <div id="cardNumber">
      <!-- An iframe will be injected here -->
    </div>

    <p>CVV</p>
    <div id="cvv">
      <!-- An iframe will be injected here -->
    </div>

    <p>Expiration Date</p>
    <div id="expirationDate">
      <!-- An iframe will be injected here -->
    </div>
  </body>
</html>

Initialize Card Viewer

The library will inject an iframe into each of these elements to render the appropriate data. You can style the content inside of each iframe by passing any combination of allowed styles.

You can initialize the Card Viewer by calling renderFields. This will return a Promise that, will contain a reference to the cardViewer instance (useful for lifecycle management and interactions such as Card Number Masking)

Render Fields
import { renderFields } from "@highnoteplatform/card-viewer";

const { unmount } = await renderFields({
  clientToken: "client token from server",
  // This is the same paymentCardId used to generate the token
  paymentCardId: "MC43LjE=",
  
  onError: (error) => {
    // Handle errors
  },

  // Specify the individual fields to render data into
  elements: {
    cardNumber: {
      selector: "#cardNumber",
    },

    cvv: {
      selector: "#cvv",
    },

    expirationDate: {
      selector: "#expirationDate",
    },
  },
});

Error Handling

You can pass an onError handler to the renderFields call. This callback will be invoked whenever an error is raised from the integration.

The Card Viewer will not render error messages or update the UI inside of iframes when errors are encountered. It is up to you to introspect and handle errors accordingly.

Error Types

InvalidCredentialError This error occurs when the provided Client Token is invalid or expired. The payload will contain the requestId which can be used for support and debugging.

Properties:

  • name: "InvalidCredential"
  • context: object - requestId: string

CardViewerRequestError This error represents errors encountered when communicating with the Highnote GraphQL API. The payload will contain the requestId which can be used for support and debugging.

Properties:

  • name: "CardViewerRequestError"
  • message: string
  • context: object - requestId: string

CardViewerFieldsInputError This error is raised when an invalid configuration is provided at runtime.

Example messages:

  • Invalid client token.
  • Invalid Payment Card ID
  • Invalid environment. Please provide test or live.

Properties:

  • name: "CardViewerFieldsInputError"
  • message: string

CardViewerError A generic catchall error.

Properties:

  • message: string

Examples

Card Viewer Errors
import { renderFields } from "@highnoteplatform/card-viewer";

const handleError = (
  error: HighnoteRequestError | HighnoteConfigError | Error
) => {
  switch (error.name) {
    case "InvalidCredential":
      // Handle invalid/expired credential
      // Unmount fields, fetch new client token, re-initialize
      console.error(error.context.requestId); // "some-request-id"
      break;

    case "CardViewerRequestError":
      console.error(error.context.requestId); // some-request-id
      break;

    case "CardViewerFieldsInputError":
      console.error(error.message); // "Invalid Payment Card ID"
      break;

    default:
      console.error(error);
  }
};


const { unmount } = await renderFields({
  clientToken: "client token from server",
  // This is the same paymentCardId used to generate the token
  paymentCardId: "MC43LjE=",

  onError: handleError,

  // Specify the individual fields to render data into
  elements: {
    cardNumber: {
      selector: "#cardNumber",
    },

    cvv: {
      selector: "#cvv",
    },

    expirationDate: {
      selector: "#expirationDate",
    },
  },
});

Styling Options

PropertyExamplesDocs
color#55f5a3, rgba(85,245,163,1), #springgreenMDN Docs
cursorpointer, noneMDN Docs
fontFamilysans-serif, serif, monospace System fonts onlyMDN Docs
fontSize12px, 1em, 1.1remMDN Docs
fontWeightbold, normalMDN Docs
letterSpacingnormal, .2remMDN Docs
lineHeightnormal, 150%MDN Docs
userSelectnone, auto, inheritMDN Docs

iframe Defaults

Highnote will inject iframes with the following defaults. Each of these can be overridden by your CSS styling.

The document and body inside the frame will have transparent backgrounds and default to margin: 0, padding: 0.

The document and body inside the frame will have transparent backgrounds and default to margin: 0, padding: 0.

Custom Fonts

Only system fonts are supported.

Layout

The layout of the payment card fields is up to you. Highnote will inject iframes into the provided container elements. The iframes will inherit the width of the container and you can also set the height to accommodate your UI as needed.

Card Styling
#cardNumber {
  margin: 1em;
}

/* You can target the iframe with a child combinator. */
#cardNumber > iframe {
  height: 140px;
}

Using the Live Environment

By default, the library will make requests against the test environment. When you are ready to switch to live, set the environment configuration option:

Note: Read more about Highnote Environments.

Live Environment
const { unmount } = await renderFields({
  clientToken: "client token from server",
  paymentCardId: "MC43LjE=",
  // Set this to `live`
  environemnt: 'live',
  onError: handleError,
  elements
})

Lifecycle

Initial loading

When rendering card viewer fields, the Highnote library will immediately write the required iframes into your UI and render them in a loading state. While in this state, the fields will be populated with placeholder characters.

  • Card number: •••• •••• •••• ••••
  • CVV: •••
  • Expiration Date: ••/••

Currently, these values cannot be changed.

Once the configuration has been validated and the fields rendered, the library will request the card details from the Highnote API and replace the loading values with the data.

Unmounting fields

If you need to unmount the payment card fields, use the unmount method on the returned reference. This is useful when you need to “restart” the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers.

Unmounting Fields
import { renderFields } from "@highnoteplatform/card-viewer";

const { unmount } = await renderFields({
  // ...config
});

// Later...unmount
await unmount()

Interactions

The Highnote Card Viewer SDK allows your Account Holders to toggle sensitive data as well as copy data to their clipboard to complete payments.

Card Number Masking

By default, the payment card number will be masked (•••• •••• •••• ••••). When the card number is available, only the last four digits will be shown.

You can toggle the masking on and off using the toggleCardNumberMask method on the returned card viewer reference.

By default, users will be able to select and copy values to their clipboard.

Copy to Clipboard

When clicked, the card number, expiration date and CVV's underlaying value will be copied to your Account Holder's clipboard. In addition to the copy event itself, there are two callback functions to allow customization when a user copies or fails to copy a value.

onCopyToClipboardSuccess callback is fired when an Account Holder successfully copies a value to their clipboard. This function will also receive an object with the property field and a property __typename of COPY_TO_CLIPBOARD_SUCCESS

onError callback will also fire with an error of type COPY_TO_CLIPBOARD_ERROR in the event this functionality fails for some reason.

enableClipboard will allow you to toggle the copy to clipboard feature on and off. By default, Account Holder's will be able to select and copy values to their clipboard on all fields.

Copy To Clipboard Config
import { renderFields } from "@highnoteplatform/card-viewer";

const { unmount } = await renderFields({
  clientToken: "client token from server",
  // This is the same paymentCardId used to generate the token
  paymentCardId: "MC43LjE=",
  // This allows a user to click and copy the value of a field. Enabled by default
  enableClipboard: true,
  // Only needed is clipboard is enabled
  onCopyToClipboardSuccess: ({ field }) => {
    console.log(`${field} value copied!`); // cardNumber value copied!
  },

  onError: (error) => {
    // Handle errors
  },

  // Specify the individual fields to render data into
  elements: {
    cardNumber: {
      selector: "#cardNumber",
    },

    cvv: {
      selector: "#cvv",
    },

    expirationDate: {
      selector: "#expirationDate",
    },
  },
});

Content-Security Policy

If your application enforces a Content Security Policy, you will need to set the frame-src header (docs) to allow iframes from the Highnote domain.

Content-Security-Policy: frame-src https://sdk.highnoteplatform.com/

Provide Feedback

Was this content helpful?