Implementing a Hosted Session Integration

The Hosted Session JavaScript client library enables you to collect sensitive payment details from the payer in payment form fields, hosted by the Mastercard Payment Gateway. The gateway collects the sensitive payment details in a payment session and temporarily stores them for later use. You can then include a payment session in place of payment details in the transaction request to process a payment. For more information, see payment session.

Hosted Session is a PCI v3 compliant integration method that facilitates SAQ-A compliance, while allowing control over the payment page layout and style. In this model, the entirety of the sensitive payment fields are embedded in iFrames sourced from and controlled by the Mastercard Payment Gateway. Standard browser security protection mechanisms isolate sensitive fields from you, preserving the integrity of the payment channel provided by the gateway.

Prerequisites

  • Ensure that your merchant profile is enabled for the Hosted Session service.
  • Hosted Session is only supported from API version 18 and later.

Request a Hosted Session Interaction

This section describes a simple integration for Hosted Session to collect payer's credit card details.

<html>
<head>
<!-- INCLUDE SESSION.JS JAVASCRIPT LIBRARY -->
<script src="https://evopaymentsmexico.gateway.mastercard.com/form/version/72/merchant/<MERCHANTID>/session.js"></script>
<!-- APPLY CLICK-JACKING STYLING AND HIDE CONTENTS OF THE PAGE -->
<style id="antiClickjack">body{display:none !important;}</style>
</head>
<body>

<!-- CREATE THE HTML FOR THE PAYMENT PAGE -->

<div>Please enter your payment details:</div>
<h3>Credit Card</h3>
<div>Card Number: <input type="text" id="card-number" class="input-field" title="card number" aria-label="enter your card number" value="" tabindex="1" readonly></div>
<div>Expiry Month:<input type="text" id="expiry-month" class="input-field" title="expiry month" aria-label="two digit expiry month" value="" tabindex="2" readonly></div>
<div>Expiry Year:<input type="text" id="expiry-year" class="input-field" title="expiry year" aria-label="two digit expiry year" value="" tabindex="3" readonly></div>
<div>Security Code:<input type="text" id="security-code" class="input-field" title="security code" aria-label="three digit CCV security code" value="" tabindex="4" readonly></div>
<div>Cardholder Name:<input type="text" id="cardholder-name" class="input-field" title="cardholder name" aria-label="enter name on card" value="" tabindex="5" readonly></div>
<div><button id="payButton" onclick="pay('card');">Pay Now</button></div>

<!-- JAVASCRIPT FRAME-BREAKER CODE TO PROVIDE PROTECTION AGAINST IFRAME CLICK-JACKING -->
<script type="text/javascript">
if (self === top) {
    var antiClickjack = document.getElementById("antiClickjack");
    antiClickjack.parentNode.removeChild(antiClickjack);
} else {
    top.location = self.location;
}

PaymentSession.configure({
    session: "<your_session_ID>",
    fields: {
        // ATTACH HOSTED FIELDS TO YOUR PAYMENT PAGE FOR A CREDIT CARD
        card: {
            number: "#card-number",
            securityCode: "#security-code",
            expiryMonth: "#expiry-month",
            expiryYear: "#expiry-year",
            nameOnCard: "#cardholder-name"
        }
    },
    //SPECIFY YOUR MITIGATION OPTION HERE
    frameEmbeddingMitigation: ["javascript"],
    callbacks: {
        initialized: function(response) {
            // HANDLE INITIALIZATION RESPONSE
        },
        formSessionUpdate: function(response) {
            // HANDLE RESPONSE FOR UPDATE SESSION
            if (response.status) {
                if ("ok" == response.status) {
                    console.log("Session updated with data: " + response.session.id);
  
                    //check if the security code was provided by the user
                    if (response.sourceOfFunds.provided.card.securityCode) {
                        console.log("Security code was provided.");
                    }
  
                    //check if the user entered a Mastercard credit card
                    if (response.sourceOfFunds.provided.card.scheme == 'MASTERCARD') {
                        console.log("The user entered a Mastercard credit card.")
                    }
                } else if ("fields_in_error" == response.status)  {
  
                    console.log("Session update failed with field errors.");
                    if (response.errors.cardNumber) {
                        console.log("Card number invalid or missing.");
                    }
                    if (response.errors.expiryYear) {
                        console.log("Expiry year invalid or missing.");
                    }
                    if (response.errors.expiryMonth) {
                        console.log("Expiry month invalid or missing.");
                    }
                    if (response.errors.securityCode) {
                        console.log("Security code invalid.");
                    }
                } else if ("request_timeout" == response.status)  {
                    console.log("Session update failed with request timeout: " + response.errors.message);
                } else if ("system_error" == response.status)  {
                    console.log("Session update failed with system error: " + response.errors.message);
                }
            } else {
                console.log("Session update failed: " + response);
            }
        }
    },
    interaction: {
        displayControl: {
            formatCard: "EMBOSSED",
            invalidFieldCharacters: "REJECT"
        }
    }
 });

