4

I've followed the guide on the selected answer here: Payment method only admin Magento 2?

But still no luck.

What I want is to be able to show the Cash On Delivery method only to certain customers. The guide above does not remove the payment method.

Thanks all!

  • The payment still showing on the front page? Or you want to do more things? – Khoa TruongDinh Aug 8 '16 at 14:45
  • The cash on delivery payment is showing fine but I want to be able to remove this from the payment method list depending on customer logged in. So, basically what I want to do is customise what is shown to the customer using code. – MarkDev Aug 8 '16 at 15:00
10

We will describe a simple solution based on the Payment Restriction module, where MageWorx – a vendor name and Payment Restriction – a module name.

  1. First, you need to create a directory for the module:

    app/code/MageWorx/PaymentRestriction

  2. Then, add a registration file:

    app/code/MageWorx/PaymentRestriction/registration.php

    <?php
    /**
     * Copyright © 2016 MageWorx. All rights reserved.
     * See LICENSE.txt for license details.
     */
    
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'MageWorx_PaymentRestriction',
        __DIR__
    );
    
  3. A Composer file (if you decide to transfer the module with the ability to install it using the Composer):

    app/code/MageWorx/PaymentRestriction/composer.json

    {
        "name": "mageworx/module-paymentrestriction",
        "description": "N/A",
        "require": {
            "php": "~5.6.0|~7.0.0"
        },
        "type": "magento2-module",
        "version": "1.0.0",
        "license": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "autoload": {
            "files": [
                "registration.php"
            ],
            "psr-4": {
                "MageWorx\\PaymentRestriction\\": ""
            }
        }
    }
    
  4. A file with the module declaration:

    app/code/MageWorx/PaymentRestriction/etc/module.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Copyright © 2016 MageWorx. All rights reserved.
     * See LICENSE.txt for license details.
     */
    -->
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <module name="MageWorx_PaymentRestriction" setup_version="1.0.0">
        </module>
    </config>
    
  5. Then, we need to create a di.xml file in a common area (this won't work on the Frontend) and declare our plugin in it:

    app/code/MageWorx/PaymentRestriction/etc/di.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Copyright © 2016 MageWorx. All rights reserved.
     * See LICENSE.txt for license details.
     */
    -->
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="Magento\OfflinePayments\Model\Cashondelivery">
            <plugin sortOrder="1" name="restrictByCustomer"
                    type="MageWorx\PaymentRestriction\Plugin\Payment\Method\CashOnDelivery\Available"/>
        </type>
    </config>
    
  6. Now, the last and main file with the plugin class that is responsible for the check:

    app/code/MageWorx/PaymentRestriction/Plugin/Payment/Method/CashOnDelivery/Available.php

    <?php
    /**
     * Copyright © 2016 MageWorx. All rights reserved.
     * See LICENSE.txt for license details.
     */
    
    namespace MageWorx\PaymentRestriction\Plugin\Payment\Method\CashOnDelivery;
    
    use Magento\Customer\Model\Session as CustomerSession;
    use Magento\Backend\Model\Auth\Session as BackendSession;
    use Magento\OfflinePayments\Model\Cashondelivery;
    
    class Available
    {
    
        /**
         * @var CustomerSession
         */
        protected $customerSession;
    
        /**
         * @var BackendSession
         */
        protected $backendSession;
    
        /**
         * @param CustomerSession $customerSession
         * @param BackendSession $backendSession
         */
        public function __construct(
            CustomerSession $customerSession,
            BackendSession $backendSession
        ) {
            $this->customerSession = $customerSession;
            $this->backendSession = $backendSession;
        }
    
        /**
         *
         * @param Cashondelivery $subject
         * @param $result
         * @return bool
         * @throws \Magento\Framework\Exception\LocalizedException
         */
        public function afterIsAvailable(Cashondelivery $subject, $result)
        {
            // Do not remove payment method for admin
            if ($this->backendSession->isLoggedIn()) {
                return $result;
            }
    
            $isLogged = $this->customerSession->isLoggedIn();
            if (!$isLogged) {
                return false;
            }
    
            return $result;
        }
    }
    

For unknown reasons, if you create this plugin only for the frontend, the payment method will be displayed on the checkout page. However, if you try to use it, it will result in an error and return to the checkout. That makes it necessary to validate not only the customer's session but also the admin session. If the admin is logged in, we should not change anything and return the original result.

Also, you can add an additional check on the frontend. For example, you can create a simple module that allows to segment the payment methods according to customer groups. Moreover, you can disable certain payment methods not only for the selected countries (the default option) but also for streets, phone numbers or any other data.

Here is the check:

  1. The Cash on Delivery method is hidden for the not logged in customer:

    The Cash on Delivery method is hidden

  2. The same for the logged in customer:

    enter image description here

  3. Visible:

    enter image description here

  4. Always visible for a store admin:

    enter image description here

Note:

  1. We recommend you to do the same actions in a separate module to have the ability to disable it.

  2. You have to change a vendor and module name to your own.

  3. This solution was created and tested on Magento 2.1.

  • 2
    @MageWorx Its usefull for me also, but when we off this and again trying to on from frontend getting this error. Do you have any solution for this issue :: like :: TypeError: window.checkoutConfig.payment.instructions is undefined – Ashish Jagnani Sep 8 '16 at 12:59
  • Really helpful solution, thank you for sharing. But I'm getting the same error of @AshishJagnani in the frontend, in the checkout page just after the shipping step. Do you know how to solve this error? – Andrea Jan 24 '17 at 8:26
  • @Andrea, override that js file and remove that line. – Ashish Jagnani Jan 24 '17 at 9:12
  • its works what i expect – divya sekar Nov 5 '19 at 12:15
1

Solution for the PayPal Express Checkout method if you want to hide it when product with specified sku was found in cart:

Create a plugin:

Vendor/Module/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- Plugins -->
    <type name="Magento\Paypal\Model\Express">
        <plugin name="disable_paypal_express"
                type="Vendor\Module\Plugin\DisablePayPalExpress"
                sortOrder="10"
                disabled="false"/>
    </type>
</config>

Vendor/Module/Plugin/DisablePayPalExpress.php

<?php
namespace Vendor\Module\Plugin;

class DisablePayPalExpress
{
    /**
     * @var \Magento\Checkout\Model\Session|\Magento\Backend\Model\Session\Quote
     */
    protected $session;

    /** List of the skus for which this method should be disabled */
    protected $disabledForSku = [
        'commission-product',
        'another-sku',
        'Gloves'
    ];

    /**
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Backend\Model\Session\Quote $backendQuoteSession
     * @param \Magento\Framework\App\State $state
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Backend\Model\Session\Quote $backendQuoteSession,
        \Magento\Framework\App\State $state
    ) {
        if ($state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) {
            $this->session = $backendQuoteSession;
        } else {
            $this->session = $checkoutSession;
        }
    }

    /**
     * @param \Magento\Paypal\Model\Express $subject
     * @param $result
     * @return bool
     */
    public function afterIsAvailable(
        \Magento\Paypal\Model\Express $subject,
        $result
    ) {
        /** @var \Magento\Quote\Model\Quote $quote */
        $quote = $this->session->getQuote();
        /** @var \Magento\Quote\Model\Quote\Item[] $quoteItems */
        $quoteItems = $quote->getAllItems();
        foreach ($quoteItems as $quoteItem) {
            if (in_array($quoteItem->getSku(), $this->disabledForSku)) {
                return false; // disable the method if we found product with specified sku
            }
        }

        return $result; // return default result
    }
}

Where inside $disabledForSku we store sku for which method sholud be disabled (unavailable). If you need a custom validation, just add it in the methods body and use a desired result.

PS: I post my answer here because question about PayPal Express Checkout was marked as duplicate of this question and may be removed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.