How can we get customer orders history with rest API
-
24-02-2021 - |
题
How can we get the customer order history over the rest API with the customer token.
If I'm trying the url
/V1/orders?searchCriteria[filter_groups][0][filters][0][field]=customer_email&searchCriteria[filter_groups][0][filters][0][value]=bob@fett.com&searchCriteria[filter_groups][0][filters][0][condition_type]=like
I'm getting this:
{
"message": "The consumer isn't authorized to access %resources.",
"parameters": {
"resources": "Magento_Sales::actions_view"
},
"trace": "#0 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/module-webapi/Controller/Rest/RequestValidator.php(68): Magento\\Webapi\\Controller\\Rest\\RequestValidator->checkPermissions()\n#1 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/module-webapi/Controller/Rest/InputParamsResolver.php(80): Magento\\Webapi\\Controller\\Rest\\RequestValidator->validate()\n#2 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver->resolve()\n#3 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callParent('resolve', Array)\n#4 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->Magento\\Framework\\Interception\\{closure}()\n#5 /var/www/vhosts/store-api.silverwax.ca/httpdocs/generated/code/Magento/Webapi/Controller/Rest/InputParamsResolver/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->___callPlugins('resolve', Array, Array)\n#6 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/module-webapi/Controller/Rest/SynchronousRequestProcessor.php(85): Magento\\Webapi\\Controller\\Rest\\InputParamsResolver\\Interceptor->resolve()\n#7 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/module-webapi/Controller/Rest.php(188): Magento\\Webapi\\Controller\\Rest\\SynchronousRequestProcessor->process(Object(Magento\\Framework\\Webapi\\Rest\\Request\\Proxy))\n#8 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(58): Magento\\Webapi\\Controller\\Rest->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#9 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(138): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callParent('dispatch', Array)\n#10 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/Interception/Interceptor.php(153): Magento\\Webapi\\Controller\\Rest\\Interceptor->Magento\\Framework\\Interception\\{closure}(Object(Magento\\Framework\\App\\Request\\Http))\n#11 /var/www/vhosts/store-api.silverwax.ca/httpdocs/generated/code/Magento/Webapi/Controller/Rest/Interceptor.php(26): Magento\\Webapi\\Controller\\Rest\\Interceptor->___callPlugins('dispatch', Array, Array)\n#12 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/App/Http.php(136): Magento\\Webapi\\Controller\\Rest\\Interceptor->dispatch(Object(Magento\\Framework\\App\\Request\\Http))\n#13 /var/www/vhosts/store-api.silverwax.ca/httpdocs/generated/code/Magento/Framework/App/Http/Interceptor.php(24): Magento\\Framework\\App\\Http->launch()\n#14 /var/www/vhosts/store-api.silverwax.ca/httpdocs/vendor/magento/framework/App/Bootstrap.php(258): Magento\\Framework\\App\\Http\\Interceptor->launch()\n#15 /var/www/vhosts/store-api.silverwax.ca/httpdocs/index.php(39): Magento\\Framework\\App\\Bootstrap->run(Object(Magento\\Framework\\App\\Http\\Interceptor))\n#16 {main}"
}
I've tried to the proposal of @aaditya in the question but it's doesn't work.
解决方案
To extend the rest API endpoint of orders(which is originally customer has no access) in order to access it using customer's token, You have to create a custom endpoint
as well otherwise the endpoint /V1/orders
will still inaccessible for the customer.
Check below example:
<?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/orders/custom" method="GET">
<service class="Magento\Sales\Api\OrderRepositoryInterface" method="getList"/>
<resources>
<resource ref="self"/>
</resources>
</route>
</routes>
And you can use the custom endpoint /V1/orders/custom
to get orders list of the customer using customer's token.
其他提示
@fmsthird is correct in regards having to create a custom endpoint, however I resorted to creating a new class that depends on \Magento\Sales\Api\OrderRepositoryInterface
rather than calling that class directly. From there I've created a new method that the endpoint utilises, and then calls the getList
method from there. As that method expects a parameter of type \Magento\Framework\Api\SearchCriteriaInterface
, this has to be built yourself first, but the advantage of this is you can tailor it to do some more filtering. Here's what I've built when I was faced with this task (you'll need to create the equivalent interface):
Your\Module\Model\Order.php
namespace Your\Module\Model;
class Order implements \Your\Module\Api\OrderInterface {
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
public $_orderRepository;
/**
* @var \Magento\Framework\Api\SearchCriteriaBuilder
*/
public $_searchCriteriaBuilder;
/**
* @var \Magento\Framework\Api\FilterBuilder
*/
public $_filterBuilder;
/**
* @var \Magento\Framework\Webapi\Rest\Request
*/
public $_request;
public function __construct(
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
\Magento\Framework\Api\FilterBuilder $filterBuilder,
\Magento\Framework\Webapi\Rest\Request $request
) {
$this->_orderRepository = $orderRepository;
$this->_searchCriteriaBuilder = $searchCriteriaBuilder;
$this->_filterBuilder = $filterBuilder;
$this->_request = $request;
}
/**
* Find entities by customer ID
* Accepts 'page' and 'show' GET params
*
* @param int $customerId
* @return \Magento\Sales\Api\Data\OrderSearchResultInterface
*/
public function getListForCustomer($customerId) {
$filters = [
$this->_filterBuilder->setField('customer_id')->setValue($customerId)->create()
];
$searchCriteria = $this->_searchCriteriaBuilder->addFilters($filters)->create();
$searchCriteria->setCurrentPage( $this->_request->getParam('page', 1) );
$searchCriteria->setPageSize( $this->_request->getParam('show', 20) );
return $this->_orderRepository->getList($searchCriteria);
}
}
Your\Module\etc\webapi.xml
<!-- Orders from the site -->
<route url="/V1/orders/mine" method="GET">
<service class="Your\Module\Api\OrderInterface" method="getListForCustomer"/>
<resources>
<resource ref="self"/>
</resources>
<data>
<parameter name="customerId" force="true">%customer_id%</parameter>
</data>
</route>
You should now be able to retrieve the orders for the customer via their key automatically with /V1/orders/mine, without any of the search criteria parts in the URL. You may also notice that the Order
class depends on Magento\Framework\Webapi\Rest\Request
to retrieve GET parameters from the used URL, which can be used to get paginated results - I'm not sure if that's the proper way of doing this, but it works for me! :-)