How to display a Hosted Pay Page (HPP) payment form inside a iframe or through a redirect (Solution code provided)

After many hours of research, I though sharing the following explanation and code on how to get the Payment form inside an iframe (or through a redirect) could help many other developers.

Moneris description of the hosted paypage (step 2) states that :

2 Once the cardholder is ready to pay, the merchant’s checkout page will submit an HTTP form POST to the Moneris Hosted Pay Page (HPP).  At this time, the customer will be redirected from the merchant’s website to the Moneris Hosted Pay Page URL. 

What I missed and should be clarified in Moneris' explanations is that the HTTP form POST has to be done inside the client's browser (not from your back end) and also that the redirection to Moneris site has to be done by your javascript code (again, inside the client's browser). We will see below that you can choose in this code if you want to perform a redirection or host the form on your web page inside an iframe.

Because the payment data goes to the client browser, and can thus be visible through developer tools (F12 key), I didn't want all the ps_store_id, hpp_key, amount, client name, etc. information to be visible, so I did a preloading of the payment data to Moneris in my back end code and chose, in my Merchant Resource Center to have the response sent in XML format .  As explained in the documentation, I got a response containing 4 fields (hpp_id, ticket, order_id and response_code) that I unmarshalled from XML in my back end code. 

Of those 4 fields, only the hpp_id and ticket need to be sent back to the client, meaning that your back end language (java, php, etc.) has to provide some js/jQuery code where those two variables will be initialized.

Here is a sample of the form that has to be posted back to Moneris to get the payment form (the blank hpp_preload field is added to tell Moneris a preload was done) :

<form id='paymentForm' method='POST' action='https://esqa.moneris.com/HPPDP/index.php' target='_self' >

    <input type='hidden' name='hpp_id' value='ABCD7376865439'>

    <input type='hidden' name='ticket' value='hpp157dOrcFbO6M1fB4805962HX8ZE'>

    <input type='hidden' name='hpp_preload' value=' '>

</form>

This form can be sent directly to Moneris if you want to do a redirect or used as the srcdoc of an iframe, if you want to host the payment form on your page.

Here is the code to do so :

Common code :

Your back end will return a string similar to this one which will be stored inside a js variable :

prelaoadResponse = '{"hpp_id" : "ABCD7376865439", "ticket" : "hpp157dOrcFbO6M1fB4805962HX8ZE", "hpp_preload" : " "}';

You noticed that this string is in Json format, so it can be converted to a javascript object with the parse function.

From this 2 functions are needed :

  • getPaymentFormContent(obj) : which will output the <input type="hidden" ...> form fields.
  • inIframe(data) : which will add an iframe  to your web page and send it to Moneris

or

  • performRedirect(data) : which will append the form to the document  and perform a redirect if you prefer this option

 

Here is the code for those functions (uses jQuery) . 

 

// The string on the right hand side of this assignment has to be generated from your back end language.
// As it is in JSON format, it woll be converted to an object with the parse method later on
prelaoadResponse = '{"hpp_id" : "ABCD7376865439", "ticket" : "hpp157dOrcFbO6M1fB4805962HX8ZE", "hpp_preload" : " "}';

var data = new Object();
data.paymentUrl = 'esqa.moneris.com/.../index.php';
data.formContent = JSON.parse(prelaoadResponse);

// To insert an iframe and submit its content to Moneris
inIframe(data);
// or to perform a redirect to Moneris site
 performRedirect(data);

// Generates the <input type='hidden' name='abc' value='xyz'> tags
// for each of the Object properties
function getPaymentFormContent(obj) {
    var formContent = "";
    for (var key in obj) {
        formContent += "\n\t<input type='hidden' name='" + key + "' value='" + obj[key] + "'>";
     }
     return formContent;
 }
 
 function inIframe(data) {
    $('body').append($('<h1>Payment Form</h><p>')
            .add($('<iframe>', {"id": "PaymentIframe",  "width":800, "height":600})));
    $('#PaymentIframe').attr('srcdoc', "<!DOCTYPE html><html>" +
        "<head><meta charset=\"utf-8\"><\/head>" +
        "<body><form id='paymentForm' method='POST' action='" + data.paymentUrl + "' target='_self' >" +
                getPaymentFormContent(data.formContent) +
                // include js to submit the form as soon as it is written in the iframe :
        " <\/form><script>document.getElementById('paymentForm').submit();<\/script><\/body><\/html>");
}

function performRedirect(data) {
    // Redirect the client browser to the payment provider web site
    $('<form>', {
        "id": "PaymentForm", "action": data.paymentUrl, "target": "_self",
        "html": getPaymentFormContent(data.formContent)
    }).appendTo(document.body).submit();    
}

 

Hope it helped you!