jlevers / selling-partner-api

A PHP client library for Amazon's Selling Partner API
BSD 3-Clause "New" or "Revised" License
398 stars 186 forks source link

`ProductPricingV0`: Calling `->dto()` on `getItemOffersBatch(..)` response fails due to 400 Bad-Request #705

Closed xHadie closed 3 months ago

xHadie commented 4 months ago

Using version 6.0.4

Problem description:

Error:

I noticed a weird issue with the SP-API endpoint for getItemOffersBatch Seems like there is an issue with the capitalization of the request paramters in the individual requests of the batch.

Amazon apparently expects the itemCondition and marketplaceId paramter to have an capitalized "I" and "M", namely "ItemCondition" and "MarketplaceId". Using lowercase letters results in the 400 response below. Strangely enough, CustomerType NEEDS to have a lowercase "c", namely "customerType" - otherwise again the 400 response in thrown.

I suppose this also causes the error further below when calling ->dto() or ->json(). Would highly appreciate a fix. Not sure whether Amazon is going to change their implementaiton, since the ProductPricing API section has a newer version, but some people still rely on it.

API Response on incorrect capitalizatoin:

{
  "responses": [
    {
      "headers": {
        "x-amzn-RequestId": "25b5dbd2-5469-4821-8592-d0f1121b040f",
        "Date": "Thu, 02 May 2024 15:00:56 GMT"
      },
      "status": {
        "statusCode": 400,
        "reasonPhrase": "Bad Request"
      },
      "body": {
        "errors": [
          {
            "message": "Invalid condition",
            "details": "",
            "code": "InvalidInput"
          }
        ]
      },
      "request": {
        "MarketplaceId": "A1PA6795UKMFR9",
        "Asin": "MY_ASIN(changed)"
      }
    }
  ]
}
#### Saloon body:
#body: Saloon\Repositories\Body\JsonBodyRepository^ {#2880
        #data: array:1 [
          "requests" => array:3 [
            0 => array:6 [
              "uri" => "/products/pricing/v0/items/$someAsin1/offers"
              "method" => "GET"
              "marketplaceId" => "A1PA6795UKMFR9"
              "itemCondition" => "New"
              "headers" => null
              "customerType" => null
            ]
            1 => array:6 [
              "uri" => "/products/pricing/v0/items/$someAsin2/offers"
              "method" => "GET"
              "marketplaceId" => "A1PA6795UKMFR9"
              "itemCondition" => "New"
              "headers" => null
              "customerType" => null
            ]
            2 => array:6 [
              "uri" => "/products/pricing/v0/items/$someAsin3/offers"
              "method" => "GET"
              "marketplaceId" => "A1PA6795UKMFR9"
              "itemCondition" => "New"
              "headers" => null
              "customerType" => null
            ]
          ]
        ]
        #jsonFlags: 4194304
      }
    }

Code

private function createRequestArrayForProduct(array $product, $mpKey)
    {
        $asin = $product["asin"];
        $request = new ItemOffersRequest(
            uri: "/products/pricing/v0/items/$asin/offers",
            method: "GET",
            marketplaceId: $mpKey,
            itemCondition: "New"
        );
        return $request;
    }
    private function doSomeStuff(array $productBatch, $mpKey)
    {
        $requests = [];
        foreach ($productBatch as $product) {
            array_push($requests, $this->createRequestArrayForProduct($product, $mpKey));
        }

        $response = $this->sellingPartnerAPIService->getProductPriceingApi()->getItemOffersBatch(
            new GetItemOffersBatchRequest($requests)
        )->dto();
    }
  ArgumentCountError 

  SellingPartnerApi\Seller\ProductPricingV0\Dto\ItemOffersRequestParams::__construct(): Argument #1 ($marketplaceId) not passed

  at vendor/jlevers/selling-partner-api/src/Seller/ProductPricingV0/Dto/ItemOffersRequestParams.php:22
     18▕      * @param  string  $itemCondition  Filters the offer listings to be considered based on item condition. Possible values: New, Used, Collectible, Refurbished, Club.
     19▕      * @param  ?string  $customerType  Indicates whether to request Consumer or Business offers. Default is Consumer.
     20▕      * @param  ?string  $asin  The Amazon Standard Identification Number (ASIN) of the item. This is the same Asin passed as a request parameter.
     21▕      */
  ➜  22▕     public function __construct(
     23▕         public readonly string $marketplaceId,
     24▕         public readonly string $itemCondition,
     25▕         public readonly ?string $customerType = null,
     26▕         public readonly ?string $asin = null,
misterakko commented 4 months ago

I seem to have met the same issue on a different call

My code: $limite = $listingsRestrictionsApi->getListingsRestrictions( asin:$i['asin'], conditionType:$item_condition, sellerId:$amazon->prefs['amazon-MERCHANT_ID'], marketplaceIds:array($amazon->prefs['amazon-MARKETPLACE_ID']), reasonLocale:'it_IT' );

Parameters are cased exactly as shown in the Amazon docs at https://developer-docs.amazon.com/sp-api/docs/listings-restrictions-api-v2021-08-01-reference

Result is an error 400 "Request has missing or invalid parameters and cannot be parsed." GET https://sellingpartnerapi-eu.amazon.com/listings/2021-08-01/restrictions?asin=8804777427&sellerId=A1DNXQQ92EWNAP&marketplaceIds=APJ6JRA9NG5V4&conditionType=New&reasonLocale=it_IT

jlevers commented 3 months ago

These issues appear to both be fixed in main, and will be released in v7 shortly.

jlevers commented 3 months ago

Released in v7.0.0.