Hosted Payment Fields

Learn how to implement Hosted Payment Fields for PCI compliance of SAQ-A & maximum flexibility.
If you still have questions after reading, check out our FAQs.

If you would like to build your custom checkout flow using the API, but keep your PCI compliance requirements limited to the minimal SAQ-A level, BlueSnap’s Hosted Payment Fields are the ideal solution.

Hosted Payment Fields are iframes that replace sensitive credit card input fields in your checkout page. When the shopper submits the checkout form, BlueSnap binds this payment data to a token. You can then easily process payments or save shopper details by including the token in your BlueSnap API requests.

📘

This setup guide supports the latest version 5 (Web SDK) of Hosted Payment Fields. If you're currently using version 4, visit our Hosted Payment Fields FAQs page to learn how to upgrade.

For setup and usage instructions, see:

  Implementing Hosted Payment Fields in your checkout form

  JavaScript errors

  Updating the BlueSnap token

  Styling the Hosted Payment Fields

  Example Forms

  Using the Hosted Payment Fields token to process payments and save shopper info

Benefits

  • Control the look and feel of your checkout flow, including the Hosted Payment Fields
  • Simplest level of PCI compliance: SAQ-A
  • Securely capture payment information without your shoppers ever leaving your site
  • Use the Hosted Payment Fields token to complete a sale, as well as create or update a Vaulted Shopper
  • Fraud Prevention Device Data Check services are already built-in

How it works

  1. You create a Hosted Payment Fields token for the specific checkout session, using a server-to-server API call.
  2. On the checkout form, you call BlueSnap’s Hosted Fields JavaScript file with this Hosted Payment Fields token.
  3. After the shopper completes the form and clicks “Submit”, the sensitive payment data from the Hosted Payment Fields is saved in BlueSnap’s database and bound to the Hosted Payment Fields token you provided. This includes the following fields:
  • Credit Card Number
  • Expiration Month/Year
  • CVV
  1. Once the form has been submitted, you can use the Hosted Payment Fields token to process the purchase, create a shopper, or update a shopper with the new card details provided on the checkout page.
750750

Back to Top

Implementing Hosted Payment Fields in your checkout form

Follow the steps below in order to implement Hosted Payment Fields in your checkout form.

📘

Insert the domain for either Sandbox or Production

In all steps below, replace the BLUESNAPDOMAINPATH with the relevant domain for either the BlueSnap Sandbox or Production environment, as follows:

  • Sandbox: https://sandpay.bluesnap.com
  • Production: https://pay.bluesnap.com

For example, the Hosted Fields token request (step 1) should be sent to https://sandpay.bluesnap.com/services/2/payment-fields-tokens on Sandbox and https://pay.bluesnap.com/services/2/payment-fields-tokens on Production.

1. Obtain the Hosted Payment Field token for the session

Obtain the Hosted Payment Field token by sending a server-to-server POST request to:

Production: https://ws.bluesnap.com/services/2/payment-fields-tokens Sandbox: https://sandbox.bluesnap.com/services/2/payment-fields-tokens

The response provides the token in the location header. For example:

Production: https://ws.bluesnap.com/services/2/payment-fields-tokens/HOSTEDFIELDTOKENID Sandbox: https://sandbox.bluesnap.com/services/2/payment-fields-tokens

📘

Note

You will need a BlueSnap account in order to generate a Hosted Payment Field token. If you don't have an account yet, you can sign up for one here.

The Hosted Payment Fields Token expires after 60 minutes.

2. Add the BlueSnap JavaScript file to your checkout form

In your checkout page, call the BlueSnap Hosted Payment Fields JavaScript file by adding the following script:

<script type="text/javascript" src="BLUESNAPDOMAINPATH/web-sdk/5/bluesnap.js"></script>

3. Add the Hosted Payment Fields to your checkout form

Replace the credit card number, expiration date, and CVV input fields in your checkout form with the following <div> elements.

🚧

Important!

The values for the data-bluesnap attributes must be typed exactly as they appear in the below code in order for your implementation to work.

<div data-bluesnap="ccn"></div>
            
<div data-bluesnap="exp"></div>
            
<div data-bluesnap="cvv"></div>

4. Add a script to initiate the Hosted Payment Fields with your Hosted Fields token