function pay() {
    // UPDATE THE SESSION WITH THE INPUT FROM HOSTED FIELDS
    PaymentSession.updateSessionFromForm('card');
}
</script>
</body>
</html>

Step 1: Create a Session

Create a session by submitting a Create Session request from your server-side application. Please specify a session authentication limit of 25. The response returns a session ID that you must use in the subsequent steps to reference this session.

URL https://evopaymentsmexico.gateway.mastercard.com/api/rest/version/72/merchant/<your_gateway_merchant_ID>/session
HTTP Method POST
 {
   "session":{
      "authenticationLimit":25
   }
}

Step 2: Update the Session with the Order Amount and Currency

Update the session with at least the currency and order amount by submitting a Update Session request from your server-side application. This step is required to subsequently inquire whether the card is supported and whether card security code is required.

URL https://evopaymentsmexico.gateway.mastercard.com/api/rest/version/72/merchant/<your_gateway_merchant_ID>/session/<your_session_ID>
HTTP Method PUT
 {
    "order":{
       "amount":100.00,
       "currency":"USD"
    }
 }

Step 3: Include session.js Client JavaScript Library in your Payment Page

Include the session.js client JavaScript library hosted by the gateway in your payment page by adding a script element within the head element. The path to this file includes both the api version and the merchant identifier for the session. This places a PaymentSession object into the window namespace.

<script type="text/javascript" src="https://evopaymentsmexico.gateway.mastercard.com/form/version/72/merchant/<your_gateway_merchant_ID>/session.js"></script>

Step 4: Create the HTML for the Payment Page Containing the Credit Card Fields

To prevent submission of sensitive data to the server, ensure the sensitive data fields are readonly and do NOT have the name attribute.

Step 5: Invoke PaymentSession.configure(configuration) Function

The configuration object allows you to attach hosted fields to your payment page and/or configure the payment interaction. You need to provide the following:

  • Include the session.id created in Step 1: Create a Session.
  • Field selectors for credit card fields, which when provided are replaced with corresponding proxy fields embedded in iFrames hosted by the Mastercard Payment Gateway. The proxy fields will have the same look and feel as the replaced fields. You can capture payment details for other payment types, see Supported Payment Methods via Hosted Session.
  • mitigation option(s) for clickjacking prevention

    Clickjacking, also known as a "UI redress attack", is when an attacker uses multiple transparent or opaque layers to trick a user into clicking on a button or link on another page when they were intending to click on the top level page. To use Hosted Session, you must implement one or more of the following defenses against clickjacking attacks.

    Frame Mitigation Option Implementation
    javascript include "frame-breaker" JavaScript in your payment page.
    x-frame-options your server should return an X-Frame Options HTTP response header.
    csp your server should return Content-Security-Policy HTTP response header containing a frame-ancestors directive.

    You must specify which defenses are implemented via the frameEmbeddingMitigation parameter in the PaymentSession.configure(configuration) call. For information on defending against clickjacking attacks, see Clickjacking Defense Cheat Sheet on the OWASP External Website.

  • callbacks for handling various events during the Hosted Session interaction
    • initialized( ): invoked when the hosted fields attach to your payment page.
    • formSessionUpdate( ): invoked in response to the PaymentSession.updateSessionFromForm(paymentType) function (see next step)

Step 6: Invoke updateSessionFromForm

Invoke PaymentSession.updateSessionFromForm('card') to store the payment details captured for the payment type 'card', into a payment session. Once the operation completes, formSessionUpdate() callback is invoked with a result parameter. You must check the result.status value to determine if the operation was successful. See Handle Callback Responses

