Ok, I found after one difficult day.
First of all, we need to create etc/webapi.xml file in my module :
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route url="/V1/order/updatecustom" method="POST">
<service class="Ns\Module\Api\CustomInterface" method="updateOrderCustomAttributes" />
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
So, we have our URL and what method to call.
Then, we need to create our custom interface : file Api/CustomInterface.php in my module directory :
<?php
namespace Ns\Module\Api;
/**
* Interface CustomInterface
* @package Ns\Module\Api
*
* @api
* @since 100.1.2
*/
interface CustomInterface
{
/**
* Update order custom attributes
*
* @param \Ns\Module\Api\Data\OrderCustomInterface $data
* @return string
*/
public function
updateOrderCustomAttributes(\Ns\Module\Api\Data\OrderCustomInterface $data);
}
Then, our method need to know what data we want to get. To do that, new interface in file Api/Data/OrderCustomInterface.php :
<?php
namespace Ns\Module\Api\Data;
/**
* Interface OrderCustomInterface
* @package Ns\Module\Api\Data
* @api
*/
interface OrderCustomInterface
{
const INCREMENT_ID = 'incrementId';
const SAP_DOC_NUMBER = 'sapDocNumber';
const INVOICE_NUMBER = 'invoiceNumber';
const BL_NUMBER = 'blNumber';
/**
* Get order increment Id
*
* @return string
*/
public function getIncrementId();
/**
* Get order Sap Doc number
*
* @return string
*/
public function getSapDocNumber();
/**
* Get invoice number
*
* @return string
*/
public function getInvoiceNumber();
/**
* Get BL number
*
* @return string
*/
public function getBlNumber();
/**
* Set increment ID
*
* @param string $incrementId
* @return $this
*/
public function setIncrementId($incrementId);
/**
* Set SAP doc number
*
* @param string $sapIncrementId
* @return $this
*/
public function setSapDocNumber($sapIncrementId);
/**
* Set Invoice number
*
* @param string $invoiceNumber
* @return $this
*/
public function setInvoiceNumber($invoiceNumber);
/**
* Set BL number
*
* @param string $blNumber
* @return $this
*/
public function setBlNumber($blNumber);
}
We have our 2 interfaces. We need to override its.
We need a etc/di.xml to do that :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Ns\Module\Api\CustomInterface" type="Ns\Module\Model\Custom" />
<preference for="Ns\Module\Api\Data\OrderCustomInterface" type="Ns\Module\Model\OrderCustom" />
</config>
And next, we create these files :
Ns/Module/Model/OrderCustom.php to get our data :
<?php
namespace Ns\Module\Model;
use \Psr\Log\LoggerInterface;
use Magento\Sales\Model\AbstractModel;
use Magento\Framework\Api\AttributeValueFactory;
/**
* Interface Custom
* @package Ns\Module\Model
*/
class OrderCustom extends AbstractModel implements \Ns\Module\Api\Data\OrderCustomInterface
{
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory
* @param AttributeValueFactory $customAttributeFactory
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
AttributeValueFactory $customAttributeFactory,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
) {
parent::__construct(
$context,
$registry,
$extensionFactory,
$customAttributeFactory,
$resource,
$resourceCollection,
$data
);
}
/**
* Get order increment Id
*
* @return string
*/
public function getIncrementId()
{
return $this->getData(self::INCREMENT_ID);
}
/**
* Get order Sap Doc number
*
* @return string
*/
public function getSapDocNumber()
{
return $this->getData(self::SAP_DOC_NUMBER);
}
/**
* Get invoice number
*
* @return string
*/
public function getInvoiceNumber()
{
return $this->getData(self::INVOICE_NUMBER);
}
/**
* Get BL number
*
* @return string
*/
public function getBlNumber()
{
return $this->getData(self::BL_NUMBER);
}
/**
* Set increment ID
*
* @param string $incrementId
* @return $this
*/
public function setIncrementId($incrementId)
{
$this->setData(self::INCREMENT_ID, $incrementId);
return $this;
}
/**
* Set SAP doc number
*
* @param string $sapIncrementId
* @return $this
*/
public function setSapDocNumber($sapIncrementId)
{
$this->setData(self::SAP_DOC_NUMBER, $sapIncrementId);
return $this;
}
/**
* Set Invoice number
*
* @param string $invoiceNumber
* @return $this
*/
public function setInvoiceNumber($invoiceNumber)
{
$this->setData(self::INVOICE_NUMBER, $invoiceNumber);
return $this;
}
/**
* Set BL number
*
* @param string $blNumber
* @return $this
*/
public function setBlNumber($blNumber)
{
$this->setData(self::BL_NUMBER, $blNumber);
return $this;
}
}
And file /Ns/Module/Model/Custom.php to process our data :
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Ns\Module\Model;
use \Magento\Sales\Model\OrderRepository;
use \Psr\Log\LoggerInterface;
use \Magento\Sales\Api\Data\OrderInterface;
/**
* Interface Custom
* @package Ns\Module\Model
*/
class Custom implements \Ns\Module\Api\CustomInterface
{
/** @var LoggerInterface */
protected $logger;
/** @var OrderInterface */
protected $order;
/** @var OrderRepository */
protected $orderRepository;
/**
* Custom constructor.
* @param LoggerInterface $logger
*/
public function __construct(
LoggerInterface $logger,
OrderInterface $order,
OrderRepository $orderRepository
)
{
$this->logger = $logger;
$this->order = $order;
$this->orderRepository = $orderRepository;
}
/**
* Update order custom attributes
*
* @param \Ns\Module\Api\Data\OrderCustomInterface $data
* @return string
*/
public function updateOrderCustomAttributes(\Ns\Module\Api\Data\OrderCustomInterface $data)
{
$order = $this->order->loadByIncrementId($data->getData($data::INCREMENT_ID));
// Update blNumber
if($data->getData($data::BL_NUMBER) != '')
{
$order->setData('bl_number', $data->getData($data::BL_NUMBER));
}
// update sapDocNumber
if($data->getData($data::SAP_DOC_NUMBER) != '')
{
$order->setData('sap_doc_number', $data->getData($data::SAP_DOC_NUMBER));
}
// update invoiceNumber
if($data->getData($data::INVOICE_NUMBER) != '')
{
$order->setData('invoice_number', $data->getData($data::INVOICE_NUMBER));
}
try{
$order->save();
}
catch(Exception $e)
{
$this->logger->info($e->getMessage());
}
return 'done';
}
}
We can now call our custom API with URL : http://domain.ext/rest/V1/order/updatecustom
Don't forget to send xml in POST data.
With this method you can send JSON too ! Magento convert JSON and XML to an object according to orderCustomInterface class.