Hosted Fields

Hosted Fields is a solution that lets merchants offer Afterpay at checkout without collecting sensitive information themselves.

The solution involves a special text entry box (or any other standard HTML data entry field) that collects data directly to AfterPay’s servers, from within the merchant’s website/app. The merchant receives only a proprietary unique ID (nonce). This can be used to identify the customer in calls to the AfterPay eCommerce API, but not to resolve the customer’s Personally Identifiable Information. This allows the merchant to avoid the obligations and risks that stem from handling sensitive data.

The solution creates a text entry box in the merchant’s website/app that is an iFrame to AfterPay’s servers. Any data entered into this field by the customer is visible only to AfterPay’s servers, and not to the merchant. The fields are displayed by the merchant’s website/app, but hosted by AfterPay’s servers.

Nonce

Hosted Fields are designed to collect the customer’s Personally Identifiable Information (name, email, national ID number, address, etc.).

The merchant wants to minimize the amount of PII handled by their systems. However, this information is required by AfterPay for its credit/risk checks and to positively identify the customer for invoicing.

The merchant’s customer signup (or checkout) includes a transparently embedded iFrame of a text entry box (or other HTML entry field). The iFrame is hosted on AfterPay’s Hosted Fields Server. When the customer submits the form, the contents of the Hosted Field are sent directly from the customer’s device to AfterPay’s server, and never pass through the merchant’s systems.

Instead, the merchant receives a nonce – a unique string that can be used as a replacement for the customer’s PII in the Authorize call to the AfterPay eCommerce API. The eCommerce API takes the nonce and sends it to the Hosted Fields Server, which provides the original data in response, all over a secure backend connection.

You can use multiple Hosted Fields in one webform. If they are all part of a single Authorize call, the merchant will receive a single nonce in return, and all the collected data will be associated with that nonce.

Integration

The solution includes the following components on AfterPay’s end:

  • ID Service:
    • Takes the merchant’s API key
    • Issues an authentication token that can be used with the Hosted Fields Server
  • Hosted Fields Server:
    • Takes the customer’s authentication token
    • Returns the iFrame code (Hosted Fields Client Library) for the PII field
    • Takes the data that was entered into the hosted PII field
    • Returns the nonce

The nonce can be used for subsequent AfterPay eCommerce API calls, as part of the Checkout Customer block. If the nonce is provided, the identificationNumber is optional.

The nonce can be used only with the same merchant API key as the one that was used to generate it. Otherwise, the eCommerce API will reject the call.

The nonce can be used only for a single Authorize call. Each checkout must be conducted with a new nonce.

Workflow

A Hosted Fields transaction using the nonce consists of the following distinct steps:

  1. User authentication
  2. Javascript library initialization
  3. Saving field contents
  4. Authorization of transaction


Hosted Fields Workflow

User Authentication

Hosted Fields require authentication to prevent abuse, and to link the nonce record to a particular merchant.

Authentication is achieved by calling the AfterPay ID service via REST API, using the merchant’s API key.

The acquisition of the JWT token must be implemented as a server-to-server call. Your API key should never be exposed to the public.

To reduce the load on the ID service, and improve the customer experience, it is recommended to reuse the token between customers. The token is valid for 48 hours (current default, configurable in AfterPay backend).


Parameter Value
URL (test environment) https://hosted-fields-pt.afterpay.nl/
URL (production environment) https://hosted-fields.afterpay.nl/
HTTP Method POST
Content type application/json
Request body
field value
service hosted-fields Required
apiKey Required

HTTP RESPONSE CODE DESCRIPTION
OK (200) JWT token issued
Unauthorized (401) Invalid or expired API key
Bad Request (400) Invalid request parameters
Server error (500) Internal server error, try again

Sample request


    curl -X POST {{URL}} \
    -H 'Content-Type: application/json' \
    -d '{
    "service": "hosted-fields",
    "apiKey": {{YOUR_API_KEY}}
    }'

Response request


    {
    "validUntil": "2019-03-09T09:59:21+00:00",
    "token": {{TOKEN}}
    }

Javascript Library Initialization


Once the merchant has the token, they can initialize the Hosted Fields client library in the customer’s browser/app.

Include javascript library



    <script src="https://hosted-fields-pt.afterpay.nl/hosted-fields.js"></script>


Configure hosted fields client library


Configuration


    var config = {
    baseAddress: {{URL}},
    token: 'JWT_TOKEN',
    form: document.getElementsByTagName('form')[0],
    fields: [
    {
    'name': 'customer.identificationNumber',
    'element': '#ssn-container',
    'bodyStyle': 'background-color: rgb(255, 0, 255);',
    'fieldStyle': "border: 1px solid #f0f; color 'green'",
    'iframeClassName': 'test-iframe',
    'fieldFocusStyle': 'border: 3px solid #f00;',
    'fieldHoverStyle': 'background-color: #9f9;',
    'iframeTitle': 'iframe__TITLE__SSN',
    'placeholder': 'DDMMYYXXXXX',
    'validationRegex': /[0-9]{2}[0,1][0-9][0-9]{2}[ ]?[0-9]{5}/,
    'numericKeypad': true
    }
    ]
    };

