user1260414 user1260414 - 1 month ago 16
PHP Question

Amazon MWS API returning SignatureDoesNotMatch

I need to call the Amazon MWS action 'RequestReport' and specify the ReportType as '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_'. i have successfully connected to get the FulfillmentInventory/ListInventorySupply, so i know that the cURL and amazon settings are correct, but every time i submit i get 'The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.' back from the server. i have tried both sort and ksort on line 23 and 14 - in the call to the FulfillmentInventory/ListInventorySupply i had to set it up with two ksorts in order to keep the list of SKUs in the correct order for the API

Here is the code, as i say, the secret, merchant, and keyid are correct:

header('Content-type: application/xml');
$secret = 'secretcodehere';

$param = array();
$param['AWSAccessKeyId'] = 'accessidhere';
$param['Action'] = 'RequestReport';
$param['Merchant'] = 'merchantidhere';
$param['SignatureVersion'] = '2';
$param['Timestamp'] = gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());

$param['Version'] = '2009-01-01';
$param['SignatureMethod'] = 'HmacSHA256';
$param['ReportType'] = '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_';
ksort($param);
$url = array();
foreach ($param as $key => $val) {

$key = str_replace("%7E", "~", rawurlencode($key));
$val = str_replace("%7E", "~", rawurlencode($val));
$url[] = "{$key}={$val}";
}

sort($url);

$arr = implode('&', $url);

$sign = 'POST' . "\n";
$sign .= 'mws.amazonservices.com';
$sign .= '/doc/2009-01-01' . "\n";
$sign .= $arr;

$signature = hash_hmac("sha256", $sign, $secret, true);
$signature = urlencode(base64_encode($signature));

$link = "https://mws.amazonservices.com/doc/2009-01-01/?";
$link .= $arr . "&Signature=" . $signature;
/*

echo($link);//for debugging

exit(); */

$ch = curl_init($link);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: text/xml'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
print_r($response);


i have tried it in MWS scratchpad and the info is correct and generates the 200 response, and when i check the url against the one generated by the scratchpad it 'looks' correct, so i must be missing something and i hope it is obvious to someone out there, 'cause i am baffled.

btw-scratchpad lists it as SellerId, but the url shows it as Merchant - i have tried both with no joy

Answer

Not to throw a curve ball at you, but the only success I've had in using the RequestReport has been through using the PHP library that Amazon created. If you don't have it already here's the link.

This is the code that I just confirmed works to request the report:

<?php

define('AWS_ACCESS_KEY_ID', $am_aws_access_key);
define('AWS_SECRET_ACCESS_KEY', $am_secret_key);
define('MERCHANT_ID', $am_merchant_id);
define('MARKETPLACE_ID', $am_marketplace_id);

include_once ('/link/to/Amazon/library/MarketplaceWebService/Samples/.config.inc.php');

include_once ('functions.php');

$serviceUrl = "https://mws.amazonservices.com";
$config = array (
    'ServiceURL' => $serviceUrl,
    'ProxyHost' => null,
    'ProxyPort' => -1,
    'MaxErrorRetry' => 3,
);
$service = new MarketplaceWebService_Client(
    AWS_ACCESS_KEY_ID,
    AWS_SECRET_ACCESS_KEY,
    $config,
    APPLICATION_NAME,
    APPLICATION_VERSION);

echo '<br />';
$parameters = array (
    'Marketplace' => MARKETPLACE_ID,
    'Merchant' => MERCHANT_ID,
    'ReportType' => '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_',
);

echo '<br /><br/>Request Report Request:<br><br>';
$request = new MarketplaceWebService_Model_RequestReportRequest($parameters);
print_r($request);
invokeRequestReport($service, $request);
echo '<br /><br/>';

