Set up PostMessage Mechanism

When integrating the Card Display form, the Card Capture form or the Card Security Code Capture Form, customers may wish to process messages and notifications from the form in the parent page - this to enable the parent page to be notified on actions taken inside the iframe.

For example, a customer may want to display only one submit button for their form and the capture form (the PCI Booking capture form includes a "submit" button of its own).
For this use case, PCI Booking has provided a secure, postMessage, cross-domain iFrame mechanism to allow customers to have one "submit" button for the combined form and initiate an action both in PCI Booking (for tokenizing the card) and in the backend of the client (for storing everything else).

PostMessage Mechanism Diagram

The diagram below will demonstrate the flow of actions from the site visitor going to the site through the process of validating and submitting the forms to the response sent back to the site visitor once completed:

1075

postMessageHost parameter

The capture and display forms include an optional parameter called postMessageHost. This parameter prevents cross-domain hacking and tells the PCI Booking form the domain of the parent page where the form is hosted on.

📘

For Example:

If you load the form in a site with the URL https://www.mysite.com/page/form, the postMessageHost parameter should be https://www.mysite.com in a URL encoded format (https%3A%2F%2Fwww.mysite.com)

Workflow

Terminology: The PCI Booking iframe will be displayed inside a parent page.

  1. The customer should include a function in the parent page to handle the messages that are returned from the iframe. The iframe can provide the following data:
  • ready - indicating that the iframe has been loaded successfully and is waiting for input
  • valid - indicating that the iframe form has been filled properly and all data entry validations have passed successfully.
  • frameDimensionsChanged - indicating that the iframe has loaded with different dimensions. This allows the customer to reload the parent page and change the display parameters for the iframe to fit the new size.
    *invalid - indicating that the data provided by the visitor is invalid and the form still cannot be submitted.
    Below is an example of such a function:
function handleFrameMessage(e) {
  var host = 'https://service.pcibooking.net/'
  var originDomain = e.origin.replace("http://", "").replace("https://", "");
  var postMessageOrigin = host.replace("http://", "").replace("https://", "").toLowerCase();
  if (postMessageOrigin.endsWith('/'))
    postMessageOrigin = postMessageOrigin.substring(0, postMessageOrigin.length - 1);


  if (originDomain.toLowerCase() === postMessageOrigin) {
    if (e.data == 'ready') {
      iframeIsReady = true;
      $("#iframePayment").fadeIn(1000);
      console.log("Messaging Log: " + e.data);
    }
    else if (e.data == 'valid') {
      continueSubmitReservationAndThenCardIframe(e);
    }
    else if (e.data.indexOf("frameDimensionsChanged") === 0) {
      var objectParts = e.data.split(':');
      var width = parseInt(objectParts[1]);
      var height = parseInt(objectParts[2]);
      $("#iframePayment").height(height).attr("height", height);
      console.log("Messaging Log: " + e.data);
    }
    else if (e.data[0] === "{") {
      console.log("Messaging Log: ");
      console.log(JSON.parse(e.data));
    }
    else {
      alert("Please fill all the mandatory fields");
    }
  }
}
  1. The customer should also include a message event listener to handle the responses from the iframe and trigger the function mentioned above.
    Below is an example of such a listener:
...
	if (window.addEventListener) {
     window.addEventListener('message', handleValidateMessageFromPciBooking);
   }
   else if (window.attachEvent) {
     window.attachEvent('onmessage', handleValidateMessageFromPciBooking);
   }
...
  1. Lastly, the customer should include a function in the parent page to process the form and redirect to the next page once the card form has been submitted successfully.
    This function should be made to store all of the form fields provided in the parent page and all of the token details that are provided after the iframe is submitted and redirected to the success / failure pages (see steps #7 and #8.
  2. When the "Submit" button is clicked, it should validate the form fields in the parent page and it should send a validation request to the iframe.
    Below is an example of such validation request:
...	
	receiver.postMessage("validate", 'https://service.pcibooking.net/');
...
  1. PCI Booking will validate the card form to show error messages and will send postMessage with a valid/invalid response back to the customer's parent page - this response will be processed by the function mentioned in step #1.
    If the validation of the form in the parent page fails or the response from the PCI Booking iframe is that the iframe is not valid, a message should be sent to the visitor informing them that there is a problem with the information provided.
    If the validation (of both the parent form and the iframe) is successful, the parent page can proceed with storing the data in the following steps:
  2. A request to store the iframe data and tokenize the card is sent to the iframe.
    Below is an example of such validation request:
...	
	receiver.postMessage("submit", 'https://service.pcibooking.net/');
...
  1. PCI Booking will tokenize the card details and redirects the iframe to the Booker's success/fail URL which was provided in the iframe request.
  2. Since the success/fail pages are within the same domain f the parent page, they will be able to pass along parameters to it and trigger a function in it to store the data (see step #3) and redirect the visitor to the confirmation page.

Possible PostMessage Message Data

When using the PostMessage mechanism, you will encounter the following scenarios and the resulting message data returned in the PostMessage:

ScenarioPostMessage Message data
Validation messages are displayed in the iframePostMessage data would include the new size of the iframe in the following format:
frameDimensionsChanged:[Width]:[Height]
One (or more) of the required fields was not enteredPostMessage data would be invalid.
Credit card number provided is invalidPostMessage data would be a JSON structure of the validation in the following format:
{ "field": "cardNumber", "validationResult": { "card_type": { "name": "Visa", "pattern": { }, "valid_length": [ 16, 13 ] }, "valid": false, "luhn_valid": true, "length_valid": false } }
Other validation errors (such as Credit card number does not match selected credit card type, expiration date in the past, invalid CVV, etc)PostMessage data would be a JSON structure of the validation in the following format:
{ "field": "[field_name]", "validationResult": "[validation_failure_reason]" }
Iframe is ready to be displayedPostMessage data would be ready.
Iframe is filled out properly and there are no validation errorsPostMessage data would be valid.
3DS challenge iFrame content is loadedPostMessage data would be ThreeDsChallengeLoaded

Example

You can see an example of the PostMessage mechanism in use in our card capture demo page.
While this demo is designed to display everything - both capture forms and confirmation pages, on the same page display, the above logic is the same.

In order to view the data being returned in the PostMessage mechanism, please open the web console on your browser:

Chrome
Opening the “Console” panel of Chrome’s DevTools:

  • Windows: Ctrl + Shift + J

  • Mac OS: Cmd + Opt + J

Firefox
Opening the “Console” panel in Firefox’s Developer Tools:

  • Windows: Ctrl + Shift + K

  • Mac OS: Cmd + Opt + K

Internet Explorer
Opening the “Console” panel in Internet Explorer’s F12 Developer Tools:

  • F12, then click on the “Console” tab

Safari
Note: In order to view the console in Safari, you have to enable the “Show Develop menu in menu bar” setting in the “Advanced” pane of Safari’s preferences (screenshot).

Opening the “Console” panel in Safari’s Web Inspector:

  • Cmd + Opt + C

Opera
Opening the “Console” panel in Opera:

  • Windows and Linux: Ctrl + Shift + I

  • Mac OS: ++I