PARAMETER DESCRIPTION
baseAddress Used to determine where the Hosted Fields API is hosted. Only relevant for integration against a dev/test environment. In a production setting, this should be removed.
token JWT Token obtained from the Afterpay ID service
form Reference to form where the hosted nonce field will be added. Useful if the Checkout button will submit the form. Note: When the value of this setting is null, then no hosted field is created, and the nonce can be retrieved from the afterpayFields.save function’s callback.
fields[].name JSON path to the field
fields[].element QuerySelector to the container element where the field iFrame will be created. The element has to be present when afterpayFields.initialize is called.
fields[].bodyStyle CSS style passed to iFrame body style
fields[].fieldStyle CSS style passed to text field style
fields[].iframeClassName CSS class added to created iFrame
fields[].fieldFocusStyle CSS focus style passed to text field style
fields[].fieldHoverStyle CSS hover style passed to text field style
fields[].iframeTitle Value passed to title attribute in iframe tag
fields[].placeholder Value passed to placeholder attribute in iframe input field
fields[].validationRegex Regex used for validate field value
fields[].numericKeypad Boolean type parameter, if TRUE then numeric keypad will be applied on mobile devices
fields[].profile Unique profile for field type. Profile names consists of three parts, first one is preferred input, second is language and the third country. Supported profiles:
Profile name Placeholder
'SSN-sv-SE' 'YYMMDD-XXXX'
'SSN-en-SE' 'YYMMDD-XXXX'
'SSN-nb-NO' 'DDMMYYXXXXX'
'SSN-en-NO' 'DDMMYYXXXXX'
'SSN-fi-FI', 'DDMMYY-XXXX'
'SSN-sv-FI' 'DDMMYY-XXXX'
'SSN-en-FI' 'DDMMYY-XXXX'
'IBAN-de-DE' 'DE00 0000 0000 0000 0000 00'
'IBAN-en-DE' 'DE00 0000 0000 0000 0000 00'
'IBAN-de-AT' 'AT00 0000 0000 0000 0000'
'IBAN-en-AT' 'AT00 0000 0000 0000 0000'
fields[].googleFonts Font name(-s) that can be fetched from google service (font names separated by |, white-spaces converted to +)

Initialize library


The Hosted Field is initialized via JavaScript. It is recommended to do this after the page has been loaded in the browser.

The client-side library exposes three methods:

METHOD SIGNATURE / PARAMETERS DESCRIPTION
afterpayFields.initialize config Initializes the solution with the provided configuration
afterpayFields.onError callback function Exposes errors received. It is highly recommended to set up error handling as the first thing in the execution line, since initialization can throw an error.
afterpayFields.save callback function Saves the fields and returns the nonce.
afterpayFields.validate callback function Checks whether a field(-s) matches a regex in config and returns overall status and invalid field names. If nothing is specified in fields[].validationRegex, it uses a predefined AfterPay rexeg, indicated by the fields[].profile parameter.
afterpayFields.onchange callback function Checks whether a field(-s) matches a validation rules based on profile name in config and returns overall status.


    document.addEventListener("DOMContentLoaded", function () {
        afterpayFields.onError = function (err, message) {
            console.error(err, message);
        }
        afterpayFields.initialize(config);
    });

ERROR CODES VALUE DESCRIPTION
ERROR 1 Generic error, check browser console
NO_FIELDS 2 No fields configured, configuration passed to initialization does not have the fields property set.
NO_TOKEN 3 No authentication token passed in configuration
SAVE_ERROR 4 Error saving fields, check browser console
NO_CONTAINER 5 Unable to find the container element where the field is to be created. Check spelling or existence of the container.

Validate Field Values

Validate function will work only if validationRegex parameter is initialized in config.


        afterpayFields.validate(function (isValid, invalidFields) {
            ...
        });

If isValid equals to TRUE: then invalidFields array is empty otherwise invalid field names will be populated.

onChange event

onChange event will return status object.


    afterpayFields.onChange = function (status) {
        console.log(JSON.stringify(status));
    }

Validation errors


ERROR CODES DESCRIPTION
400.000 Input invalid
400.001 Too short
400.002 Too long
400.003 Too young
400.004 Too old
400.005 Checksum incorrect
400.006 Bank not found

Status object will vary on configuration, validationRegex or profile is required to get validation result. Profiles give more options, for example 'maskedInput', 'bic' and 'bankName' for IBAN.

Save Field Contents

Saving of the field contents has to be explicit:


    afterpayFields.save(function (nonce) {console.log('saved!', nonce);});


If there are multiple Hosted Fields in a form, their contents are saved in the browser’s local storage before being sent to the Hosted Fields Server.

Authorization of transaction

To complete the transaction, the merchant calls the Afterpay API authorization endpoint with small modifications.

Please refer to official documentation on how to make authorization call (https://developer.afterpay.io/guidelines). The main difference is the addition of a new request field, “nonce”. If this field is present, the customer’s identificationNumber is not required.Authorization request



    {
        "payment": {
            ...
        },
        "customer": {
            ...
        },
        "order": {
            ...
        },
        "nonce": "abcd1234defg", //ReceivedfromafterpayFields.savecallback
    }