Making a Payment
This topic describes the steps you need to follow to make a payment using a session where you gather sensitive payment data from the payer with hosted fields on your payment page. This is accomplished using the Session JavaScript library
(session.js) in addition to the WSAPI. For a full code snippet example of the entire payment page implementation on a web site, see Payment Page Code Example.
Step 1: Create a session
Create a Session by submitting a Create Session
request from your server. 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://test-nbkpayment.mtf.gateway.mastercard.com/api/rest/version/72/merchant/<merchant_ID>/session |
HTTP Method | POST |
{ "session": { "authenticationLimit": 25 } }
Step 2: Update the session with the order details
Update the Session with at least the currency and order amount by submitting an Update Session
request from your server.
The order currency is needed so that you can determine whether the credit card the payer wants to use is supported and whether they need to provide their Card Security Code (CSC).
URL | https://test-nbkpayment.mtf.gateway.mastercard.com/api/rest/version/72/merchant/<merchant_ID>/session/<session_ID> |
HTTP Method | PUT |
{ "order": { "amount": 100, "currency": "USD" } }
Step 3: Include the session JavaScript library
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.
<html> <head> <script src="https://test-nbkpayment.mtf.gateway.mastercard.com/form/version/72/merchant/<MERCHANTID>/session.js"></script> </head> </html>
Step 4: Create the payment page
Create the HTML code for your payment page, including the fields for gathering the necessary payment details from the payer.
readonly
and omit the name
attribute.You can use one or more of the following payment methods to capture payment details from the payer. The fields you need to include on your payment page depend on the payment method:
Credit and Debit cards
You can capture the following card details in hosted fields:
card.number
card.expiryMonth
card.expiryYear
card.securityCode
card.nameOnCard
card.expiryMonth
is used then card.expiryYear
is mandatory and vice versa.Gift cards
You can capture the following gift card details in hosted fields:
giftCard.number
giftCard.pin
For more information, see Gift Cards.
Automated Clearing House (ACH) Payments
You can capture payment details for Direct Payments (payments) and Direct Deposits (refunds) through Automated Clearing House. You can capture the following Automated Clearing House details in hosted fields:
ach.routingNumber
ach.bankAccountNumber
ach.bankAccountNumberConfirmation
ach.bankAccountHolder
ach.accountType
For more information, see Automated Clearing House.
Click to Pay
You can capture payment details from Click to Pay interaction. For more information, see Click to Pay Hosted Session Integration.
The following sample code illustrates the necessary payment page fields for a credit card payment.
<!-- 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>
Step 5: Configure the session
Invoke the PaymentSession.configure() function with a configuration object as an argument to attach the hosted fields to your payment page and configure the payment interaction. You need to provide the following in the configuration object:
- Session ID received when you created the Session.
- Field selectors for hosted fields for specific payment methods. The configuration replaces them with corresponding proxy fields embedded in iFrames hosted by the Mastercard Gateway. The proxy fields have the same look and feel as the replaced fields.
- Mitigation options 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 the Hosted Session, you must implement one or more of the following defenses against clickjacking attacks and specify which defenses are implemented using the frameEmbeddingMitigation field:
- Javascript: Include "frame-breaker" JavaScript on your payment page.
- x-frame-options: Your server returns an X-Frame Options HTTP response header.
- csp: Your server returns a Content-Security-Policy HTTP response header containing a frame-ancestors directive.
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() is invoked when the hosted fields attach to your payment page.
- formSessionUpdate() is invoked in response to the PaymentSession.updateSessionFromForm(paymentType) function (see next step).
- Interaction details that define the visibility and payer interaction options for some displayed information.
<body> 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 }, }, interaction: { displayControl: { formatCard: “EMBOSSED”, invalidFieldCharacters: “REJECT” } } }); </body>
Step 6: Update the session with field details
After the payer has entered their payment details in the hosted fields, invoke the PaymentSession.updateSessionFromForm() function with the applicable payment method as an argument. The function stores the captured payment details into the payment Session. Once the operation completes, the formSessionUpdate() callback is invoked with a result parameter. Check the result.status field to determine if the operation was successful. For more information, see Handling Callback Responses.
function pay() { // UPDATE THE SESSION WITH THE INPUT FROM HOSTED FIELDS PaymentSession.updateSessionFromForm('card'); }
Step 7: Create payment using the session
Send the payment transaction (or other related operation) from your server to the gateway using the Session ID (session.id) in the request:
- Send the Retrieve Session request to verify the details included in the Session.
- Create the transaction request by adding any necessary fields not included in the Session.
- Send the transaction request. For more information about handling API requests, see Making a Server API Request.
You can send multiple operations related to the payment using the same Session. For example, you can both initiate a payment with a PAY operation and store a token representing the payment details (for use in future transactions) with the Create or Update Token operation.
Payment page code example
The following sample code illustrates the HTML code for a full payment page.
<html> <head> // INCLUDE SESSION.JS JAVASCRIPT LIBRARY <script src="https://test-nbkpayment.mtf.gateway.mastercard.com/form/version/<version>/merchant/<merchant_ID>/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>
Payment page callbacks
The Hosted Session allows you to use various callbacks to customize how the payment page behaves and what kind of feedback it provides to the payer.
Callbacks for session configuration
This section defines the Session configuration callbacks and the responses returned by their result callbacks. For an example of how to handle the callbacks in your payment page code, see Payment Page Code Example.
The callbacks used in the PaymentSession.configure() function:
- initialized(result) callback is invoked when the hosted fields are attached to the payment page:
- If result.status=="ok", the hosted fields are successfully attached to your payment page.
- If result.status=="system_error" or result.status=="request_timeout", an error has occurred while attaching the hosted fields. Retry after a short delay.
Successful Initialization response example// An ok response { "status": "ok", }
Failed Initialization response example// 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." }
- formSessionUpdate(result) callback is invoked when the hosted field content is stored in the Session:
- If result.status=="ok", the Session now contains the collected payment details.
Form Session update example for successful response// 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. Prompt the payer to update their input. The errors response structure contains information about the invalid fields.
- If result.status=="system_error" or result.status=="request_timeout", an error has occurred when processing the update. Retry the Session update after a short delay.
// An error response (fields_in_error) { "status": "fields_in_error", "session": { "id": "SESSION000218450948092491657986" }, "errors": { "cardNumber": "invalid", "securityCode": "invalid" }, version: "43" }
// 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" }
Callbacks for hosted fields
The Hosted Session allows you to register callback functions to handle events that can occur on the hosted fields during the payer's interaction. The events allow you to track what the payer is doing and provide validation feedback to them during various payment interaction stages.
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. Once the payer has finished typing and leaves the field, and this event is triggered, invoke the validate() function and display any errors for the field from the validate() function’s callback.
- onMouseOver(): Invoked when a mouse over event occurs in the hosted field.
- onMouseOut(): Invoked when a mouse out event occurs in the hosted field.
- onValidityChange(): Invoked after the payer’s each keystroke, providing feedback on the validity of the payer’s data entry so far.
/** * 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", "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"; } }); 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 }); 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"; } });
Frequently asked questions
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, first use the PAYMENT OPTIONS INQUIRY operation to get a list of supported card types. Then inspect the card type information (sourceOfFunds.provided.card.brand and sourceOfFunds.provided.card.scheme) in the PaymentSession.updateSessionFromForm('card') response, validate it against the list of supported card types, and display an error message if the card type is not accepted.
How do I know whether the payer's CSC or CVV is needed and has been provided?
To find out whether CSC or CVV is required, use the PAYMENT OPTIONS INQUIRY operation. 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, you need to 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.