Intro: In a custom extension that adds a custom shipping method (pickup type) and extends Magento2 Checkout, an issue came up with order creation - logged in customers can't place orders (not-logged-in ones can).
Details If the extension is named vendor_extension: 1. The vendor_extension adds custom shipping method (method:click_and_collect). Here is the model creating the method:
namespace Vendor\Extension\Model\Carrier;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
class ClickAndCollect extends AbstractCarrier implements CarrierInterface
{
protected $_code = 'click_and_collect';
protected $_isFixed = true;
protected $_rateResultFactory;
protected $_rateMethodFactory;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
array $data = [] - List item
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
public function collectRates(RateRequest $request)
{
$result = $this->_rateResultFactory->create();
$method = $this->_rateMethodFactory->create();
$method->setCarrier('click_and_collect');
$method->setCarrierTitle('click_and_collect');
$method->setMethod('click_and_collect');
$method->setMethodTitle('click_and_collect');
$amount = $this->getConfigData('price');2
$method->setPrice($amount);
$method->setCost($amount);
$result->append($method);
return $result;
}
public function getAllowedMethod()
{
return ['click_and_collect' => $this->getConfigData('name')];22
}
}
For the checkout, it overrides in the extension's checkout_index_index.xml,
<item name="shippingMethodItemTemplate" xsi:type="string"> <item name="shippingMethodListTemplate" xsi:type="string">
shippingMethodListTemplate and shippingMethodItemTemplate are irrelevant, for the question, I can provide the code if need be.There is also a mixin, which creates a few knockout.js methods/vars for usage in the templates.
Steps
1. A user, logged-in or not, enters the Checkout, selects "click_and_collect" shipping method, enters checkout#payments step,
hits "Place Order" button:
1.1 Not-logged-in user - order is placed, redirect to success screen happens, the new order is visible in admin panel.
1.2. Logged-in user - an error message pops-up
email is required field.
1.2.1 After that I edit vendor/magento/module-checkout/view/frontend/web/js/action/place-order.js to test, if overriding it, could solve the issue:
{
payload = {
cartId: quote.getQuoteId(),
billingAddress: quote.billingAddress(),
paymentMethod: paymentData
};
if (customer.isLoggedIn()) {
serviceUrl = urlBuilder.createUrl('/guest-carts/mine/payment-information', {});
payload.email = window.customerData.email;
window.quote = quote;
} else {
window.quote = quote;
serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/payment-information', {
quoteId: quote.getQuoteId()
});
payload.email = quote.guestEmail;
}
return placeOrderService(serviceUrl, payload, messageContainer);
}
After that, the error message that originates from QuoteRepository.php changes to
No such entity with cartId = null
p.s. additional info, seems that quoteId/cartId for non-logged-in users are unique hash values like
660b2d37306b1d83fe82c17b8adbeb99
and for logged in customers are of type integer
int (6)
Guessing it is designed this way, to give ability to edit carts from previous sessions for registered customers. Naturally, I have split-screen compared mine shipping-method model against shipping-method models, that work for logged in customers.
Edit:: Turned out a faulty Magento2 instance was involved, as well. On clean instance the issue turned out to be of the type:
"Please select shipping method"
The problem behind and the solution to this issue are described here:
Magento 2 : Checkout with new shipping method issue when code length exceeds 40 characters