Hi, I am sort of new to Magento, especially Magento 2.. I am trying to restrict a payment method (for a specific customer group) by implementing an Observer for "payment_method_is_active" event. Nothing I try seems to do the job though.
Currently, I have stripped down the code and simply am trying to turn off Purchase Order method for everyone, but it doesn't work. Could somebody point me the errors in the code?
Zen/PaymentMethod/etc/module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Zen_PaymentMethod" setup_version="2.0.0" /></config>
Zen/PaymentMethod/etc/event.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="Zen_PaymentMethod_DisablePMbyGroup" instance="Zen\PaymentMethod\Observer\DisablePMbyGroup" /> </event> </config>
Zen/PaymentMethod/registration.php
\Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Zen_PaymentMethod', __DIR__);
Zen/PaymentMethod/Observer/Observer.php
<?php
namespace Zen\PaymentMethod\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\App\ObjectManager;
class DisablePMbyGroup implements ObserverInterface
{
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $loggerInterface) {
$this->logger = $loggerInterface;
}
/**
*
* @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();
$this->logger->debug($observer->getEvent());
if ($method_instance->getCode() == 'purchaseorder') {
$result->setData('is_available', false);
}
}
}
Even the logger doesn't trigger when I get the payment methods displayed..
SOLUTION: @Sunil Patel's solution with plugin does the job great. I have included the extended plugin code that restricts Payment Method according to specific customer group at the end of this thread.
It seems however that the solution to the problem with Observer hasn't been solved, but I feel as long as there's an alternative we can mark this solved... If anyone wants to chip in to the Observer issue, I can help with testing...
EDIT #2:
Just wanted to add this here: according to Magento docs, events' data must not be modified by observers, so @Sunil Patel answer was the only way to do it and my original question about the observer was invalid..
Solved! Go to Solution.
Hello @Zendo
you can use plugin method for that
you need to create di.xml into etc/di.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Payment\Model\MethodList"> <plugin name="methodlist" type="CompnayName\ModuleName\Plugin\Model\Method\Available" sortOrder="1" />
</type> </config>
Availbale.php code
<?php namespace CompanyName\ModuleName\Plugin\Model\Method; class Available { public function afterGetAvailableMethods($subject, $result) { foreach ($result as $key=>$_result) { if ($_result->getCode() == "purchaseorder") { $isAllowed = false; // your logic here if (!$isAllowed) { unset($result[$key]); } } } return $result; } }
Hope it will help you.
If works then mark as solution
keep below way to get logger details,
$this->logger->debug($observer->getEvent()->debug());
$this->logger->debug($observer->getEvent()->debug());
This still didn't get any details to the logs. How to know if my Observer module even gets executed properly?
It is enabled as a module and shows up in the list...
Yes, thanks.. As I said the module is enabled. It indeed says so in app/etc/config.php as well..
Do you see any other issues with the code?
Or could some other configuration mess with this module?
Check with below code without use of logger and check log inside var/log/mylog.log,
public function execute(\Magento\Framework\Event\Observer $observer) { $result = $observer->getEvent()->getResult(); $method_instance = $observer->getEvent()->getMethodInstance(); $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/mylog.log'); $logger = new \Zend\Log\Logger(); $logger->addWriter($writer); $logger->info(print_r($observer->getEvent()->debug(),true)); if ($method_instance->getCode() == 'purchaseorder') { $result->setData('is_available', false); } }
Just clear cache and remove var/generated folder.
Hi @Zendo
I think main issue here is your observer file is not called !!
Yes , its because of you have issue with your code - Name of your observer file !!
At on this location - Zen/PaymentMethod/Observer/Observer.php
You have given file name as an Observer.php but your actual class name is - DisablePMbyGroup
So here fileName should DisablePMbyGroup.php instead of Observer.php and that is the reason your file is not calling !!
Hope it helps !!!
Hello @Zendo
you can use plugin method for that
you need to create di.xml into etc/di.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Payment\Model\MethodList"> <plugin name="methodlist" type="CompnayName\ModuleName\Plugin\Model\Method\Available" sortOrder="1" />
</type> </config>
Availbale.php code
<?php namespace CompanyName\ModuleName\Plugin\Model\Method; class Available { public function afterGetAvailableMethods($subject, $result) { foreach ($result as $key=>$_result) { if ($_result->getCode() == "purchaseorder") { $isAllowed = false; // your logic here if (!$isAllowed) { unset($result[$key]); } } } return $result; } }
Hope it will help you.
If works then mark as solution
@Manthan Dave lol thanks! I absolutely missed it!
I have now renamed Observer according to it's class name, and I am using the code @Rakesh Jesadiya suggested to write log into mylog file, but that still didn't work.
Then I went back to the version with logger and it still didn't work..
In between tests I run setup:upgrade, clear cache and even start a new anon session just to be sure..
It seems that for some reason the file is still not getting called, even though the observer has been named properly now..
Please check with below code,
<?php namespace Zen\PaymentMethod\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Framework\App\ObjectManager; class DisablePMbyGroup implements ObserverInterface { protected $logger; public function __construct(\Psr\Log\LoggerInterface $loggerInterface) { $this->logger = $loggerInterface; } /** * * @param \Magento\Framework\Event\Observer $observer * @return void */ public function execute(\Magento\Framework\Event\Observer $observer) { $paymentMethod = $observer->getEvent()->getMethodInstance()->getCode(); $result = $observer->getEvent()->getResult(); $quote = $observer->getEvent()->getQuote(); $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/mylog.log'); $logger = new \Zend\Log\Logger(); $logger->addWriter($writer); $logger->info(print_r($observer->getEvent()->debug(),true)); if (!$quote) { return; } if ($paymentMethod == 'purchaseorder') { $result->setData('is_available', false); return; } } }
@Rakesh Jesadiya I tested this code as well, absolutely no change. The log file doesn't get created and there's no effect on payment methods.
If we assume that the code is fine, what other issues could there be? Why isn't the observer working when the payment methods get called?
Does the payment_method_is_active get dispatched when on "/checkout/#payment" ?