In order to call the Hosted Payment Fields script, add the following script to your checkout page below the <div> elements.

<script>
  var bsObj = {
    token: " HOSTEDFIELDTOKENID ",
    onFieldEventHandler: {
      /*OPTIONAL*/ setupComplete: function () {
        console.warn("setupComplete");
      },
      /*OPTIONAL*/ threeDsChallengeExecuted: function () {
        console.warn("threeDsChallengeExecuted");
      },
      // tagId returns: "ccn", "cvv", "exp"
      onFocus: function (tagId) {}, // Handle focus
      onBlur: function (tagId) {}, // Handle blur
      onError: function (tagId, errorCode /*, errorDescription, eventOrigin*/) {}, // Handle a change in validation
      /*errorCode returns:
              "10" --> invalid | empty where errorDescription will return invalid if input field invalid or empty if input field is empty (tagId will indicate which input);
              "22013" --> "CC type is not supported by the merchant"; 
              "14040" --> " Token is expired";
              "14041" --> " Could not find token";
              "14042" --> " Token is not associated with a payment method, please verify your client integration or contact BlueSnap support";
              "400" --> "Session expired please refresh page to continue";
              "403", "404", "500" --> "Internal server error please try again later"; 
          */

      /* errorDescription is optional. Returns BlueSnap's standard error description */
      /* eventOrigin is optional. Returns BlueSnap's event origin: onBlur | onSubmit */

      onType: function (tagId, cardType /*, cardData*/) {
        /* cardType will give card type, and only applies to ccn: AMEX, VISA, MASTERCARD, AMEX, DISCOVER, DINERS, JCB */
        if (null != cardData) {
          /* cardData is an optional parameter which will provide ccType, last4Digits, issuingCountry, isRegulatedCard, cardSubType, binCategory and ccBin details (only applies to ccn) in a JsonObject */
          console.log(cardData);
        }
      },
      onEnter: function(tagId) {} // Will trigger when shopper presses enter while inside one of the inputs
    
      onValid: function (tagId) {} // Handle a change in validation
    },
    /* example:
          style: {
          "Selector": {
          "Property": "Value",
          "Property2": "Value2"
          },                                                                                                                                                             
          "Selector2": {
          "Property": "Value"
          } 
      }, */
    style: {
      ":focus": {
        //style for all input elements on focus event
        color: "orange"
      },
      input: {
        //style for all input elements
        color: "blue"
      },
      ".invalid": {
        //style for all input elements when invalid
        color: "red"
      }
    },
    ccnPlaceHolder: "1234 5678 9012 3456", //for example
    cvvPlaceHolder: "123", //for example
    expPlaceHolder: "MM/YY", //for example
  };

  //Run the following command after Document Object Model (DOM) is fully loaded
  bluesnap.hostedPaymentFieldsCreate(bsObj);
</script>

Replace HOSTEDFIELDTOKENID with the token you obtained in step 1.

Use onFieldEventHandler to handle focus, blur, validation events, and to get the card type. For example, you can use this to identify when the user has entered a Visa card and then show the relevant icon for Visa.

Note: If you want to use BlueSnap icons per card type, simply choose the appropriate URL path and add it to the end of the URL below:

URL: https://pay.bluesnap.com/web-sdk/5/assets/cards/.

URL Paths:

  • AMEX: amex.png
  • DINERS: diners.png
  • DISCOVER: discover.png
  • JCB: jcb.png
  • MASTERCARD: mastercard.png
  • VISA: visa.png

Styling is optional. For more details on style capabilities, see Styling the Hosted Payment Fields.

Customizing accessibility features is optional. For more details on accessibility capabilities, see Customizing Accessibility Features.

Masking is optional. For more details on the masking capabilities, see Masking Hosted Payment Fields.

Optionally, use these to define what placeholder appears in each Hosted Payment Field input:

  • ccnPlaceHolder
  • cvvPlaceHolder
  • expPlaceHolder

📘

If you're using the Complete fraud prevention level, include enterpriseId set to your Kount ID within bsObj.

var bsObj = {
  // ...
  enterpriseId: "KOUNT_ID"
};
bluesnap.hostedPaymentFieldsCreate(bsObj);

5. Add a script to submit credit card, expiration date, and CVV data

Add the script below into your checkout form:

