javascriptjqueryrealex-payments-api

How to trigger click event without simulating it for Realex payments API


I built a shopping cart that processes orders through AJAX before calling the Realex payment API. The issue I am having is that occasionally browsers will outright block the lightbox popup because it assumes it's a spam popup because of how it's initiated.

new Promise((resolve,reject) => {
    $.ajax({
        method: 'POST',
        url: 'processOrder.php',
        data: $('form').serialize(),
    }).done(function(response){
        resolve(response);
    }).fail(function(){
        reject('Response failed');
    })
}).then((data) => {
    RealexHpp.setHppUrl('https://pay.sandbox.realexpayments.com/pay');
    RealexHpp.lightbox.init('rhpp', data.return, JSON.parse(data.hpp));
    $('#rhpp').click();
}).catch((error) => {
    console.log(error);
});

I've contacted technical support, and I've been told that the issue is specifically the $('#rhpp').click(); because it's simulating the click rather than being an actual click desired by the user.

So, without actually editing the #rhpp element to ask users to click manually, is there anything I can do to get around this issue?


Solution

  • The first parameter of the init method for the Hosted Payment Page (HPP) lightbox is the ID of the button element that when clicked, will initiate the lightbox.

    If you modify the rxp-js.js, you can include a new init method (or override the existing one) that doesn't register a click event handler on a button but instead initializes the lightbox immediately.

    Example:

    This is the original init method of rxp-js.js as per version 1.3.1.

    init: function (idOfLightboxButton, merchantUrl, serverSdkJson) {
        //Get the lightbox instance (it's a singleton) and set the sdk json
        var lightboxInstance = RxpLightbox.getInstance(serverSdkJson);
    
        // Sets the event listener on the PAY button. The click will invoke the lightbox method
        if (document.getElementById(idOfLightboxButton).addEventListener) {
            document.getElementById(idOfLightboxButton).addEventListener("click", lightboxInstance.lightbox, true);
        } else {
            document.getElementById(idOfLightboxButton).attachEvent('onclick', lightboxInstance.lightbox);
        }
    
        if (window.addEventListener) {
            window.addEventListener("message", internal.receiveMessage(lightboxInstance, merchantUrl), false);
        } else {
            window.attachEvent('message', internal.receiveMessage(lightboxInstance, merchantUrl));
        }
    },
    

    This is my modified version of the init method.

    init: function (merchantUrl, serverSdkJson) {
        //Get the lightbox instance (it's a singleton) and set the sdk json
        var lightboxInstance = RxpLightbox.getInstance(serverSdkJson);
    
        lightboxInstance.lightbox();
    }
    

    Note the changes I have made:

    1. Removed the first parameter named idOfLightboxButton, and related code that adds the click event handler to the button.
    2. Removed the second parameter named merchantUrl, and related code that adds a message event handler (I handle the response from the merchant in my own way).
    3. Added a called to the lightbox() method on the lightboxInstance object. This is what opens the lightbox.

    If you were to take this approach, you would then just update your promise callback to read like.

    ...
    .then((data) => {
        RealexHpp.setHppUrl('https://pay.sandbox.realexpayments.com/pay');
        RealexHpp.lightbox.init(JSON.parse(data.hpp));
    })
    ...
    

    Of course, if you were keeping the merchantUrl parameter then the above would read a little differently.