Magento2: [2.2.4] Checkout: Address extension attributes incorrectly processed by shipping estimation API

Created on 6 May 2018  路  2Comments  路  Source: magento/magento2

Preconditions

  1. Magento 2.2.4 Community / Commerce with sample data
  2. Add custom quote address total collector which will work with address extension attribute like this:
$extensionAttributes = $address->getExtensionAttributes();
if (!$extensionAttributes) {
    $extensionAttributes = $this->extensionAttributeFactory->create(\Magento\Quote\Api\Data\AddressInterface::class);
    $address->setExtensionAttributes($extensionAttributes);
}
$extensionAttributes->setMyValue('some string here');

Steps to reproduce

  1. Add any configurable product to cart and proceed to checkout
  2. Open network-tab of your browser and navigate to next POST request:
    /rest/default/V1/guest-carts/.../estimate-shipping-methods

Expected result

  1. Here should be no exception in response

Actual result

  1. Note exception in response:
    > Can not call "setMyValue" on array

First I though that the issue lies in the "Temando Shipping" module, because "estimate-shipping" POST request is initiated by it's JS file on checkout:
Temando_Shipping/js/model/shipping-rate-processor/new-address.js

And this POST includes "extension_attribute" as parameter, which looks like this on backend: https://prnt.sc/jeg9hp

But with more deeper investigation I noted that it is Magento core method:
\Magento\Quote\Api\ShipmentEstimationInterface::estimateByExtendedAddress

Which have a bug inside it's deeper implementation:
\Magento\Quote\Model\ShippingMethodManagement::getShippingMethods

Detailed info you can find here: https://prnt.sc/jegj3p
Just take a look at code debug position and right side of the picture (variable watcher).

So, the basic flow inside "getShippingMethods" is:

  1. Convert accepted $address object with method "extractAddressData" to array. It will convert everything to array, including nested objects.
  1. Add converted data to current quote shipping address. But the way how it is done is completely wrong. Since, $shippingAddress->addData() will only copy raw data to object, without restoring objects which were converted to arrays...

  2. At the right side of the picture it is clearly displayed, that "getExtensionAttributes" from incoming and result adresses will return different types. That's the reason why during collecting totals we will get exception this time (Can not call "setMyValue" on array)

Added

Seems like here is more easier (and dirty) way on how we can reproduce the issue, even without adding any extension attributes:

  1. Add $address->save(); to the end of (before return) :
    \Magento\Quote\Model\ShippingMethodManagement::getShippingMethods

This will force run next observer:
\Temando\Shipping\Observer\SaveCheckoutFieldsObserver

  1. Do the same as in "steps to reproduce" part. But this time you will get next error:
    > Fatal error: Uncaught Error: Call to a member function getCheckoutFields() on array in \vendortemando\module-shipping-m2\ObserverSaveCheckoutFieldsObserver.php on line 63
Quote Confirmed P2 ready for dev Reproduced on 2.2.x Reproduced on 2.3.x S2

Most helpful comment

Hi Guys,
We get the same bugs on the 2.3 version, any update or anybody have a permanent solution on this issues?

All 2 comments

Hello @IgorVitol, thank you for your report.
We've acknowledged the issue and added to our backlog.

Hi Guys,
We get the same bugs on the 2.3 version, any update or anybody have a permanent solution on this issues?

Was this page helpful?
0 / 5 - 0 ratings