Step 7: Use Payment Session Data

You can use the returned payment session (session.id) to perform a tokenization or a payment transaction when required. For more information, see Perform an Operation Using the Session.

Supported Payment Methods via Hosted Session

Hosted Session allows you to configure one or more of the following payment methods to capture payment details from the payer. The payment details are captured via hosted fields attached to your payment form with the exception of digital wallets where the payment details are captured from a wallet interaction.

For every supported payment method, Hosted Session allows you to collect and submit full, partial, or individual (except card expiry month and card expiry year) payment details into a payment session. You can use the returned payment session in combination with multiple sources to process a payment. For example, if you have already tokenized the payer's card number and expiry date, then you can use Hosted Session to collect only the CSC/CVV, and use the card details from both the sources collectively to perform a payment. Or, you can use Hosted Session to collect only the card expiry date in a payment session, and update an expired card stored against a token.
Credit/Debit Cards

You can capture the following card details via hosted fields:

  • card.number
  • card.expiryMonth
  • card.expiryYear
  • card.securityCode
  • card.nameOnCard
All the fields are optional; however, if card.expiryMonth is configured then card.expiryYear is mandatory and vice versa.
Gift Cards

You can capture the following gift card details via hosted fields:

  • giftCard.number
  • giftCard.pin

See Gift Card integration via Hosted Session.

Automated Clearing House Payments

Hosted Session allows you to capture payment details for Direct Payments (payments) and Direct Deposits (refunds) via Automated Clearing House. You can capture the following Automated Clearing House details via hosted fields:

  • ach.routingNumber
  • ach.bankAccountNumber
  • ach.bankAccountNumberConfirmation
  • ach.bankAccountHolder
  • ach.accountType

See Automated Clearing House integration via Hosted Session.

Digital Wallets

Hosted Session allows you to capture payment details from a wallet interaction. Currently, Secure Remote Commerce wallet interactions are supported. You must be enabled for Secure Remote Commerce via the Mastercard Payment Gateway to initiate this interaction. See Secure Remote Commerce.

Field Data Validation Feedback

Hosted Session allows you to provide validation feedback to the payer during the various payment interaction stages on the user interface:

  • On every keystroke by listening to onValidityChange callback:
       PaymentSession.onValidityChange(["card.number", "card.nameOnCard"], function (selector, result) {
    
          if (result.isValid) {
    
            console.log("The field value is valid");
    
            document.querySelector(selector).style.borderColor = "green";
    
          } else if (result.isIncomplete) {
            console.log("The field value is not yet valid");
            document.querySelector(selector).style.borderColor = "grey";
             } else {
    
                    console.log("The field value is invalid");
    
            document.querySelector(selector).style.borderColor  = "red";
    
          }
    
        });
    
  • Once the payer is finished typing and leaves the field:
    1. Listening for the onBlur() event
    2. Invoking validate()
    3. Displaying any errors for that field from the validate() callback
    PaymentSession.onBlur( ["card.number", "card.nameOnCard", "card.securityCode", "card.expiryYear", "card.expiryMonth"],
    
    function (selector, role)
    
    { PaymentSession.validate('card', function (allresult) {
    
    if (allresult.card[role].isValid) {
    
    console.log("The field is valid");
    document.querySelector(selector).style.borderColor = "green";
    
    } else {
    
    console.log("The field is invalid");
    
    document.querySelector(selector).style.borderColor = "red";
    
    }
    
    });
    
    });
    
  • When the payer clicks the page's next action button:
    1. Invoking updateSessionFromForm()
    2. Displaying any errors from the formSessionUpdate callback

Regardless of your approach, you must expect and handle errors from the formSessionUpdate callback. While the validate() method may indicate validity, the formSessionUpdate validation is more comprehensive and may detect additional errors.

Handle Callback Responses

Results for Hosted Fields via initialized(result)
If result.status=="ok"

The hosted fields are successfully attached to your payment page.

       // An ok response
{
    "status":"ok",
}
       
If result.status=="system_error" or result.status=="request_timeout"

An error has occurred while attaching the hosted fields. You should retry after a short period.

