PayFacto API - v1.0 - Solution : Secure Hosted Checkout (SHC)

PayFacto API - v1.0 - Solution : Secure Hosted Checkout (SHC)

 PayFacto API - v1.0 - Solution : Secure Hosted Checkout (SHC)

Implementation Guide

Secure Hosted Checkout (SHC) is a JavaScript library that lets merchants collect and submit cardholder information to PayFacto for verification, without ever handling that information directly. This page covers what SHC is, how to set it up, how to call it, how to handle responses, and how to customize the form to match your site. 

  What is Secure Hosted Checkout?

Secure Hosted Checkout (SHC) is a JavaScript library that allows merchants to collect and send cardholder information to PayFacto for verification without needing to access that information directly. When called, SHC verifies the card information and provides the merchant with a token that can be used with the /v1/preauthorizationWithToken or /v1/purchaseWithToken endpoints in PayFacto's Payment API.

SHC creates a secure iframe for accepting credit card information. Four steps are required to configure it:

1

Include the SHC library

Add the script tag to your webpage: <script src="https://form.gateway.staging.payfacto.cloud/secure-hosted-checkout/v1/shc.js"></script>

2

Add a container div

Add a <div id="shc-fields"></div> tag where the iframe should appear.

3

Acquire an SHC token

Call the /secure-hosted-checkout/v1/session endpoint from your server application to obtain a secure token.

4

Call the shc function

Call shc(shcToken, callback) with the secure token and a callback function. The callback receives the results of the credit card verification.

ℹ️

A fully functional example application is available in PayFacto's public Bitbucket repository.

🔑

  What You Need for SHC

A merchant will need the following information to get started:

🔑

A Company Number

🔑

A Merchant Number

🔑

An API Key

ℹ️

This information is provided when you create a new developer account with PayFacto.

🔄

  For SecureFields Developers

For developers who have previously worked with SecureFields: SHC is not a new version of SecureFields — it is an entirely new product, with new API calls for both the server and the client. A number of requested changes were incorporated into SHC to simplify development and integration:

The endpoint for requesting a shcToken is different than for a secureToken.

The request object no longer needs to be converted into a string.

The request object properties no longer start with an upper case letter.

A shcToken is an object rather than a string. The whole object needs to be passed to the shc function.

The shc function takes a callback rather than returning a promise.

shc is not in a modal by default — there is no longer a need to embed an iframe in the page to have the fields appear within it.

🔗

  Calling Secure Hosted Checkout

Calling SHC is a two-step process:

1

Obtain a Secure Token

Call the /secure-hosted-checkout/v1/session endpoint.

2

Pass the token to shc()

After obtaining the token, pass it to the shc function, which displays the fields for the cardholder to fill in.

Why a two-step process?

The first step — calling /secure-hosted-checkout/v1/session — requires secret information that could be stolen if it was available to the client application. This call must be made by the merchant's server, with the result passed to the client.

📝

  Examples

ℹ️

All the examples on this page use JavaScript.

Obtaining a Secure Token for SHC

Secure tokens are obtained by having the merchant's server call the /secure-hosted-checkout/v1/session endpoint. This endpoint is RESTful — it expects a JSON object as input and returns a JSON object as output.

JavaScript — Request a secure token
const endpoint = 'https://form.gateway.staging.payfacto.cloud/secure-hosted-checkout/v1/session';
// NOTE: customerNumber and operatorId are supplied by merchant
// NOTE: language can be either 'en' or 'fr'
const body = {
companyNumber: companyNumberSuppliedByPayFacto,
merchantNumber: merchantNumberSuppliedByPayFacto,
customerNumber: customerNumber,
operatorId: operatorId,
language: language
};
const payload = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Access-Control-Allow-Origin': '*',
'Authorization': `Basic ${authApiKeySuppliedByPayFacto}`
},
body: JSON.stringify(body)
};

fetch(endpoint, payload)
.then(response => response.json())
.then(response => sendResponseToBrowser(response))
.catch(error => handleError(response));
});

Displaying the Fields on the Screen

