Magento 2.3.2: Active payment method on specific category for the products in cart
Please try this way using payment_method_is_active event observer.
Create events.xml
file with the below content.
<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="payment_method_is_active" instance="Vendor\Module\Observer\MethodIsActive" />
</event>
</config>
And create MethodIsActive.php
with the following code.
<?php
namespace Vendor\Module\Observer\Payment;
use Magento\Framework\Event\ObserverInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
class MethodIsActive implements ObserverInterface
{
protected $_cart;
protected $_checkoutSession;
protected $productRepository;
public function __construct(
\Magento\Checkout\Model\Cart $cart,
\Magento\Checkout\Model\Session $checkoutSession,
ProductRepositoryInterface $productRepository
)
{
$this->_cart = $cart;
$this->_checkoutSession = $checkoutSession;
$this->productRepository = $productRepository;
}
/**
* Execute observer
*
* @param \Magento\Framework\Event\Observer $observer
* @return void
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
$quote = $this->getCheckoutSession()->getQuote();
$categoryID = 155; //Add your category ID
$items = $quote->getAllItems();
$flag = false;
foreach($items as $item) {
$product = $this->getProduct($item->getProductId());
$categoryIds = $product->getCategoryIds();
if(in_array($categoryID, $categoryIds)){
$flag = true;
break;
}
}
// you can replace "checkmo" with your required payment method code
if($flag == false && $observer->getEvent()->getMethodInstance()->getCode()=="paypal"){
$checkResult = $observer->getEvent()->getResult();
$checkResult->setData('is_available', false);
}
else if($flag == true && $observer->getEvent()->getMethodInstance()->getCode()=="checkmo"){
$checkResult = $observer->getEvent()->getResult();
$checkResult->setData('is_available', false);
}
}
public function getProduct($productId)
{
return $product = $this->productRepository->getById($productId);
}
public function getCart()
{
return $this->_cart;
}
public function getCheckoutSession()
{
return $this->_checkoutSession;
}
}
You can get it with payment_method_is_active
event observer.
Create events.xml
file with below content.
<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="payroll_payment_method_is_active" instance="Vendor\Module\Observer\DisablePayment" />
</event>
</config>
And create DisablePayment.php
with your condition.
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use use \Magento\Checkout\Model\Session;
class DisablePayment implements ObserverInterface
{
protected $_session;
private $_objectManager;
public function __construct(
Session $session,
\Magento\Framework\ObjectManagerInterface $objectmanager
) {
$this->_session = $session;
$this->_objectManager = $objectmanager
}
/**
* @param Observer $observer
*
* @return void
*/
public function execute(Observer $observer)
{
$result = $observer->getEvent()->getResult();
$method_instance = $observer->getEvent()->getMethodInstance()->getCode();
$quote = $observer->getEvent()->getQuote();
if($method_instance == 'your_payment_code')
{
if (in_array('category id to match', $this->getCategoryIds())) {
$result = $observer->getResult();
$result->isAvailable = false;
}
}
}
public function getCategoryIds()
{
/**
@var $item \Magento\Quote\Model\Quote\Item
*/
$items = $this->_session->getQuote()->getAllItems();
$categoryIds = [];
foreach ($items as $item){
var_dump($item->getName());
$productid = $item->getProductId();
$product = $this->_objectManager->create('Magento\Catalog\Model\Product')- >load($productid);
$categoryIds[] = $product->getCategoryIds();
}
return $categoryIds;
}
}
Hope it helps!!!