// An error response (system_error)
{
    "status": "system_error",  
    "message": "System error message." 
}
// An error response (request_timeout)
{
    "status" : "request_timeout", 
    "message": "Request timeout error message."
}
       
Results for Update Session via formSessionUpdate(result)
If result.status=="ok"

The session now contains the collected card details.

// An ok response
{
    "status":"ok",
    "merchant": "TESTMERCHANT",
    "session": {
        "id": "SESSION000218450948092491657986"
        "updateStatus":"SUCCESS",
        "version":"e3f144ce02"
    },
    "sourceOfFunds": {
        "provided": {
            "card": {
                "brand": "MASTERCARD",
                "expiry": {
                    "month": "1",
                    "year": "39"
                },
                "fundingMethod": "DEBIT",
                "nameOnCard": "John Smith",
                "number": "512345xxxxxx8769",
                "scheme": "MASTERCARD"
            }
        },
        "type": "CARD"
    },   
    "version": "43"
}
       
If result.status=="fields_in_error"

The payer input is invalid and you should prompt the payer to update their input. The errors response structure contains information about the invalid fields.

       // An error response (fields_in_error)
{
    "status": "fields_in_error",  
    "session": {
        "id": "SESSION000218450948092491657986"
    },
    "errors": {
        "cardNumber": "invalid",
        "securityCode": "invalid"  
    },
    version: "43"
}
       
If result.status=="system_error" or result.status=="request_timeout"

An error has occurred when processing the update. You should retry the session update after a short period.

       // An error response (system_error)
{
    "status": "system_error",  
    "session": {
        "id": "SESSION000218450948092491657986"
    },
    "errors": {
        "message": "System error message." 
    },
    "version": "43"
}
  // An error response (request_timeout)
{
    "status" : "request_timeout", 
    "session": {
        "id": "SESSION000218450948092491657986"
    },
    "errors": {
        "message": "Request timeout error message."
    },
    "version": "43"
}
       

Listen to Events on Hosted Fields

Hosted Session allows you to register callback functions to handle events that may occur on the hosted fields during the payer's interaction.

You can register callback functions for the following events:
  • onChange( ): Invoked when the input value in the hosted field in the iFrame has changed.
  • onFocus( ): Invoked when the hosted field in the iFrame has gained focus.
  • onBlur( ): Invoked when the hosted field in the iFrame has lost focus.
  • onMouseOver( ): Invoked when a mouse over event occurs in the hosted field.
  • onMouseOut( ): Invoked when a mouse out event occurs in the hosted field.
 /**
 * Provide an array of field roles for proxy fields as the first parameter
 * Each callback function is invoked with the selector for the field whose proxy triggered the event.
 */
 
PaymentSession.onBlur(['card.number'], function(selector) {
    //handle blur event
});
PaymentSession.onFocus(['card.number', 'card.securityCode'], function(selector) {
    //handle focus event
});
PaymentSession.onChange(['card.securityCode'], function(selector) {
    //handle change event
});
PaymentSession.onMouseOver(['card.number'], function(selector) {
    //handle mouse over event
});
PaymentSession.onMouseOut(['card.number'], function(selector) {
    //handle mouse out event
});
    

Advanced Styling of Hosted Fields

Hosted Session allows you to style hosted fields to match the look and feel of the replaced fields on your payment page.

You can invoke the following functions for styling:
  • setFocus( ): Sets focus on the specified hosted field.
  • setFocusStyle( ): Sets the styling attributes for the specified hosted fields when the focus is gained.
  • setHoverStyle( ): Sets the styling attributes for the specified hosted fields when a mouse hover occurs.
  • setPlaceholderStyle( ): Sets the styling attributes for the placeholder text for the specified hosted fields.
  • setPlaceholderShownStyle( ): Sets the styling attributes for the specified hosted fields when the placeholder text is visible.
PaymentSession.setFocus('card.number');
    
PaymentSession.setFocusStyle(["card.number","card.securityCode"], {
  borderColor: 'red',
  borderWidth: '3px'
});

PaymentSession.setHoverStyle(["card.number","card.securityCode"], {
  borderColor: 'red',
  borderWidth: '3px'
});