The fields for the cardholder to fill in are created and displayed when the shc function is called. The secure token is retrieved from the merchant server and passed to shc. The second argument, the callback, is a merchant-defined function that receives the results of the credit card validation and decides what action to take.

HTML — Embedding the SHC fields
<!DOCTYPE html>
<html>
<head>
<script src="https://form.gateway.staging.payfacto.cloud/secure-hosted-checkout/v1/shc.js" ></script>
<script src="/merchantCode.js" ></script>
<title>SHC Example</title>
</head>
<body>
<!-- The shc-fields div is required. The shc function will put the fields within that div -->
<div id="shc-fields"></div>
<script type="text/javascript">
merchantGetShcToken(shcToken => {
shc(shcToken, response => merchantProcessResponse(response));
});
</script>
</body>
</html>
📤

  SHC Responses

After calling SHC, the response guides you to the next step.

SHC Callback Response Object

When shc is called, it is passed a callback to accept the results of the card validation. When validation succeeds, the resulting object looks like this:

JSON — Successful validation
{
brand: "Visa",
card: "411111******1111",
cvv2Cvc2Status: "M",
expiry: "1223",
name: "Test Card",
profileId: "72e042dd-a518-4ec2-8df0-58125f815a68",
secureId: "656dp9d7058gf3958hlb5e53o37hr0x8kwi",
success: true,
token: "5k46v51j238tpt5v7v4u4a18hc4f04m9926"
}
FieldDescription
brandThe card brand. Supported brand names are Amex, Diners, Discover, Mastercard, Maestro, Visa, and Unknown.
cardThe masked card number.
cvv2Cvc2StatusDownstream provider verification status.
expiryThe card expiry date.
nameThe cardholder's name.
profileIdThe cardholder profile.
secureIdThe secure token id used to generate the verification request.
successA boolean value indicating if the request was successful.
tokenThe purchase token created when the card is successfully verified.

The Error Response

Sometimes things don't go as expected. When that happens, an error is returned to the calling object:

JSON — Error response
{
code: "INVALID_NUMBER",
message: "card number is incorrect",
success: false,
type: "CARD_DECLINED"
}
FieldDescription
codeThe subclass of error returned. Valid values: INVALID_EXPIRY_DATE, INVALID_NUMBER, TOKEN_EXPIRED.
messageA message that briefly describes the nature of the error.
successAlways false for an error response.
typeThe class of error returned. Valid values: CARD_DECLINED, INTERNAL_ERROR, UNAUTHORIZED.

Errors Returned by 3DS

Error TypeError Code
CARD_ERRORNOT_VERIFIED — could not verify card number
CARD_ERRORNOT_AUTHENTICATED — issuer rejected card
DOWNSTREAM_ERRORNOT_VERIFIED — 3DS provider is having technical issues
⚙️

  Adding Optional Fields

By default, SHC displays the minimum number of fields needed to validate a credit card online — cardholder name, card number, expiry date, and CVV. SHC can also display fields for address, postal code, and email address, and can change the display behavior of the Pay button. By default the Pay button changes from the word "Pay" to a spinner; you can disable this if needed.

To include these fields, supply the optional values when creating the secure token:

JavaScript — Optional fields
const body = {
companyNumber: companyNumberSuppliedByPayFacto,
merchantNumber: merchantNumberSuppliedByPayFacto,
customerNumber: customerNumber,
operatorId: operatorId,
language: language,
avs: both,
email: true,
disableSubmitIndicator: true,
useRecaptcha: false,
ignoreInitAuthTimedOut: true
}
ℹ️

companyNumber, merchantNumber, customerNumber, operatorId, and language are all required when calling SHC.

FieldDescription
avsCollects the customer's address. Takes one of: address (street only), postal (postal code only), both (both fields).
emailTakes a boolean value to collect the cardholder's email address.
disableSubmitIndicatorTakes a boolean value to control whether the Pay button shows a spinner during submission.
useRecaptchaTakes a boolean value. Defaults to true; include this line only to disable reCAPTCHA on the page.
ignoreInitAuthTimeoutTakes a boolean value. Defaults to false. Include this line to ignore 3D Secure authentication initialization errors.

