In this post, we’ll expose our new attribute in the API so that our finance system can retrieve the value of this attribute when it makes a REST request for an order. There are two steps, first add a getter method for this attribute to the order extension interface and for the class which implements it, and second add the new attribute’s value during order data retrieval. We’ll do the second with a plugin that gets the attribute and sets it in methods which add attributes for both single and multiple records (i.e. for multiple in the case of an order search).
First step, create getter methods:-
DavidMann/OrderSource/etc/extension_attributes.xml – add getter methods to the order extension interface
1<?xml version=”1.0″?>
2<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:Api/etc/extension_attributes.xsd”>
3<extension_attributes for=”Magento\Sales\Api\Data\OrderInterface”>
4<attribute code=”order_source” type=”string” />
5</extension_attributes>
6</config>
Note we’ve also created setter methods with this step.
To actually generate the getter methods and setter methods, we’ll need to use the compile command at the CLI:
bin/magento setup:di:compile
Only then we’ll see the interface generated/code/Magento/Sales/Api/Data/OrderExtensionInterface.php and it’s implementation generated/code/Magento/Sales/Api/Data/OrderExtension.php with added getter and setter methods for our new attribute order_source.
generated/code/Magento/Sales/Api/Data/OrderExtension.php
531/**
532* @return string|null
533*/
534public function getOrderSource()
535{
536return $this->_get(‘order_source’);
537}
538
539/**
540* @param string $orderSource
541* @return $this
542*/
543public function setOrderSource($orderSource)
544{
545$this->setData(‘order_source’, $orderSource);
546return $this;
547}
Next step is to register a plugin as shown in orange in our already created di.xml.
DavidMann/OrderSource/etc/di.xml – register the plugin that will add the new attribute to order data (orange)
1<?xml version=”1.0″?>
2<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:ObjectManager/etc/config.xsd”>
3<virtualType name=”Magento\Sales\Model\ResourceModel\Order\Grid” type=”Magento\Sales\Model\ResourceModel\Grid”>
4<arguments>
5<argument name=”columns”>
6<item name=”order_source” xsi:type=”string”>sales_order.order_source</item>
7</argument>
8</arguments>
9</virtualType>
10<type name=”Magento\Sales\Api\OrderRepositoryInterface”>
11<plugin name=”orderSourceUpdate” type=”DavidMann\OrderSource\Plugin\Api\OrderRepository” />
12</type>
13</config>
And next in the plugin we’ll add the value of order_source to the order for both of our REST requests, for retrieving single and multiple records.
DavidMann/OrderSource/Plugin/Api/OrderRepository.php – add our custom field value during the order data loading
1<?php
2
3namespace DavidMann\OrderSource\Plugin\Api;
4
5use Magento\Sales\Api\Data\OrderExtensionFactory;
6use Magento\Sales\Api\Data\OrderInterface;
7use Magento\Sales\Api\Data\OrderSearchResultInterface;
8use Magento\Sales\Api\OrderRepositoryInterface;
9
10
11class OrderRepository
12{
13
14const ORDER_SOURCE = ‘order_source’;
15
16/**
17* Order Extension Attributes Factory
18*
19* @var OrderExtensionFactory
20*/
21protected $extensionFactory;
22
23/**
24* OrderRepositoryPlugin constructor
25*
26* @param OrderExtensionFactory $extensionFactory
27*/
28public function __construct(OrderExtensionFactory $extensionFactory)
29{
30$this->extensionFactory = $extensionFactory;
31}
32
33/**
34* Add “order_source” extension attribute to order to make it accessible in API data
35*
36* @param OrderRepositoryInterface $subject
37* @param OrderInterface $order
38*
39* @return OrderInterface
40*/
41public function afterGet(OrderRepositoryInterface $subject, OrderInterface $order)
42{
43$orderSource = $order->getData(self::ORDER_SOURCE);
44$extensionAttributes = $order->getExtensionAttributes();
45$extensionAttributes = $extensionAttributes ? $extensionAttributes : $this->extensionFactory->create();
46$extensionAttributes->setOrderSource($orderSource);
47$order->setExtensionAttributes($extensionAttributes);
48
49return $order;
50}
51
52/**
53* Add “order_source” extension attribute to order to make it accessible in API data
54*
55* @param OrderRepositoryInterface $subject
56* @param OrderSearchResultInterface $searchResult
57*
58* @return OrderSearchResultInterface
59*/
60public function afterGetList(OrderRepositoryInterface $subject, OrderSearchResultInterface $searchResult)
61{
62$orders = $searchResult->getItems();
63
64foreach ($orders as &$order) {
65$orderSource = $order->getData(self::ORDER_SOURCE);
66$extensionAttributes = $order->getExtensionAttributes();
67$extensionAttributes = $extensionAttributes ? $extensionAttributes : $this->extensionFactory->create();
68$extensionAttributes->setOrderSource($orderSource);
69$order->setExtensionAttributes($extensionAttributes);
70}
71
72return $searchResult;
73}
74}
And run bin/magento setup:di:compile again.
Try now retrieving the order data in Postman or your preferred alternative tool.
We’ll need to get a token initially for the session before making either of our requests with:-
https://davidmann.test/rest/V1/integration/admin/token?username=davidmann&password=*********
The request for a single order record is quite straightforward:-
https://davidmann.test/rest/V1/orders/42408
where 42408 is the order ID. As part of the request, we’ll also need to specify the token in ‘Authorization’ as a ‘Bearer Token’ in Postman.
This request uses the afterGet method on line 41 of DavidMann/OrderSource/Plugin/Api/OrderRepository.php.
You can see order_source and its value for this record in the Postman response to your request:
https://davidmann.test/rest/V1/orders/42408 – Response under ‘extension_attributes’
57“extension_attributes”: {
58“converting_from_quote”: true,
59“connectors_sales_order”: {
60“parent_id”: 42408,
61“is_exported_to_io”: 0
62},
63“order_source”: “Admin”
64}
65}
The request for multiple records is a little more demanding:-
https://davidmann.test/rest/V1/orders?searchCriteria[filter_groups][0][filters][0][field]=order_source&searchCriteria[filter_groups][0][filters][0][value]=Admin&searchCriteria[filter_groups][0][filters][0][condition_type]=eq
https://magento2.test/rest/V1/orders?
searchCriteria[filter_groups][0][filters][0][field]=order_source
&searchCriteria[filter_groups][0][filters][0][value]=Admin
&searchCriteria[filter_groups][0][filters][0][condition_type]=eq
Again, we’ll need to specify the token in ‘Authorization’ as a ‘Bearer Token’ in Postman.
This request pulls back all orders placed in Admin, i.e. those that have the value ‘Admin’ in the order_source column.
This request uses the afterGetList method on line 60 of DavidMann/OrderSource/Plugin/Api/OrderRepository.php.
When constructing a search, keep the following in mind:
1) To perform a logical OR, specify multiple filters within a filter_groups.
2) To perform a logical AND, specify multiple filter_groups.
For example, to request records created between April 26, 2020 AND April 30, 2020 specify two filter groups with value 0 and 1.
https://davidmann.test/rest/V1/orders?
searchCriteria[filter_groups][0][filters][0][field]=created_at
&searchCriteria[filter_groups][0][filters][0][value]=2020-04-26T04:00:00.0000000Z
&searchCriteria[filter_groups][0][filters][0][condition_type]=from
&searchCriteria[filter_groups][1][filters][0][field]=created_at
&searchCriteria[filter_groups][1][filters][0][value]=2020-04-30T17:59:00.0000000Z
&searchCriteria[filter_groups][1][filters][0][condition_type]=to
&searchCriteria[currentPage]=1
&searchCriteria[pageSize]=100
That’s it! We’ve successfully exposed order_source to incoming requests by providing the necessary methods and data.