1

How to get an order's extension attribute value when creating the order via the API?

For example to create an order I'm calling /rest/V1/carts/mine/payment-information with the following payload:

{
    "payment_method": {
        "method": "cashondelivery"
    },
    "email": "[email protected]",
    "billingAddress": {
        "country_id": "US",
        "street": [
            "N/A"
        ],
        "telephone": "012345678911",
        "postcode": "11501",
        "city": "Bangkok",
        "firstname": "John",
        "lastname": "Key",
        "region": "New York",
        "region_code": "",
        "region_id": 43
    },
    "extension_attributes" : {
       "my_custom_order_attribute": "Custom String"
    }
}

Plugin File: AddCustomOrderAttribute.php - Not getting the value of ExtensionAttribute in the $myCustomOrderAttribute even in the $order->getData()

public function setMyCustomOrderAttributeData(OrderInterface $order)
    {
        /**
         * {@SetLogger}
         */
        $writer = new \Laminas\Log\Writer\Stream(BP . '/var/log/attr.log');
        $logger = new \Laminas\Log\Logger();
        $logger->addWriter($writer);

        if ($order instanceof \Magento\Sales\Model\Order) {
        $myCustomOrderAttribute = $order->getExtensionAttributes();
        } else {
            $orderModel = $this->orderFactory->create();
            $orderModel->load($order->getId());
            $myCustomOrderAttribute = $orderModel->getMyCustomOrderAttribute();
        }

        $logger->info(json_encode($order->getData()));

        $extensionAttributes = $order->getExtensionAttributes();
        $orderExtensionAttributes = $extensionAttributes ? $extensionAttributes
            : $this->orderExtensionFactory->create();

        $orderExtensionAttributes->setMyCustomOrderAttribute($myCustomOrderAttribute);
        $order->setExtensionAttributes($orderExtensionAttributes);
    }
    
    /**
     * Add "my_custom_order_attribute" extension attribute to order data object
     * to make it accessible in API data
     *
     * @param OrderRepositoryInterface $subject
     * @param OrderSearchResultInterface $searchResult
     *
     * @return OrderSearchResultInterface
     */
    public function afterGetList(
        OrderRepositoryInterface $subject,
        OrderSearchResultInterface $orderSearchResult
    ) {
        foreach ($orderSearchResult->getItems() as $order) {
            $this->setMyCustomOrderAttributeData($order);
        }
        return $orderSearchResult;
    }

    /**
     * Add "my_custom_order_attribute" extension attribute to order data object
     * to make it accessible in API data
     *
     * @param OrderRepositoryInterface $subject
     * @param OrderInterface $order
     *
     * @return OrderInterface
     */
    public function afterGet(
        OrderRepositoryInterface $subject,
        OrderInterface $resultOrder
    ) {
        $this->setMyCustomOrderAttributeData($resultOrder);
        return $resultOrder;
    }

extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
    <attribute code="my_custom_order_attribute" type="string"/>
</extension_attributes>
</config>

di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Api\OrderRepositoryInterface">
        <plugin name="ord_attr_get_order_extension_attributes" type="Ord\Attr\Plugin\OrderRepositoryPlugin" />
     </type>        
</config>

setAttribute is working fine but getting attribute value from API in this code is not working. Please help me to fix this issue.

Thanks in Advance!!

1 Answer 1

0

Let me know if you need any further assistance. This should load the extension attributtes to the order object whenever you get the order, either from a plugin or anywhere else !

In your vendor\module\etc\ create the file extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
        <attribute code="my_custom_order_attribute" type="string" />
    </extension_attributes>
</config>

Now lets create a plugin to return this value on order Get and GetList.

On your vendor\module\etc\di.xml paste the following code:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">         
    <type name="Magento\Sales\Api\OrderRepositoryInterface">
        <plugin name="venbdor_module_get_order_extension_attributes" type="vendor\module\Plugin\OrderRepositoryPlugin" />    
    </type>
</config>

Now at vendor\module\Plugin create the file OrderRepositoryPlugin.php

<?php

namespace vendor\module\Plugin;
use Magento\Sales\Api\Data\OrderExtensionFactory;
use Magento\Sales\Api\Data\OrderExtensionInterface;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderSearchResultInterface;
use Magento\Sales\Api\OrderRepositoryInterface;
use elastron\elcustom\Api\Data\SimpleNoteInterface;
use Magento\Sales\Api\Data\OrderAddressExtensionInterfaceFactory;
use Magento\Sales\Api\Data\OrderAddressExtension;
use Magento\Sales\Api\Data\OrderAddressInterface;

class OrderRepositoryPlugin
{
    
    protected $extensionFactory;

    protected $productloader;
    protected $timezone;
    protected $addressRepository;
    
    public function __construct(
        OrderExtensionFactory $extensionFactory,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
        \Magento\Catalog\Model\ProductFactory $_productLoader,
        \Magento\Customer\Api\AddressRepositoryInterface $addressRepository
    )
    {
        $this->extensionFactory  = $extensionFactory;
        $this->timezone          = $timezone;
        $this->productloader     = $_productLoader;
        $this->addressRepository = $addressRepository;
        
    }

    public function afterGet(OrderRepositoryInterface $subject, OrderInterface $order)
    {   
        $my_custom_order_attribute = $order->getData('my_custom_order_attribute');

        //get extension atributtes
        $extensionAttributes = $order->getExtensionAttributes();
        $extensionAttributes = $extensionAttributes ? $extensionAttributes : $this->extensionFactory->create();

         //set custom atributtes
        $extensionAttributes->setMyCustomOrderAttribute($my_custom_order_attribute);

        $order->setExtensionAttributes($extensionAttributes);

        return $order;
    }
    
    public function afterGetList(OrderRepositoryInterface $subject, OrderSearchResultInterface $searchResult)
    {
        $orders = $searchResult->getItems();
        foreach ($orders as $order) 
        {   
            
            $my_custom_order_attribute = $order->getData('my_custom_order_attribute');

            //get extension atributtes
            $extensionAttributes = $order->getExtensionAttributes();
            $extensionAttributes = $extensionAttributes ? $extensionAttributes : $this->extensionFactory->create();

            //set custom atributtes
            $extensionAttributes->setMyCustomOrderAttribute($my_custom_order_attribute );
        }

        return $searchResult;
    }
}
?>
8
  • Hi Joao, I have tried this solution but still not getting the extension_attributes value in the $my_custom_order_attribute variable. I have print the log for $my_custom_order_attribute and $extensionAttributes variable and both are print null and blank json.
    – Alok Kumar
    Oct 8, 2022 at 15:19
  • Could you please update the question with your extension_attributes.xml ?
    – Joao71
    Oct 8, 2022 at 19:06
  • Hi Joao, I have updated the question with extension_attributes.xml and di.xml, btw I use the same which you provided and send the same payload in the /rest/V1/carts/mine/payment-information API.
    – Alok Kumar
    Oct 9, 2022 at 5:01
  • Hi Joao, I have one more question, If I send the extension_attribute in the /rest/V1/carts/mine/payment-information API payload, is it possible to get that extension_attribute value in this OrderInterface?
    – Alok Kumar
    Oct 9, 2022 at 7:03
  • I can't think of any issue that might be causing this, it's usually pretty straight forward.... Can you confirm that the attribute is being saved in the database? Running out of options to help you sorry :)
    – Joao71
    Oct 9, 2022 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.