PaymentSession.setPlaceholderStyle(["card.number", "card.nameOnCard"], {
  color: 'blue',
  fontWeight: 'bold',
  textDecoration: 'underline'
});
PaymentSession.setPlaceholderShownStyle(["card.number", "card.nameOnCard"], {
  color: 'green',
  fontWeight: 'bold',
  textDecoration: 'underline'
});

Drop-down Fields for Expiry Month and Year

Hosted Session allows you to use drop-down values for the expiry month and expiry year. See the sample code below for details.

Details
<html>
<head>
<!-- INCLUDE SESSION.JS JAVASCRIPT LIBRARY -->
<script src="https://evopaymentsmexico.gateway.mastercard.com/form/version/72/merchant/<MERCHANTID>/session.js"></script>
<!-- APPLY CLICK-JACKING STYLING AND HIDE CONTENTS OF THE PAGE -->
<style id="antiClickjack">body{display:none !important;}</style>
</head>
<body>

<!-- CREATE THE HTML FOR THE PAYMENT PAGE -->

<div>Please enter your payment details:</div>

<div>Card Number: <input type="text" id="card-number" class="input-field" title="card number" aria-label="enter your card number" value="" tabindex="1" readonly></div>

<div>Expiry Month: 
<select id="expiry-month" class="form-control input-md" required="" readonly>
	<option value="">Select Month</option>
	<option value="01">January</option>
	<option value="02">February</option>
	<option value="03">March</option>
	<option value="04">April</option>
	<option value="05">May</option>
	<option value="06">June</option>
	<option value="07">July</option>
	<option value="08">August</option>
	<option value="09">September</option>
	<option value="10">October</option>
	<option value="11">November</option>
	<option value="12">December</option>
</select>
</div>
<div>Expiry Year: 
<select id="expiry-year" class="form-control input-md" required="" readonly>
	<option value="">Select Year</option>
	<option>21</option>
	<option>22</option>
	<option>23</option>
	<option>24</option>
	<option>25</option>
	<option>26</option>
	<option>27</option>
	<option>28</option>
	<option>29</option>
	<option>30</option>
	<option>31</option>
	<option>32</option>
	<option>33</option>
	<option>34</option>
	<option>35</option>
	<option>36</option>
	<option>37</option>
	<option>38</option>
	<option>39</option>
</select>
</div>
<div>Security Code:<input type="text" id="security-code" class="input-field" title="security code" aria-label="three digit CCV security code" value="" tabindex="4" readonly></div>

<div>Cardholder Name:<input type="text" id="cardholder-name" class="input-field" title="cardholder name" aria-label="enter name on card" value="" tabindex="3" readonly></div>

<div><button id="payButton" onclick="pay();">Pay Now</button></div>

<!-- JAVASCRIPT FRAME-BREAKER CODE TO PROVIDE PROTECTION AGAINST IFRAME CLICK-JACKING -->
<script type="text/javascript">
if (self === top) {
    var antiClickjack = document.getElementById("antiClickjack");
    antiClickjack.parentNode.removeChild(antiClickjack);
} else {
    top.location = self.location;
}
var sessions = [];
PaymentSession.configure({
    fields: {
        // ATTACH HOSTED FIELDS TO YOUR PAYMENT PAGE FOR A CREDIT CARD
        card: {
        	number: "#card-number",
        	securityCode: "#security-code",
        	expiryMonth: "#expiry-month",
        	expiryYear: "#expiry-year",
            nameOnCard: "#cardholder-name"
        }
    },   
//SPECIFY YOUR MITIGATION OPTION HERE
frameEmbeddingMitigation: ["javascript"],
  	callbacks: {
 		initialized: function(response) {
 		// HANDLE INITIALIZATION RESPONSE
 },
 	formSessionUpdate: function(response) {
	// HANDLE RESPONSE FOR UPDATE SESSION
 	if (response.status) {
   	if ("ok" == response.status) {
		console.log("Session updated with data: " + response.session.id);
		//check if the security code was provided by the user
 		if (response.sourceOfFunds.provided.card.securityCode) {
 		console.log("Security code was provided.");
 		}
		//check if the user entered a Mastercard credit card
		if (response.sourceOfFunds.provided.card.scheme == 'MASTERCARD') {
		console.log("The user entered a Mastercard credit card.")
       }
         } else if ("fields_in_error" == response.status)  {
                 console.log("Session update failed with field errors.");
                 if (response.errors.cardNumber) {
                 console.log("Card number invalid or missing.");
                  }
                 if (response.errors.expiryYear) {
                 console.log("Expiry year invalid or missing.");
                  }
                 if (response.errors.expiryMonth) {
                 console.log("Expiry month invalid or missing.");
                  }
              	 if (response.errors.securityCode) {
                 console.log("Security code invalid.");   
                 }
                } else if ("request_timeout" == response.status)  {
                  console.log("Session update failed with request timeout: " + response.errors.message);
                } else if ("system_error" == response.status)  { 
                  console.log("Session update failed with system error: " + response.errors.message); 
               }
            } else {
              console.log("Session update failed: " + response);
           }
        }
    },
    interaction: {
        displayControl: {
            formatCard: "EMBOSSED",
            invalidFieldCharacters: "REJECT"
			 }
 		}
 });
