4

I'm developing a payment module called Payment fee, when choosing this payment, customer will pay a fee (Surcharge fee)? I think we need to use Ajax to re-calculate. I know how to build a offline payment. But when customer select this payment, I want to re-calculate the total?

enter image description here

There is a guide- how to add fee to order totals in magento2: how to add fee to order totals in magento2. But I don't know how to apply in this case.

2
  • Did you find any solution for this? I am also looking for same things. Feb 8, 2017 at 10:19
  • @DhirenVasoya see my answer below. Feb 10, 2017 at 15:50

1 Answer 1

5

First of all, we can save the collect totals by using Checkout session:

/** @var \Magento\Checkout\Model\Session $_checkoutSession */

$this->_checkoutSession->getQuote()->collectTotals()->save();

We need to create a controller to trigger the collect totals. When customer clicks the Payment radio button, we will make a request to this controller.

Override the Magento_Checkout/js/action/select-payment-method to add the custom method:

app/code/Vendor/PaymentFee/view/frontend/requirejs-config.js

var config = {
    map: {
        '*': {
            'Magento_Checkout/js/action/select-payment-method':
                'Vendor_PaymentFee/js/action/payment/select-payment-method'
        }
    }
};

app/code/Vendor/PaymentFee/view/frontend/web/js/action/payment/select-payment-method.js

define(
    [
        'jquery',
        'ko',
        'Magento_Checkout/js/model/quote',
        'Vendor_PaymentFee/js/action/checkout/cart/totals' // Our custom script
    ],
    function($, ko ,quote, totals) {
        'use strict';
        var isLoading = ko.observable(false);

        return function (paymentMethod) {
            quote.paymentMethod(paymentMethod);
            totals(isLoading, paymentMethod['method']);
        }
    }
);

Vendor_PaymentFee/js/action/checkout/cart/totals is used for building the request.

define(
    [
        'ko',
        'jquery',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/resource-url-manager',
        'Magento_Checkout/js/model/payment-service',
        'mage/storage',
        'mage/url',
        'Magento_Checkout/js/action/get-totals',
        'mage/translate',
        'Magento_Checkout/js/model/payment/method-list'
    ],
    function(
        ko,
        $,
        quote,
        urlManager,
        paymentService,
        storage,
        urlBuilder,
        getTotalsAction
    ) {
        'use strict';

        return function (isLoading, payment) {
            var serviceUrl = urlBuilder.build('paymentfee/checkout/totals'); // Our controller to re-collect the totals
            return storage.post(
                serviceUrl,
                JSON.stringify({payment: payment})
            ).done(
                function(response) {
                    if(response) {
                        var deferred = $.Deferred();
                        isLoading(false);
                        getTotalsAction([], deferred);
                    }
                }
            ).fail(
                function (response) {
                    isLoading(false);
                    //var error = JSON.parse(response.responseText);
                }
            );
        }
    }
);

The urlBuilder.build('paymentfee/checkout/totals') is to build the controller ur.

The controller: app/code/Vendor/PaymentFee/Controller/Checkout/Totals.php

<?php

namespace Vendor\PaymentFee\Controller\Checkout;

use Magento\Framework\App\Action\Context;

class Totals extends \Magento\Framework\App\Action\Action
{
    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $_checkoutSession;

    /**
     * @var \Magento\Framework\Controller\Result\JsonFactory
     */
    protected $_resultJson;

    /**
     * @var \Magento\Framework\Json\Helper\Data
     */
    protected $_helper;

    public function __construct(
        Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Framework\Json\Helper\Data $helper,
        \Magento\Framework\Controller\Result\JsonFactory $resultJson
    )
    {
        parent::__construct($context);
        $this->_checkoutSession = $checkoutSession;
        $this->_helper = $helper;
        $this->_resultJson = $resultJson;
    }

    /**
     * Trigger to re-calculate the collect Totals
     *
     * @return bool
     */
    public function execute()
    {
        $response = [
            'errors' => false,
            'message' => 'Re-calculate successful.'
        ];
        try {
            //Trigger to re-calculate totals
            $payment = $this->_helper->jsonDecode($this->getRequest()->getContent());
            $this->_checkoutSession->getQuote()->getPayment()->setMethod($payment['payment']);
            $this->_checkoutSession->getQuote()->collectTotals()->save();

        } catch (\Exception $e) {
            $response = [
                'errors' => true,
                'message' => $e->getMessage()
            ];
        }

        /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */
        $resultJson = $this->_resultJson->create();
        return $resultJson->setData($response);
    }
}

This is the basic frontend logic. We can follow this guide to add a specific fee to order total:. how to add fee to order totals in magento2

You can download full source code of this module here.

5
  • 3
    Method save of totals collector is deprecated on 2.1.10..
    – Erfan
    Nov 27, 2017 at 8:25
  • Also don't forget to add in the appropriate sections.xml file to force a flush of the minicart cache.
    – Erfan
    Aug 1, 2018 at 8:18
  • @Erfan then what to use now instead of save method? Oct 9, 2019 at 13:38
  • @KowsiganAtsayam I can't remember exactly, but I think it's calling save on the quote repository with the quote. Total collectors change values in the quote.
    – Erfan
    Oct 11, 2019 at 2:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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