Magento 1.9 – Place Order Button Disabled with Virtual Products and PayPal Express

checkoutmagento-1.9paypal-express

I have seen some ask this question around the web but without much of an answer given so I'm asking it here.

Customers who are trying to place an order for a Virtual Product using PayPal Express Checkout are unable to click the Place Order button on the review step after they have clicked the agree checkbox for terms and conditions. The button is disabled after checking the agree checkbox but not before.

This issue does not occur when dealing with a Simple Product or any product that appears to have a shipping method attached. The only visible difference I see on the page is the shipping option selection but I could be missing something.

I would imagine this is some sort of bug and not the intended outcome. Any thoughts on how to fix this?

It may also be important to note that I am using PayPal Payments Pro (Includes Express Checkout) method.

Best Answer

The issue is with how

skin/frontend/base/default/js/checkout/review.js

interacts with

design/frontend/base/default/template/paypal/express/review.phtml

review.js has not been updated since 1.7 (or maybe before) review.phtml has been updated with 1.9

When a virtual order happens, there is no shipping section on the review page, and the logic of the "OrderReviewController" tells it to observe all the inputs of the form 'order_review_form', and if they change, to disable the "Place Order" button.

This seems to be a legacy behaviour, because the only remaining input in the 'order_review_form' is the checkbox to agree with Terms and Conditions - and you actually want precisely the opposite behaviour with that checkbox.

The solution: Create a copy of review.js in your theme's "skin" area, eg:

skin/frontend/default/modern/js/checkout/review.js

Edit this review.js, and replace line 358

Event.observe(input, 'change', this._onElementChange.bindAsEventListener(this));

with

        if (typeof input.id !== 'string' || input.id.substr(0,9) !== 'agreement') {
            Event.observe(input, 'change', this._onElementChange.bindAsEventListener(this));    
        }

A proper solution would require review.js being rewritten to be compatible with review.phtml...