<script>
    function do_when_clicking_submit_button(){
    bluesnap.hostedPaymentFieldsSubmitData( function(callback){
        if (null != callback.cardData) {
            var fraudSessionId = callback.transactionFraudInfo.fraudSessionId;

            console.log('card type: ' + callback.cardData.ccType +
                ', last 4 digits: ' + callback.cardData.last4Digits +
                ', exp: ' + callback.cardData.exp +
                ', issuing Country: ' + callback.cardData.issuingCountry +
                ', isRegulatedCard: ' + callback.cardData.isRegulatedCard +
                ', cardSubType: ' + callback.cardData.cardSubType +
                ', binCategory: ' + callback.cardData.binCategory +
                ', cardCategory: ' + callback.cardData. cardCategory +
                ', ccBin: ' + callback.cardData.ccBin +
                ' and fraudSessionId: ' + fraudSessionId +
                ', after that I can call final submit');
            // submit the form 
        } else {
            var errorArray = callback.error;
            for (i in errorArray) {
                console.log("Received error: tagId= " +
                    errorArray[i].tagId + ", errorCode= " +
                    errorArray[i].errorCode + ", errorDescription= " +
                    errorArray[i].errorDescription);
            }
        }
    });
}                                             
</script>

This function should be activated when the shopper clicks the Submit button. This submits the credit card number, expiration date, and CVV data to BlueSnap, where it is associated with the Hosted Payment Fields token.

