Objectives

Issue: to make these 2 modules works together:

  • IWD_Opc v4.0.5
  • Payone_Core v3.2.0

Spent time to solve the issue: 14h Spent time to write this article: 1h

Development Setup

You can use this composer.json to build sample project with these modules:

{
  "repositories": [
      {
          "type": "git",
          "url": "https://github.com/kirchbergerknorr/magento"
      },
      {
          "type": "git",
          "url": "https://github.com/kirchbergerknorr/IWD_Opc"
      },
      {
          "type": "git",
          "url": "https://github.com/kirchbergerknorr/IWD_All"
      },
      {
          "type": "git",
          "url": "https://github.com/quafzi/payone-magento"
      },
      {
          "type": "git",
          "url": "https://github.com/Cotya/magento-composer-installer"
      },
      {
          "type": "composer",
          "url": "http://packages.firegento.com"
      }
  ],
  "require": {
    "magento-hackathon/magento-composer-installer":"*",
    "kirchbergerknorr/magento": "1.9.*",
    "kirchbergerknorr/IWD_Opc": "4.0.5",
    "kirchbergerknorr/IWD_All": "1.2.1",
    "payone/magento": "3.1.3"
  },
  
  "extra": {
      "magento-root-dir": "src",
      "auto-append-gitignore": true,
      "magento-deploystrategy": "copy",
      "magento-force": true
  }

Initial research and pessimism

Google and Stackoverflow just created more problems and less optimism with solving this problem.

First that I found that lots of people recommend not to use IWD One Page Checkout:

Maybe it was like that, but recent version of IWD One Page Checkout which I use in a project doesn’t have this problem anymore.

Then I found exactly my problem:

And possible next problem:

I asked collegues, friends and magento-community in twitter and slack-chat, but no one had this problem or any idea what to do.

Сontinuation of research and first ideas

Then I googled one interesting post:

Anonymous asked: Can you help me integrate Payone module with IWD OnePage checkout? What I already did is updated the xml so the required scripts will load in theme during checkout. But if I choose pay with credit card the configId comes empty.

Your issue as discussed somewhere in SO is related to different handling of checkout process. Payone depends on certain methods and dom elements to be existing. For example it will make a ajax validation on payment.save() call and append it’s own values to payment form and replacing the entered data for PCI compliance sake. So your task here is to check wether this method payment.save is called and if the ajax validation is made and if the data that is resulted from this validation is passed to where it needs to be passed. Original Post

The idea is clear, but how and what exactly should I do?

And finally I found wiki-page of OneStepCheckout with optimistic title Add-payone-support.

Basicly it says that I need to:

  • rename checkout_onepage_index to onestepcheckout_index_index in layout/payone/core.xml
  • add js in checkout.phtml:
if(payment.currentMethod == 'payone_creditcard') {
  payment.save();

This 2 advices helped to understand where could be a problem. But it wasn’t a complete solution, because there is no checkout.phtml in IWD One Page Checkout

While I was trying to integrate Payone in IWD One Page Checkout the majors problems were:

  • IWD One Page Checkout is using non-standard methods and own way to solve problems.
  • Payone Payment Method javascripts are oriented to use only with standard checkout.

Solution

Copy core.xml:

  • from app/design/frontend/base/default/layout/payone/core.xml
  • to your theme app/design/frontend/yourtheme/default/layout/payone/core.xml

Find and rename in core.xml:

  • xml node <checkout_onepage_index> which is responsible to add js to standard checkout
  • to <opc_index_index> which will add payone js to IWD One Page Checkout

I found very useful extend.js in IWD One Page Checkout.

Copy extend.js:

  • from skin/frontend/base/default/js/iwd/opc/extend.js
  • to your theme skin/frontend/yourtheme/default/js/iwd/opc/extend.js
;
// dummy Checkout Object for backward compatibility
var checkout = {
    steps: new Array("login", "billing", "shipping", "shipping_method", "payment", "review"),

    gotoSection: function (section) {
        IWD.OPC.backToOpc();
    },

    accordion: {},

    loadWaiting: false,

    setLoadWaiting: function (type, waiting) {
        this.loadWaiting = type;
    },

    ajaxFailure: function (data) {
        console.log('ajaxFailure', data);
    }
};

IWD.OPC.prepareExtendPaymentForm = function () {
    $j('.opc-col-left').hide();
    $j('.opc-col-center').hide();
    $j('.opc-col-right').hide();
    $j('.opc-menu p.left').hide();
    $j('#checkout-review-table-wrapper').hide();
    $j('#checkout-review-submit').hide();

    $j('.review-menu-block').addClass('payment-form-full-page');

};

IWD.OPC.backToOpc = function () {
    $j('.opc-col-left').show();
    $j('.opc-col-center').show();
    $j('.opc-col-right').show();
    $j('#checkout-review-table-wrapper').show();
    $j('#checkout-review-submit').show();

    //hide payments form
    $j('#payflow-advanced-iframe').hide();
    $j('#payflow-link-iframe').hide();
    $j('#hss-iframe').hide();

    $j('.review-menu-block').removeClass('payment-form-full-page');

    IWD.OPC.saveOrderStatus = false;
};


IWD.OPC.Plugin = {

    observer: {},

    dispatch: function (event, data) {
        if (typeof(IWD.OPC.Plugin.observer[event]) != "undefined") {
            var callback = IWD.OPC.Plugin.observer[event];
            callback(data);
        }
    },

    event: function (eventName, callback) {
        IWD.OPC.Plugin.observer[eventName] = callback;
    }
};

/** 3D Secure Credit Card Validation - CENTINEL **/
IWD.OPC.Centinel = {
    init: function () {
        IWD.OPC.Plugin.event('savePaymentAfter', IWD.OPC.Centinel.validate);
    },

    validate: function () {
        if (typeof(CentinelAuthenticateController) != "undefined") {
            $j('.opc-col-left').hide();
            $j('.opc-col-center').hide();
            $j('.opc-col-right').addClass('full-page');
        }
    },

    success: function () {
        if (typeof(CentinelAuthenticateController) != "undefined") {
            $j('.opc-col-right').removeClass('full-page');
            $j('.opc-col-left').show();
            $j('.opc-col-center').show();
        }
    }
};

IWD.OPC.PayoneCreditCard = {
    init: function () {
        PAYONE.Handler.CreditCardCheck.OnepageCheckout = function () {
            this.origMethod = '';

            this.haveToValidate = function () {
                var radio_p1_cc = $('p_method_payone_creditcard');
                if (radio_p1_cc != undefined && radio_p1_cc != null && radio_p1_cc.checked) {
                    if (checkout.loadWaiting != false) {
                        return 0;
                    }
                    if (IWD.OPC.saveOrderStatus == false) {
                        return 0;
                    }
                    if (payment.validate() != true) {
                        return 0;
                    }
                    return 1;
                }
                return 0;
            };

            this.handleResponse = function (response) {
                if (response.status != 'VALID') {
                    // Failure
                    alert(response.customermessage);
                    checkout.setLoadWaiting(false);
                    return false;
                }

                // Success!
                var pseudocardpan = response.pseudocardpan;
                var truncatedcardpan = response.truncatedcardpan;

                $('payone_pseudocardpan').setValue(pseudocardpan);
                $('payone_truncatedcardpan').setValue(truncatedcardpan);
                $('payone_creditcard_cc_number').setValue(truncatedcardpan);

                cid = $('payone_creditcard_cc_cid');
                if (cid != undefined) {
                    $('payone_creditcard_cc_cid').setValue('')
                }

                checkout.setLoadWaiting('payment', false);

                IWD.OPC.saveOrderStatus = true;

                IWD.OPC.Checkout.success = IWD.OPC.Checkout.config.baseUrl + 'checkout/onepage/success',
                IWD.OPC.savePayment();
            };
        };

        window.payone = new PAYONE.Service.CreditCardCheck(
            new PAYONE.Handler.CreditCardCheck.OnepageCheckout()
        );

        IWD.OPC.validatePayment = function(){
            // check all required fields not empty
            var is_empty = false;
            $j('#co-payment-form .required-entry').each(function(){
                if($j(this).val() == '' && $j(this).css('display') != 'none' && !$j(this).attr('disabled'))
                    is_empty = true;
            });

            if(!IWD.OPC.saveOrderStatus){
                if(is_empty){
                    IWD.OPC.saveOrderStatus = false;
                    IWD.OPC.Checkout.hideLoader();
                    IWD.OPC.Checkout.unlockPlaceOrder();
                    return false;
                }
            }

            var vp = payment.validate();
            if(!vp)
            {
                IWD.OPC.saveOrderStatus = false;
                IWD.OPC.Checkout.hideLoader();
                IWD.OPC.Checkout.unlockPlaceOrder();
                return false;
            }

            var paymentMethodForm = new Validation('co-payment-form', { onSubmit : false, stopOnFirst : false, focusOnError : false});

            if(payment.currentMethod == 'payone_creditcard'){
                window.payone.exec(function () {
                    if (paymentMethodForm.validate()){
                        IWD.OPC.savePayment();
                    } else {
                        IWD.OPC.saveOrderStatus = false;
                        IWD.OPC.Checkout.hideLoader();
                        IWD.OPC.Checkout.unlockPlaceOrder();

                        IWD.OPC.bindChangePaymentFields();
                    }
                });
            } else {
                if (paymentMethodForm.validate()){
                    IWD.OPC.savePayment();
                } else {
                    IWD.OPC.saveOrderStatus = false;
                    IWD.OPC.Checkout.hideLoader();
                    IWD.OPC.Checkout.unlockPlaceOrder();

                    IWD.OPC.bindChangePaymentFields();
                }
            }
        }
    }
};

$j(document).ready(function () {
    IWD.OPC.Centinel.init();
    IWD.OPC.PayoneCreditCard.init();
});

Collaboration

If it was useful for you and you use it please let me know if I should create a new module for it.

Feel informed? I hope so.

Like this article? Share it on Facebook, Twitter, or Linkedin, send a smoke signal or even try some morse code.

I will be glad to answer your questions or get some feedback from you here in comments below.