Secure Inputs SDK for PINs
Overview
The Highnote Secure Inputs SDK enables customers to securely set and update their PIN from your UI using iframes. This prevents PCI-scoped data from flowing through your servers or from being accessible to scripts running on your page.
Prerequisites
- A Highnote account
- A server-side integration using an API key
- Payment card ID
Installation
The Highnote Secure Inputs SDK follows semver and can be installed using the following:
- JavaScript package manager:
npm,yarn, orpnpm - Content Delivery Network (CDN) via traditional
<script>tag or ECMAScript module.
Install by package manager
Installation steps are the same for both the PIN and tokenization Secure Inputs SDKs.
The Secure Inputs SDK supports the following JavaScript package managers: npm, yarn, and pnpm.
npm i @highnoteplatform/secure-inputs
yarn add @highnoteplatform/secure-inputs
pnpm add @highnoteplatform/secure-inputs
Install by CDN
To ensure stability and avoid potential issues caused by updates, replace @latest with a specific version number such as @1.0.0.
You can install Secure Inputs SDK directly from a content delivery network (CDN) such as JSDelivr.
The SDK supports both traditional script tags and ECMAScript module imports. ESM imports require modern browsers. To support older browsers, use the traditional script tag approach with appropriate polyfills.
Script tag
To install the Secure Inputs SDK by <script> tag, add the following to your HTML file:
<script src="https://cdn.jsdelivr.net/npm/@highnoteplatform/secure-inputs@latest/lib/index.js"></script>
ESM import
To install the Secure Inputs SDK by ESM module, add the following to your HTML file:
<script type="module">
import { SecureInputs } from "https://cdn.jsdelivr.net/npm/@highnoteplatform/secure-inputs@latest/lib/index.js";
// Initialize the Secure Inputs
const secureInputs = new SecureInputs({
// configuration options
});
</script>
Usage
To render secure input fields in your UI, configure elements to hold each field as follows:
- Prepare your HTML
- Fetch a client token
- Initialize secure inputs.
Prepare your HTML
To use the Secure Inputs SDK, you must provide an element for the PIN field.
The following code sample uses a div element to contain the iframe for the secure input field:
<!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>Edit Payment Card PIN</title>
</head>
<body>
<p>Enter a new PIN for your Payment Card</p>
<div id="pin">
<!-- An iframe will be injected here -->
</div>
</body>
</html>
Fetch a client token
To obtain a client token from your server for the secure inputs SDK, use the GeneratePaymentCardClientToken mutation.
Refer to the following guidelines when generating a payment card client token:
- Provide the
paymentCardIdof the payment card that needs the PIN set or updated. - The client token is only valid for 10 minutes, but can be used multiple times.
- Once a token expires, you must generate a new one.
Use the following mutation to generate a payment card client token:
GeneratePaymentCardClientToken
Query
mutation GeneratePaymentCardClientToken(
$input: GeneratePaymentCardClientTokenInput!
) {
generatePaymentCardClientToken(input: $input) {
... on ClientToken {
value
expirationDate
}
}
}
Variables
{ "input": { "paymentCardId": "PAYMENT_CARD_ID", "permissions": [ "SET_PAYMENT_CARD_PIN" ] } }
Result
{
"data": {
"generatePaymentCardClientToken": {
"value": "TOKEN",
"expirationDate": "2022-02-07T20:04:50.633Z"
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Initialize secure inputs
The secure inputs library works by injecting an iframe into the PIN element to render the appropriate data. You can style the content inside each iframe by passing any combination of styling options.
You can initialize the card viewer by using a renderFields function.
This returns a Promise that contains a reference to the secureInputs instance.
This is useful for lifecycle management and interactions such as field submission.
The following example shows how to initialize the Secure Inputs SDK:
import { renderFields } from "@highnoteplatform/secure-inputs";
const secureInputs = await renderFields({
// Specify the individual fields to render data into
elements: {
pin: {
clientToken: "client token from server",
// This is the same paymentCardId used to generate the token
paymentCardId: "PAYMENT_CARD_ID",
selector: "#pin",
},
},
onSuccess: (element) => {
// Inform the user on success
},
onError: (error) => {
// Handle errors
},
});
Error handling
The Secure Inputs SDK doesn't render error messages or update your UI inside iframes when errors occur. You must introspect and handle errors accordingly.
You can pass an onError handler to the renderFields call. This callback will be invoked whenever an error is raised from the integration.
Error types
The following error types are supported for the secure inputs SDK:
| Error | Description |
|---|---|
| InvalidCredentialError | The provided client token is invalid or expired. Use the requestId in the payload for support and debugging. |
| SecureInputsRequestError | Represents errors encountered when communicating with the Highnote API, such as an incorrect payment card ID. Use the requestId in the payload for support and debugging. |
| SecureInputsFieldsInputError | Raised when an invalid configuration is provided at runtime. |
| SecureInputsError | A generic catchall error. |
Example errors
The following code sample provides examples of secure inputs errors:
import {
type SecureInputsError,
renderFields,
} from "@highnoteplatform/secure-inputs";
const handleError = (error: SecureInputsError) => {
switch (error.name) {
case "InvalidCredentialError":
// Handle invalid/expired credential
// Unmount fields, fetch new client token, re-initialize
console.error(error.context.requestId); // "some-request-id"
break;
case "SecureInputsRequestError":
// Handle invalid payment card IDs
console.error(error.context.requestId); // some-request-id
break;
case "SecureInputsFieldInputError":
// Handle user input errors such as invalid pin
console.error(error.message); // "Invalid Payment Card ID"
break;
default:
console.error(error);
}
};
const { unmount } = await renderFields({
// ...
onError: handleError,
// ...
});
Styling options
The following styling options are available for use in elements for your secure inputs fields:
| Property | Examples | Docs |
|---|---|---|
color | #55f5a3, rgba(85,245,163,1), #springgreen | MDN Docs |
cursor | pointer, none | MDN Docs |
fontFamily | sans-serif, serif, monospace System fonts only | MDN Docs |
fontSize | 12px, 1em, 1.1rem | MDN Docs |
fontWeight | bold, normal | MDN Docs |
letterSpacing | normal, .2rem | MDN Docs |
lineHeight | normal, 150% | MDN Docs |
userSelect | none, auto, inherit | MDN Docs |
iframe defaults
Highnote injects card viewer iframes with the following defaults. Your CSS styling can override each of these:
border: nonewidth: 300px(browser default)height: 150px(browser default)
The document and body inside the frame will have transparent backgrounds and default to margin: 0, padding: 0
Custom fonts
The Secure Inputs SDK only supports system fonts.
Layout
The layout of payment card fields in the card viewer is customizable. Highnote injects iframes into the provided container elements, which will inherit the width of the container.
You can customize the width and height of the container to accommodate your UI as needed.
The following code sample provides an example of custom layout styling:
#pin {
margin: 1em;
}
/* You can target the iframe with a child combinator. */
#pin > iframe {
height: 140px;
}
Using the Live environment
By default, the card viewer library will make requests against the Test environment. When you are ready to switch to the Live environment, set the environment configuration option using the following function call:
const { unmount } = await renderFields({
// Set this to `live`
environment: "live",
// ...
});
Lifecycle
If you need to unmount 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.
The following code sample provides an example function to unmount fields:
import { renderFields } from "@highnoteplatform/secure-inputs";
const { submit, unmount } = await renderFields({
onSuccess: async (field) => {
if (field === "pin") {
// Inform customer their PIN changed successfully.
await unmount();
}
},
// ...config
});
// ...
submit();
Content security policy
If your application enforces a content security policy, you must set the frame-src header to allow iframes from the Highnote domain:
Content-Security-Policy: frame-src https://cdn.highnote.com