Disabling useRecaptcha

SHC uses Google's reCAPTCHA to prevent some automated attacks. For security purposes, useRecaptcha is set to true by default. However, some merchants have reported that reCAPTCHA interferes with their site. In these rare instances, SHC allows you to disable this feature.

🚧

Risks of disabling useRecaptcha

If you pass useRecaptcha as false in the options, you are disabling the SHC reCAPTCHA feature and you risk exposing your custom form to various attacks, including a velocity attack.

Usage of ignoreInitAuthTimeout

As part of the 3D Secure authentication process, SHC collects information about the customer's device and browser. In rare cases, this can cause a timeout and generate an initAuthTimeout error that fails the transaction. Setting ignoreInitAuthTimeout to true ignores the timeout error and allows the rest of the 3D Secure process to continue.

🚧

Risks of disabling ignoreInitAuthTimedOut

If you pass ignoreInitAuthTimeout as true, part of the 3D Secure process is bypassed and the merchant may be liable for fraudulent transactions.

🏷️

  Options — The Third Argument

In some cases, additional information is required to render the fields correctly in your custom form. For this, you can provide a third argument containing options.

📖

Available option

Currently, the only supported option for custom forms is sourceElement.

sourceElement

When working with custom forms, SHC requires the id of the tag containing the form. This id is passed to SHC as the sourceElement property in the options parameter.

JavaScript — Using the third argument
const options = { sourceElement: 'custom-form' };
shc(shcToken, response => handleResponse(response), options);
🎨

  Customizing

SHC provides a number of CSS classes that you can override to change the appearance of the SHC fields. The classes are structured so you can overwrite fields as a group for consistency, while each element also has its own unique id for granular manipulation.

A field's generic layout resembles the following:

HTML — Field structure
<label for="${name}" id="shc-${name}-label" class="confidante-field-label">
<div id="shc-${name}-img" class="confidante-field-img"></div>
<input id="shc-${name}-input" required="required" type="text" class="confidante-field-input shc-field-${name}" name="${name}" placeholder="${placeholder}" />
<span id="shc-${name}-span">${label}</span>
<div id="shc-${name}-validate" class="confidante-field-validate"></div>
</label>

Where ${name} represents the field name. Valid field names are: name, card, expiry, cvv, email, address, and postal.

CSS — Hide all field icons
.confidante-field-img svg {
visibility: collapse;
}
CSS — Hide only the card field icon
#shc-card-img {
visibility: collapse;
}

You can also customize the Pay button. The default layout is:

HTML — Default Pay button
<button id="shc-pay-button" type="button" class="disabled">Pay</button>

Use the #shc-pay-button CSS identifier to apply different styles to the Pay button.

Where to Put the CSS Styles

Place the shc-style id in a style tag so all the styles inside are applied to the SHC fields and buttons:

HTML — Style tag placement
<style id="shc-style">
/* place the custom styles here */
</style>
📝

  Creating a Custom Form

No need to use the default form — custom forms allow for a standardized look that matches your website. SHC allows a merchant developer to create a custom form containing both SHC fields and the merchant's own fields. To designate a field as an SHC field, the field id must match an auto-generated SHC field id.

FieldDescription
shc-name-inputThe cardholder name field.
shc-card-inputThe card number field.
shc-expiry-inputThe card expiry date field.
shc-cvv-inputThe card's CVV value field.
shc-email-inputThe cardholder's email address field.
shc-address-inputThe cardholder's postal address field.
shc-postal-inputThe cardholder's postal code field.

If a field has an SHC field id, all the formatting and listeners are applied to that field. When the Pay button is clicked, the values in the user fields are collected and returned to the caller.

