Learn how to implement Hosted Payment Fields for PCI compliance of SAQ-A & maximum flexibility.
If you still have questions after reading, check out the 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
Styling the Hosted Payment Fields
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
- You create a Hosted Payment Fields token for the specific checkout session, using a server-to-server API call.
- On the checkout form, you call BlueSnap’s Hosted Fields JavaScript file with this Hosted Payment Fields token.
- 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
- 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.
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 andhttps://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 the 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 withinbsObj
.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.
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"
}
}
};
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
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>