function pay() {
// UPDATE THE SESSION WITH THE INPUT FROM HOSTED FIELDS
PaymentSession.updateSessionFromForm('card');
}
</script>
</body>
</html>
	

Configure Accessibility of Hosted Fields

Hosted Session provides functionality that may improve the accessibility of your website.

Details
<!-- CREATE THE HTML FOR THE PAYMENT PAGE -->
<div>Please enter your payment details:</div> 

<div>Cardholder Name: <input type="text" id="cardholder-name" class="input-field" title="cardholder name" aria-label="enter name on card" value="" tabindex="1" readonly></div>

<div>Card Number: <input type="text" id="card-number" class="input-field" title="card number" aria-label="enter your card number" value="" tabindex="2" readonly></div>

<div>Expiry Month:<input type="text" id="expiry-month" class="input-field" title="expiry month" aria-label="two digit expiry month" value="" tabindex="3" readonly></div>

<div>Expiry Year:<input type="text" id="expiry-year" class="input-field" title="expiry year" aria-label="two digit expiry year" value="" tabindex="4" readonly></div>

<div>Security Code:<input type="text" id="security-code" class="input-field" title="security code" aria-label="card security code" value="" tabindex="5" readonly></div>

<div><button id="payButton" onclick="pay();">Pay Now</button></div> 

The following options allow you to better control the user experience for payers with accessibility needs:

Set the iFrame Title

The hosted field's iframe title attribute can be controlled using a title attribute on the field.

Set Accessibility Rich Internet Application Attributes

Hosted Session supports aria attributes, which you can use to enhance the experience for payers that use assistive technologies.

Set Invalid Character Display Parameter

Consider accepting all characters in hosted fields for a better experience for payers using assistive technology. To do this, set the display parameter interaction.displayControl.invalidFieldCharacters=ALLOW in the PaymentSession.configure() method.

Set the lang Attribute

Add lang attribute to the html element.

<html lang="en">
    <head></head>
    <body></body>
</html>

Hidden Label and Error Message

All hosted fields contain a hidden label and mandatory hosted fields contain a hidden error message. Any errors resulting from invoking PaymentSession.updateSessionFromForm() will raise error message labels. You may additionally raise your own errors using the PaymentSession.setMessage() method.

For example, the hidden label for the card number field is “Card Number”. The hidden error message for missing card number is “Card Number is missing, please enter the value”. The hidden error message for invalid card number is “Card Number is invalid, please enter correct value”. While tabbing between the hosted fields only the hidden label and hidden error message are read by the screen reader but not the actual label or error message displayed on the UI.

Set the Locale Property in the Configuration Object

The locale property provides translations for all the hosted fields, including the hidden labels and error messages. If this is not set, it will default to English. The supported values for this property are de_DE, el_GR, en_US, es_MX, es_ES, fr_CA, fr_FR, it_IT, ja_JA, pl_PL, pt_BR, ro_RO, zh_CN.

To avoid confusing the payers, it's recommended that the lang attribute matches the locale property.

PaymentSession.configure({
    fields: {
        card: {
            nameOnCard: cardHolderNameField ? "#card-holder-name" : null,
            number: "#card-number",
            securityCode: "#security-code",
            expiryMonth: "#expiry-month",
            expiryYear: "#expiry-year"
        }
    },
    frameEmbeddingMitigation: ["javascript"],
    locale:"fr",
        callbacks: {
    }
});