HTML — Custom form example
<div id="custom-form">
<form style="display: flex;">
<input id="secureId" name="secureId" type="hidden" value="bonJeton" />
<input type="hidden" name="name" value="JOHN DOE" />
<input type="text" id="shc-card-input" name="card" placeholder="1234 1234 1234 1234" required="required" autocomplete="cc-number" />
<div style="display: flex; flex-direction: row;">
<input type="text" id="shc-expiry-input" name="expiry" placeholder="MM / YY" required="required" />
<input type="text" id="shc-cvv-input" name="cvv" placeholder="123" required="required" autocomplete="cc-csc" />
</div>
<button id="shc-pay-button" type="button">Pay</button>
</form>
</div>

To use your custom form, pass the form's id to shc as an option in the third argument:

JavaScript — Activate the custom form
shc(shcToken, response => handleResponse(response), { sourceElement : 'custom-form'})

Custom Required Fields

If you add a required custom field, set the required attribute on the field to prevent the Pay button from enabling until that field contains a value:

HTML — Required custom field
<input required="required" type="text" name="myRequiredField" />

Custom Forms and 3DS

When working with custom forms, the merchant is responsible for adding the hidden 3DS fields:

HTML — Required 3DS fields
<input id="purchaseAmount" name="purchaseAmount" type="hidden" value="920">
<input id="purchaseCurrency" name="purchaseCurrency" type="hidden" value="CAD">
<input id="purchaseDate" name="purchaseDate" type="hidden" value="2025-11-03T18:16:43.948Z">
FieldDescription
purchaseAmountThe monetary amount of the transaction in minor units. In the example above, the value is $9.20, not $920.00.
purchaseCurrencyThe currency the transaction is conducted in. For most merchant accounts the value is "CAD". Must match the merchant account's currency.
purchaseDateThe date and time the transaction is taking place, in extended ISO-8601 format (YYYY-MM-DDTHH:MM:SS.000Z).
ℹ️

These fields are treated as read-only by SHC, so the required values can be safely pre-loaded before SHC is called.

🔒

  Custom Form Security

To protect against the injection of fraudulent code, SHC prevents the transfer of the following HTML tags to the SHC secure iframe:

<SCRIPT>

<IFRAME>

<OBJECT>

<A> (the anchor tag)

<INPUT TYPE="SUBMIT">

<BUTTON TYPE="SUBMIT">

As an added measure of security, the ACTION and METHOD attributes are removed from the <FORM> tag. In addition, no JavaScript is transferred to the SHC secure iframe — including JavaScript that is part of a permissible HTML tag, or any events attached to an HTML tag before transferring the form to the SHC secure iframe.

📡

  Custom Events

In a custom form, buttons that contain the data-message attribute send the contents of that message to the parent form via a message event. Use a message event listener to receive it:

JavaScript — Listening for messages
window.addEventListener('message', messageEventHandler);

The message uses the format { message: 'data-message contents' }.

💬

  The shcMessenger Object

The shcMessenger object allows the SHC form to communicate with the calling application. It is created when the shc function is called.

JavaScript — Creating the shcMessenger
let shcMessenger;
getShcToken(shcToken => {
shcMessenger = shc(shcToken, response => processResponse(response), options);
});

Receiving Messages

The SHC form emits messages during execution. Receive them with shcMessenger.on(event, callback):

JavaScript — Listening for an SHC event
shcMessenger.on('shc-event', optionalData => handleEvent(optionalData));
FieldDescription
shc-card-brandThe detected card brand when the cardholder enters the number.
shc-submitThe card information has been submitted for verification.
shc-responseThe same response sent to the shc callback.
shc-3dsThe 3D Secure process has started.
shc-3ds-challengeThe 3D Secure challenge flow is being executed.
shc-ready-to-submitAll validation passes and the form can be submitted (or becomes invalid again if a required field changes).

Sending Messages

The SHC form can also accept messages from the shcMessenger via method calls:

FieldDescription
sendBlockSubmit()Requests that the SHC form not consider itself ready to submit until sendUnblockSubmit() is sent. The Pay button stays disabled even when all fields are valid.
sendUnblockSubmit()Cancels a sendBlockSubmit() and allows the form to be ready to submit once all fields are valid.
sendCancel()Requests that the SHC form destroy itself.
sendSubmit()Requests that the SHC form submit itself. The form will not submit if any field is invalid.