Pregunta

I want to remove the below lines in Magento\Quote\Model\PaymentMethodManagement model file

 if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
            throw new InvalidTransitionException(__('The requested Payment Method is not available.'));
        }

In PaymentMethodManagement file:

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Quote\Model;

use Magento\Framework\Exception\State\InvalidTransitionException;

/**
 * Class PaymentMethodManagement
 */
class PaymentMethodManagement implements \Magento\Quote\Api\PaymentMethodManagementInterface
{
    /**
     * @var \Magento\Quote\Api\CartRepositoryInterface
     */
    protected $quoteRepository;

    /**
     * @var \Magento\Payment\Model\Checks\ZeroTotal
     */
    protected $zeroTotalValidator;

    /**
     * @var \Magento\Payment\Model\MethodList
     */
    protected $methodList;

    /**
     * Constructor
     *
     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
     * @param \Magento\Payment\Model\Checks\ZeroTotal $zeroTotalValidator
     * @param \Magento\Payment\Model\MethodList $methodList
     */
    public function __construct(
        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
        \Magento\Payment\Model\Checks\ZeroTotal $zeroTotalValidator,
        \Magento\Payment\Model\MethodList $methodList
    ) {
        $this->quoteRepository = $quoteRepository;
        $this->zeroTotalValidator = $zeroTotalValidator;
        $this->methodList = $methodList;
    }

    /**
     * {@inheritdoc}
     */
    public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
    {
        /** @var \Magento\Quote\Model\Quote $quote */
        $quote = $this->quoteRepository->get($cartId);

        $method->setChecks([
            \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
            \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
            \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
            \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
        ]);
        $payment = $quote->getPayment();

        $data = $method->getData();
        $payment->importData($data);

        if ($quote->isVirtual()) {
            $quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
        } else {
            // check if shipping address is set
            if ($quote->getShippingAddress()->getCountryId() === null) {
                throw new InvalidTransitionException(__('Shipping address is not set'));
            }
            $quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
        }
        if (!$quote->isVirtual() && $quote->getShippingAddress()) {
            $quote->getShippingAddress()->setCollectShippingRates(true);
        }

        if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
            throw new InvalidTransitionException(__('The requested Payment Method is not available.'));
        }

        $quote->setTotalsCollectedFlag(false)->collectTotals()->save();
        return $quote->getPayment()->getId();
    }}

How to do this. Thanks.

¿Fue útil?

Solución

All other answers tell you how to rewrite the model, exactly what is asked. But Magento 2 offers another solution to your problem: Plugins. With plugins you can change the outcome of just about any public method in Magento 2. You stated you want to change the result of this function:

if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
    throw new InvalidTransitionException(__('The requested Payment Method is not available.'));
}

You can do this by adding a plugin on the \Magento\Payment\Model\Checks\ZeroTotal class. Add this to your etc/di.xml file:

<type name="Magento\Payment\Model\Checks\ZeroTotal">
    <plugin name="your_unique_name_for_this_plugin" type="Vendor\Module\Plugin\ZeroTotal" />
</type>

Then create the class:

<VendorName>\<ModuleName>\Plugin\ZeroTotal

namespace Vendor\Module\Plugin;

class ZeroTotal
{
    public function afterIsApplicable($subject, $result)
    {
        return true;
    }
}

This will make sure the function always returns true. If you want a more granular approach you can change the function to this:

public function aroundIsApplicable($subject, callable $proceed, ...$args)
{
   if ($this->meetsMyCustomRequirement()) {
       // This will call the original function and return it's results.
       return $proceed(...$args);
   }

   return false;
}

If the $proceed function isn't called then the original function is also never called.

Otros consejos

Steps to Follow :

  • Override di.xml
  • Override PaymentMethodManagement.php
  • Launch SSH and Run Commands

Override di.xml

app/code/Namespace/Modulename/etc

<?xml version="1.0"?>
   <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
      <preference for="Magento\Quote\Model\PaymentMethodManagement" type="Namespace\Modulename\PaymentMethodManagement" />
   </config>

Override PaymentMethodManagement.php

/**
* {@inheritdoc}
*/
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
    /** @var \Magento\Quote\Model\Quote $quote */
    $quote = $this->quoteRepository->get($cartId);

    $method->setChecks([
        \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
        \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
        \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
        \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
    ]);
    $payment = $quote->getPayment();

    $data = $method->getData();
    $payment->importData($data);

    if ($quote->isVirtual()) {
        $quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
    } else {
        // check if shipping address is set
        if ($quote->getShippingAddress()->getCountryId() === null) {
            throw new InvalidTransitionException(__('Shipping address is not set'));
        }
        $quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
    }
    if (!$quote->isVirtual() && $quote->getShippingAddress()) {
        $quote->getShippingAddress()->setCollectShippingRates(true);
    }
    /*** Do stuff with this code ***/
    if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
        throw new InvalidTransitionException(__(''));
    }
    /*** Do stuff with this code ***/

    $quote->setTotalsCollectedFlag(false)->collectTotals()->save();
    return $quote->getPayment()->getId();
}

Launch SSH and Run Commands

php bin/magento setup:di:compile
php bin/magento cache:clean
php bin/magento cache:flush

I hope it helps!

You can do it by using Preference in your di.xml file of your custom module.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <preference for="Magento\Quote\Model\PaymentMethodManagement" type="vendor\module\Model\PaymentMethodManagement" />

</config>

in you 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">

    <preference for="Magento\Quote\Model\PaymentMethodManagement" type="Vendor\Module\Model\Rewrite\Quote\PaymentMethodManagement" />

</config>

in your Model file

<?php 
 namespace Vendor\Module\Model\Rewrite\Quote;

        class PaymentMethodManagement extends \Magento\Quote\Model\PaymentMethodManagement
        {
            public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
            {
                /** @var \Magento\Quote\Model\Quote $quote */
                $quote = $this->quoteRepository->get($cartId);

                $method->setChecks([
                    \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
                    \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
                    \Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
                    \Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
                ]);
                $payment = $quote->getPayment();

                $data = $method->getData();
                $payment->importData($data);

                if ($quote->isVirtual()) {
                    $quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
                } else {
                    // check if shipping address is set
                    if ($quote->getShippingAddress()->getCountryId() === null) {
                        throw new InvalidTransitionException(__('Shipping address is not set'));
                    }
                    $quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
                }
                if (!$quote->isVirtual() && $quote->getShippingAddress()) {
                    $quote->getShippingAddress()->setCollectShippingRates(true);
                }
                /*** Do stuff with this code ***/
                if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
                    throw new InvalidTransitionException(__(''));
                }
                /*** Do stuff with this code ***/

                $quote->setTotalsCollectedFlag(false)->collectTotals()->save();
                return $quote->getPayment()->getId();
            }

        }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top