Auto Focus

One of the default HTML5 functionality doe not work with the hosted fields i.e., when the payer clicks on the label it does not auto focus on the corresponding input/select element. Use setFocus to achieve this.

Hosted fields are not web accessible when using IE 11 in combination with the screen reader SuperNova.

Accepting Multiple Cards via Hosted Session

Hosted Session allows you to accept multiple cards from your payer on the same page. In this case, each card becomes a separate payment session and a separate order (when you use the payment session in a payment transaction). This may be useful, for example, where a customer wants to be able to pay using more than one card for the same booking. Your website must then be able to assemble these orders generated from separate payment sessions into a single booking for the customer.

Multiple cards via Hosted Session is only supported from version 51 of the API.
Details

Request a Multiple Hosted Session Interaction

To accept multiple cards, you must invoke PaymentSession.configure() function using the scope parameter. This parameter can be any unique string used to identify a block of card payment data, and does not need to reference any specific html on the page. The data stored by you on your merchant server for each card should be retained in a separate scope.

  • PaymentSession.configure('configuration', scope)

The scope parameter on the following Hosted Session calls becomes mandatory once the initial PaymentSession.configure() call is invoked with scope.

  • PaymentSession.updateSessionFromForm('card', 'card-type', scope)
  • PaymentSession.setFocus('cardNumber', scope)

The scope parameter is optional on the following calls if an interaction is configured with a scope. If a scope is not specified on the calls, the function/callback will apply to all card data sets within the hosted iFrame.

  • PaymentSession.setFocusStyle([<HostedFieldsRole>], styles, scope)
  • PaymentSession.setHoverStyle([<HostedFieldsRole>], styles, scope)
  • PaymentSession.onFocus([<HostedFieldsRole>],function(selector), scope)
  • PaymentSession.onBlur([<HostedFieldsRole>], function(selector), scope)
  • PaymentSession.onChange([<HostedFieldsRole>], function(selector), scope)
  • PaymentSession.onMouseOver([<HostedFieldsRole>], function(selector), scope)
  • PaymentSession.onMouseOut([<HostedFieldsRole>], function(selector), scope)

Example

<html>
<head>
<!-- INCLUDE SESSION.JS JAVASCRIPT LIBRARY -->
<script src="https://evopaymentsmexico.gateway.mastercard.com/form/version/72/merchant/<MERCHANTID>/session.js"></script>
<!-- APPLY CLICK-JACKING STYLING AND HIDE CONTENTS OF THE PAGE -->
<style id="antiClickjack">body{display:none !important;}</style>
</head>
<body>

<!-- CREATE THE HTML FOR THE PAYMENT PAGE -->

<div>Please enter your payment details:</div>
<div>Cardholder Name: <input type="text" id="cardholder-name" class="input-field" title="cardholder name" aria-label="enter name on card" value="" tabindex="1" readonly></div>
<div>Card Number: <input type="text" id="card-number" class="input-field" title="card number" aria-label="enter your card number" value="" tabindex="2" readonly></div>
<div>Expiry Month:<input type="text" id="expiry-month" class="input-field" title="expiry month" aria-label="two digit expiry month" value="" tabindex="3" readonly></div>
<div>Expiry Year:<input type="text" id="expiry-year" class="input-field" title="expiry year" aria-label="two digit expiry year" value="" tabindex="4" readonly></div>
<div>Security Code:<input type="text" id="security-code" class="input-field" title="security code" aria-label="three digit CCV security code" value="" tabindex="5" readonly></div>
<div><button id="payButton" onclick="pay();">Pay Now</button></div>

<!-- JAVASCRIPT FRAME-BREAKER CODE TO PROVIDE PROTECTION AGAINST IFRAME CLICK-JACKING -->
<script type="text/javascript">
if (self === top) {
    var antiClickjack = document.getElementById("antiClickjack");
    antiClickjack.parentNode.removeChild(antiClickjack);
} else {
    top.location = self.location;
}

