Skip to content

Repository files navigation

skyflow-react-js

A React wrapper for Skyflow JS SDK


Browsers support

IE / Edge
IE / Edge
Firefox
Firefox
Chrome
Chrome
Safari
Safari

Table of Contents


Including Skyflow-React

Requirements

  • The minimum supported version of React is v16.8.0. If you use an older version, upgrade React to use this library

Installation

Using npm

npm install --save skyflow-react-js

Initializing Skyflow-React

React components are wrapped in Skyflow provider which takes in config object and SDK internally initializes a Skyflow client.

import{SkyflowElements,LogLevel,Env}from'skyflow-react-js';constroot=ReactDOM.createRoot(document.getElementById('root')asHTMLElement);constconfig={vaultID: 'string',// Id of the vault that the client should connect to.vaultURL: 'string',// URL of the vault that the client should connect to.getBearerToken: helperFunc,// Helper function that retrieves a Skyflow bearer token from your backend.options: {logLevel: LogLevel.DEBUG,// Optional, if not specified default is ERROR.env: Env.DEV,// Optional, if not specified default is PROD.},};root.render(<SkyflowElementsconfig={config}><App/></SkyflowElements>);

For the getBearerToken parameter, pass in a helper function that retrieves a Skyflow bearer token from your backend. This function will be invoked when the SDK needs to insert or retrieve data from the vault. A sample implementation is shown below:

For example, if the response of the consumer tokenAPI is in the below format

{
'accessToken': string,
'tokenType': string
}

then, your getBearerToken Implementation should be as below

constgetBearerToken=()=>{returnnewPromise((resolve,reject)=>{constHttp=newXMLHttpRequest()Http.onreadystatechange=()=>{if(Http.readyState===4){if(Http.status===200){constresponse=JSON.parse(Http.responseText)resolve(response.accessToken)}else{reject('Error occurred')}}}Http.onerror=(error)=>{reject('Error occurred')}consturl='https://api.acmecorp.com/skyflowToken'Http.open('GET',url)Http.send()})}

For logLevel parameter, there are 4 accepted values in LogLevel

  • DEBUG

    When LogLevel.DEBUG is passed, all level of logs will be printed(DEBUG, INFO, WARN, ERROR).

  • INFO

    When LogLevel.INFO is passed, INFO logs for every event that has occurred during the SDK flow execution will be printed along with WARN and ERROR logs.

  • WARN

    When LogLevel.WARN is passed, WARN and ERROR logs will be printed.

  • ERROR

    When LogLevel.ERROR is passed, only ERROR logs will be printed.

Note:

  • The ranking of logging levels is as follows : DEBUG < INFO < WARN < ERROR
  • Since logLevel is optional, by default the logLevel will be ERROR.

For env parameter, there are 2 accepted values in Env

  • PROD

  • DEV

    In Event Listeners, actual value of element can only be accessed inside the handler when the env is set to DEV.

Note:

  • Since env is optional, by default the env will be PROD.
  • Use env option with caution, make sure the env is set to PROD when using skyflow-react-js in production.

Securely collecting data client-side

Using Skyflow Elements to collect data

Skyflow Elements provide developers with pre-built form elements to securely collect sensitive data client-side. These elements are hosted by Skyflow and injected into your web page as iFrames. This reduces your PCI compliance scope by not exposing your front-end application to sensitive data. Follow the steps below to securely collect data with Skyflow Elements.

Step 1: Create a container

First create a container for the form elements using the useCollectContainer hook as shown below:

constcontainer=useCollectContainer()

Step 2: Create a collect Element

import{CardNumberElement}from'skyflow-react-js';<CardNumberElementtable='<TABLE_NAME>'container='<CONTAINER>'column='<COLUMN_NAME>'props/>

The following props can be passed to Skyflow collect Element:

{
container: 'CollectContainer'// Required, the collect container.table: 'string',// Required, the table this data belongs to.column: 'string',// Required, the column into which this data should be inserted.id: string,// Optional, id that can passed to the element.classes: {},// Optional, styles that should be applied to the element.label: 'string',// Optional, label for the form element.placeholder: 'string',// Optional, placeholder for the form element.validations: [],// Optional, array of validation rules.options: {},// Optional, options that can be passed to an element.onChange: Function,// Optional, function that is passed to trigger the onChange event.onFocus: Function,// Optional, function that is passed to trigger the onFocus event.onBlur: Function,// Optional, function that is passed to trigger the onBlur event.onReady: Function,// Optional, function that is passed to trigger the onReady event.}

The table and column fields indicate which table and column in the vault the Element corresponds to.

Note:

  • Use dot delimited strings to specify columns nested inside JSON fields (e.g. address.street.line1)

All elements can be styled using JSS syntax.

An example of styling an element with makeSkyflowStyles hook :

import{useMakeSkyflowStyles}from'skyflow-react-js'constuseSkyflowStyles=useMakeSkyflowStyles({inputStyles: {base: {color: '#013370',fontFamily: '"Roboto", sans-serif'// ...otherStyles},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},copyIcon: {position: 'absolute',right: '8px',},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}},labelStyles: {base: {color: '#0D4370',// ...otherStyles},},errorTextStyles: {base: {color: '#f44336',// ...otherStyles},},})

The inputStyles field accepts a style object which consists of CSS properties that should be applied to the form element in the following states:

  • base: all other variants inherit from these styles.
  • complete: applied when the Element has valid input.
  • empty: applied when the Element has no input.
  • focus: applied when the Element has focus.
  • invalid: applied when the Element has invalid input.
  • cardIcon: applied to the card type icon in CARD_NUMBER Element.
  • copyIcon: applied to copy icon in Elements when enableCopy option is true.
  • global: used for global styles like font-family.

The states that are available for labelStyles are base, focus, global and requiredAsterisk.

  • requiredAsterisk: styles applied for the Asterisk symbol in the label.

An example of a labelStyles object:

labelStyles: {base: {fontSize: '12px',fontWeight: 'bold'},focus: {color: '#1d1d1d'},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',},requiredAsterisk:{color: 'red'}}

The state that is available for errorTextStyles are base and global, it shows up when there is some error in the collect element.

An example of a errorTextStyles object:

errorTextStyles: {base: {color: '#f44336',fontFamily: '"Roboto", sans-serif'},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}}

We support the following collect elements in the react SDK:

  • CardHolderNameElement
  • CardNumberElement
  • ExpirationDateElement
  • CVVElement
  • PinElement
  • ExpirationDateElement
  • ExpirationMonthElement
  • ExpirationYearElement
  • InputFieldElement
  • FileInputElement

The InputFieldElement type is a custom UI element without any built-in validations. See the section on validations for more information on validations.

Along with Collect Element we can define other options which takes a object of optional parameters as described below:

constoptions={required: false,// Optional, indicates whether the field is marked as required. Defaults to 'false'.enableCardIcon: true,// Optional, indicates whether card icon should be enabled (only applicable for CARD_NUMBER ElementType).format: String,// Optional, format for the element.translation: {},// Optional, indicates the allowed data type value for format. enableCopy: false,// Optional, enables the copy icon in collect and reveal elements to copy text to clipboard. Defaults to 'false').allowedFileType: string[],// Optional, allowed extensions for the file to be uploaded.cardMetadata: {},// Optional, metadata to control card number element behavior. (only applicable for CARD_NUMBER ElementType).masking: true,// Optional, indicates whether the input should be masked. Defaults to 'false'.maskingChar: '*',// Optional, character used for masking input when masking is enabled. Defaults to '*'.}
  • required parameter indicates whether the field is marked as required or not. If not provided, it defaults to false

  • enableCardIcon parameter indicates whether the icon is visible for the CARD_NUMBER element, defaults to true

  • enableCopy parameter indicates whether the copy icon is visible in collect and reveal elements.

  • allowedFileType parameter indicates the allowedFileType extensions to be uploaded.

  • format: A string value that indicates the format pattern applicable to the element type. Only applicable to EXPIRATION_DATE, CARD_NUMBER, EXPIRATION_YEAR, and INPUT_FIELD elements.

    - For INPUT_FIELD elements,
    - the length of `format` determines the expected length of the user input.
    - if `translation` isn't specified, the `format` value is considered a string literal.
    

    translation: An object of key value pairs, where the key is a character that appears in format and the value is a simple regex pattern of acceptable inputs for that character. Each key can only appear once. Only applicable for INPUT_FIELD elements.

    Accepted values by element type:

    Element typeformat and translation valuesExamples
    EXPIRATION_DATE
  • format
    • mm/yy (default)
    • mm/yyyy
    • yy/mm
    • yyyy/mm
    • 12/27
    • 12/2027
    • 27/12
    • 2027/12
    EXPIRATION_YEAR
  • format
    • yy (default)
    • yyyy
    • 27
    • 2027
    CARD_NUMBER
  • format
    • XXXX XXXX XXXX XXXX (default)
    • XXXX-XXXX-XXXX-XXXX
    • 1234 5678 9012 3456
    • 1234-5678-9012-3456
    INPUT_FIELD
  • format: A string that matches the desired output, with placeholder characters of your choice.
  • translation: An object of key/value pairs. Defaults to {"X": "[0-9]"}
  • With a format of +91 XXXX-XX-XXXX and a translation of {"X": "[0-9]"}, user input of "1234121234" displays as "+91 1234-12-1234".

    Note: If format isn't specified or receives an invalid value, it uses the element type's default value.

    Collect Element Options examples for INPUT_FIELD

    Example 1

    constoptions={format:'+91 XXXX-XX-XXXX',translation: {'X': '[0-9]'}}

    User input: "1234121234" Value displayed in INPUT_FIELD: "+91 1234-12-1234"

    Example 2

    constoptions={required: true,enableCardIcon: true,format: 'AY XX-XXX-XXXX',translation: {'X': '[0-9]','Y': '[A-Z]'}}

    User input: "B123412124" Value displayed in INPUT_FIELD: "AB 12-341-2124"

  • cardMetadata: An object of metadata keys to control card number element behavior. It supports an optional key called scheme, which accepts an array of Skyflow accept card types based on which SDK will display card brand choice dropdown in the card number element. CardType is an enum with all skyflow supported card schemes.

importReactfrom'react';import{CardType}from'skyflow-react-js'constcardMetadata={scheme: CardType[]// Optional, array of skyflow supported card types.}
Supported card types by CardType :
  • VISA
  • MASTERCARD
  • AMEX
  • DINERS_CLUB
  • DISCOVER
  • JCB
  • MAESTRO
  • UNIONPAY
  • HIPERCARD
  • CARTES_BANCAIRES

masking : A boolean value for whether to mask the input of the element. When masking is enabled, user input will be replaced with a masking character. The default masking character is *, but you can customize masking character using the maskingChar property.

maskingChar: A single character used to mask the input when masking is enabled. Defaults to *, but can be customized to any character of your choice.

Collect Element Options examples for masking:

Example for CVV:

constoptions={required: true,enableCopy: false,masking: true,maskingChar: '•',}

User input: "1234" Value displayed in CVV: "••••"

Example for CARDHOLDER_NAME:

constoptions={required: true,enableCopy: false,masking: true,}

User input: "John Doe" Value displayed in CARDHOLDER_NAME: "********"

Example for CARD_NUMBER:

constoptions={required: true,enableCopy: false,masking: true,maskingChar: '#'}

User input: "4111 1111 1111 1111" Value displayed in CARD_NUMBER: "#### #### #### ####"

Example for PIN:

constoptions={required: true,enableCopy: false,masking: true,maskingChar: '&'}

User input: "98364721" Value displayed in PIN: "&&&&&&&&"

Note:

  • Unmasked data will be stored in the vault.

Step 3: Collect data from Elements

When the form is ready to be submitted, call the collect(options?) method on the container object. The options parameter takes a object of optional parameters as shown below:

  • tokens: indicates whether tokens for the collected data should be returned or not. Defaults to 'true'
  • additionalFields: Non-PCI elements data to be inserted into the vault which should be in the records object format.
  • upsert: To support upsert operations while collecting data from Skyflow elements, pass the table and column marked as unique in the table.
constoptions={tokens: true,// Optional, indicates whether tokens for the collected data should be returned. Defaults to 'true'additionalFields: {records: [{table: 'string',// Table into which record should be insertedfields: {column1: 'value',// Column names should match vault column names// ...additional fields here},},// ...additional records here],},// Optionalupsert: [// Upsert operations support in the vault{table: 'string',// Table namecolumn: 'value',// Unique column in the table},],//Optional}container.collect(options)

End to end example of collecting data with Skyflow Elements

importReactfrom'react'import{CardNumberElement,useCollectContainer,useMakeSkyflowStyles}from'skyflow-react-js'constApp=()=>{constcontainer=useCollectContainer()constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'blue',},},})constoptions={enableCopy: true,}constclasses=useStyles()consthandleCollect=()=>{constresponse=container.collect()response.then((res: unknown)=>{console.log(JSON.stringify(res))}).catch((e: unknown)=>{console.log(e)})}return(<divclassName='App'><headerclassName='App-header'><CardNumberElementcontainer={container}table={'cards'}classes={classes}column={'cardNumber'}label={'Collect Card Number'}options={options}/><buttononClick={handleCollect}>Collect</button></header></div>)}exportdefaultApp

Sample Response :

{"records": [{"table": "cards","fields": {"cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1",}}]}

Insert call example with upsert support

importReactfrom'react'import{CardNumberElement,CVVElement,useCollectContainer,useMakeSkyflowStyles,}from'skyflow-react-js'functionApp(){constcontainer=useCollectContainer()constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'blue',},},})constclasses=useStyles()consthandleCollect=()=>{constoptions={tokens: true,upsert: [{table: 'cards',column: 'cardNumber',},],}constresponse=container.collect(options)response.then((res: any)=>{console.log(JSON.stringify(res))}).catch((e: any)=>{console.log(e)})}return(<divclassName='App'><headerclassName='App-header'><CardNumberElementcontainer={container}table={'cards'}classes={classes}column={'cardNumber'}label={'Collect Card Number'}options={options}/><CVVElementcontainer={container}table={'cards'}classes={classes}column={'cvv'}label={'Collect CVV'}options={options}/><buttononClick={handleCollect}>Collect</button></header></div>)}exportdefaultApp

Skyflow returns tokens for the record you just inserted.

{"records": [{"table": "cards","fields": {"cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1","cvv": "l4907186-e7e2-466f-91e5-985e12c2bcbc1"}}]}

Validations:

Skyflow-React which internally uses Skyflow-JS SDK provides two types of validations on Collect Elements

1. Default Validations:

Every Collect Element except of type InputFieldElement has a set of default validations listed below:

  • CARD_NUMBER: Card number validation with checkSum algorithm(Luhn algorithm). Available card lengths for defined card types are [12, 13, 14, 15, 16, 17, 18, 19]. A valid 16 digit card number will be in the format - XXXX XXXX XXXX XXXX
  • CARD_HOLDER_NAME: Name should be 2 or more symbols, valid characters should match pattern - ^([a-zA-Z\\ \\,\\.\\-\\']{2,})$
  • CVV: Card CVV can have 3-4 digits
  • EXPIRATION_DATE: Any date starting from current month. By default valid expiration date should be in short year format - MM/YY
  • PIN: Can have 4-12 digits

2. Custom Validations:

Custom validations can be added to any element which will be checked after the default validations have passed. The following Custom validation rules are currently supported:

  • REGEX_MATCH_RULE: You can use this rule to specify any Regular Expression to be matched with the input field value
constregexMatchRule={type: REGEX_MATCH_RULE,params: {regex: RegExp,error: string,// Optional, default error is 'VALIDATION FAILED'.},}
  • LENGTH_MATCH_RULE: You can use this rule to set the minimum and maximum permissible length of the input field value
constlengthMatchRule={type: LENGTH_MATCH_RULE,params: {min: number,// Optionalmax: number,// Optionalerror: string,// Optional, default error is 'VALIDATION FAILED'.},}
  • ELEMENT_VALUE_MATCH_RULE: You can use this rule to match the value of one element with the value of another element. elementId is the id of the collect element with which you want to compare values. Collect elements must have an id property to compare values.
constelementValueMatchRule={type: ELEMENT_VALUE_MATCH_RULE,params: {elementId: string,// 'id' of element you want to compare values witherror: string// Optional, default error is 'VALIDATION FAILED'.}}

Example usage of custom validations

The sample code snippet for using custom validations:

/* A simple example that illustrates custom validations. Adding REGEX_MATCH_RULE, LENGTH_MATCH_RULE and ELEMENT_VALUE_MATCH_RULE to collect elements.*/import{CardNumberElement,InputFieldElementasPasswordElement,LENGTH_MATCH_RULE,REGEX_MATCH_RULE,ELEMENT_VALUE_MATCH_RULE}from'skyflow-react-js';// This rule allows 1 or more alphabets.constalphabetsOnlyRegexRule={type: REGEX_MATCH_RULE,params: {regex: /^[A-Za-z]+$/,error: 'Only alphabets are allowed'}};// This rule allows input length between 4 and 6 characters.constlengthRule={type: LENGTH_MATCH_RULE,params: {min: 4,max: 6,error: 'Must be between 4 and 6 alphabets'}};// This rule will compare values of passwords entered in InputField elementsconstelementValueMatchRule={type: ELEMENT_VALUE_MATCH_RULE,params: {elementId: 'collectPassword',// 'id' of Password (InputField) elementerror: 'passwords does not match'}}constForm=(props)=>{return(<><CardNumberElementcontainer='COLLECT CONTAINER'table='<TABLE_NAME>'column='<COLUMN_NAME>'validations={[alphabetsOnlyRegexRule,lengthRule]}...props/><PasswordElementid={'collectPassword'}// required, same as passed in element match rulecontainer='COLLECT CONTAINER'table='<TABLE_NAME>'column='<COLUMN_NAME>'...props/><PasswordElementcontainer='COLLECT CONTAINER'table='<TABLE_NAME>'column='<COLUMN_NAME>'validations={[elementValueMatchRule]}// pass rule to element...props/></>);};exportdefaultForm;

Using Skyflow Elements to update data

You can update the data in a vault with Skyflow Elements. Use the following steps to securely update data.

Step 1: Create a container

First create a container for the form elements using the useCollectContainer hook as shown below:

constcontainer=useCollectContainer()

Step 2: Create a collect Element

import{CardNumberElement}from'skyflow-react-js';<CardNumberElementtable='<TABLE_NAME>'container='<CONTAINER>'column='<COLUMN_NAME>'skyflowID='<SKYFLOW_ID>'// The skyflow_id of the record to be updated....props/>

The following props can be passed to Skyflow collect Element:

{
container: 'CollectContainer'// Required, the collect container.table: 'string',// Required, the table this data belongs to.column: 'string',// Required, the column into which this data should be inserted.id: string,// Optional, id that can passed to the element.classes: {},// Optional, styles that should be applied to the element.label: 'string',// Optional, label for the form element.placeholder: 'string',// Optional, placeholder for the form element.validations: [],// Optional, array of validation rules.options: {},// Optional, options that can be passed to an element.onChange: Function,// Optional, function that is passed to trigger the onChange event.onFocus: Function,// Optional, function that is passed to trigger the onFocus event.onBlur: Function,// Optional, function that is passed to trigger the onBlur event.onReady: Function,// Optional, function that is passed to trigger the onReady event.skyflowID: 'string',// The skyflow_id of the record to be updated.}

The table and column fields indicate which table and column in the vault the Element corresponds to.

skyflowID indicates the record that you want to update.

Note:

  • Use dot delimited strings to specify columns nested inside JSON fields (e.g. address.street.line1)

Step 3: Update data from Elements

When the form is ready to be submitted, call the collect(options?) method on the container object. The options parameter takes a object of optional parameters as shown below:

  • tokens: indicates whether tokens for the collected data should be returned or not. Defaults to 'true'
  • additionalFields: Non-PCI elements data to be inserted into the vault which should be in the records object format.
constoptions={tokens: true,// Optional, indicates whether tokens for the collected data should be returned. Defaults to 'true'additionalFields: {records: [{table: 'string',// Table into which record should be insertedfields: {column1: 'value',// Column names should match vault column namesskyflowID: "value",// The skyflow_id of the record to be updated.// ...additional fields here},},// ...additional records here],},// Optional}container.collect(options)

Note:skyflowID is required if you want to update the data using skyflow id. If skyflowID isn't specified, the collect(options?) method creates a new record in the vault.

End to end example of updating data with Skyflow Elements

importReactfrom'react'import{CardNumberElement,useCollectContainer,useMakeSkyflowStyles,CardHolderNameElement}from'skyflow-react-js'constApp=()=>{constcontainer=useCollectContainer()constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'blue',},},})constoptions={enableCopy: true,}constclasses=useStyles()consthandleCollect=()=>{constnonPCIRecords={records: [{table: 'cards',fields: {gender: 'MALE',skyflowID: '431eaa6c-5c15-4513-aa15-29f50babe882',},},],};constresponse=container.collect({tokens: true,additionalFields: nonPCIRecords,});response.then((res: unknown)=>{console.log(JSON.stringify(res))}).catch((e: unknown)=>{console.log(e)})}return(<divclassName='App'><headerclassName='App-header'><CardNumberElementcontainer={container}table={'cards'}classes={classes}column={'cardNumber'}label={'Collect Card Number'}options={options}skyflowID={'431eaa6c-5c15-4513-aa15-29f50babe882'}/><CardHolderNameElementcontainer={container}table={'cards'}column={'name'}label={'card holder name'}skyflowID={'431eaa6c-5c15-4513-aa15-29f50babe882'}/><buttononClick={handleCollect}>Collect</button></header></div>)}exportdefaultApp

Sample Response :

{"records": [{"table": "cards","fields": {"skyflow_id": "431eaa6c-5c15-4513-aa15-29f50babe882","cardNumber": "f3907186-e7e2-466f-91e5-48e12c2bcbc1","first_name": "131e70dc-6f76-4319-bdd3-96281e051051","gender": "12f670af-6c7d-4837-83fb-30365fbc0b1e"}}]}

Event Listener on Collect Elements

Helps to communicate with Skyflow elements / iframes by listening to an event. Event listeners can be triggered by passing the handler methods as props to the Element components.

There are 4 events which SDK supports:

  • CHANGE
    Change event is triggered when the Element's value changes.

  • READY
    Ready event is triggered when the Element is fully rendered

  • FOCUS
    Focus event is triggered when the Element gains focus

  • BLUR
    Blur event is triggered when the Element loses focus.

The handler function(state) => void is a callback function you provide, that will be called when the event is fired with the state object as shown below.

state: {
elementType: Skyflow.ElementType
isEmpty: boolean
isFocused: boolean
isValid: boolean
value: string
selectedCardScheme: CardType// only for CARD_NUMBER element type}

Note:

  • Values of SkyflowElements will be returned in element state object only when env is DEV, else it is empty string i.e, '', but in case of CARD_NUMBER type element when the env is PROD for all the card types except AMEX, it will return first eight digits, for AMEX it will return first six digits and rest all digits in masked format.
    • selectedCardScheme will exist for CARD_NUMBER element state and the value of CardType will be only populated when cardbrand choice selection is triggered otherwise, it will always be an empty string.

Example Usage of Event Listener on Collect Elements

importReactfrom'react'import{CardNumberElement,CardHolderNameElement,useCollectContainer}from'skyflow-react-js'constApp=()=>{constcontainer=useCollectContainer()consthandleCollect=()=>{constresponse=container.collect()response.then((res: unknown)=>{console.log(JSON.stringify(res))}).catch((e: unknown)=>{console.log(e)})}consthandleOnChange=(changeState: unknown)=>{console.log('Change',changeState)}consthandleOnBlur=(changeState: unknown)=>{console.log('Blur',changeState)}return(<divclassName='App'><headerclassName='App-header'><CardNumberElementcontainer={container}table={'table1'}column={'card_number'}label={'Collect Card Number'}onChange={handleOnChange}onBlur={handleOnBlur}/><CardHolderNameElementcontainer={container}table={'table1'}column={'first_name'}label={'Collect Card Holder Name'}onChange={handleOnChange}onBlur={handleOnBlur}/><buttononClick={handleCollect}>Collect</button></header></div>)}exportdefaultApp

Sample Element state object when env is DEV

{elementType: 'CARDHOLDER_NAME',isEmpty: false,isFocused: true,isValid: true,value: 'John',};{elementType: 'CARD_NUMBER',isEmpty: false,isFocused: true,isValid: true,value: '4111111111111111',};

Sample Element state object when env is PROD

{elementType: 'CARDHOLDER_NAME',isEmpty: false,isFocused: true,isValid: true,value: '',};{elementType: 'CARD_NUMBER',isEmpty: false,isFocused: true,isValid: true,value: '41111111XXXXXXXX',};

Override default error Messages

You can override the default error messages with custom ones by using setErrorOverride. This is especially useful to override default error messages in non-English languages.

To override error messages dynamically, you need to:

  1. Create a ref using React.useRef.

  2. Pass the ref to the Skyflow element for which you want to set the custom error.

  3. Use setErrorOverride on ref.current to set the custom message.

setErrorOverride overrides the default error message when the value is invalid. The error resets automatically when the value becomes valid.

import{CardNumberElement,useCollectContainer,CardHolderNameElement,SkyflowCollectElementRef,}from'skyflow-react-js';constCollectElements=()=>{constcontainer=useCollectContainer();constcardNumberRef=React.useRef<SkyflowCollectElementRef|null>(null);constcardholderNameRef=React.useRef<SkyflowCollectElementRef|null>(null);constonCardNumberBlur=(state: any)=>{if(state.isEmpty){//can override the message when the field is required and emptycardNumberRef.current?.setErrorOverride("custom error for required");}elseif(!state.isValid){//can override the message when the input is invalidcardNumberRef.current?.setErrorOverride("custom error for invalid number");}}constonCardholderNameBlur=(state: any)=>{if(state.isEmpty){//can override the message when the field is required and emptycardNameRef.current?.setErrorOverride("custom error for required");}elseif(!state.isValid){//can override the message when the input is invalidcardNameRef.current?.setErrorOverride("custom error for invalid name");}}return(<div><CardNumberElementid={'collectCardNumber'}container={container}table={'table1'}column={'card_number'}label='Card number'ref={cardNumberRef}options={{required:true}}onBlur={onCardNumberBlur}/><CardHolderNameElementid={'collectCardName'}container={container}table={'table1'}column={'cardholder_name'}label='Name'ref={cardNameRef}options={{required:true}}onBlur={onCardholderNameBlur}/></div>)}

Note:

  • Maintain different references for different elements.
  • setErrorOverride can only override default error messages.
  • setErrorOverride can only be used in BLUR event listener as shown in the above example.

Using Skyflow File Input Element to upload a file

You can upload binary files to a vault using the Skyflow File Input Element. Use the following steps to securely upload a file.

Step 1: Create a container

First create a container for the form elements using the useCollectContainer hook as shown below:

constcontainer=useCollectContainer()

Step 2: Create a File Input Element

import{FileInputElement}from'skyflow-react-js';<FileInputElementtable='<TABLE_NAME>'column='<COLUMN_NAME>'skyflowID='<SKYFLOW_ID>'...props/>

The following props can be passed to file input element:

{
container: 'CollectContainer'// Required, the collect container.table: 'string',// Required, the table this data belongs to.column: 'string',// Required, the column into which this data should be inserted.skyflowID: 'string',//Required, skyflowID of the record that stores the file.id: 'string',// Optional, id that can passed to the element.classes: {},// Optional, styles that should be applied to the element.label: 'string',// Optional, label for the form element.validations: [],// Optional, array of validation rules.options: {},// Optional, options that can be passed to an element.}

The table and column fields indicate which table and column the Element corresponds to.

skyflowID indicates the record that stores the file.

Notes:

  • skyflowID is required while creating File element
  • Use period-delimited strings to specify columns nested inside JSON fields (e.g. address.street.line1).

Step 3: Collect data from elements

When the file is ready to be uploaded, call the uploadFiles() method on the container object.

container.uploadFiles(options);

File upload limitations:

  • Only non-executable file are allowed to be uploaded.
  • Files must have a maximum size of 32 MB
  • File columns can't enable tokenization, redaction, or arrays.
  • Re-uploading a file overwrites previously uploaded data.
  • Partial uploads or resuming a previous upload isn't supported.

End-to-end file upload

importReactfrom'react'import{FileInputElement,useCollectContainer,useMakeSkyflowStyles}from'skyflow-react-js'constApp=()=>{constcontainer=useCollectContainer()constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'blue',},},})constclasses=useStyles()consthandleUpload=()=>{constresponse=container.uploadFiles({})response.then((res: unknown)=>{console.log(JSON.stringify(res))}).catch((e: unknown)=>{console.log(e)})}return(<divclassName='App'><headerclassName='App-header'><FileInputElementcontainer={container}table={'newTable'}skyflowID={'431eaa6c-5c15-4513-aa15-29f50babe882'}column={'file_input'}label={'File Input'}classes={classes}/><buttononClick={handleUpload}>upload File</button></header></div>)}exportdefaultApp

Sample Response :

{fileUploadResponse: [{"skyflow_id": "431eaa6c-5c15-4513-aa15-29f50babe882"}]}

File upload with allowedFileType option

importReactfrom'react';import{CardNumberElement,useCollectContainer,useMakeSkyflowStyles,FileInputElement,}from'skyflow-react-js';constCollectElements=()=>{constcontainer=useCollectContainer();consthandleCollect=()=>{constresponse=container.collect();response.then((res: unknown)=>{console.log(JSON.stringify(res));}).catch((e: unknown)=>{console.log(e);});};constoptions={allowedFileType: [".pdf",".png"]};consthandleFile=()=>{constresponse=container.uploadFiles({});response.then((res: unknown)=>{console.log(JSON.stringify(res));}).catch((e: unknown)=>{console.log(e);});};constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'red',},},});constclasses=useStyles();return(<divclassName='CollectElements'style={{width: '300px'}}><CardNumberElementid={'collectCardNumber'}container={container}table={'newTable'}classes={classes}column={'card_number'}label={'Collect Card Number'}/><FileInputElementid='file-input'container={container}classes={classes}table={'newTable'}column={'file_input'}label={'File Input'}skyflowID={'431eaa6c-5c15-4513-aa15-29f50babe882'}options={options}/><buttononClick={handleFile}>Submit file</button><buttononClick={handleCollect}>Collect</button></div>);};exportdefaultCollectElements;

Sample Response for collect():

{"records": [{"table": "newTable","fields": {"card_number": "f3907186-e7e2-466f-91e5-48e12c2bcbc1",}}]}

Sample Response for file uploadFiles() :

{"fileUploadResponse": [{"skyflow_id": "431eaa6c-5c15-4513-aa15-29f50babe882"}]}

File upload with additional elements

importReactfrom'react';import{CardNumberElement,useCollectContainer,useMakeSkyflowStyles,FileInputElement,}from'skyflow-react-js';constCollectElements=()=>{constcontainer=useCollectContainer();consthandleCollect=()=>{constresponse=container.collect();response.then((res: unknown)=>{console.log(JSON.stringify(res));}).catch((e: unknown)=>{console.log(e);});};consthandleFile=()=>{constresponse=container.uploadFiles({});response.then((res: unknown)=>{console.log(JSON.stringify(res));}).catch((e: unknown)=>{console.log(e);});};constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',},},errorTextStyles: {base: {color: 'red',},},});constclasses=useStyles();return(<divclassName='CollectElements'style={{width: '300px'}}><CardNumberElementid={'collectCardNumber'}container={container}table={'newTable'}classes={classes}column={'card_number'}label={'Collect Card Number'}/><FileInputElementid='file-input'container={container}classes={classes}table={'newTable'}column={'file_input'}label={'File Input'}skyflowID={'431eaa6c-5c15-4513-aa15-29f50babe882'}/><buttononClick={handleFile}>Submit file</button><buttononClick={handleCollect}>Collect</button></div>);};exportdefaultCollectElements;

Sample Response for collect():

{"records": [{"table": "newTable","fields": {"card_number": "f3907186-e7e2-466f-91e5-48e12c2bcbc1",}}]}

Sample Response for file uploadFiles() :

{"fileUploadResponse": [{"skyflow_id": "431eaa6c-5c15-4513-aa15-29f50babe882"}]}

Securely collecting data client-side using Composable Elements

Composable Elements combine multiple Skyflow Elements in a single iframe, letting you create multiple Skyflow Elements in a single row. The following steps create a composable element and securely collect data through it.

Step 1: Create a composable container

Create a container for the composable element using the useComposableContainer hook of the Skyflow client:

constcontainer=useComposableContainer(containerOptions)

The container requires an options object that contains the following keys:

  • layout: An array that indicates the number of rows in the container and the number of elements in each row. The index value of the array defines the number of rows, and each value in the array represents the number of elements in that row, in order.

    For example: [2,1] means the container has two rows, with two elements in the first row and one element in the second row.

    Note: The sum of values in the layout array should be equal to the number of elements created

  • styles: CSS styles to apply to the composable container.

  • errorTextStyles: CSS styles to apply if an error is encountered.

constoptions={layout: [2,1],// Requiredstyles: {// Optionalbase: {border: '1px solid #DFE3EB',padding: '8px',borderRadius: '4px',margin: '12px 2px',},},errorTextStyles: {// Optionalbase: {color: 'red',fontFamily: '"Roboto", sans-serif'},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}},};

Step 2: Create Composable Elements

Composable Elements use the following format. Create other elements within the Composable Element.

import{ComposableContainer,CardHolderNameElement,CardNumberElement,}from"skyflow-react-js";<ComposableContainerid="<ID>"container="<CONTAINER>"><CardHolderNameElementid="<ID>"table="<TABLE_NAME>"container="<CONTAINER>"column="<COLUMN_NAME>"...props/><CardNumberElementid="<ID>"table="<TABLE_NAME>"container="<CONTAINER>"column="<COLUMN_NAME>"...props/></ComposableContainer>

The following props can be passed to Skyflow Composable Element:

{
container: 'ComposableContainer'// Required, the Composable Container.table: 'string',// Required, the table this data belongs to.column: 'string',// Required, the column into which this data should be inserted.id: string,// Optional, id that can passed to the element.classes: {},// Optional, styles that should be applied to the element.label: 'string',// Optional, label for the form element.placeholder: 'string',// Optional, placeholder for the form element.validations: [],// Optional, array of validation rules.options: {},// Optional, options that can be passed to an element.onChange: Function,// Optional, function that is passed to trigger the onChange event.onFocus: Function,// Optional, function that is passed to trigger the onFocus event.onBlur: Function,// Optional, function that is passed to trigger the onBlur event.onReady: Function,// Optional, function that is passed to trigger the onReady event.}

The table and column fields indicate which table and column in the vault the Element correspond to.

Note: Use dot-delimited strings to specify columns nested inside JSON fields (for example, address.street.line1).

All elements can be styled with JSS syntax.

An example of styling an element with makeSkyflowStyles hook:

constuseSkyflowStyles=makeSkyflowStyles({inputStyles: {base: {color: "#013370",// ...otherStyles},complete: {color: "#4caf50",},empty: {},focus: {},invalid: {},cardIcon: {position: "absolute",left: "8px",bottom: "calc(50% - 12px)"},copyIcon: {position: "absolute",right: "8px",}},labelStyles: {base: {color: "#0D4370",// ...otherStyles}},errorTextStyles: {base: {color: "#f44336",// ...otherStyles}}})

The inputStyles field accepts an object of CSS properties to apply to the form element in the following states:

  • base: all variants inherit from these styles
  • complete: applied when the Element has valid input
  • empty: applied when the Element has no input
  • focus: applied when the Element has focus
  • invalid: applied when the Element has invalid input
  • cardIcon: applied to the card type icon in CARD_NUMBER Element
  • copyIcon: applied to copy icon in Elements when enableCopy option is true
  • global: used for global styles like font-family

An example of an inputStyles object:

inputStyles: {base: {border: '1px solid #eae8ee',padding: '10px 16px',borderRadius: '4px',color: '#1d1d1d',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},copyIcon: {position: 'absolute',right: '8px',},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}}

The labelStyles field supports the base, focus, global.

  • requiredAsterisk: styles applied for the Asterisk symbol in the label.

An example labelStyles object:

labelStyles: {base: {fontSize: '12px',fontWeight: 'bold'},focus: {color: '#1d1d1d'},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}}

The React SDK supports the following composable elements:

  • CardHolderNameElement
  • CardNumberElement
  • ExpirationDateElement
  • CVVElement
  • PinElement
  • ExpirationDateElement
  • ExpirationMonthElement
  • ExpirationYearElement
  • InputFieldElement

Note: Only when the entered value in the below composable elements is valid, the focus shifts automatically. The element types are:

  • CardNumberElement
  • ExpirationDateElement
  • ExpirationMonthElement
  • ExpirationYearElement

The InputFieldElement type is a custom UI element without any built-in validations. For information on validations, see validations.

Along with the Composable Element definition, you can define additional options for the element:

constoptions={required: false,// Optional, indicates whether the field is marked as required. Defaults to 'false'enableCardIcon: true,// Optional, indicates whether card icon should be enabled (only applicable for CARD_NUMBER ElementType)format: String,// Optional, format for the element (only applicable currently for EXPIRATION_DATE ElementType),enableCopy: false// Optional, enables the copy icon in collect and reveal elements to copy text to clipboard. Defaults to 'false')}
  • required: Whether or not the field is marked as required. Defaults to false.
  • enableCardIcon: Whether or not the icon is visible for the CARD_NUMBER element. Defaults to true.
  • format: Format pattern for the element. Only applicable to EXPIRATION_DATE and EXPIRATION_YEAR element types.
  • enableCopy: Whether or not the copy icon is visible in collect and reveal elements. Defaults to false.

The accepted EXPIRATION_DATE values are

  • MM/YY (default)
  • MM/YYYY
  • YY/MM
  • YYYY/MM

The accepted EXPIRATION_YEAR values are

  • YY (default)
  • YYYY

Step 3: Collect data from Elements

When the form is ready to be submitted, call the collect(options?) method on the container object. The options parameter takes an object of optional parameters as follows:

  • tokens: Whether or not tokens for the collected data are returned. Defaults to 'true'
  • additionalFields: Non-PCI elements data to insert into the vault, specified in the records object format.
  • upsert: To support upsert operations, the table containing the data and a column marked as unique in that table.
constoptions={tokens: true,// Optional, indicates whether tokens for the collected data should be returned. Defaults to 'true'.additionalFields: {records: [{table: 'string',// Table into which record should be inserted.fields: {column1: 'value',// Column names should match vault column names.// ...additional fields here.},},// ...additional records here.],},// Optionalupsert: [// Upsert operations support in the vault {table: 'string',// Table namecolumn: 'value',// Unique column in the table},],// Optional};

End to end example of collecting data with Composable Elements:

importReactfrom'react';import{CardNumberElement,CVVElement,useMakeSkyflowStyles,useComposableContainer,ComposableContainer,CardHolderNameElement,}from'skyflow-react-js';constCollectElements=()=>{constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {fontFamily: 'Inter',fontStyle: 'normal',fontWeight: 400,fontSize: '14px',lineHeight: '21px',color: '#1d1d1d',padding: '0px 16px'},complete: {color: '#4caf50',}},empty: {},focus: {},invalid: {color: '#f44336',},});constuseCVVStyles=useMakeSkyflowStyles({inputStyles: {base: {fontFamily: 'Inter',fontStyle: 'normal',fontWeight: 400,fontSize: '14px',lineHeight: '21px',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},},labelStyles: {},errorTextStyles: {base: {display: 'none'},},})constclasses=useStyles();constcvvClasses=useCVVStyles();constcontainerOptions={layout: [1,2],styles: {base: {border: '1px solid #DFE3EB',padding: '8px',borderRadius: '4px',margin: '12px 2px',}},errorTextStyles: {base: {color: '#f44336'}}}constcontainer=useComposableContainer(containerOptions);consthandleCollect=()=>{constoptions={tokens: true}constresponse=container?.collect(options);response?.then((res: any)=>{console.log(JSON.stringify(res));}).catch((e: any)=>{console.log(e);});};return(<divclassName='CollectElements'><ComposableContainerid='composecontainer'container={container}><CardHolderNameElementid='collectCardHolderName'container={container}table='pii_fields'classes={classes}placeholder='Cardholder Name'column='first_name'/><CardNumberElementid='collectCardNumber'container={container}table='pii_fields'classes={classes}placeholder='XXXX XXXX XXXX XXXX'column='card_number'/><CVVElementid='cvv'container={container}table='pii_fields'classes={cvvClasses}placeholder='CVC'column='cvv'/></ComposableContainer><buttononClick={handleCollect}>Collect</button></div>);};exportdefaultCollectElements;

Sample Response:

{"records": [{"table": "pii_fields","fields": {"first_name": "63b5eeee-3624-493f-825e-137a9336f882","card_number": "f3907186-e7e2-466f-91e5-48e12c2bcbc1","cvv": "7baf5bda-aa22-4587-a5c5-412f6f783a19",}}]}

For information on validations, see validations.

Set an event listener on Composable Elements:

You can communicate with Skyflow Elements by listening to element events:

The SDK supports four events:

  • CHANGE: Triggered when the Element's value changes.
  • READY: Triggered when the Element is fully rendered.
  • FOCUS: Triggered when the Element gains focus.
  • BLUR: Triggered when the Element loses focus.

The handler function(state) => void is a callback function you provide that's called when the event is fired with a state object that uses the following schema:

state : {
elementType: Skyflow.ElementType
isEmpty: boolean isFocused: boolean
isValid: boolean
value: string}

Note: Events only include element values when in the state object when env is DEV. By default, value is an empty string.

Example Usage of Event Listener on Composable Elements

importReactfrom'react';import{CardNumberElement,CVVElement,useMakeSkyflowStyles,useComposableContainer,ComposableContainer,CardHolderNameElement,}from'skyflow-react-js';constCollectElements=()=>{constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {fontFamily: 'Inter',fontStyle: 'normal',fontWeight: 400,fontSize: '14px',lineHeight: '21px',color: '#1d1d1d',padding: '0px 16px'},complete: {},empty: {},focus: {},invalid: {},},labelStyles: {},errorTextStyles: {base: {display: 'none'},},});constclasses=useStyles();consthandleOnChange=(changeState: any)=>{console.log('Value',changeState);};consthandleOnBlur=(changeState: any)=>{console.log('Blur',changeState);};consthandleOnFocus=(changeState: any)=>{console.log('Focus',changeState);};consthandleOnReady=(changeState: any)=>{console.log('Ready',changeState);}constcontainerOptions={layout: [1,2],styles: {base: {border: '1px solid #DFE3EB',padding: '8px',borderRadius: '4px',margin: '12px 2px',}}}constcontainer=useComposableContainer(containerOptions);consthandleCollect=()=>{constresponse=container?.collect();response?.then((res: any)=>{console.log(JSON.stringify(res));}).catch((e: any)=>{console.log(e);});};return(<divclassName='CollectElements'><ComposableContainerid='composecontainer'container={container}><CardHolderNameElementid='collectCardHolderName'container={container}table='pii_fields'classes={classes}placeholder='Cardholder Name'column='first_name'onChange={handleOnChange}onBlur={handleOnBlur}onFocus={handleOnFocus}onReady={handleOnReady}/><CardNumberElementid='collectCardNumber'container={container}table='pii_fields'classes={classes}placeholder='XXXX XXXX XXXX XXXX'column='card_number'onChange={handleOnChange}onBlur={handleOnBlur}onFocus={handleOnFocus}onReady={handleOnReady}/><CVVElementid='cvv'container={container}table='pii_fields'classes={classes}placeholder='CVC'column='cvv'onChange={handleOnChange}onBlur={handleOnBlur}onFocus={handleOnFocus}onReady={handleOnReady}/></ComposableContainer><buttononClick={handleCollect}>Collect</button></div>);};exportdefaultCollectElements;

Set an event listener on a composable container

Currently, the SDK supports one event:

  • SUBMIT: Triggered when the Enter key is pressed in any container element.

The handler function(void) => void is a callback function you provide that's called when the `SUBMIT' event fires.

Example usage of event listener on composable container

importReactfrom'react';import{CardNumberElement,CVVElement,useMakeSkyflowStyles,useComposableContainer,ComposableContainer,CardHolderNameElement,}from'skyflow-react-js';constComposableElements=()=>{constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {color: '#1d1d1d',},},labelStyles: {},errorTextStyles: {base: {display: 'none'},},});constclasses=useStyles();consthandleOnSubmit=()=>{// Your implementation when the SUBMIT(enter) event occurs.console.log('Submit Event Listener is being Triggered.');};constcontainerOptions={layout: [1,2],styles: {base: {border: '1px solid #DFE3EB',padding: '8px',borderRadius: '4px',margin: '12px 2px',}}}constcontainer=useComposableContainer(containerOptions);consthandleCollect=()=>{constresponse=container?.collect();response?.then((res: any)=>{console.log(JSON.stringify(res));}).catch((e: any)=>{console.log(e);});};return(<divclassName='CollectElements'><ComposableContainerid='composecontainer'container={container}onSubmit={handleOnSubmit}// Pass onSubmit handler.><CardHolderNameElementid='collectCardHolderName'container={container}table='pii_fields'classes={classes}placeholder='Cardholder Name'column='first_name'/><CardNumberElementid='collectCardNumber'container={container}table='pii_fields'classes={classes}placeholder='XXXX XXXX XXXX XXXX'column='card_number'/><CVVElementid='cvv'container={container}table='pii_fields'classes={classes}placeholder='CVC'column='cvv'/></ComposableContainer><buttononClick={handleCollect}>Collect</button></div>);};exportdefaultComposableElements;

Securely revealing data client-side

Retrieving data from the vault

For non-PCI use-cases, retrieving data from the vault and revealing it in the browser can be done either using the SkyflowID's, unique column values as described below

  • Using Skyflow ID's or Unique Column Values

    You can retrieve data from the vault with the get(records) method using either Skyflow IDs or unique column values.

    The records parameter accepts a JSON object that contains an array of either Skyflow IDs or unique column names and values.

    Note: You can use either Skyflow IDs or unique values to retrieve records. You can't use both at the same time.

    Skyflow.RedactionTypes accepts four values:

    • PLAIN_TEXT
    • MASKED
    • REDACTED
    • DEFAULT

    You must apply a redaction type to retrieve data.

Schema (Skyflow IDs)

data={records: [{ids: ["SKYFLOW_ID_1","SKYFLOW_ID_2"],// List of skyflow_ids for the records to fetch.table: "NAME_OF_SKYFLOW_TABLE",// Name of table holding the records in the vault.redaction: Skyflow.RedactionType,// Redaction type to apply to retrieved data.},],};

Schema (Unique column values)

data={records: [{table: "NAME_OF_SKYFLOW_TABLE",// Name of table holding the records in the vault.columnName: "UNIQUE_COLUMN_NAME",// Unique column name in the vault.columnValues: [// List of given unique column values. "<COLUMN_VALUE_2>","<COLUMN_VALUE_3>",],// Required when specifying a unique columnredaction: Skyflow.RedactionType,// Redaction type applies to retrieved data.},],};

Example usage (Skyflow IDs)

importReactfrom'react';import{useSkyflow}from'skyflow-react-js';constGetRecords=()=>{constskyflow=useSkyflow()consthandleGetMethod=()=>{constresponse=skyflow.get({records: [{ids: ['f8d8a622-b557-4c6b-a12c-c5ebe0b0bfd9'],table: 'cards',redaction: Skyflow.RedactionType.PLAIN_TEXT,},{ids: ["da26de53-95d5-4bdb-99db-8d8c66a35ff9"],table: "contacts",redaction: Skyflow.RedactionType.PLAIN_TEXT,},],});response.then((res: any)=>{console.log(res)}).catch((e: any)=>{console.log(e)});}return(<divid='get-div'><buttonid='get-button'onClick={callGet}> Get Records </button></div>)}

Example response

{"records": [{"fields": {"card_number": "4111111111111111","cvv": "127","expiry_date": "11/2035","fullname": "myname","id": "f8d8a622-b557-4c6b-a12c-c5ebe0b0bfd9"},"table": "cards"}],"errors": [{"error": {"code": "404","description": "No Records Found"},"ids": ["da26de53-95d5-4bdb-99db-8d8c66a35ff9"]}]}

Example usage (Unique column values)

importReactfrom'react';import{useSkyflow}from'skyflow-react-js';constGetRecords=()=>{constskyflow=useSkyflow()consthandleGetMethod=()=>{constresponse=skyflow.get({records: [{table: "cards",redaction: RedactionType.PLAIN_TEXT,columnName: "card_id",columnValues: ["123","456"],}],});response.then((res: any)=>{console.log(res)}).catch((e: any)=>{console.log(e)});}return(<divid='get-div'><buttonid='get-button'onClick={callGet}> Get Records </button></div>)}

Sample response:

{"records": [{"fields": {"card_id": "123","expiry_date": "11/35","fullname": "myname","id": "f8d2-b557-4c6b-a12c-c5ebfd9"},"table": "cards"},{"fields": {"card_id": "456","expiry_date": "10/23","fullname": "sam","id": "da53-95d5-4bdb-99db-8d8c5ff9"},"table": "cards"}]}

Using Skyflow Elements to reveal data

Skyflow Elements can be used to securely reveal data in a browser without exposing your front end to the sensitive data. This is great for use cases like card issuance where you may want to reveal the card number to a user without increasing your PCI compliance scope.

Step 1: Create a container

To start, create a container using the useRevealContainer() method of the Skyflow client as shown below.

constrevealContainer=useRevealContainer()

Step 2: Create a reveal element

import{RevealElement}from'skyflow-react-js';importSkyflowfrom'skyflow-js';<RevealElementtoken='<DATA_TOKEN>'container='<CONTAINER>'...props/>

The following props can be passed to Skyflow reveal element:

{container: 'RevealContainer',// Required, the reveal container.token:'string',// Required, the actual data token.id: string,// Optional, id that can passed to the element.classes: {},// Optional, styles that should be applied to the element.label: 'string',// Optional, label for the form element.redaction: Skyflow.RedactionType// Optional. Redaction to apply for retrieved data. E.g. RedactionType.MASKED}

Note:

  • The inputStyles, labelStyles and errorTextStyles parameters accepts a styles object as described in the previous section for collecting data. But for reveal element, inputStyles accepts only base variant and copyIcon and global style objects.
  • redaction defaults to RedactionType.PLAIN_TEXT.

Redaction Types

There are four accepted values for RedactionType:

  • PLAIN_TEXT
  • MASKED
  • REDACTED
  • DEFAULT

End to end example using Reveal Element

importReactfrom'react'import{RevealElement,useRevealContainer,useMakeSkyflowStyles}from'skyflow-react-js'importSkyflowfrom'skyflow-js';constApp=()=>{constrevealContainer=useRevealContainer()constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',fontFamily: '"Roboto", sans-serif'},copyIcon: {position: 'absolute',right: '8px',top: 'calc(50% - 10px)',},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',fontFamily: '"Roboto", sans-serif'},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}},errorTextStyles: {base: {color: 'red',fontFamily: '"Roboto", sans-serif'},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}},})consthandleReveal=()=>{revealContainer.reveal().then((res)=>{console.log(res)}).catch((err)=>{console.log(err)})}constclasses=useStyles()return(<divclassName='App'><headerclassName='App-header'><RevealElementcontainer={revealContainer}token={'1404-8379-9069-7378'}label={'Reveal Card Number'}classes={classes}redaction={Skyflow.RedactionType.MASKED}/><RevealElementcontainer={revealContainer}token={'89024714-6a26-4256-b9d4-55ad69aa4047'}label={'Reveal Card Holder Name'}classes={classes}redaction={Skyflow.RedactionType.DEFAULT}/><buttononClick={handleReveal}>Reveal</button></header></div>)}exportdefaultApp

Sample Response

{"success": [{"token": "1404-8379-9069-7378"}],"errors": [{"token": "89024714-6a26-4256-b9d4-55ad69aa4047","error": {"code": 404,"description": "Tokens not found for 89024714-6a26-4256-b9d4-55ad69aa4047"}}]}

Render a file with a File Element

You can render files using the Skyflow File Element. Use the following steps to securely render a file.

Step 1: Create a container

To start, create a container using the useRevealContainer() method of the Skyflow client as shown below.

constrevealContainer=useRevealContainer()

Step 2: Create a File Element

Define a Skyflow Element to render the file as shown below.

import{FileRenderElement}from'skyflow-react-js';importSkyflowfrom'skyflow-js';<FileRenderElementid='string'// Required, id that can passed to the element, it should be unique.skyflowID='string'// Required, skyflow id of the file to be rendercolumn='string'// Required, column name of the file to be rendertable='string'// Required, table name of the file to be render...props/>

The following props can be passed to Skyflow file render element:

{container: 'RevealContainer',// Required, the reveal container.id: 'string',// Required, id that can passed to the element, it should be unique.classes: {},// Optional, styles that should be applied to the element.altText: 'string',// Optional, string that is shown before file render callskyflowID: 'string',// Required, skyflow id of the file to be rendercolumn: 'string',// Required, column name of the file to be rendertable: 'string',// Required, table name of the file to be render}

The inputStyles and errorTextStyles parameters accept a styles object as described in theprevious section for collecting data. But for render file elements, inputStyles accepts only base variant, global style objects.

An example of a inputStyles object:

inputStyles: {base: {height: '400px',width: '300px',},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}}

An example of a errorTextStyles object:

errorTextStyles: {base: {color: '#f44336',},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',}}

Step 3: Render File

When the element is created and mounted, use useRenderFile(id) hook to pass the div id of file render element and call the renderFile() method on the file render element instance return by useRenderFile(id) as shown below:

constfileElement=useRenderFile('fileElement-1');fileElement.renderFile().then(data=>{// Handle success.}).catch(err=>{// Handle error.});

Note: The div id passed in the element should be unique, and the same div id should be passed in the useRenderFile('id') hook.

End to end example of file render

importReact,{useEffect,useState}from'react';import{useMakeSkyflowStyles,useRevealContainer,useRenderFile,FileRenderElement,}from'skyflow-react-js';constApp=()=>{constrevealContainer=useRevealContainer();const[visible,setVisible]=useState(false);const[skyflowID,updateSkyflowID]=useState('');// REPLACE with your custom implementation to fetch skyflow_id from backend service.// Sample implementationuseEffect(()=>{fetch('<BACKEND_URL>').then((response: any)=>{// on successful fetch skyflow_idconstskyflowID=response.skyflow_id;// set skyflow idupdateSkyflowID(skyflowID);setVisible(true);}).catch((error)=>{// failed to fetch skyflow_idconsole.log(error);});},[]);// pass file render element div id in useRenderFile hookconstrender=useRenderFile('fileElement-1');consthandleRender=()=>{// call render file methodrender?.renderFile().then((data)=>console.log(data)).catch(err=>console.log(err));}constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {height: '300px',width: '400px',},},errorTextStyles: {base: {color: 'red',fontFamily: '"Roboto", sans-serif'},global: {'@import' :'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',},},});constclasses=useStyles()return(<divclassName='App'><headerclassName='App-header'><h4>Render PDF</h4>{visible&&<FileRenderElement// create element, pass fetched skyflow id and other details here.id={'fileElement-1'}container={revealContainer}classes={classes}skyflowID={skyflowID}column={'file'}table={'credit_cards'}altText={'Image File'}/>}<buttononClick={handleRender}>Reveal</button></header></div>)}exportdefaultApp

Sample Success Response

{
"success": [
{
"skyflow_id": "b63ec4e0-bbad-4e43-96e6-6bd50f483f75",
"column": "file"
},
]
}

Update Skyflow Elements Properties

You can dynamically update Skyflow Elements’ properties dynamically by using the React useState hook. You can maintain the element properties via React state and update them at runtime as and when required. The Skyflow React SDK provides the following elements:

  • Collect Elements
  • Reveal Elements
  • Composable Elements
  • File Render Element

Note - You cannot update the type property for Collect and Composable Elements.

End-to-end example for updating properties in Collect and Reveal Elements

importReact,{useState}from'react'importSkyflowfrom'skyflow-js'import{CardNumberElement,FileInputElement,FileRenderElement,RevealElement,useCollectContainer,useMakeSkyflowStyles,useRenderFile,useRevealContainer,}from'skyflow-react-js'constApp=()=>{// Initialise states for properties to updateconst[table,setTable]=useState<string>('dummy-table')const[skyflowID,setSkyflowID]=useState<string>('dummy-id')const[cardNumberLabel,setCardNumberLabel]=useState<string>('card number')const[cardNumberToken,setCardNumberToken]=useState<string>('43wrf-23v-9vf-fdvjcknfsk')constcontainer=useCollectContainer()constrevealContainer=useRevealContainer()constfileElement=useRenderFile('fileRenderElement-1')constuseStyles=useMakeSkyflowStyles({inputStyles: {base: {border: '1px solid black',borderRadius: '4px',color: '#1d1d1d',padding: '10px 16px',fontFamily: '"Roboto", sans-serif',},complete: {color: '#4caf50',},empty: {},focus: {},invalid: {color: '#f44336',},cardIcon: {position: 'absolute',left: '8px',bottom: 'calc(50% - 12px)',},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',},},labelStyles: {base: {fontSize: '16px',fontWeight: 'bold',fontFamily: '"Roboto", sans-serif',},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',},},errorTextStyles: {base: {color: 'blue',fontFamily: '"Roboto", sans-serif',},global: {'@import': 'url("https://fonts.googleapis.com/css2?family=Roboto&display=swap")',},},})constoptions={enableCopy: true,}constclasses=useStyles()// handler function for collecting dataconsthandleCollect=()=>{constresponse=container.collect({tokens: true,})response.then((res: unknown)=>{console.log(JSON.stringify(res))constid=res.records[0].fields.skyflow_idconsttoken=res.records[0].fields.card_numbersetSkyflowID(id)// updates skyflowID with received IDsetCardNumberToken(token)// updates token with received token}).catch((e: unknown)=>{console.log(e)})}// handler function for revealing dataconsthandleReveal=()=>{revealContainer.reveal().then((res: any)=>{console.log(res)}).catch((err: any)=>{console.log(err)})}// handler function for rendering fileconstrenderFile=()=>{fileElement?
.renderFile().then((res: any)=>{console.log(res)}).catch((err: any)=>{console.log(err)})}// uploads file after skyflowID is updatedReact.useEffect(()=>{if(skyflowID!=='dummy-id'){container.uploadFiles({}).then((res)=>{console.log(res)}).catch((err)=>{console.log(err)})}},[skyflowID])// updates table property valueconsthandleCollectUpdate=()=>{setTable('pii_fields_upsert')}// updates card number label property valueconsthandleRevealUpdate=()=>{setCardNumberLabel('Reveal Card Number')}return(<divclassName='App'><headerclassName='App-header'><CardNumberElementcontainer={container}table={table}classes={classes}column={'card_number'}label={'Collect Card Number'}options={options}/><FileInputElementcontainer={container}table={table}column={'file'}label={'Collect File'}classes={classes}skyflowID={skyflowID}/><RevealElementid={'dynamicRevealElement-1'}container={revealContainer}token={cardNumberToken}label={cardNumberLabel}classes={classes}redaction={Skyflow.RedactionType.PLAIN_TEXT}altText={'card number'}/><FileRenderElementcontainer={revealContainer}id={'fileRenderElement-1'}skyflowID={skyflowID}altText={'image.png'}classes={classes}table={table}column={'file'}/><buttononClick={handleCollect}>Collect</button><buttononClick={handleCollectUpdate}>Update Collect</button><buttononClick={handleReveal}>Reveal</button><buttononClick={handleRevealUpdate}>Update Reveal</button><buttononClick={renderFile}>Render File</button></header></div>)}exportdefaultApp

Reporting a Vulnerability

If you discover a potential security issue in this project, please reach out to us at security@skyflow.com. Please do not create public GitHub issues or Pull Requests, as malicious actors could potentially view them.

License

This project is licensed under the MIT license. See the LICENSE file for more info.

About

Skyflow SDK for the React JS web framework.

Resources

Security policy

Stars

10 stars

Watchers

13 watching

Forks

Releases

Packages

Used by

Contributors

Languages