And the functions.php file (basically is the important function in the last half of the code in the MarketplaceWebService\Samples\RequestReportSample.php file:

function invokeRequestReport(MarketplaceWebService_Interface $service, $request)
{
    try {
        $response = $service->requestReport($request);
        echo ("Service Response\n");
        echo ("=============================================================================\n");
        echo("        RequestReportResponse\n");
        if ($response->isSetRequestReportResult()) {
            echo("            RequestReportResult\n");
            $requestReportResult = $response->getRequestReportResult();
            if ($requestReportResult->isSetReportRequestInfo()) {
                $reportRequestInfo = $requestReportResult->getReportRequestInfo();
                echo("                ReportRequestInfo\n");
                if ($reportRequestInfo->isSetReportRequestId())
                {
                    echo("                    ReportRequestId\n");
                    echo("                        " . $reportRequestInfo->getReportRequestId() . "\n");
                }
                $report_request_id = $reportRequestInfo->getReportRequestId();
                $report_type = '';
                if ($reportRequestInfo->isSetReportType())
                {
                    echo("                    ReportType\n");
                    echo("                        " . $reportRequestInfo->getReportType() . "\n");
                    $report_type = $reportRequestInfo->getReportType();
                }
                if ($reportRequestInfo->isSetStartDate())
                {
                    echo("                    StartDate\n");
                    echo("                        " . $reportRequestInfo->getStartDate()->format(DATE_FORMAT) . "\n");
                }
                if ($reportRequestInfo->isSetEndDate())
                {
                    echo("                    EndDate\n");
                    echo("                        " . $reportRequestInfo->getEndDate()->format(DATE_FORMAT) . "\n");
                }
                if ($reportRequestInfo->isSetSubmittedDate())
                {
                    echo("                    SubmittedDate\n");
                    echo("                        " . $reportRequestInfo->getSubmittedDate()->format(DATE_FORMAT) . "\n");
                }
                if ($reportRequestInfo->isSetReportProcessingStatus())
                {
                    echo("                    ReportProcessingStatus\n");
                    echo("                        " . $reportRequestInfo->getReportProcessingStatus() . "\n");
                }
                if($report_type == '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_') {
                    if(!empty($report_request_id)) {
                        $parameters = array (
                            'Marketplace' => MARKETPLACE_ID,
                            'Merchant' => MERCHANT_ID,
                            'Report' => @fopen('php://memory', 'rw+'),
                            'ReportRequestIdList' => $report_request_id,
                        );
                        $report = new MarketplaceWebService_Model_GetReportRequestListRequest($parameters);
                        print_r($report);
                    }
                }
            }
        }
        if ($response->isSetResponseMetadata()) {
            echo("            ResponseMetadata\n");
            $responseMetadata = $response->getResponseMetadata();
            if ($responseMetadata->isSetRequestId())
            {
                echo("                RequestId\n");
                echo("                    " . $responseMetadata->getRequestId() . "\n");
            }
        }
    } catch (MarketplaceWebService_Exception $ex) {
        echo("Caught Exception: " . $ex->getMessage() . "\n");
        echo("Response Status Code: " . $ex->getStatusCode() . "\n");
        echo("Error Code: " . $ex->getErrorCode() . "\n");
        echo("Error Type: " . $ex->getErrorType() . "\n");
        echo("Request ID: " . $ex->getRequestId() . "\n");
        echo("XML: " . $ex->getXML() . "\n");
    }
}

EDIT

Here's the important parts of the .config.inc.php file:

<?php

define ('DATE_FORMAT', 'Y-m-d\TH:i:s\Z');
date_default_timezone_set('America/Denver');

$app_name = "Just make up a name like 'Awesome Sync'";
$app_version = "1.0";
define('APPLICATION_NAME', $app_name);
define('APPLICATION_VERSION', $app_version);

set_include_path('/link/to/Amazon/library/');
...rest of code...

EDIT

This code will create the request for the report, however, it doesn't actually create the report. You have to continue to poll Amazon using this same code until you receive a "Complete" or something similar (can't remember the exact word Amazon send back when the report has been created). Then you need to actually retrieve the report.