Skip to content

Add fee to Payment method

I’m trying to add an extra fee to the order when the payment method is Cash on delivery and the shipping country is Greece.

I have created the following files:

app/code/HectorCustom/CodFee/registration.php

MagentoFrameworkComponentComponentRegistrar::register(
    MagentoFrameworkComponentComponentRegistrar::MODULE,
    'HectorCustom_CodFee',
    __DIR__
);

app/code/HectorCustom/CodFee/Observer/AddCodFee.php

namespace HectorCustomCodFeeObserver;
use MagentoFrameworkEventObserver;
use MagentoFrameworkEventObserverInterface;
use PsrLogLoggerInterface;

class AddCodFee implements ObserverInterface
{
    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    public function execute(Observer $observer)
    {
        
        // Retrieve the quote from the observer
        $quote = $observer->getEvent()->getQuote();
        
        if ($quote === null) {
            $this->logger->info('Quote is null');
            return;
        }

        // Get the shipping address from the quote
        $shippingAddress = $quote->getShippingAddress();
        if ($shippingAddress === null) {
            $this->logger->info('Shipping Address is null');
            return;
        }

        // Get shipping country and payment method
        $shippingCountry = $shippingAddress->getCountryId();
        $paymentMethod = $quote->getPayment()->getMethod();

        // Log the shipping country and payment method
        $this->logger->info('Shipping Country: ' . $shippingCountry);
        $this->logger->info('Payment Method: ' . $paymentMethod);

        // Check conditions
        if ($shippingCountry === 'GR' && $paymentMethod === 'cashondelivery') {
            $fee = 5.00; // Set fee

            // Set the fee on the shipping address
            $shippingAddress->setFeeAmount($fee);
            $shippingAddress->setBaseFeeAmount($fee);

            // Add fee to grand total
            $quote->setGrandTotal($quote->getGrandTotal() + $fee);
            $quote->setBaseGrandTotal($quote->getBaseGrandTotal() + $fee);

            // Log the fee addition
            $this->logger->info('Cash on Delivery fee added: ' . $fee);
        } else {
            $this->logger->info('Conditions not met for adding fee');
        }
    }
}

app/code/HectorCustom/CodFee/Model/Total/Quote/CodFee.php

namespace HectorCustomCodFeeModelTotalQuote;

use MagentoQuoteModelQuoteAddressTotalAbstractTotal;
use MagentoQuoteModelQuote;

use PsrLogLoggerInterface;

class CodFee extends AbstractTotal
{
    public function __construct(LoggerInterface $logger)
    {
        $this->setCode('cod_fee');
        $this->logger = $logger;
    }

    public function collect(
        Quote $quote,
        MagentoQuoteApiDataShippingAssignmentInterface $shippingAssignment,
        MagentoQuoteModelQuoteAddressTotal $total
    ) {
        parent::collect($quote, $shippingAssignment, $total);
        
         // Retrieve the fee amount
        $fee = $quote->getShippingAddress()->getFeeAmount();

$this->logger->info('Collector RUN!!!');

        if ($fee > 0) {
            // Set total amounts
            $total->setTotalAmount('cod_fee', $fee);
            $total->setBaseTotalAmount('cod_fee', $fee);

            // Update grand totals
            $total->setGrandTotal($total->getGrandTotal() + $fee);
            $total->setBaseGrandTotal($total->getBaseGrandTotal() + $fee);
        }
        return $this;
    }

    public function fetch(Quote $quote, MagentoQuoteModelQuoteAddressTotal $total)
    {
        $fee = $quote->getShippingAddress()->getFeeAmount();

        if ($fee > 0) {
            $total->setTotalAmount('cod_fee', $fee);
            $total->setBaseTotalAmount('cod_fee', $fee);
            $total->setGrandTotal($total->getGrandTotal() + $fee);
            $total->setBaseGrandTotal($total->getBaseGrandTotal() + $fee);
        }
    }

}

app/code/HectorCustom/CodFee/etc/events.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="sales_quote_collect_totals_before">
        <observer name="add_cod_fee" instance="HectorCustomCodFeeObserverAddCodFee" />
    </event>
</config>

app/code/HectorCustom/CodFee/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="MagentoQuoteModelQuoteAddressTotalCollector">
        <arguments>
            <argument name="collectors" xsi:type="array">
                <item name="cod_fee" xsi:type="object">HectorCustomCodFeeModelTotalQuoteCodFee</item>
            </argument>
        </arguments>
    </type>
</config>

app/code/HectorCustom/CodFee/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="HectorCustom_CodFee" setup_version="1.0.0"/>
</config>

app/code/HectorCustom/CodFee/etc/checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart.totals">
            <block class="MagentoCheckoutBlockCartTotals" name="cod_fee" template="HectorCustom_CodFee::cart/totals/cod_fee.phtml">
                <arguments>
                    <argument name="total" xsi:type="string">cod_fee</argument>
                </arguments>
            </block>
        </referenceBlock>
    </body>
</page>

appcodeHectorCustomCodFeeviewfrontendtemplatescarttotalscod_fee.phtml

if ($block->getTotal()->getValue()):
<tr class="totals cod-fee">
    <th><?= $block->escapeHtml(__('Cash on Delivery Fee')) ?></th>
    <td><?= $block->formatPrice($block->getTotal()->getValue()) ?></td>
</tr>
endif;

Althought I see the logs from AddCodFee.php written in system.log, I see no logs from CodFee.php and the order total is not changing.

My magento version is 2.4.6.

I’d like some help or guidance as to what I’m missing.

I’m fairly new to magento and this is my first time experimenting with a custom module.

Thank you in advance.