Home to skip shipping address step during checkout in Magento 2?
-
14-04-2021 - |
Pregunta
In case of virtual products, we do not need a shipping step so customer directly goes for payment step during checkout.
I have a simple product and a custom field delivery_type
in quote
table. delivery_type
field's value is updated on the cart page by selecting what is the delivery type (home/store).
If the value of delivery_type
is store
shipping step is not required and the customer should see only payment step similar to virtual products at checkout. Can anyone guide me on how I should go about customizing it?
I tried changing the value of field is_virtual
to 1 in quote
and quote_item
table manually but it does not make any difference. I have logged window.checkoutConfig.quoteData.is_virtual
which still shows 0.
Solución
Please have a look at this class
Magento\Quote\Model\Quote
in this class you have this method isVirtual() [image attached]
if the return result is true, Magento will skip the Shipping Step.
You can override this method or create a "after plugin" (recommended) to change the return value as you want
https://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
Otros consejos
Found generic way to skip shipping, not just for virtual products, in my case I have table driven shipping rate according to zip code (distance), and shipping screen is redundant. The idea is waiting for the shipping screen to load and then approve and continue automatically.
- Create requirejs-config.js file in
app/code/[Vendor]/[Modulename]/view/
folder and add below code see why.
var config = {
paths: {
'Magento_Checkout/js/view/shipping': '[Vendor]_[Modulename]/js/view/shipping'
}
};
Copy Shipping.js from magento source folder:
vendor/magento/module-checkout/view/frontend/web/js/view
to your module in the following folder:
app/code/[Vendor]/[Modulename]/view/frontend/web/js/view
Revising the Shipping.js to include the following code:
define([
'jquery',
'underscore',
'Magento_Ui/js/form/form',
'ko',
'Magento_Customer/js/model/customer',
'Magento_Customer/js/model/address-list',
'Magento_Checkout/js/model/address-converter',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/action/create-shipping-address',
'Magento_Checkout/js/action/select-shipping-address',
'Magento_Checkout/js/model/shipping-rates-validator',
'Magento_Checkout/js/model/shipping-address/form-popup-state',
'Magento_Checkout/js/model/shipping-service',
'Magento_Checkout/js/action/select-shipping-method',
'Magento_Checkout/js/model/shipping-rate-registry',
'Magento_Checkout/js/action/set-shipping-information',
'Magento_Checkout/js/model/step-navigator',
'Magento_Ui/js/modal/modal',
'Magento_Checkout/js/model/checkout-data-resolver',
'Magento_Checkout/js/checkout-data',
'uiRegistry',
'mage/translate',
'Magento_Checkout/js/model/shipping-rate-service'
], function (
$,
_,
Component,
ko,
customer,
addressList,
addressConverter,
quote,
createShippingAddress,
selectShippingAddress,
shippingRatesValidator,
formPopUpState,
shippingService,
selectShippingMethodAction,
rateRegistry,
setShippingInformationAction,
stepNavigator,
modal,
checkoutDataResolver,
checkoutData,
registry,
$t
) {
'use strict';
var popUp = null;
// ### 1st revision start
var timer = setInterval(function() {
// Wait until all page was loaded, using Next button div id
var nextVar = $( "#shipping-method-buttons-container");
if (nextVar.length > 0) {
clearInterval(timer);
// Make sure 'Next' button is visible
var nextBtn = $("button", nextVar);
if (nextBtn.is(":visible")) {
__self.setShippingInformation();
}
}
}, 100);
// ### 1st revision end
return Component.extend({
defaults: {
template: 'Magento_Checkout/shipping',
shippingFormTemplate: 'Magento_Checkout/shipping-address/form',
shippingMethodListTemplate: 'Magento_Checkout/shipping-address/shipping-method-list',
shippingMethodItemTemplate: 'Magento_Checkout/shipping-address/shipping-method-item'
},
visible: ko.observable(!quote.isVirtual()),
errorValidationMessage: ko.observable(false),
isCustomerLoggedIn: customer.isLoggedIn,
isFormPopUpVisible: formPopUpState.isVisible,
isFormInline: addressList().length === 0,
isNewAddressAdded: ko.observable(false),
saveInAddressBook: 1,
quoteIsVirtual: quote.isVirtual(),
/**
* @return {exports}
*/
initialize: function () {
var self = this,
hasNewAddress,
fieldsetName = 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset';
// ### last revision start
__self = self;
// ### last revision end
this._super();
...
Using setInterval
is not best practice, but couldn't find a way to trigger setShippingInformation()
after the shipping screen fully loaded. Tried $(document).ready
as well as $(window).on("load", function)
but the document wasn't fully loaded even then, making the call to setShippingInformation()
to be ignored.
Hope this helps anyone.