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.