3

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.

  • Did you find any solution for this? I am also looking for same things. – Dhiren Vasoya Feb 8 '17 at 10:19
  • @DhirenVasoya see my answer below. – Khoa TruongDinh Feb 10 '17 at 15:50
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.

| improve this answer | |
  • 2
    Method save of totals collector is deprecated on 2.1.10.. – Erfan Nov 27 '17 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 '18 at 8:18
  • @Erfan then what to use now instead of save method? – Kowsigan Atsayam Oct 9 '19 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 '19 at 2:23

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.