Secure Fields
Stitch provides Secure Fields within an SDK to enable merchants to collect sensitive card details for payment. This ensures sensitive data never reaches your server unencrypted, while still allowing for fully customisable checkout flows.
Key features of Stitch Secure Fields include:
- Automatic input formatting and validation as customers type,
- Responsive design to fit seamlessly on any screen size,
- Custom styling rules to match the look and feel of your site, and
- No PCI-DSS compliance requirement for the merchant.
Usage Overview
The Secure Fields SDK will provide you with encrypted details (limiting PCI-DSS scope), which may be used as inputs when creating transactions within the following flows:
Follow the steps below to add Secure Fields to your web application to capture customer card data.
Installing SDK
Install the SDK and component package applicable to your client-side framework: The @stitch-money/react
package should be used for React applications, while the @stitch-money/web
package should be used for non-React applications.
- React
- Non-React
npm install @stitch-money/react
npm install @stitch-money/web
Rendering Secure Form and Fields
The SDK consists of two components:
- Stitch Secure Form: Contains shared logic and coordinates Stitch Secure Fields composed within the component. It must be placed high enough in your component tree to wrap all instances of
<StitchSecureField>
. - Stitch Secure Field: An individual field for capturing one aspect of the customer's card. You require at least two fields to capture the
number
andcvc
.
Stitch Secure Form
- React
- Non-React
This component accepts the following properties:
Name | Description |
---|---|
clientId | The client ID assigned to you by Stitch that you will be processing your transactions on. |
onReady | A function for handling the ready event emitted when all secure fields have loaded successfully. |
onChange | A function for handling change events emitted when the customer makes changes to any of the secure fields. |
theme | (Optional) A custom theme which changes the appearance of the secure fields, supports most CSS attributes. |
This component accepts the following properties:
Name | Description |
---|---|
clientId | The client ID assigned to you by Stitch that you will be processing your transactions on. |
theme | (Optional) A custom theme which changes the appearance of the secure fields, supports most CSS attributes. |
The following are event listeners on the form component (in JavaScript):
Name | Description |
---|---|
stitch-secure-fields-ready | A function for handling the ready event emitted when all secure fields have loaded successfully. |
stitch-secure-fields-change | A function for handling change events emitted when the customer makes changes to any of the secure fields. |
stitch-secure-fields-error | A function for handling change events emitted when there is an error initializing a field. |
An example of importing and rendering this component (depending on your JavaScript framework) is as follows:
- React
- Non-React
import { StitchSecureForm } from '@stitch-money/react';
export function PaymentPage() {
const handleSecureFormChange = ({ payload }) => {
console.log(payload);
if (payload.isComplete) {
// This function should send the encrypted card data to your backend which would in turn send it to the Stitch Secure API
sendEncryptedCardDataToBackend(payload);
}
};
const handleSecureFormReady = () => {
// This function could toggle a state variable to update the visibility of the loaded Secure Field components
console.log('Secure Fields Loaded');
};
const theme = {
styles: {
':root': {
'color-scheme': 'dark',
},
// Style all field inputs
'.field input': {
marginTop: 8,
padding: '8px 12px',
},
},
};
return (
<div>
<StitchSecureForm
clientId="your Stitch client ID"
onReady={handleSecureFormReady}
onChange={handleSecureFormChange}
theme={theme}
>
{/* add child secure field components */}
</StitchSecureForm>
</div>
);
}
import { StitchSecureForm } from '@stitch-money/web/secure-fields';
const form = document.createElement('stitch-secure-form');
form.setAttribute('clientId', 'your Stitch client ID');
// add child secure field components
document.getElementById('form-container').appendChild(form);
form.addEventListener('stitch-secure-fields-ready', () => {
// This function could toggle a state variable to make the now loaded Secure Field components visible
console.log('Secure Fields Loaded');
});
form.addEventListener('stitch-secure-fields-change', (event) => {
const { payload } = event.detail;
console.log('Form payload changed:', payload);
if (payload.isComplete) {
// This function should send the encrypted card data to your backend which would in turn send it to the Stitch Secure API
sendEncryptedCardDataToBackend(payload);
}
});
This example shows a vanilla JavaScript usage. This may be adapted accordingly, based on the JS framework you use in your platform.
Stitch Secure Fields
This component accepts the following properties / attributes:
Name | Description |
---|---|
field | The field that should be rendered, can be one of name , number , expiry , or cvc . |
label | (Optional) Custom label text for this input. |
An example of rendering a form with secure fields (depending on your JavaScript framework) is as follows:
- React
- Non-React
import { StitchSecureField, StitchSecureForm } from '@stitch-money/react';
export function PaymentPage() {
// ... setup from previous step
return (
<div>
<StitchSecureForm
clientId="your Stitch client ID"
onChange={handleSecureFormChange}
theme={theme}
>
<div>
<StitchSecureField field="name" label="Cardholder Name" />
<StitchSecureField field="number" label="Card Number" />
<StitchSecureField field="expiry" label="Expiry Date" />
<StitchSecureField field="cvc" label="CVC" />
</div>
</StitchSecureForm>
</div>
);
}
import { StitchSecureForm, StitchSecureField } from '@stitch-money/web/secure-fields';
// ... setup from previous step
const nameField = document.createElement('stitch-secure-field');
nameField.setAttribute('field', 'name');
nameField.setAttribute('label', 'Cardholder Name');
const numberField = document.createElement('stitch-secure-field');
numberField.setAttribute('field', 'number');
numberField.setAttribute('label', 'Card Number');
const expiryField = document.createElement('stitch-secure-field');
expiryField.setAttribute('field', 'expiry');
expiryField.setAttribute('label', 'Expiry Date');
const cvcField = document.createElement('stitch-secure-field');
cvcField.setAttribute('field', 'cvc');
cvcField.setAttribute('label', 'CVC');
form.append(nameField, numberField, expiryField, cvcField);
document.getElementById('form-container').appendChild(form);
// ... listeners from previous step
The structure of the elements within <StitchSecureForm>
is up to you - The only requirement is that all <StitchSecureField>
elements are contained by a single <StitchSecureForm>
element somewhere up the component tree.
Ready Event
- React
- Non-React
The onReady
handler function is used to determine when all <StitchSecureField>
elements have loaded successfully.
Below is an example of a handler function that toggles a loading state variable once the ready event has been fired:
const handleSecureFormReady = () => {
// Here you could toggle your loading state variable to display the <StitchSecureForm> and <StitchSecureField> elements once they have loaded
setIsStitchSecureFormLoading(false);
};
The stitch-secure-fields-ready
event listener is used to determine when all <StitchSecureField>
elements have loaded successfully.
Below is an example of an event listener that toggles a loading state variable once the ready event has been fired:
form.addEventListener('stitch-secure-fields-ready', function () {
// Here you could toggle your loading state variable to display the form and field elements once they have loaded
console.log('Secure Fields Loaded');
});
Change Events
The onChange
handler function (or stitch-secure-fields-change
event listener) is used to determine when the customer has completed capturing card details and to receive those encrypted details.
The payload
that is supplied as an argument to your handler function is structured as follows:
Name | Description |
---|---|
card.name | The card holder's name. |
card.number | The encrypted card number (PAN). This will only be present if the number is valid. |
card.brand | The network that issued the card. |
card.lastFour | The last four digits of the card number. This will only be present if the number is valid. |
card.bin | The Bank Identification Number (BIN) for the card. This will only be present if the number is valid. |
card.expiry.month | The month of the card expiration date. |
card.expiry.year | The year of the card expiration date. |
card.cvc | The encrypted card CVC. |
card.issuer | The financial institution that issued the card. This will only be present for a subset of issuers. |
errors | Validation errors scoped by field. |
isValid | Whether or not there are any validation errors currently on any of the fields. |
isComplete | Whether or not all of the fields have been successfully filled out with valid values. |
fingerprint | Contains data used to identify the user's device. This must be forwarded to your server and included in a Stitch API request |
You can access these values within your change handler function:
- React
- Non-React
const handleSecureFormChange = ({ payload }) => {
if (!payload.isValid) {
// Here, we know values the customer has entered are invalid - Show validation error
showErrorStateToCustomer(payload.errors.number); // Contains the validation error associated with the card number field.
}
if (payload.isComplete) {
// Here we know the customer has completed filling out the fields, and the associated values are valid - Send to backend for processing.
sendEncryptedCardDataToBackend({
name: payload.card.name,
pan: payload.card.number,
expiryMonth: payload.card.expiry.month,
expiryYear: payload.card.expiry.year,
cvc: payload.card.cvc,
fingerprint: payload.fingerprint,
});
}
};
form.addEventListener('stitch-secure-fields-change', (event) => {
const payload = event.detail?.payload;
if (!payload) return;
if (!payload.isValid) {
// Here, we know values the customer has entered are invalid - Show validation error
showErrorStateToCustomer(payload.errors?.number); // Contains the validation error associated with the card number field.
}
if (payload.isComplete) {
// Here we know the customer has completed filling out the fields, and the associated values are valid - Send to backend for processing.
sendEncryptedCardDataToBackend({
name: payload.card.name,
pan: payload.card.number,
expiryMonth: payload.card.expiry.month,
expiryYear: payload.card.expiry.year,
cvc: payload.card.cvc,
fingerprint: payload.fingerprint,
});
}
});
These details must be submitted to your backend, and can be included as inputs for the Once-off or Tokenization API calls.
Custom Styling
By default the secure fields will be rendered with a simple appearance that should fit into most applications.
If you want to customise the appearance of the fields and their associated validation error messages you can supply a theme
object to the <StitchSecureForm>
component.
The keys of the object are CSS selectors and the values are the same values you would use when writing CSS for the respective selector.
Currently only custom fonts from Google Fonts are supported.
Examples
To set styles that affect every part of all fields you can use the :root
selector:
const theme = {
styles: {
':root': {
'color-scheme': 'dark', // dark mode
},
},
};
To apply styles to all secure field label elements use the label
selector:
const theme = {
styles: {
label: {
fontWeight: 500,
textTransform: 'uppercase',
},
},
};
To apply styles to all secure field input elements use the .field input
selector:
const theme = {
styles: {
'.field input': {
marginTop: 4,
padding: 8px 12px,
}
}
}
To apply styles to the secure field input element that currently has focus use the .field:focus-within input
selector:
const theme = {
styles: {
'.field:focus-within input': {
borderColor: '#5F19E2',
},
},
};
To apply styles to the secure field validation messages use the .error
selector:
const theme = {
styles: {
'.error': {
display: 'none', // Hide built-in validation error messages
},
},
};
To apply styles to a specific secure field input use the .field[ev-name=<field name here>]
selector:
const theme = {
styles: {
'.field[ev-name=number]': {
// Style only the card number input
'font-size': '24px',
},
},
};
To load custom fonts, provide the Google Font links in the fonts
array and specify the corresponding
fontFamily
value within the selectors for the target elements:
const theme = {
// This will load the font from Google Fonts
fonts: ['https://fonts.googleapis.com/css2?family=Comic+Neue'],
styles: {
// This will apply the font to the field labels
'.field label': {
fontFamily: "'Comic Neue'",
},
// This will apply the font to the error text
'.error': {
fontFamily: "'Comic Neue'",
},
},
};
Incorporating StitchPass
StitchPass provides a more seamless way for returning users to pay, with on-device remembrance of payment methods. If StitchPass is enabled on your client configuration, using this only requires minor additions to the above integration.
To enable StitchPass functionality whereby a user's method may be added, or used for returning payments, a button should be added to your checkout journey. This is provided with the <StitchPassButton>
and may be used in place of your custom 'Add Card' or 'Pay with Card' button.
When using this button component, a payerId
must be included. This is the unique payer ID on your system, and must correspond to the payerId
provided within any PayerInformation
of transactions that are processed.
As an example of this usage is:
import { StitchPassButton } from '@stitch-money/react';
export function PaymentPage() {
// ... payment page setup
return (
<div>
<StitchPassButton
clientId="your Stitch client ID"
payerId="unique ID of user viewing your checkout"
></StitchPassButton>
</div>
);
}
Note that this will automatically be styled according to your branding, with your brand's logo and colours (Stitch will assist with configuring this against your client ID).