Magento – OnePage Checkout – Hide Payment method depending on selected shipping method

dependencyevent-observeronepage-checkoutpayment-methodsshipping-methods

I have a problem that is driving me nuts.
What I'm trying to accomplish is the following:

During checkout I want to have different payment methods available depending on which shipping method was chosen.

I know there was already the same question before, but the answerrsprovided there didn't do he job. I tell you why:
I have done exactly what is suggested in the answer of OnePage Checkout – Hide Payment method depending on Shipping Method

What I have done is to create an Observer on the payment_method_is_active event:

class MyNameSpace_PaymentMethodFilter_Model_Observer{

public function paymentMethodIsActive(Varien_Event_Observer $observer){
    $event = $observer->getEvent();
    $method = $event->getMethodInstance();

    $result = $event->getResult();
    $carriers = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod();
    if($carriers == 'flatrate_flatrate' ){
                if($method->getCode() == 'checkmo'){
                    $result->isAvailable = true;
                }else{
                    $result->isAvailable = false;
                }
        }

}
}

The Problem with this observer is, that the payment_method_is_active event is only dispatched when the onepage is loaded the first time. This means, that after saving the shipping method, the observer doesn't receive any event and therefore can not apply the changes to the payment methods.

The availability of payment methods would rather need to be set when checkout_controller_onepage_save_shipping_method is fired. But if I write an Observer for this event I don't know how I can access the current payment method instances to modify availability accordingly.

Can anyone show me how to solve my problem?

Thanks a lot!

Best Answer

I've had a similar problem (removing dynamically payment methods) and solved it by extending the _canUseMethod($method) function in Mage_Checkout_Block_Onepage_Payment_Methods. There you can return false for specific payment methods which should not be shown in the payment selection.

Example:

class Company_Module_Block_Methods extends Mage_Checkout_Block_Onepage_Payment_Methods {
    protected function _canUseMethod($method) {
        if ($method != null && $method == 'checkmo') {
            $carriers = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod();
            if ($carriers == 'flatrate_flatrate') {
                return parent::_canUseMethod($method);
            } else {
                return false;
            }
        }

        return parent::_canUseMethod($method);
    }
}

The config XML would look like:

<config>
    <global>
        <blocks>
            <checkout>
                <rewrite>
                    <onepage_payment_methods>Company_Module_Block_Methods</onepage_payment_methods>
                </rewrite>
            </checkout>
        </blocks>
    </global>
</config>

That way I could remove payment methods right before they get shown in the one page checkout.

Hope that helps anyone.