You could create a custom extension to look through every item in the cart and disable the payment method
MagePal/PaymentRestrictions/etc/events.xml
<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="mp_payment_restrictions" instance="MagePal\PaymentRestrictions\Observer\PaymentMethodActiveObserver" />
</event>
</config>
MagePal/PaymentRestrictions/Observer/PaymentMethodActiveObserver.php
namespace MagePal\PaymentRestrictions\Observer;
use Magento\Framework\DataObject;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Payment\Helper\Data as paymentData;
use Magento\Payment\Model\Method\AbstractMethod;
use Magento\Quote\Api\Data\CartInterface;
class PaymentMethodActiveObserver implements ObserverInterface
{
/**
* @var Data
*/
private $helperData;
/**
* @var paymentData
*/
private $paymentData;
/**
* PaymentMethodActiveObserver constructor.
* @param Data $helperData
* @param paymentData $paymentData
*/
public function __construct(
Data $helperData,
paymentData $paymentData
) {
$this->helperData = $helperData;
$this->paymentData = $paymentData;
}
/**
* @param Observer $observer
* @throws LocalizedException
*/
public function execute(Observer $observer)
{
/** @var DataObject $result */
$result = $observer->getResult();
/** @var AbstractMethod $methodInstance */
$methodInstance = $observer->getMethodInstance();
/** @var CartInterface $quote */
$quote = $observer->getQuote();
$paymentCode = $methodInstance->getCode();
$storeId = $quote ? $quote->getStoreId() : null;
if ($paymentCode == 'cod code here') {
$notAllow = []
foreach ($quote->getAllItems() as $item) {
if ($item->getProduct()->getCodValue()) {
$notAllow[] = $item->getProduct()->getCodValue();
}
}
if (!empty($notAllow)) {
$result->setIsAvailable(false);
}
}
}
}