Search code examples
phpcurlamazon-selling-partner-api

Amazon SP API Batch call with PHP curl


I am trying to call the batch process for getItemOffersBatch using PHP and curl to sign and make the call -- I am able to call the getItemOffers individually with no issues. I ran a batch of 2 and I get a 403 Forbidden error -- here is the code (PHP 8):

json_encode($body, JSON_THROW_ON_ERROR);
$post = 'POST';
$body=json_encode($body, JSON_UNESCAPED_SLASHES);
//var_dump($body);
$urlbatch= "https://sellingpartnerapi-na.amazon.com/batches/products/pricing/v0/itemOffers". $body ;
//var_dump($urlbatch);
$ch = curl_init($urlbatch);
curl_setopt_array($ch, [CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true
,CURLOPT_CONNECTTIMEOUT => 5,]);
//  var_dump($header);
if ($post) curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
if ($header) curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, fopen('curl.log', 'a+'));
$out = curl_exec($ch);
if (curl_errno($ch)) exit('Error: ' . curl_error($ch));
if ($status !== null) $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return $out

Where there are ***** is valid private Amazon data. After going back and forth with amazon and using POSTMAN i got it to work in POSTMAN but i am struggling to add the data part correctly here is the code from POSTMAN that worked.

curl --location 'https://sellingpartnerapi-na.amazon.com/batches/products/pricing/v0/itemOffers' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-amz-access-token: ****' \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=****/20240110/us-east-1/execute-api/aws4_request,SignedHeaders=host;user-agent;x-amz-access-token;x-amz-date,Signature=******' \
--data '{
"requests": [
    {
        "uri": "/products/pricing/v0/items/B000P6Q7MY/offers",
        "method": "GET",
        "MarketplaceId": "ATVPDKIKX0DER",
        "ItemCondition": "New",
        "CustomerType": "Consumer"
    },
    {
        "uri": "/products/pricing/v0/items/B001Q3KU9Q/offers",
        "method": "GET",
        "MarketplaceId": "ATVPDKIKX0DER",
        "ItemCondition": "New",
        "CustomerType": "Consumer"
    }
]

}'

i tried adding data to

curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

but that did not work any help would be great i almost have it


Solution

  • Here is the answer --simple sometimes is best

     $canonicalRequest = $method . "\n" // HTTP method
    . $path . "\n" //  Path component of the URL
    . $qs . "\n" // Query string component of the URL (without '?')
    . 'host:' . HOST . "\n" // Header
    . 'user-agent:' . USER_AGENT . "\n" // Header
    . 'x-amz-access-token:' . $accessToken . "\n" // Header
    . 'x-amz-date:' . $date . "\n" // Header
    . "\n" // A newline is needed here after the headers
    . 'host;user-agent;x-amz-access-token;x-amz-date' . "\n" // Header names
    . hash('sha256', $data); // Hash of the payload (empty string okay)
    
    function httpRequest($url,  $post = '', $header = null, &$status = null) {
    $ch = curl_init($url);
    
    curl_setopt_array($ch, [
        CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_CONNECTTIMEOUT => 5,
    ]);
    if ($post) curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    if ($header) curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_STDERR, fopen('curl.log', 'a+'));
    
    $out = curl_exec($ch);
    
    if (curl_errno($ch)) exit('Error: ' . curl_error($ch));
    if ($status !== null) $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    return $out;
    

    }

    was not putting in the data into the canonicalRequest so it could go through hash