8

I have asked this question on Magento Stackexchange without any success, hence me now asking here.


I'm using Magento Community Edition 1.9.0.1 and have correctly created and registered my module, but I can't seem to detect the shipping methods. Basically, I want to hide Cash on Delivery if Flat Rate or Free Shipping is chosen. Here is the code I have for my observer class:

class Kol_PaymentToggle_Model_Observer
{
  public function paymentMethodIsActive(Varien_Event_Observer $observer) {
      $event  = $observer->getEvent();
      $method = $event->getMethodInstance();
      $result = $event->getResult(); 
    $quote = $observer->getEvent()->getQuote();
    $shippingMethod = $quote->getShippingAddress()->getShippingMethod();
      if($shippingMethod == "standardshipping" || $shippingMethod == "free") {
        if($method->getCode() == 'cashondelivery' ) {
              $result->isAvailable = false;
          }
    }
  }
}

I'm guessing that I haven't used the correct shipping method code names or payment method code names, but I'm unsure. Anyone has any advice?

I only have 3 shipping methods enabled:

  • Collect In Store
    Title = Collect in Store
    Method Name = Collect In Store (Extension link)
  • Flat Rate
    Title = Standard Delivery
    Method Name = Standard Shipping
  • Free Shipping
    Title = Free Delivery
    Method Name = Free

Output of config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Kol_PaymentToggle>
            <version>0.0.1</version>
        </Kol_PaymentToggle>
    </modules>
    <frontend>
        <events>
            <payment_method_is_active>
                <observers>
                    <paymentfilter_payment_method_is_active>
                        <type>singleton</type>
                        <class>Kol_PaymentToggle_Model_Observer</class>
                        <method>paymentMethodIsActive</method>
                    </paymentfilter_payment_method_is_active>
                </observers>
            </payment_method_is_active>
        </events>
    </frontend>
</config>
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
maGz
  • 787
  • 3
  • 8
  • 25
  • can you please tell me on which event the code is fire? – Amit Bera Oct 28 '14 at 09:36
  • Hi Amit. It is meant to fire on the onepage checkout at the point where the person must choose a payment method. – maGz Oct 28 '14 at 09:40
  • Sorry, you meant the event in code, correct? In the config.xml for this module the event is called `payment_method_is_active`, and the observer is called `paymentfilter_payment_method_is_active` – maGz Oct 28 '14 at 09:45
  • @Amit: Edited my post to include `config.xml` output – maGz Oct 28 '14 at 09:48
  • can you tell are going to paymentMethodIsActive function on payment_method_is_active event? – Amit Bera Oct 28 '14 at 09:50
  • I know that the function does fire. If I change the condition on line 9 to `if($shippingMethod != "blahblahblah") {...`, then indeed the cash on delivery payment option does not show – maGz Oct 28 '14 at 09:52
  • it should be freeshipping_freeshipping and standardshipping_standardshipping – Amit Bera Oct 28 '14 at 09:59
  • Aah, I see! That's what I was looking for actually - the actual method code names. Let me try that and get back to you. – maGz Oct 28 '14 at 10:08
  • Hi Amit. Sorry, I tried this, but it unfortunately does not work. I have also noticed that I now get this error on the Product Detail page: `Fatal error: Call to a member function getShippingAddress() on a non-object in /var/www/app/code/local/Kol/PaymentToggle/Model/Observer.php on line 10` – maGz Oct 28 '14 at 12:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63785/discussion-between-magz-and-amit-bera). – maGz Oct 28 '14 at 12:48
  • Ok, no worries...when you have some free time I'd appreciate it. Thanks! – maGz Oct 28 '14 at 12:52

3 Answers3

11

As for I got, you trying to hide some payment methods based on shipping method. For this you don't need to observe things at all. Simply you can do this, just follow me,

Every methods(in one page check out) post the methods which are chosen to the next level. so you can get the shipping method which are chosen, in payment method level. Just print the post things in

app/design/frontend/base/default/template/checkout/onepage/payment/methods.phtml

in this add below one,

<?php print_r($_POST); ?>

So now you can get the shipping methods which are chosen previous step. And note it, so now, you can add just simple logic (if else) condition in same file for hiding payment,

For example here I want hide check / money order payment method, if shipping method is flat. Here the payment method code is checkmo. you can get payment method code by simply printing that variable like echo $_code = $_method->getCode(); in same file. so here just add simple if else ,

  <?php
    $methods = $this->getMethods();


    $oneMethod = count($methods) <= 1;
?>
<?php if (empty($methods)): ?>
    <dt>
        <?php echo $this->__('No Payment Methods') ?>
    </dt>
<?php else:
    foreach ($methods as $_method):
       echo  $_code = $_method->getCode();


if($_POST['shipping_method'] == 'flatrate_flatrate') {
if($_code == 'checkmo') {
    continue;
}
}
?>

Here,

 if($_POST['shipping_method'] == 'flatrate_flatrate') {
if($_code == 'checkmo') {
    continue;
}
}

checks the shipping method and skip the payment method which we don't want to display. That's it. Please comment here if you have any doubt.

Note:

 shipping_method => flatrate_flatrate
 paymet_method   => checkmo
Elavarasan
  • 2,579
  • 2
  • 25
  • 42
  • @Elvarasan: Thank you! I knew I should be modifying the PHTML instead. makes a lot more sense. I'll override the PHTML for my sub-theme – maGz Oct 28 '14 at 13:54
  • Question: where would I stick `` – maGz Oct 28 '14 at 13:56
  • Elvarasan, you are a star! Works beautifully. Even if I go back a few steps and select a different shipping method, it updates..no need to check for Mage checkout session or anything like that – maGz Oct 28 '14 at 14:16
  • 2
    Brilliant solution. Thanks Elavarasan. – Alan Nov 20 '14 at 14:56
  • If i have OnePage Checkout from IWD, i have all steps in same page, so i can't use POST. How can i have in this methods.phtml the array $_shippingRateGroups from shipping_method/available.phtml? If i can obtain this, I can do a check like this `... foreach ($methods as $_method): $_code = $_method->getCode(); if ( array_key_exists('freeshipping', $_shippingRateGroupsCheck )) { if($_code == 'msp_cashondelivery') { continue; } } ...` – Simbus82 May 28 '15 at 08:36
1

Though the accepted answer works, it is not an elegant solution since it prompts us to check the post data in a phtml file which is not a good method. Instead, you should definitely look for an event to do this job.

Luckily we have a perfect event to do this job and which is payment_method_is_active. Please see the detailed answer here.

Basically, you need to set the payment method inactive through this method as you can see in the answer.

Rajeev K Tomy
  • 2,206
  • 1
  • 18
  • 35
0

In addition to the solution for the OnePage Checkout IWD provided by @Simbus82:

$shipping = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress()->getShippingMethod();

foreach ($methods as $_method): 
        $_code = $_method->getCode(); 
        if ( $shipping == 'matrixrate_matrixrate_140' or $shipping == 'matrixrate_matrixrate_148' ) { 
            if($_code != 'cashondelivery') { 
                continue;   
            } 
        }
HebeleHododo
  • 3,620
  • 1
  • 29
  • 38