5

I have created custom shipping method "Pick up at the store" and payment method "Pay in store" and I would like to hide all other payment methods, when I choose "Pick up at the store" shipping method.

I know, that payment method class has function "isAvailable", but it isn't a good idea to create special conditions for all available methods.

Please advice how I can hide all other payment method except "Pay in store", when "Pick up at the store" shipping method is choose. Thanks.

3
  • Did you get this? What's going on?
    – 3CE
    Commented Sep 24, 2018 at 18:11
  • Have you got any solution? Commented Oct 28, 2020 at 19:30
  • Checkout my answer below. It should solve your problem. Let me know if you face any problem. Thanks. Commented Nov 2, 2020 at 14:35

5 Answers 5

5

I tried DRAJAs code, but this does not work for me. The Shipping Method title is always NULL. I found another solution using the deprecated Cart Model. I also tried the new Quote model that should replace the Cart Model, but again this returned NULL... so I know it’s not according to Magento Standards, but it does do the trick for now.

The below example is used to hide the Klara payment method when a pick-up location is selected.

app/code/Company/Module/etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="payment_method_is_active">
        <observer name="custom_payment" instance="Company\Module\Observer\PaymentMethodAvailable" />
    </event>
</config> 

Company/Module/Observer/PaymentMethodAvailable.php

<?php
namespace Company\Module\Observer;

use Magento\Framework\Event\ObserverInterface;
use \Magento\Checkout\Model\Cart;


class PaymentMethodAvailable implements ObserverInterface
{

    /**
     * @var Cart
     */
    protected $cart;

    /**
     * PaymentMethodAvailable constructor.
     * @param Cart $cart
     */
    public function __construct(
        Cart $cart ){
        $this->cart = $cart;
    }

    /**
     * payment_method_is_active event handler.
     *
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $shippingMethod = $this->cart->getQuote()->getShippingAddress()->getShippingMethod();
        $paymentMethod = $observer->getEvent()->getMethodInstance()->getCode();
    
        if ($paymentMethod == "klarna_kp" && $shippingMethod == 'tablerate_pickup') {
            $checkResult = $observer->getEvent()->getResult();
            $checkResult->setData('is_available', false);
        }
    }
}
2
  • i want to do this but vice versa depends on the payment method show or hide a shipping method ? do you know how can i do it . ? Commented Aug 19, 2019 at 23:50
  • I try your code but not working in magento2.3.5 Commented Oct 28, 2020 at 19:31
1

You can disable remaining payment methods using "payment_method_is_active" event

app/code/Company/Module/etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="payment_method_is_active">
        <observer name="custom_payment" instance="Company\Module\Observer\PaymentMethodAvailable" />
    </event>
</config>

Company/Module/Observer/PaymentMethodAvailable.php

<?php

namespace Company\Module\Observer;

use Magento\Framework\Event\ObserverInterface;


class PaymentMethodAvailable implements ObserverInterface
{

    protected $shippingMethod;

    public function __construct(
           \Magento\Quote\Api\Data\ShippingMethodInterface $shippingMethod){

           $this->shippingMethod = $shippingMethod;
    } 
    /**
     * payment_method_is_active event handler.
     *
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
         $methodTitle = $this->shippingMethod->getMethodTitle();
          if($methodTitle=="Pick up at the store"){
                if($observer->getEvent()->getMethodInstance()->getCode()!=="payinstore"){
                $checkResult = $observer->getEvent()->getResult();
                $checkResult->setData('is_available', false);
           }
         }

    }
}

Ref link - https://webkul.com/blog/disable-payment-method-programmatically-magento2/

1
  • For magento 1, is any resources available?
    – zus
    Commented Aug 7, 2019 at 9:07
1

Just a note to previous answers. Both are using payment_method_is_active event, let's see the code (2.3 here)

$this->_eventManager->dispatch(
    'payment_method_is_active',
    [
        'result' => $checkResult,
        'method_instance' => $this,
        'quote' => $quote
    ]
); 

So, quote is accessible through the event itself, and so the shipping address (where we can get shipping method info: code, description, etc...)

$shippingAddress = $observer->getEvent()->getQuote()->getShippingAddress();

No need to inject anything extra in observer class constructor

0

I tried with DRAJIs code, \Magento\Quote\Api\Data\ShippingMethodInterface this api always return NULL for shipping method.

We cant use \Magento\Checkout\Model\Cart, This is deprecated.

We can use \Magento\Checkout\Model\Session for getting the current shipping method but Model does not update on shipping method change. For updating session we need to reload the page. So This will also not Serve Our Purpose.

The below Approach will solve the problem.

In order to dynamically disable any given payment method based on selected shipping method we need to use Magentos plugin functionality

Create these files in a custom module.

etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<type name="Magento\Payment\Model\MethodList">
    <plugin name="override_method" type="Bp\HidePaymentMethod\Plugin\Model\MethodList" sortOrder="10" disabled="false"  />
</type>
</config>

Plugin/Model/MethodList.php

<?php

namespace Bp\HidePaymentMethod\Plugin\Model;
 
class MethodList
{
protected $logger;

public function __construct(
    \Psr\Log\LoggerInterface $logger
) {
        $this->logger = $logger;
} 

public function afterGetAvailableMethods(
    \Magento\Payment\Model\MethodList $subject,
    $availableMethods,
    \Magento\Quote\Api\Data\CartInterface $quote = null
) {

    $shippingMethod = $this->getShippingMethodFromQuote($quote);
    
    // you can check your shipping method from log
    $this->logger->info("Shipping Code From Plugin=>". $shippingMethod);
    
    if($shippingMethod == "matrixrate_matrixrate_13" || $shippingMethod == "matrixrate_matrixrate_14") {

        foreach ($availableMethods as $key => $method) {
            // Here we will hide Cash method while customer select any of the 2 of above shipping method
            if(($method->getCode() == 'cash')) {
                unset($availableMethods[$key]);
            }
        }
    }
    return $availableMethods;



}

/**
* @param \Magento\Quote\Api\Data\CartInterface $quote
* @return string
*/
private function getShippingMethodFromQuote($quote)
{
    if($quote) {
        return $quote->getShippingAddress()->getShippingMethod();
    }

    return '';
}
}

Note: Replace Bp/HidePaymentMethod with your Vendor/Module

0

Add this in events.xml

 <event name="payment_method_is_active">
        <observer name="disable_po" instance="Dev14\Replacements\Observer\PaymentMethod" />
    </event>

and in file use this code

<?php
namespace Dev14\Replacements\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;

class PaymentMethod implements ObserverInterface
{
    protected $_appState;
    public function __construct(
        \Magento\Framework\App\State $appState,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ) {
        $this->_appState = $appState;
        $this->scopeConfig = $scopeConfig;
    }

    /**
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $result = $observer->getEvent()->getResult();
        $method_instance = $observer->getEvent()->getMethodInstance();
        $quote = $observer->getEvent()->getQuote();
        if(null !== $quote){
            if($method_instance->getCode() =='cashondelivery')
            {
                $result->setData('is_available',false);
            }
        }


    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.