var sessions = [];
PaymentSession.configure({
    fields: {
        // ATTACH HOSTED FIELDS TO YOUR PAYMENT PAGE FOR A CREDIT CARD
        card: {
        	number: "#card-number",
        	securityCode: "#security-code",
        	expiryMonth: "#expiry-month",
        	expiryYear: "#expiry-year",
        	nameOnCard: "#cardholder-name"
        }
    },
    //SPECIFY YOUR MITIGATION OPTION HERE
    frameEmbeddingMitigation: ["javascript"],
    callbacks: {
        initialized: function(response) {
            // HANDLE INITIALIZATION RESPONSE
        },
        formSessionUpdate: function(response) {
            // HANDLE RESPONSE FOR UPDATE SESSION AS PER USUAL MANNER.
            if (response.status) {
                if ("ok" == response.status) {
                    // RECORD THE SESSIONID RETURNED AND ASSOCIATE IT WITH THE SCOPE CONFIGURED.
                    sessions.push(JSON.parse('{ "scopeId": "' + response.scopeId + '", "sessionId": "' + response.session.id + '"}'));
                }
            } else {
                console.log("Session update failed: " + response);
            }
        }
    },
    interaction: {
        displayControl: {
            formatCard: "EMBOSSED",
            invalidFieldCharacters: "REJECT"
        }
    }
  }, 'card-payment-details-#1'); // ADD ANY UNIQUE STRING IDENTIFIER VALUE TO THE CONFIGURE CALL

function pay() {
    sessions.forEach(function (e) {
        // UPDATE THE SESSION WITH THE FIELD VALUES. THE SCOPE MUST BE THE THIRD PARAMETER.
        PaymentSession.updateSessionFromForm('card', undefined, e.scopeId);
     });
}
</script>
</body>
</html>

Test Your Integration

Before going live, you must test your integration to ensure correct functionality.

To support extra logging while testing your Hosted Session integration (using a TEST merchant ID), append ?debug=true to the URL.

https://evopaymentsmexico.gateway.mastercard.com/form/version/72/merchant/<TESTMERCHANTID>/session.js?debug=true

Troubleshooting and FAQs

How do I handle the event where a card type entered by the payer is not supported on my merchant profile?

To handle this event, inspect the card type information (sourceOfFunds.provided.card.brand and sourceOfFunds.provided.card.scheme) in the PaymentSession.updateSessionFromForm('card') response, validate against your list of supported card types, and display an error message if the card type is not accepted.

How do I detect whether the payer has provided CSC/CVV in a Hosted Session interaction?

If the payer does not provide CSC/CVV, the securityCode field is NOT returned in the PaymentSession.updateSessionFromForm('card') response. If you require a CSC/CVV and no value is present then you should display an error to the payer.

Do event callbacks for hosted fields work on all browsers?

There are known issues with event callbacks on the following operating systems and browsers:

  • Internet Explorer 11 on Windows 10: If interaction.displayControl.formatCard=EMBOSSED, the onChange event is not triggered when you change the value of a hosted field.
  • iOS9 on iPhone 6+: The onChange( ) and onBlur( ) events are not triggered when the payer enters data in a hosted field and touches another field in the payment page. Further, the payer cannot navigate from hosted fields to other fields on the payment page and vice versa.
  • Hover events are not supported on touch-screen devices.
Can I collect payment details for multiple cards in a Hosted Session interaction?

From version 51 of the API, you can collect payment details from one or more credit cards in a Hosted Session interaction. This allows the payer to use multiple credit cards to pay for a single booking; however, since payment details for each card generate a separate order, it's your responsibility to assemble these separate orders into a single booking for the payer.

A unique session identifier is created for each card, which you must store on your web server. The payer can choose to remove a card during the interaction and this action removes the session data associated with the card from your web server.

Where can I find the integration guidelines and the API reference for the Hosted Payment Session POST model?

The Hosted Payment Session POST model is being deprecated by the Hosted Session JavaScript (session.js) integration.

For existing Hosted Payment Session POST integrations, see integration guidelines and API Reference.

Where can I find the integration guidelines and the API reference for the Hosted Payment Session HPF.js JavaScript model?

The Hosted Payment Session HPF.js JavaScript model is being deprecated by the Hosted Session JavaScript (session.js) integration.

For existing Hosted Payment Session HPF.js integrations, see integration guidelines and API Reference.

Copyright © 2023 Mastercard