TransWikia.com

Magento 2: Hide payment methods depends on shipping method

Magento Asked by O.Petrov on December 22, 2021

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.

5 Answers

Add this in events.xml

 <event name="payment_method_is_active">
        <observer name="disable_po" instance="Dev14ReplacementsObserverPaymentMethod" />
    </event>

and in file use this code

<?php
namespace Dev14ReplacementsObserver;

use MagentoFrameworkEventObserverInterface;
use MagentoFrameworkAppRequestDataPersistorInterface;
use MagentoFrameworkAppObjectManager;

class PaymentMethod implements ObserverInterface
{
    protected $_appState;
    public function __construct(
        MagentoFrameworkAppState $appState,
        MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig
    ) {
        $this->_appState = $appState;
        $this->scopeConfig = $scopeConfig;
    }

    /**
     *
     * @param MagentoFrameworkEventObserver $observer
     * @return void
     */
    public function execute(MagentoFrameworkEventObserver $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);
            }
        }


    }

}

Answered by Asad Ullah on December 22, 2021

I tried with DRAJIs code, MagentoQuoteApiDataShippingMethodInterface this api always return NULL for shipping method.

We cant use MagentoCheckoutModelCart, This is deprecated.

We can use MagentoCheckoutModelSession 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="MagentoPaymentModelMethodList">
    <plugin name="override_method" type="BpHidePaymentMethodPluginModelMethodList" sortOrder="10" disabled="false"  />
</type>
</config>

Plugin/Model/MethodList.php

<?php

namespace BpHidePaymentMethodPluginModel;
 
class MethodList
{
protected $logger;

public function __construct(
    PsrLogLoggerInterface $logger
) {
        $this->logger = $logger;
} 

public function afterGetAvailableMethods(
    MagentoPaymentModelMethodList $subject,
    $availableMethods,
    MagentoQuoteApiDataCartInterface $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 MagentoQuoteApiDataCartInterface $quote
* @return string
*/
private function getShippingMethodFromQuote($quote)
{
    if($quote) {
        return $quote->getShippingAddress()->getShippingMethod();
    }

    return '';
}
}

Note: Replace Bp/HidePaymentMethod with your Vendor/Module

Answered by Masud Islam on December 22, 2021

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

Answered by Raul Sanchez on December 22, 2021

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="CompanyModuleObserverPaymentMethodAvailable" />
    </event>
</config> 

Company/Module/Observer/PaymentMethodAvailable.php

<?php
namespace CompanyModuleObserver;

use MagentoFrameworkEventObserverInterface;
use MagentoCheckoutModelCart;


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 MagentoFrameworkEventObserver $observer
     */
    public function execute(MagentoFrameworkEventObserver $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);
        }
    }
}

Answered by Dennis van Schaik on December 22, 2021

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="CompanyModuleObserverPaymentMethodAvailable" />
    </event>
</config>

Company/Module/Observer/PaymentMethodAvailable.php

<?php

namespace CompanyModuleObserver;

use MagentoFrameworkEventObserverInterface;


class PaymentMethodAvailable implements ObserverInterface
{

    protected $shippingMethod;

    public function __construct(
           MagentoQuoteApiDataShippingMethodInterface $shippingMethod){

           $this->shippingMethod = $shippingMethod;
    } 
    /**
     * payment_method_is_active event handler.
     *
     * @param MagentoFrameworkEventObserver $observer
     */
    public function execute(MagentoFrameworkEventObserver $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/

Answered by DRAJI on December 22, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP