Generate AWS signature for Amazon Shipping API using PHP

Viewed 1349

I am trying to generate signature for Authorization header to call Amazon Shipping API. Also interested in knowing if there is some other way of integrating Shippin API as amazon has given different documents but none of them are clear in how to integrate. Their support team has told to use AWS signing method to generate headers but its sdk is not available in PHP.

This is my code for generating the signature but it is always resulting in 400 HTTP error.

$host               = "https://sellingpartnerapi-eu.amazon.com";
$accessKey          = ACCESS_KEY;
$secretKey          = SECRET_KEY;
$region             = "eu-west-1";
$service            = "execute-api";
$requestUrl         = "https://sellingpartnerapi-eu.amazon.com/shipping/v2/shipments/rates";
$uri                = 'shipping/v2/shipments/rates';

function calcualteAwsSignatureAndReturnHeaders($host, $uri, $requestUrl, 
            $accessKey, $secretKey, $region, $service, 
            $httpRequestMethod, $data, $debug = TRUE){

    $terminationString  = 'aws4_request';
    $algorithm      = 'AWS4-HMAC-SHA256';
    $phpAlgorithm       = 'sha256';
    $canonicalURI       = $uri;
    $canonicalQueryString   = '';
    $signedHeaders      = 'content-type;host;x-amz-date';


    $currentDateTime = new DateTime('UTC');
    $reqDate = $currentDateTime->format('Ymd');
    $reqDateTime = $currentDateTime->format('Ymd\THis\Z');

    // Create signing key
    $kSecret = $secretKey;
    $kDate = hash_hmac($phpAlgorithm, $reqDate, 'AWS4' . $kSecret, true);
    $kRegion = hash_hmac($phpAlgorithm, $region, $kDate, true);
    $kService = hash_hmac($phpAlgorithm, $service, $kRegion, true);
    $kSigning = hash_hmac($phpAlgorithm, $terminationString, $kService, true);

    // Create canonical headers
    $canonicalHeaders = array();
    $canonicalHeaders[] = 'content-type:application/x-www-form-urlencoded';
    $canonicalHeaders[] = 'host:' . $host;
    $canonicalHeaders[] = 'x-amz-date:' . $reqDateTime;
    $canonicalHeadersStr = implode("\n", $canonicalHeaders);

    // Create request payload
    $requestHasedPayload = hash($phpAlgorithm, $data);

    // Create canonical request
    $canonicalRequest = array();
    $canonicalRequest[] = $httpRequestMethod;
    $canonicalRequest[] = $canonicalURI;
    $canonicalRequest[] = $canonicalQueryString;
    $canonicalRequest[] = $canonicalHeadersStr . "\n";
    $canonicalRequest[] = $signedHeaders;
    $canonicalRequest[] = $requestHasedPayload;
    $requestCanonicalRequest = implode("\n", $canonicalRequest);
    $requestHasedCanonicalRequest = hash($phpAlgorithm, utf8_encode($requestCanonicalRequest));
    if($debug){
        echo "<h5>Canonical to string</h5>";
        echo "<pre>";
        echo $requestCanonicalRequest;
        echo "</pre>";
    }

    // Create scope
    $credentialScope = array();
    $credentialScope[] = $reqDate;
    $credentialScope[] = $region;
    $credentialScope[] = $service;
    $credentialScope[] = $terminationString;
    $credentialScopeStr = implode('/', $credentialScope);

    // Create string to signing
    $stringToSign = array();
    $stringToSign[] = $algorithm;
    $stringToSign[] = $reqDateTime;
    $stringToSign[] = $credentialScopeStr;
    $stringToSign[] = $requestHasedCanonicalRequest;
    $stringToSignStr = implode("\n", $stringToSign);
    if($debug){
        echo "<h5>String to Sign</h5>";
        echo "<pre>";
        echo $stringToSignStr;
        echo "</pre>";
    }

    // Create signature
    $signature = hash_hmac($phpAlgorithm, $stringToSignStr, $kSigning);

    // Create authorization header
    $authorizationHeader = array();
    $authorizationHeader[] = 'Credential=' . $accessKey . '/' . $credentialScopeStr;
    $authorizationHeader[] = 'SignedHeaders=' . $signedHeaders;
    $authorizationHeader[] = 'Signature=' . ($signature);
    $authorizationHeaderStr = $algorithm . ' ' . implode(', ', $authorizationHeader);


    // Request headers
    $headers = array();
    $headers[] = 'authorization:'.$authorizationHeaderStr;
    $headers[] = 'content-length:'.strlen($data);
    $headers[] = 'content-type: application/x-www-form-urlencoded';
    $headers[] = 'host: ' . $host;
    $headers[] = 'x-amz-date: ' . $reqDateTime;

    return $headers;
}

1 Answers

You need to add "x-amz-access-token" in header field as like

$headers = array();
$headers[] = 'authorization:'.$authorizationHeaderStr;
$headers[] = 'content-length:'.strlen($data);
$headers[] = 'content-type: application/json';
$headers[] = 'host: ' . $host;
$headers[] = 'x-amz-date: ' . $reqDateTime;
$headers[] = 'x-amz-access-token: ' . $reqToken;

You can generate the x-amz-access-token from https://api.amazon.com/auth/o2/token

Related