If the data submission to BlueSnap is successful, a card data object containing the card type, last four digits, and expiration date are passed to the function(callback) { // callback.cardData}, else if there is an error in submission callback.error receives an array and each item contains errorArray[i].tagId, errorArray[i].errorCode, errorArray[i].errorDescription, if it is either a client error or server error.

📘

Card validation

The card is validated when you send it in a transaction or you save it to a shopper.

👍

Add 3D Secure for increased checkout security

Visit the 3D Secure guide to learn how to add 3D Secure to your configuration.

Back to Top

BlueSnap JavaScript errors

The following are all the errors that can be passed to your onError callback function in the errorCode and errorDescription parameters.

errorCode

errorDescription value

'10'

  • If tagId is ccn, errorDescription is 'invalid' or ‘empty’.
  • If tagId is cvv, errorDescription is 'invalid' or ‘empty’.
  • If tagId is exp, errorDescription is 'invalid' or ‘empty’.

'22013'

'CC type is not supported by the merchant'

'14040'

'Token is expired'

'14041'

'Could not find token'

'14042'

'Token is not associated with a payment method, please verify your client integration or contact BlueSnap support'

'400'

'Session expired please refresh page to continue'

'403', '404', '500'

'Internal server error please try again later'

3-D Secure Errors

For all the 3-D Secure JavaScript errors, see the 3-D Secure for API Guide.

Updating the BlueSnap Token

If the token expires (expiration occurs after 60 minutes, see error code event 14040), you can update it by creating a new token (see Obtain the Hosted Payment Field token for the session) and update the solution accordingly:

bluesnap.hostedPaymentFieldsUpdateToken(new token string);

Styling the Hosted Payment Fields

Much of the styling of the Hosted Payment Fields (i.e. width, height, and outer styling) can be performed as usual via CSS.

The Hosted Payment Fields are iframes within the <div> containers, and they are nearly invisible in terms of styling. The iframes themselves do not have a border and their width and height are 100%. Input inside the iframes has no border margin or padding, has a width and height of 100%, and has a transparent background. Placeholders for inputs are provided automatically.

To apply styling inside of the Hosted Payment Fields, use the style JavaScript shown in step 4.

Supported CSS properties

We support the following CSS properties inside of the Hosted Payment Fields:

  • -webkit-appearance
  • appearance
  • background-color, background-origin, background-position, background-repeat, background-size
  • border-bottom, border-bottom-color, border-bottom-left-radius, border-bottom-right-radius, border-bottom-style, border-bottom-width, border-color, border-left, border-left-color, border-left-style, border-left-width, border-radius, border-right, border-right-color, border-right-style, border-right-width, border-style, border-top, border-top-color, border-top-left-radius, border-top-right-radius, border-top-style, border-top-width, border-width
  • bottom
  • color
  • display
  • font, font-family, font-size, font-style, font-weight
  • height
  • left
  • letter-spacing
  • line-height
  • margin, margin-bottom, margin-left, margin-right, margin-right, margin-top
  • opacity
  • outline
  • padding, padding-bottom, padding-left, padding-right, padding-top
  • position,
  • right
  • text-align
  • text-decoration
  • text-shadow
  • top
  • transition
  • width

Note: Using any unsupported CSS properties results in failure of the Hosted Payment Fields.

Selectors

You can use the following selectors to define when the style is applied:

  • #ccn, #ccn:focus, #ccn:focus:-moz-placeholder, #ccn:focus:-ms-input-placeholder, #ccn:focus::-moz-placeholder, #ccn:focus::placeholder, #ccn:focus::-webkit-input-placeholder, #ccn:hover, #ccn.invalid, #ccn.valid
  • #cvv, #cvv:focus, #cvv:focus:-moz-placeholder, #cvv:focus:-ms-input-placeholder, #cvv:focus::-moz-placeholder, #cvv:focus::placeholder, #cvv:focus::-webkit-input-placeholder, #cvv:hover, #cvv.invalid, #cvv.valid
  • #exp:hover
  • :focus, :focus:-moz-placeholder, :focus:-ms-input-placeholder, :focus::-moz-placeholder, :focus::placeholder, :focus::-webkit-input-placeholder
  • :hover, :hover::placeholder
  • input
  • .invalid, .invalid:focus
  • :-moz-placeholder
  • ::-moz-placeholder
  • :-ms-input-placeholder
  • ::placeholder
  • .valid, .valid:focus
  • ::-webkit-input-placeholder

Examples

var bsObj = {
  //...
  style: {
    "input": {
      //style for all input elements
      "font": "bold 14px Arial",
      "color": "#4A5157
    },
    ":focus": {
      //style for all elements on focus event
      "color": "orange"
    },
    "#ccn": {
      //style only ccn element
      "color": "blue"
    },
    "#cvv.invalid": {
      //style cvv input when invalid
      "color": "red"
    }
  }
};

Back to Top

Customizing Accessibility Features

Hosted Payment Fields accessibility features are provided as part of the solution but, you also have the option to customize some of these features.

Customizing field names for screen readers

  • Add a fieldNames object inside the accessibility object and provide names for each or some of the fields inside it. The names you provide will replace the default names we use for the aria-label attribute (which can be used by screen readers to address each field).
var bsObj = {
  //...
    accessibility: /*OPTIONAL*/ { 
      fieldNames: /*OPTIONAL*/{
        ccn: 'Card number input', //for example
        exp: 'Card expiration date input', //for example
        cvv: 'Card CVC/CVV input' //for example
      }
    }

};

UpdateAccessibilityError Callback Function

  • We pass updateAccessibilityError to your onError handler. this callback function accepts only strings and allows you to change the field’s accessibility error message (error message is invisible and meant for screen reader usage).
  • This function will only be passed if the error originated from a specific field, and it is meant to be used inside your onError function. You can use other parameters that you receive to determine an appropriate error message.
  • If you don’t make use of this function inside your onError, the field accessibility error message will default to the errorDescription that we pass as a parameter to your onError.
onError: function (tagId, errorCode, errorDescription, eventOrigin, updateAccessibilityError){
// ...Handle the error

// Update the error message:
    if (updateAccessibilityError) { // Make sure the function was passed
           var error = 'invalid input';
           switch(tagId) { // Conditionally determine an appropriate error message
                 case 'ccn':
                       error = 'invalid card number';//for example
                       break;
                 case 'exp':
                       error = 'invalid expiration date';//for example
                       break;
                 case 'cvv':
                       error = 'invalid card verification value'; //for example
                       break;
                 default:
                       break;
        }
         updateAccessibilityError(error); // Update the error message of the field
    }
}

Masking Hosted Payment Field Inputs

You can activate masking for the CCN and the CVV fields by using the ccnMask and cvvMask properties inside your sdkRequest object.

  • ccnMask: When set to true, this enables masking capability for the credit card number input. The input will be masked when the shopper leaves the field and unmasked when he enters it. The last four digits of the number will always be visible.
  • cvvMask: When set to true, this enables masking capability for the cvv input. The shopper will be able to toggle the field from masked to unmasked by clicking the eye icon which will appear inside the cvv field.
var bsObj = {
  //...
    ccnMask: true,
    cvvMask: true
};

Example forms

Below are two examples of checkout forms that use BlueSnap's Hosted Payment Fields. Click the HTML/CSS/JS tabs to view the code.

Example 1: with Bootstrap styling

Example 2: with Material styling


Back to Top

Using the Hosted Payment Fields token to process payments and save shopper info

Once you have implemented Hosted Payment Fields in your checkout form, you can then process payments, as well as save shopper information, by including the Hosted Payment Fields token in your API requests. See below for more information on how to do this in either the Payment API or the Extended Payment API.

📘

Note

The Hosted Payment Fields token can be used only once to either process a transaction or save shopper payment info.

If you want to use Hosted Payment Fields to vault a shopper and then process a charge, please contact BlueSnap implementation to enable a multi-use-token for improved conversions.

In the Payment API

To use the Hosted Payment Fields token to process a payment, send the token within the pfToken property in your Auth Capture, Auth Only, or Create Subscription.

To save the card information from the Hosted Payment Fields in a new or existing vaulted shopper, send the token within the pfToken property in your Create Vaulted Shopper or Update Vaulted Shopper request.

Example requests:

{
    "amount": 11,
    "softDescriptor": "DescTest",
    "cardHolderInfo": {
        "firstName": "test first name",
        "lastName": "test last name", 
        "zip": "123456"
    },
    "currency": "USD",
    "cardTransactionType": "AUTH_CAPTURE",
    "pfToken": "abcde12345**********"
}
{
    "paymentSources": {"creditCardInfo": [{"pfToken": "9688f4f6945f615b1ab6954ceb5dbf67f63d6b41fa27dbff6ac342cff9bf50fc_"}]},
    "firstName": "FirstName",
    "lastName": "LastName"
}
{
    "firstName": "FirstName",
    "lastName": "LastName",
    "paymentSources": {"creditCardInfo": [{
         "pfToken": "9688f4f6945f615b1ab6954ceb5dbf67f63d6b41fa27dbff6ac342cff9bf50fc_"
    }]}
}

In the Extended Payment API

New shopper

To use the Hosted Payment Fields token to process a payment for a new shopper, you can send the token within the pf-token property in your Create Order and New Shopper or Create Shopping Context request.

<batch-order xmlns="http://ws.plimus.com">
  <shopper>
    <web-info>
      <ip>62.219.121.253</ip>
    </web-info>
    <shopper-info>
      <shopper-currency>USD</shopper-currency>
      <store-id>4677</store-id>
      <locale>en</locale>
      <shopper-contact-info>
        <title>Mr.</title>
        <first-name>John</first-name>
        <last-name>Doe</last-name>
        <email>[email protected]</email>
        <company-name>JohnDoeAndSons</company-name>
        <address1>138 Market st</address1>
        <city>San Francisco</city>
        <zip>756543</zip>
        <state>CA</state>
        <country>US</country>
        <phone>1413555666</phone>
        <fax>1413555666789</fax>
      </shopper-contact-info>
      <payment-info>
        <credit-cards-info>
          <credit-card-info>
            <billing-contact-info>
              <first-name>John</first-name>
              <last-name>Doe</last-name>
              <address1>138 Market st</address1>
              <city>San Francisco</city>
              <zip>756543</zip>
              <state>CA</state>
              <country>US</country>
            </billing-contact-info>
            <pf-token>c7c69ff853ab784ef35a0c78ffec08e78cf1d1b5b4bb9e2644c2bcc73f3f818f_1</pf-token>
          </credit-card-info>
        </credit-cards-info>
      </payment-info>
    </shopper-info>
  </shopper>
  <order>
    <ordering-shopper>
      <web-info>
        <ip>62.219.121.253</ip>
        <remote-host>www.merchant.com</remote-host>
        <user-agent>Mozilla/5.0 (Linux; X11)</user-agent>
      </web-info>
    </ordering-shopper>
    <cart>
      <cart-item>
        <sku>
          <sku-id>2152762</sku-id>
        </sku>
        <quantity>1</quantity>
      </cart-item>
    </cart>
    <expected-total-price>
      <amount>15.00</amount>
      <currency>USD</currency>
    </expected-total-price>
  </order>
</batch-order>
<shopping-context xmlns="http://ws.plimus.com">
  <web-info>
    <ip>62.219.121.253</ip>
    <remote-host>
    bzq-219-121-253.static.bezeqint.net.reinventhosting.com</remote-host>
    <user-agent>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;
    SV1; GTB6.3; .NET CLR 2.0.50727)</user-agent>
    <accept-language>en-us</accept-language>
  </web-info>
  <shopper-details>
    <shopper>
      <shopper-info>
        <shopper-contact-info>
          <title>Mr</title>
          <first-name>shopper first name</first-name>
          <last-name>shopper last name</last-name>
          <email>[email protected]</email>
          <company-name>JS Company</company-name>
          <address1>123 Oxford</address1>
          <address2 />
          <city>London</city>
          <state>ny</state>
          <zip>54321</zip>
          <country>us</country>
          <phone>1800808080</phone>
          <fax>1800808080</fax>
        </shopper-contact-info>
        <shipping-contact-info>
          <first-name>Shipping first name</first-name>
          <last-name>Shipping last name</last-name>
          <address1>123 Oxford</address1>
          <address2 />
          <city>London</city>
          <state>ny</state>
          <zip>54321</zip>
          <country>us</country>
        </shipping-contact-info>
        <invoice-contacts-info>
          <invoice-contact-info>
            <default>true</default>
            <company-name>BlueSnap UK</company-name>
            <vat-code></vat-code>
            <title>Mrs.</title>
            <first-name>John</first-name>
            <last-name>Black</last-name>
            <address1>5 star drive</address1>
            <address2>3rd entrance</address2>
            <city>Purchase</city>
            <state>NY</state>
            <zip>34645</zip>
            <country>us</country>
            <phone>1800400500</phone>
            <fax>1800400500</fax>
            <email>[email protected]</email>
          </invoice-contact-info>
        </invoice-contacts-info>
        <payment-info>
          <credit-cards-info>
            <credit-card-info>
              <billing-contact-info>
                <first-name>John</first-name>
                <last-name>Doe</last-name>
                <address1>138 Market st</address1>
                <city>San Francisco</city>
                <zip>756543</zip>
                <state>CA</state>
                <country>US</country>
              </billing-contact-info>
              <pf-token>c7c69ff853ab784ef35a0c78ffec08e78cf1d1b5b4bb9e2644c2bcc73f3f818f_1</pf-token>
            </credit-card-info>
          </credit-cards-info>
        </payment-info>
        <store-id>12700</store-id>
        <vat-code></vat-code>
        <shopper-currency>USD</shopper-currency>
        <locale>en</locale>
      </shopper-info>
    </shopper>
  </shopper-details>
  <order-details>
    <order>
      <cart>
        <cart-item>
          <sku>
            <sku-id>2178316</sku-id>
            <sku-charge-price>
              <charge-type>initial</charge-type>
              <amount>50.00</amount>
              <currency>USD</currency>
            </sku-charge-price>
          </sku>
          <quantity>1</quantity>
        </cart-item>
      </cart>
      <expected-total-price>
        <amount>50.00</amount>
        <currency>USD</currency>
      </expected-total-price>
    </order>
  </order-details>
</shopping-context>

Existing shopper

To use the Hosted Payment Fields token to process a payment for an existing shopper, first update the existing shopper with the information from the Hosted Payment Fields by sending the token within the pf-token property in your Update Shopper request.

You can then process the payment as usual, by including the relevant shopper ID in the Create Order with Existing Shopper or Create Shopping Context request.

<shopper xmlns="http://ws.plimus.com">
  <web-info>
    <ip>62.219.121.253</ip>
  </web-info>
  <shopper-info>
    <store-id>4677</store-id>
    <payment-info>
      <credit-cards-info>
        <credit-card-info>
          <billing-contact-info>
            <first-name>John</first-name>
            <last-name>Doe</last-name>
            <address1>138 Market st</address1>
            <city>San Francisco</city>
            <zip>756543</zip>
            <state>CA</state>
            <country>US</country>
          </billing-contact-info>
          <pf-token>c7c69ff853ab784ef35a0c78ffec08e78cf1d1b5b4bb9e2644c2bcc73f3f818f_1</pf-token>
        </credit-card-info>
      </credit-cards-info>
    </payment-info>
  </shopper-info>
</shopper>

Back to Top