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.

Khoa TruongDinh
  • 32,054
  • 11
  • 88
  • 155

1 Answers1

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.

Khoa TruongDinh
  • 32,054
  • 11
  • 88
  • 155