├── .github └── ISSUE_TEMPLATE.md ├── .scrutinizer.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── amazon-mws.php └── src ├── AmazonMWSServiceProvider.php ├── Exceptions ├── CountryIsMissingException.php └── CountryNotAvailableException.php ├── Facades └── AmazonMWS.php ├── MWSClient.php ├── MWSFeeds.php ├── MWSMerchantFulfillment.php ├── MWSOrders.php └── MWSService.php /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | - Laravel Amazon MWS Version: #.#.# 2 | - PHP Version: 3 | 4 | ### Description: 5 | 6 | 7 | ### Steps To Reproduce: -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | external_code_coverage: true -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.3.0] - 2021-05-23 8 | ### Updated 9 | - Add PHP 8 Support 10 | 11 | ## [0.2.4] - 2021-04-12 12 | ### Updated 13 | - Add SE, PL and TR marketplaces 14 | 15 | ## [0.2.3] - 2021-03-23 16 | ### Updated 17 | - Fixed Feed Result Response for Invoice 18 | 19 | ## [0.2.2] - 2021-03-23 20 | ### Added 21 | - Add Submit VAT Invoice 22 | 23 | ## [0.2.1] - 2020-11-17 24 | ### Added 25 | - Add Merchant Fulfillment Service Class 26 | - Add Get Eligible Shipping Services Method 27 | - Add Get Shipment Method 28 | - Add Create Shipment Method 29 | - Add Cancel Shipment Method 30 | - Add Get Additional Seller Inputs Method 31 | - Add Get Service Status Method (Merchant Fulfillment) 32 | - Add readme notice for Amazon Seller Rest Api 33 | ## [0.2.0] - 2020-10-09 34 | ### Updated 35 | - Add Laravel 8 Support 36 | 37 | ## [0.1.12] - 2020-10-09 38 | ### Added 39 | - Add getFeedSubmissionResult() method on the MWSFeeds Class and parse to convenient response structure 40 | - Add x-www-form-urlencoded header if action is GetFeedSubmissionResult in MWSClient 41 | 42 | ## [0.1.11] - 2020-10-06 43 | ### Fixed 44 | - Take the default_market_place environment variable if given in MWSClient 45 | - Set MWS_auth_token to null instead of empty string if not given 46 | 47 | ## [0.1.10] - 2020-08-03 48 | ### Added 49 | - Add MWS Auth Token to MWSClient requests and amazon-mws config file 50 | 51 | ## [0.1.8] - 2020-04-14 52 | ### Updated 53 | - Wrap Single List Order Results in an array 54 | - Set data null if nothing gets returned 55 | 56 | ## [0.1.7] - 2020-04-11 57 | ### Updated 58 | - Fix Set Marketplaces in MWS Service 59 | 60 | ## [0.1.6] - 2020-04-11 61 | ### Updated 62 | - Fix Set Marketplaces 63 | 64 | ## [0.1.5] - 2020-04-10 65 | ### Added 66 | - Add List Orders Endpoint 67 | 68 | ## [0.1.4] - 2020-03-06 69 | ### Updated 70 | - Re Release 71 | 72 | ## [0.1.3] - 2020-03-06 73 | ### Updated 74 | - Wrap Single Order Items in data for List Order Items 75 | 76 | ## [0.1.2] - 2020-03-06 77 | ### Updated 78 | - Fix bug with amazon order id in get Items 79 | - Edit Readme with correct Travis Shields Image 80 | 81 | ## [0.1.1] - 2020-03-06 82 | ### Added 83 | - Add List Order Items functionality for Orders endpoint 84 | 85 | ## [0.1.0] - 2020-03-05 86 | ### Added 87 | - Add Scrutinizer 88 | - Advanced Readme 89 | - Add guzzle client timeout 90 | - parsed and casted order responses 91 | - Add SubmitFeed functionality 92 | 93 | ## [0.0.1] - 2020-02-27 94 | ### Added 95 | - Initial Release 96 | - Orders Get Order Action 97 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) LOOXIS GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Amazon MWS 2 | 3 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 4 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/looxis/laravel-amazon-mws.svg?style=flat-square)](https://packagist.org/packages/looxis/laravel-amazon-mws) 5 | [![Build Status](https://travis-ci.org/looxis/laravel-amazon-mws.svg?branch=master)](https://travis-ci.org/looxis/laravel-amazon-mws) 6 | [![StyleCI](https://styleci.io/repos/242777921/shield?branch=master)](https://styleci.io/repos/242777921) 7 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/looxis/laravel-amazon-mws/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/looxis/laravel-amazon-mws/?branch=master) 8 | 9 | Simple Amazon Marketplace Web Service API Package for Laravel 10 | 11 | This package is under development. Currently we have only implemented the endpoints we are using. 12 | Feel free to add the endpoints you need ([contribute](#contributing)). 13 | A List of all available endpoints you can see under the endpoint [road map](#road-map). 14 | 15 | 🚨 Amazon Introduced a new [Selling Partner API](https://developer.amazonservices.com/) 16 | A modernized suite of REST APIs utilizing standards. [Github Docs](https://github.com/amzn/selling-partner-api-docs) 17 | The laravel-amazon-mws package provides only methods for the Amazon MWS service. 18 | We will add a laravel package for the SP-Api next year (2021). 19 | 20 | ## Contents 21 | 22 | - [Installation](#installation) 23 | - [Configuration](#configuration) 24 | - [Usage](#usage) 25 | - [Authentication](#authentication) 26 | - [Marketplaces](#marketplaces) 27 | - [Orders](#orders) 28 | - [List Orders](#list-orders) 29 | - [Get Order](#get-order) 30 | - [List Order Items](#list-order-items) 31 | - [Feeds](#feeds) 32 | - [Submit Feed](#submit-feed) 33 | - [Submit Invoice Feed](#submit-invoice-feed) 34 | - [Get Feed Submission Result](#get-feed-submission-result) 35 | - [Merchant Fulfillment](#merchant-fulfillment) 36 | - [Get Eligible Shipping Services](#get-eligible-shipping-services) 37 | - [Get Shipment](#get-shipment) 38 | - [Create Shipment](#create-shipment) 39 | - [Cancel Shipment](#cancel-shipment) 40 | - [Get Additional Seller Inputs](#get-additional-seller-inputs) 41 | - [Get Service Status](#get-merchant-fulfillment-service-status) 42 | - [Responses](#responses) 43 | - [Exceptions](#exceptions) 44 | - [Road Map](#road-map) 45 | - [Testing](#testing) 46 | - [Changelog](#changelog) 47 | - [Contributing](#contributing) 48 | - [Security](#security) 49 | - [License](#license) 50 | 51 | Link to the [Official Amazon MWS Documentation](https://docs.developer.amazonservices.com/en_US/dev_guide/index.html) 52 | 53 | ## Installation 54 | This package requires PHP 7.3 and Laravel 8.0 or higher. 55 | For older laravel versions install the latest 0.1.x version. 56 | 57 | Require the package using composer: 58 | 59 | ```bash 60 | composer require looxis/laravel-amazon-mws 61 | ``` 62 | 63 | The package will automatically register itself. 64 | 65 | Add your Environment Variables for MWS to your .env File. The variable names are listed in the amazon-mws.php [config file](#configuration). 66 | 67 | 68 | ## Configuration 69 | 70 | To successfully authenticate with the Amazon Marketplace Web Service you need to add the Environment variables to your `.env` File. The variable names are listed in the amazon-mws.php [config file](#configuration). 71 | Also you can set a default marketplace. 72 | 73 | You can optionally publish the configuration with: 74 | 75 | ```bash 76 | $ php artisan vendor:publish --provider="Looxis\LaravelAmazonMWS\AmazonMWSServiceProvider" --tag="config" 77 | ``` 78 | 79 | This will create an `amazon-mws.php` in your config directory. 80 | 81 | Config file content with the env variables: 82 | 83 | ```php 84 | env('MWS_ACCESS_KEY_ID'), 88 | 'secret_key' => env('MWS_SECRET_KEY'), 89 | 'seller_id' => env('MWS_SELLER_ID'), 90 | 'mws_auth_token' => env('MWS_AUTH_TOKEN'), 91 | 'default_market_place' => env('MWS_DEFAULT_MARKET_PLACE', 'DE'), 92 | ]; 93 | ``` 94 | 95 | 96 | ## Usage 97 | 98 | 99 | ### Authentication 100 | Amazon MWS authenticates you via the [Canonicalized Query String](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_QueryString.html). The Laravel Amazon MWS Package handles this for you and adds the string for each request. You just have to add your seller specific credentials to your .env file ([configuration](#configuration)). 101 | 102 | 103 | ### Marketplaces 104 | If you need to change the marketplaces just set the country/countries in your code via the MWS Facade. 105 | For simplicity the package chooses the right endpoint and market place id via the given country. 106 | You do not have to set them by yourself. 107 | ([Amazon MWS endpoints and Market Place IDS Overview](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Endpoints.html)) If something is missing do not hesitate to create an issue. 108 | 109 | ```php 110 | AmazonMWS::setMarketplaces('FR'); 111 | 112 | AmazonMWS::setMarketplaces('DE', 'FR'); //to append multiple marketplaces to your request query strings. 113 | ``` 114 | 115 | 116 | ### Orders 117 | Retrieve order information that you need. 118 | [Amazon MWS Orders Documentation Overview](https://docs.developer.amazonservices.com/en_US/orders-2013-09-01/Orders_Overview.htm) 119 | 120 | 121 | #### List Orders 122 | Returns orders created or updated during a time frame that you specify. 123 | [MWS List Orders Documentation](https://docs.developer.amazonservices.com/en_US/orders-2013-09-01/Orders_ListOrders.html) 124 | 125 | ```php 126 | $response = AmazonMWS::orders()->list([ 127 | 'CreatedAfter' => '2020-04-09T18:56:29+02:00' 128 | ]); 129 | 130 | // List Order By Next Token 131 | $response = AmazonMWS::orders()->list([ 132 | 'NextToken' => '27u07N+WSfaaJkJYLDm0ZAmQazDrhw3C...' 133 | ]); 134 | ``` 135 | ##### Throttling 136 | - maximum request quota of six and a restore rate of one request every minute. 137 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 138 | - Throws a ServerException with `Request is throttled` 139 | 140 | 141 | #### Get Order 142 | Returns orders based on the AmazonOrderId values that you specify. 143 | [MWS Get Order Documentation](https://docs.developer.amazonservices.com/en_US/orders-2013-09-01/Orders_GetOrder.html) 144 | 145 | ```php 146 | $response = AmazonMWS::orders()->get("1234-1234-1234"); //get amazon order by id 147 | 148 | $response = AmazonMWS::orders()->get("1234-1234-1234", "123-123-123"); //get multiple orders 149 | ``` 150 | ##### Throttling 151 | - maximum request quota of six and a restore rate of one request every minute. 152 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 153 | - Throws a ServerException with `Request is throttled` 154 | 155 | 156 | #### List Order Items 157 | Returns order items based on the AmazonOrderId that you specify. 158 | [MWS List Order Items Documentation](https://docs.developer.amazonservices.com/en_US/orders-2013-09-01/Orders_ListOrderItems.html) 159 | 160 | ```php 161 | $response = AmazonMWS::orders()->getItems("1234-1234-1234"); 162 | ``` 163 | ##### Throttling 164 | - ListOrderItems and ListOrderItemsByNextToken share same throttling 165 | - maximum request quota of 30 and a restore rate of one request every two seconds. 166 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 167 | - Throws a ServerException with `Request is throttled` 168 | 169 | 170 | ### Feeds 171 | The Feeds API lets you upload inventory and order data to Amazon 172 | [Amazon MWS Orders Documentation Overview](https://docs.developer.amazonservices.com/en_US/feeds/Feeds_Overview.html) 173 | 174 | 175 | #### Submit Feed 176 | Uploads a feed for processing by Amazon MWS. 177 | 178 | You must set the feed type and content to successfully submit the feed. 179 | The content for the xml depends on the [FeedType](https://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html) 180 | 181 | ```php 182 | $feedXmlContent = ' ...'; 183 | $response = AmazonMWS::feeds() 184 | ->setType("_POST_ORDER_ACKNOWLEDGEMENT_DATA_") 185 | ->setContent($xml) 186 | ->submit(); 187 | ``` 188 | ##### Throttling 189 | - maximum request quota of 15 and a restore rate of one request every two minutes. 190 | - Hourly request quote: 30 191 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 192 | - Throws a ServerException with `Request is throttled` 193 | 194 | 195 | #### Submit Invoice Feed (VAT) 196 | You can upload invoices using _UPLOAD_VAT_INVOICE_ Feed Type via Feeds API. Use the SubmitFeed 197 | operation with the below mentioned parameters to submit an invoice for an order. 198 | 199 | [Invoice Uploader developer documentation](https://m.media-amazon.com/images/G/03/B2B/invoice-uploader-developer-documentation.pdf) 200 | 201 | ```php 202 | // File Content 203 | $invoiceFileContent = \File::get(storage_path('invoice.pdf')); 204 | 205 | // Feed Options 206 | $params = [ 207 | 'orderid' => 'XXX-XXXXXXX-XXXXXXX', //Amazon Order Id 208 | 'invoicenumber' => 'R21-1234', //Your Invoice Number 209 | 'documenttype' => 'Invoice' 210 | ]; 211 | 212 | // Generate Feed Option metadata from params 213 | $feedOptions = collect($params)->map(function($param, $key) { 214 | return "metadata:{$key}={$param}"; 215 | })->values()->implode(';'); 216 | 217 | // Submit 218 | $response = AmazonMWS::feeds() 219 | ->setType("_UPLOAD_VAT_INVOICE_") 220 | ->setContent($invoiceFileContent) 221 | ->setParams([ 222 | 'FeedOptions' => $feedOptions 223 | ]) 224 | ->submit(); 225 | ``` 226 | ##### Throttling 227 | For the feed type _UPLOAD_VAT_INVOICE_, the throttle limit is 1 invoice upload per 3 seconds, or 20 invoices per minute, 228 | or 1200 invoices per hour, or 28800 invoices per day. 229 | 230 | ##### Responses 231 | The Amazon MWS XML responses are parsed and will be casted into a convenient array structure. 232 | For checking if the Feed was successful you need to check the result via the [GetSubmissionFeedResult](https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionResult.html) endpoint. 233 | 234 | SubmitFeedResponse Example: 235 | 236 | ```php 237 | [ 238 | "request_id" => "e86f7299-9712-43e3-b290-b659da85b527" 239 | "data" => [ 240 | "FeedSubmissionId" => "2291326430" 241 | "FeedType" => "_POST_ORDER_ACKNOWLEDGEMENT_DATA_" 242 | "SubmittedDate" => "2020-03-04T14:54:14+00:00" 243 | "FeedProcessingStatus" => "_SUBMITTED_" 244 | ] 245 | ] 246 | ``` 247 | 248 | 249 | #### Get Feed Submission Result 250 | Returns the feed processing report and the Content-MD5 header. 251 | 252 | Pass the Feed Submission Id as a parameter to retrieve the feed result 253 | Amazon MWS Description [GetFeedSubmissionResult](https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionResult.html) 254 | 255 | _Warning: Invoice Feed Submission Results are returning blank strings instead of a SubmitFeedResponse_ 256 | ```php 257 | $response = AmazonMWS::feeds() 258 | ->getFeedSubmissionResult($feedSubmissionId); 259 | ``` 260 | ##### Throttling 261 | - maximum request quota of 15 and a restore rate of one request every minute. 262 | - Hourly request quote: 60 263 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 264 | - Throws a ServerException with `Request is throttled` 265 | 266 | ##### Responses 267 | The Feed Submission Result responses are parsed and will be casted into a convenient structure. 268 | 269 | SubmitFeedResponse Example: 270 | 271 | ```php 272 | [ 273 | "status_code" => "Complete", 274 | "processing_summary" => [ 275 | "MessagesProcessed" => "2" 276 | "MessagesSuccessful" => "2" 277 | "MessagesWithError" => "0" 278 | "MessagesWithWarning" => "0" 279 | ], 280 | "result" => null 281 | ] 282 | ``` 283 | 284 | 285 | 286 | ### Merchant Fulfillment 287 | With the Merchant Fulfillment service, you can build applications that let sellers purchase shipping for non-Prime and Prime orders using Amazon’s Buy Shipping Services. 288 | 289 | [Amazon MWS Merchant Fulfillment Documentation Overview](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_Overview.html) 290 | 291 | 292 | #### Get Eligible Shipping Services 293 | Returns a list of shipping service offers. 294 | [MWS Get Eligible Shipping Services Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_GetEligibleShippingServices.html) 295 | 296 | Fill the params with the [ShipmentRequestDetails](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_Datatypes.html#ShipmentRequestDetails) and the [ShippingOfferingFilter](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_Datatypes.html#ShippingOfferingFilter) 297 | 298 | ```php 299 | $params = [ 300 | 'ShipmentRequestDetails' => [...], 301 | 'ShippingOfferingFilter' => [...] 302 | ]; 303 | $response = AmazonMWS::merchantFulfillment()->getEligibleShippingServices($params); 304 | ``` 305 | ##### Throttling 306 | - maximum request quota of 10 and a restore rate of 5 requests every second. 307 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 308 | - Throws a ServerException with `Request is throttled` 309 | 310 | 311 | #### Get Shipment 312 | Returns an existing shipment for a given identifier. 313 | [MWS Get Shipment Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_GetShipment.html) 314 | 315 | ```php 316 | $response = AmazonMWS::merchantFulfillment()->getShipment($shipmentId); 317 | ``` 318 | ##### Throttling 319 | - maximum request quota of 10 and a restore rate of 5 requests every second. 320 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 321 | - Throws a ServerException with `Request is throttled` 322 | 323 | 324 | #### Create Shipment 325 | The CreateShipment operation purchases shipping and returns PDF, PNG, or ZPL document data for a shipping label, depending on the carrier. 326 | [MWS Create Shipment Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_CreateShipment.html) 327 | 328 | ```php 329 | $data = [ 330 | 'ShippingServiceId' => 'shipment-service-id', //get the shipment id with getEligibleShippingServices() 331 | 'ShipmentRequestDetails' => [...], 332 | ]; 333 | $response = AmazonMWS::merchantFulfillment()->createShipment($data); 334 | ``` 335 | ##### Throttling 336 | - maximum request quota of 10 and a restore rate of 5 requests every second. 337 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 338 | - Throws a ServerException with `Request is throttled` 339 | 340 | 341 | #### Cancel Shipment 342 | Cancels an existing shipment. 343 | [MWS Cancel Shipment Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_CancelShipment.html) 344 | 345 | ```php 346 | $shipmentId = '1234xx1231xx1234'; 347 | $response = AmazonMWS::merchantFulfillment()->cancelShipment($shipmentId); 348 | ``` 349 | ##### Throttling 350 | - maximum request quota of 10 and a restore rate of 5 requests every second. 351 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 352 | - Throws a ServerException with `Request is throttled` 353 | 354 | 355 | #### Get Additional Seller Inputs 356 | Returns a list of additional seller inputs that are required from the seller to purchase the shipping service that you specify. 357 | [MWS Get Additional Seller Inputs Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_GetAdditionalSellerInputs.html) 358 | 359 | ```php 360 | $data = [ 361 | 'OrderId' => 'XXX-XXXXXXX-XXXXXXX', 362 | 'ShippingServiceId' => 'shipment-service-id', //get the shipment id with getEligibleShippingServices() 363 | 'ShippingFromAddress' => [...], 364 | ]; 365 | $response = AmazonMWS::merchantFulfillment()->getAdditionalSellerInputs($data); 366 | ``` 367 | ##### Throttling 368 | - maximum request quota of 10 and a restore rate of 5 requests every second. 369 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 370 | - Throws a ServerException with `Request is throttled` 371 | 372 | 373 | #### Get Service Status 374 | Returns the operational status of the Merchant Fulfillment service. 375 | [MWS Get Service Status Documentation](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MWS_GetServiceStatus.html) 376 | 377 | ```php 378 | $response = AmazonMWS::merchantFulfillment()->getServiceStatus(); 379 | ``` 380 | ##### Throttling 381 | - maximum request quota of 2 and a restore rate of 1 request every 5 seconds. 382 | [MWS Throttling Algorithm](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Throttling.html) 383 | - Throws a ServerException with `Request is throttled` 384 | 385 | 386 | 387 | ### General Responses 388 | 389 | [Response Format Documentation](https://docs.developer.amazonservices.com/en_US/dev_guide/DG_ResponseFormat.html) 390 | The Amazon MWS XML responses are parsed and will be casted into a convenient array structure. 391 | GetOrder Response Example: 392 | 393 | ```php 394 | [ 395 | "request_id" => "be781aff-3c63-485a-aec8-951ed3be2ba4", 396 | "data" => [ 397 | "AmazonOrderId" => "902-3159896-1390916", 398 | ... 399 | ] 400 | ] 401 | ``` 402 | 403 | ### Exceptions 404 | The Laravel Amazon MWS package does not catch the Exceptions returned by guzzle. 405 | For Example for throttling ServerExceptions or missing Parameter Client Exceptions. 406 | 407 | 408 | 409 | ## Endpoint Road map 410 | 411 | Laravel Amazon MWS is still under development. We have only added the endpoints we currently are using ourselfs. We decided to ship it in this early stage so you can help to add some endpoits or use the already existing. 412 | 413 | Endpoint List: 414 | 415 | - [X] Orders ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/orders-2013-09-01/Orders_Overview.html)) 416 | - [X] ListOrders 417 | - [X] ListOrdersByNextToken 418 | - [X] GetOrder 419 | - [X] ListOrderItems 420 | - [ ] ListOrderItemsByNextToken 421 | - [ ] GetServiceStatus 422 | - [ ] Orders Datatypes 423 | - [X] Feeds ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/feeds/Feeds_Overview.html)) 424 | - [X] SubmitFeed 425 | - [X] Submit Invoice VAT Feed 426 | - [ ] GetFeedSubmissionList 427 | - [ ] GetFeedSubmissionListByNextToken 428 | - [ ] GetFeedSubmissionCount 429 | - [ ] CancelFeedSubmissions 430 | - [X] GetFeedSubmissionResult 431 | - [ ] Easy Ship ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/easy_ship/EasyShip_Overview.html)) 432 | - [ ] Finances ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/finances/Finances_Overview.html)) 433 | - [ ] FulFillment Inbound Shipment ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/fba_inbound/FBAInbound_Overview.html)) 434 | - [ ] FulFillment Inventory ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/fba_inventory/FBAInventory_Overview.html)) 435 | - [ ] FulFillment Outbound Shipment ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/fba_outbound/FBAOutbound_Overview.html)) 436 | - [X] Merchant Fulfillment ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/merch_fulfill/MerchFulfill_Overview.html)) 437 | - [X] GetEligibleShippingServices 438 | - [X] GetAdditionalSellerInputs 439 | - [X] CreateShipment 440 | - [X] GetShipment 441 | - [X] CancelShipment 442 | - [X] GetServiceStatus 443 | - [ ] Products ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/products/Products_Overview.html)) 444 | - [ ] Recommendations ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/recommendations/Recommendations_Overview.html)) 445 | - [ ] Reports ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/reports/Reports_Overview.html)) 446 | - [ ] Sellers ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/sellers/Sellers_Overview.html)) 447 | - [ ] Shipment Invoicing ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/shipment_invoicing/ShipmentInvoicing_Overview.html)) 448 | - [ ] Subscriptions ([MWS Documentation Overview](https://docs.developer.amazonservices.com/en_US/subscriptions/Subscriptions_Overview.html)) 449 | 450 | 451 | 452 | ## Testing 453 | 454 | ``` bash 455 | composer test 456 | ``` 457 | 458 | 459 | ## Changelog 460 | 461 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 462 | 463 | 464 | ## Contributing 465 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 466 | 467 | Please make sure to update tests as appropriate. 468 | 469 | 470 | ## Security 471 | 472 | If you discover any security related issues, please email dev@looxis.com instead of using the issue tracker. 473 | 474 | ## Credits 475 | 476 | - [Christian Stefener](https://github.com/ChrisSFR) 477 | - [Jannik Malken](https://github.com/mannikj) 478 | - [All Contributors](../../contributors) 479 | 480 | ## About us 481 | LOOXIS GmbH based in Minden, Germany. 482 | 483 | LOOXIS is a manufacturer of personalised gift articles, which are sold throughout Europe in (photo) specialist shops and via our online shop under [www.looxis.com](https://looxis.de). 484 | 485 | 486 | ## License 487 | [MIT](./LICENSE.md) 488 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "looxis/laravel-amazon-mws", 3 | "description": "Simple Amazon MWS API Package for Laravel", 4 | "keywords": [ 5 | "looxis", 6 | "amazon", 7 | "mws", 8 | "amazon-mws", 9 | "laravel-amazon-mws" 10 | ], 11 | "homepage": "https://github.com/looxis/laravel-amazon-mws", 12 | "type": "library", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Christian Stefener", 17 | "email": "christian.stefener@looxis.de", 18 | "role": "Developer" 19 | }, 20 | { 21 | "name": "Jannik Malken", 22 | "email": "jannik.malken@looxis.de", 23 | "role": "Developer" 24 | } 25 | ], 26 | "require": { 27 | "php": "^8.0", 28 | "guzzlehttp/guzzle": "^7.0", 29 | "spatie/array-to-xml": "^3.0" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "Looxis\\LaravelAmazonMWS\\": "src/" 34 | } 35 | }, 36 | "autoload-dev": { 37 | "psr-4": { 38 | "Looxis\\LaravelAmazonMWS\\Tests\\": "tests" 39 | } 40 | }, 41 | "require-dev": { 42 | "phpunit/phpunit": "^9.3", 43 | "orchestra/testbench": "^6.0", 44 | "dms/phpunit-arraysubset-asserts": "^0.2.0" 45 | }, 46 | "extra": { 47 | "laravel": { 48 | "providers": [ 49 | "Looxis\\LaravelAmazonMWS\\AmazonMWSServiceProvider" 50 | ], 51 | "aliases": { 52 | "AmazonMWS": "Looxis\\LaravelAmazonMWS\\Facades\\AmazonMWS" 53 | } 54 | } 55 | }, 56 | "scripts": { 57 | "test": "phpunit" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /config/amazon-mws.php: -------------------------------------------------------------------------------- 1 | env('MWS_ACCESS_KEY_ID'), 5 | 'secret_key' => env('MWS_SECRET_KEY'), 6 | 'seller_id' => env('MWS_SELLER_ID'), 7 | 'mws_auth_token' => env('MWS_AUTH_TOKEN'), 8 | 'default_market_place' => env('MWS_DEFAULT_MARKET_PLACE', 'DE'), 9 | ]; 10 | -------------------------------------------------------------------------------- /src/AmazonMWSServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 12 | __DIR__.'/../config/amazon-mws.php' => config_path('amazon-mws.php'), 13 | ], 'config'); 14 | } 15 | 16 | public function register() 17 | { 18 | $this->app->bind('amazon-mws', function () { 19 | return new MWSService(); 20 | }); 21 | 22 | $this->mergeConfigFrom(__DIR__.'/../config/amazon-mws.php', 'amazon-mws'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Exceptions/CountryIsMissingException.php: -------------------------------------------------------------------------------- 1 | 'mws.amazonservices.com', 27 | 'A2EUQ1WTGCTBG2' => 'mws.amazonservices.ca', 28 | 'A1AM78C64UM0Y8' => 'mws.amazonservices.com.mx', 29 | 'ATVPDKIKX0DER' => 'mws.amazonservices.com', 30 | 'A2VIGQ35RCS4UG' => 'mws.amazonservices.ae', 31 | 'A1PA6795UKMFR9' => 'mws-eu.amazonservices.com', 32 | 'ARBP9OOSHTCHU' => 'mws-eu.amazonservices.com', 33 | 'A1RKKUPIHCS9HS' => 'mws-eu.amazonservices.com', 34 | 'A13V1IB3VIYZZH' => 'mws-eu.amazonservices.com', 35 | 'A1F83G8C2ARO7P' => 'mws-eu.amazonservices.com', 36 | 'A21TJRUUN4KGV' => 'mws.amazonservices.in', 37 | 'APJ6JRA9NG5V4' => 'mws-eu.amazonservices.com', 38 | 'A17E79C6D8DWNP' => 'mws-eu.amazonservices.com', 39 | 'A33AVAJ2PDY3EV' => 'mws-eu.amazonservices.com', 40 | 'A19VAU5U5O7RUS' => 'mws-fe.amazonservices.com', 41 | 'A39IBJ37TRP1C6' => 'mws.amazonservices.com.au', 42 | 'A1VC38T7YXB528' => 'mws.amazonservices.jp', 43 | 'A1805IZSGTT6HS' => 'mws-eu.amazonservices.com', 44 | 'A1C3SOZRARQ6R3' => 'mws-eu.amazonservices.com', 45 | 'A2NODRKZP88ZB9' => 'mws-eu.amazonservices.com', 46 | ]; 47 | 48 | protected $countries = [ 49 | 'BR' => 'A2Q3Y263D00KWC', 50 | 'CA' => 'A2EUQ1WTGCTBG2', 51 | 'MX' => 'A1AM78C64UM0Y8', 52 | 'US' => 'ATVPDKIKX0DER', 53 | 'AE' => 'A2VIGQ35RCS4UG', 54 | 'DE' => 'A1PA6795UKMFR9', 55 | 'EG' => 'ARBP9OOSHTCHU', 56 | 'ES' => 'A1RKKUPIHCS9HS', 57 | 'FR' => 'A13V1IB3VIYZZH', 58 | 'GB' => 'A1F83G8C2ARO7P', 59 | 'IN' => 'A21TJRUUN4KGV', 60 | 'IT' => 'APJ6JRA9NG5V4', 61 | 'SA' => 'A17E79C6D8DWNP', 62 | 'TR' => 'A33AVAJ2PDY3EV', 63 | 'SG' => 'A19VAU5U5O7RUS', 64 | 'AU' => 'A39IBJ37TRP1C6', 65 | 'JP' => 'A1VC38T7YXB528', 66 | 'NL' => 'A1805IZSGTT6HS', 67 | 'PL' => 'A1C3SOZRARQ6R3', 68 | 'SE' => 'A2NODRKZP88ZB9', 69 | ]; 70 | 71 | public function __construct(Client $client = null) 72 | { 73 | $this->accessKeyId = config('amazon-mws.access_key_id'); 74 | $this->secretKey = config('amazon-mws.secret_key'); 75 | $this->sellerId = config('amazon-mws.seller_id'); 76 | $this->mwsAuthToken = config('amazon-mws.mws_auth_token') ?: null; 77 | $this->marketPlaces = explode(',', config('amazon-mws.default_market_place') ?: 'DE'); 78 | $this->client = $client ?: new Client(['timeout' => 60]); 79 | } 80 | 81 | public function setMarketPlaces($countryCodes) 82 | { 83 | $countryCodes = is_array($countryCodes) ? $countryCodes : func_get_args(); 84 | $this->marketPlaces = $countryCodes; 85 | } 86 | 87 | public function getCurrentMarketPlaces() 88 | { 89 | return $this->marketPlaces; 90 | } 91 | 92 | public function getTimeStamp() 93 | { 94 | return gmdate(self::DATE_FORMAT, time()); 95 | } 96 | 97 | public function getAccessKeyId() 98 | { 99 | return $this->accessKeyId; 100 | } 101 | 102 | public function setAccessKeyId($key) 103 | { 104 | $this->accessKeyId = $key; 105 | 106 | return $this; 107 | } 108 | 109 | public function getSellerId() 110 | { 111 | return $this->sellerId; 112 | } 113 | 114 | public function setSellerId($id) 115 | { 116 | $this->sellerId = $id; 117 | 118 | return $this; 119 | } 120 | 121 | public function getMWSAuthToken() 122 | { 123 | return $this->mwsAuthToken; 124 | } 125 | 126 | public function getSignatureMethod() 127 | { 128 | return self::SIGNATURE_METHOD; 129 | } 130 | 131 | public function getSignatureVersion() 132 | { 133 | return self::SIGNATURE_VERSION; 134 | } 135 | 136 | public function getDomain() 137 | { 138 | $mainMarketPlace = $this->marketPlaces[0]; 139 | if ($mainMarketPlace) { 140 | $marketPlaceId = $this->countries[$mainMarketPlace]; 141 | 142 | return $this->marketplaceIds[$marketPlaceId]; 143 | } 144 | 145 | throw new CountryIsMissingException(); 146 | } 147 | 148 | public function getCountry() 149 | { 150 | return $this->country; 151 | } 152 | 153 | public function setCountry($country) 154 | { 155 | if (in_array($country, array_keys($this->countries))) { 156 | $this->country = $country; 157 | 158 | return $this; 159 | } else { 160 | throw new CountryNotAvailableException(); 161 | } 162 | } 163 | 164 | public function getMarketPlaceIds() 165 | { 166 | return $this->marketplaceIds; 167 | } 168 | 169 | public function post($action, $path, $version, $params = [], $body = null) 170 | { 171 | $headers = [ 172 | 'Accept' => 'application/xml', 173 | 'x-amazon-user-agent' => self::APPLICATION_NAME.'/'.self::APPLICATION_VERSION, 174 | ]; 175 | 176 | if ($action === 'SubmitFeed') { 177 | $headers['Content-Type'] = 'text/xml; charset=iso-8859-1'; 178 | } 179 | 180 | if ($action === 'GetFeedSubmissionResult') { 181 | $headers['Content-Type'] = 'x-www-form-urlencoded'; 182 | } 183 | 184 | $requestOptions = [ 185 | 'headers' => $headers, 186 | 'body' => $body, 187 | 'query' => $this->getQuery($path, $action, $version, $params), 188 | ]; 189 | $uri = 'https://'.$this->getDomain().$path; 190 | $response = $this->client->post($uri, $requestOptions); 191 | 192 | $xmlResponse = simplexml_load_string($response->getBody()->getContents(), 'SimpleXMLElement', LIBXML_NOWARNING | LIBXML_NOERROR); 193 | 194 | if (! $xmlResponse) { 195 | return (string) $response->getBody(); 196 | } 197 | 198 | $json = json_encode($xmlResponse); 199 | 200 | return json_decode($json, true); 201 | } 202 | 203 | public function getDefaultQueryParams($action, $version, $params = []) 204 | { 205 | $queryParameters = [ 206 | 'Action' => $action, 207 | 'Timestamp' => $this->getTimeStamp(), 208 | 'AWSAccessKeyId' => $this->getAccessKeyId(), 209 | 'SellerId' => $this->getSellerId(), 210 | 'MWSAuthToken' => $this->getMWSAuthToken(), 211 | 'SignatureMethod' => $this->getSignatureMethod(), 212 | 'SignatureVersion' => $this->getSignatureVersion(), 213 | 'Version' => $version, 214 | ]; 215 | $type = data_get($params, 'FeedType'); 216 | $queryParameters = array_merge($queryParameters, $this->getMarketPlaceParams($type)); 217 | $queryParameters = array_merge($queryParameters, Arr::dot($params)); 218 | ksort($queryParameters); 219 | 220 | return $queryParameters; 221 | } 222 | 223 | public function getMarketPlaceParams($type = null) 224 | { 225 | $params = []; 226 | foreach ($this->marketPlaces as $index => $marketPlace) { 227 | if ($type === '_UPLOAD_VAT_INVOICE_') { 228 | $marketPlaceKeyName = 'MarketplaceIdList.Id.'; 229 | } else { 230 | $marketPlaceKeyName = 'MarketplaceId.Id.'; 231 | } 232 | 233 | $keyName = $marketPlaceKeyName.($index + 1); 234 | $params[$keyName] = $this->countries[$marketPlace]; 235 | } 236 | 237 | return $params; 238 | } 239 | 240 | public function generateRequestUri($action, $version, $params = []) 241 | { 242 | return http_build_query($this->getDefaultQueryParams($action, $version, $params), '', '&', PHP_QUERY_RFC3986); 243 | } 244 | 245 | public function getQueryStringForSignature($path, $action, $version, $params = []) 246 | { 247 | return 'POST' 248 | ."\n" 249 | .$this->getDomain() 250 | ."\n" 251 | .$path 252 | ."\n" 253 | .$this->generateRequestUri($action, $version, $params); 254 | } 255 | 256 | public function generateSignature($path, $action, $version, $params = []) 257 | { 258 | $signature = base64_encode( 259 | hash_hmac( 260 | 'sha256', 261 | $this->getQueryStringForSignature($path, $action, $version, $params), 262 | $this->secretKey, 263 | true 264 | ) 265 | ); 266 | 267 | return $signature; 268 | } 269 | 270 | public function getQuery($path, $action, $version, $params = []) 271 | { 272 | $queryParameters = $this->getDefaultQueryParams($action, $version, $params); 273 | $queryParameters['Signature'] = $this->generateSignature($path, $action, $version, $params); 274 | 275 | return $queryParameters; 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/MWSFeeds.php: -------------------------------------------------------------------------------- 1 | client = $client; 17 | } 18 | 19 | public function getContent() 20 | { 21 | return $this->content; 22 | } 23 | 24 | public function setParams($params) 25 | { 26 | $this->params = $params; 27 | 28 | return $this; 29 | } 30 | 31 | public function getParams() 32 | { 33 | return $this->params; 34 | } 35 | 36 | public function setContent($content) 37 | { 38 | $this->content = $content; 39 | 40 | return $this; 41 | } 42 | 43 | public function getType() 44 | { 45 | return $this->type; 46 | } 47 | 48 | public function setType($type) 49 | { 50 | $this->type = $type; 51 | 52 | return $this; 53 | } 54 | 55 | public function submit($purgeAndReplace = false, $amazonOrderId = null, $documentType = null) 56 | { 57 | $contentmd5Hash = base64_encode(md5($this->getContent(), true)); 58 | $params = array_merge([ 59 | 'FeedType' => $this->type, 60 | 'PurgeAndReplace' => $purgeAndReplace, 61 | 'ContentMD5Value' => $contentmd5Hash, 62 | ], $this->getParams()); 63 | $response = $this->client->post('SubmitFeed', '/', self::VERSION, $params, $this->getContent()); 64 | 65 | return $this->parseSubmitFeedResponse($response); 66 | } 67 | 68 | protected function parseSubmitFeedResponse($response) 69 | { 70 | $requestId = data_get($response, 'ResponseMetadata.RequestId'); 71 | $feed = data_get($response, 'SubmitFeedResult.FeedSubmissionInfo'); 72 | 73 | return [ 74 | 'request_id' => $requestId, 75 | 'data' => $feed, 76 | ]; 77 | } 78 | 79 | public function getFeedSubmissionResult($amazonFeedSubmissionId) 80 | { 81 | $params = [ 82 | 'FeedSubmissionId' => $amazonFeedSubmissionId, 83 | ]; 84 | 85 | $response = $this->client->post('GetFeedSubmissionResult', '/', self::VERSION, $params); 86 | 87 | return $this->parseSubmissionResultResponse($response); 88 | } 89 | 90 | protected function parseSubmissionResultResponse($response) 91 | { 92 | if (is_null(data_get($response, 'Message.ProcessingReport.StatusCode'))) { 93 | return (string) $response; 94 | } 95 | 96 | return [ 97 | 'status_code' => data_get($response, 'Message.ProcessingReport.StatusCode'), 98 | 'processing_summary' => data_get($response, 'Message.ProcessingReport.ProcessingSummary'), 99 | 'result' => data_get($response, 'Message.ProcessingReport.Result'), 100 | ]; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/MWSMerchantFulfillment.php: -------------------------------------------------------------------------------- 1 | client = $client; 14 | } 15 | 16 | public function getEligibleShippingServices($params = []) 17 | { 18 | $action = 'GetEligibleShippingServices'; 19 | 20 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION, $params); 21 | 22 | return $this->parseResponse($response, $action.'Result'); 23 | } 24 | 25 | public function parseResponse($response, $resultTypeName) 26 | { 27 | $requestId = data_get($response, 'ResponseMetadata.RequestId'); 28 | $data = data_get($response, $resultTypeName); 29 | 30 | $data = [ 31 | 'request_id' => $requestId, 32 | 'data' => $data, 33 | ]; 34 | 35 | return $data; 36 | } 37 | 38 | public function createShipment($params = []) 39 | { 40 | $action = 'CreateShipment'; 41 | 42 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION, $params); 43 | 44 | return $this->parseResponse($response, $action.'Result'); 45 | } 46 | 47 | public function cancelShipment($shipmentId) 48 | { 49 | $action = 'CancelShipment'; 50 | 51 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION, [ 52 | 'ShipmentId' => $shipmentId, 53 | ]); 54 | 55 | return $this->parseResponse($response, $action.'Result'); 56 | } 57 | 58 | public function getShipment($shipmentId) 59 | { 60 | $action = 'GetShipment'; 61 | 62 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION, [ 63 | 'ShipmentId' => $shipmentId, 64 | ]); 65 | 66 | return $this->parseResponse($response, $action.'Result'); 67 | } 68 | 69 | public function getServiceStatus() 70 | { 71 | $action = 'GetServiceStatus'; 72 | 73 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION); 74 | 75 | return $this->parseResponse($response, $action.'Result'); 76 | } 77 | 78 | public function getAdditionalSellerInputs($params) 79 | { 80 | $action = 'GetAdditionalSellerInputs'; 81 | 82 | $response = $this->client->post($action, '/MerchantFulfillment/'.self::VERSION, self::VERSION, $params); 83 | 84 | return $this->parseResponse($response, $action.'Result'); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/MWSOrders.php: -------------------------------------------------------------------------------- 1 | client = $client; 14 | } 15 | 16 | public function list($params = []) 17 | { 18 | $nextToken = data_get($params, 'NextToken'); 19 | $action = 'ListOrders'; 20 | 21 | if ($nextToken) { 22 | $action = 'ListOrdersByNextToken'; 23 | } 24 | 25 | $response = $this->client->post($action, '/Orders/'.self::VERSION, self::VERSION, $params); 26 | 27 | return $this->parseResponse($response, $action.'Result', 'Orders.Order'); 28 | } 29 | 30 | public function get($ids) 31 | { 32 | $ids = is_array($ids) ? $ids : func_get_args(); 33 | $params = []; 34 | 35 | foreach ($ids as $key => $id) { 36 | $keyName = 'AmazonOrderId.Id.'.($key + 1); 37 | $params[$keyName] = $id; 38 | } 39 | 40 | $response = $this->client->post('GetOrder', '/Orders/'.self::VERSION, self::VERSION, $params); 41 | 42 | return $this->parseResponse($response, 'GetOrderResult', 'Orders.Order'); 43 | } 44 | 45 | public function getItems($id) 46 | { 47 | $params = [ 48 | 'AmazonOrderId' => $id, 49 | ]; 50 | $response = $this->client->post('ListOrderItems', '/Orders/'.self::VERSION, self::VERSION, $params); 51 | 52 | return $this->parseResponse($response, 'ListOrderItemsResult', 'OrderItems.OrderItem'); 53 | } 54 | 55 | public function parseResponse($response, $resultTypeName, $dataName) 56 | { 57 | $requestId = data_get($response, 'ResponseMetadata.RequestId'); 58 | $data = data_get($response, $resultTypeName.'.'.$dataName); 59 | $nextToken = data_get($response, $resultTypeName.'.NextToken'); 60 | $createdBefore = data_get($response, $resultTypeName.'.CreatedBefore'); 61 | 62 | //Check if single list item and wrap 63 | if (! is_null($data) && (! data_get($data, '0')) && in_array($resultTypeName, [ 64 | 'ListOrderItemsResult', 65 | 'ListOrderItemsByNextTokenResult', 66 | 'ListOrdersResult', 67 | 'ListOrdersByNextTokenResult', 68 | ])) { 69 | $data = [$data]; 70 | } 71 | 72 | $data = [ 73 | 'request_id' => $requestId, 74 | 'data' => $data, 75 | ]; 76 | 77 | if ($nextToken) { 78 | $data['next_token'] = $nextToken; 79 | } 80 | 81 | if ($createdBefore) { 82 | $data['created_before'] = $createdBefore; 83 | } 84 | 85 | if ($resultTypeName == 'ListOrderItemsResult') { 86 | $data['order_id'] = data_get($response, $resultTypeName.'.AmazonOrderId'); 87 | } 88 | 89 | return $data; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/MWSService.php: -------------------------------------------------------------------------------- 1 | mwsClient = $mwsClient ?: new MWSClient(); 10 | } 11 | 12 | public function orders() 13 | { 14 | return new MWSOrders($this->mwsClient); 15 | } 16 | 17 | public function feeds() 18 | { 19 | return new MWSFeeds($this->mwsClient); 20 | } 21 | 22 | public function merchantFulfillment() 23 | { 24 | return new MWSMerchantFulfillment($this->mwsClient); 25 | } 26 | 27 | public function setMarketPlaces($countries) 28 | { 29 | $countries = is_array($countries) ? $countries : func_get_args(); 30 | $this->mwsClient->setMarketPlaces($countries); 31 | } 32 | } 33 | --------------------------------------------------------------------------------