Using the below code, the only result I can get to echo is the URL. When I copy and paste into browser, I get:
<Message>
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.
Code Being Used;
<?php
date_default_timezone_set('America/New_York');
define('AWS_ACCESS_KEY_ID', '***');
define('AWS_SECRET_ACCESS_KEY', '***');
define('APPLICATION_NAME', 'test');
define('APPLICATION_VERSION', '1.0');
define ('MERCHANT_ID', '***');
define ('MARKETPLACE_ID', '***');
$base_url = "https://mws.amazonservices.com/Products/2011-10-01";
$method = "GET";
$host = "mws.amazonservices.com";
$uri = "/Products/2011-10-01";
function amazon_xml($searchTerm) {
$params = array(
'AWSAccessKeyId' => AWS_ACCESS_KEY_ID,
'Action' => "GetCompetitivePricingForASIN",
'SellerId' => MERCHANT_ID,
'SignatureMethod' => "HmacSHA256",
'SignatureVersion' => "2",
'Timestamp'=> gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
'Version'=> "2011-10-01",
'MarketplaceId' => MARKETPLACE_ID,
'Query' => $searchTerm,
'QueryContextId' => "Automotive");
// Sort the URL parameters
$url_parts = array();
foreach(array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
// Construct the string to sign
$url_string = implode("&", $url_parts);
$string_to_sign = "GET\nmws.amazonservices.com\n/Products/2011-10-01\n" . $url_string;
// Sign the request
$signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE);
// Base64 encode the signature and make it URL safe
$signature = urlencode(base64_encode($signature));
$url = "https://mws.amazonservices.com/Products/2011-10-01" . '?' . $url_string . "&Signature=" . $signature;
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
echo $url;
// return $xml if you still want to parse the data elsewhere
$xml = simplexml_load_string($response);
// return this if you just want the raw XML string
return $xml->asXML();
echo $xml->GetMatchingProductResult->Product->Identifiers->MarketplaceASIN->ASIN;
}
$searchTerm = "B00FNNLBK2";
amazon_xml($searchTerm);
//foreach ($xml->GetMatchingProductResult->Product as $product) {
// do something for each <Product>, such as output the ASIN...
//}
echo $xml;
echo $searchTerm;
echo $xml->GetMatchingProductResult->Product->Identifiers->MarketplaceASIN->ASIN;
echo $url;
?>
I did verify multiple times that the sign in credentials are correct, with no absract leading or trailing space.
Those parameters (e.g. Query and QueryContextId) don't match with the Action you are trying to call (GetCompetitivePricingForASIN). They correspond to the ListMatchingProducts action.
Assuming that you meant ListMatchingProducts try this:
<?php
date_default_timezone_set('America/New_York');
define('AWS_ACCESS_KEY_ID', '***');
define('AWS_SECRET_ACCESS_KEY', '***');
define('APPLICATION_NAME', 'test');
define('APPLICATION_VERSION', '1.0');
define ('MERCHANT_ID', '***');
define ('MARKETPLACE_ID', '***');
function amazon_xml($searchTerm)
{
$params = array(
'AWSAccessKeyId' => AWS_ACCESS_KEY_ID,
'Action' => "ListMatchingProducts",
'SellerId' => MERCHANT_ID,
'SignatureMethod' => "HmacSHA256",
'SignatureVersion' => "2",
'Timestamp' => gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
'Version' => "2011-10-01",
'MarketplaceId' => MARKETPLACE_ID,
'Query' => $searchTerm,
'QueryContextId' => "Automotive"
);
$url_parts = array();
foreach (array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
$url_string = implode("&", $url_parts);
$string_to_sign = "GET\nmws.amazonservices.com\n/Products/2011-10-01\n" . $url_string;
$signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE);
$signature = urlencode(base64_encode($signature));
$url = "https://mws.amazonservices.com/Products/2011-10-01" . '?' . $url_string . "&Signature=" . $signature;
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
$xml = simplexml_load_string($response);
return $xml->asXML();
}
$searchTerm = "B00FNNLBK2";
echo amazon_xml($searchTerm);
You can find the relevant parameters for each Action in the MWS documentation e.g. here:
http://docs.developer.amazonservices.com/en_US/products/Products_GetCompetitivePricingForASIN.html
You can also see them using the MWS Scratchpad:
https://mws.amazonservices.com/scratchpad/index.html
Related
What is wrong?
This is all my code, I think that it should be fine, but I don't know why... with postman I haven't errors and I receive the tokens while with Curl I receive this error. I'm working in local with Mamp pro.
The error received is:
My Code To generete the Signature and get the Token:
$url = "https://account.api.here.com/oauth2/token";
$data = array(
"grant_type" => "client_credentials"
);
$oauthNonce = mt_rand();
$oauthTimestamp = time();
$oauthCustomereKey = "******";
$oauthSignatureMethod = "HMAC-SHA256";
$httpMethod = "POST";
$oauthVersion = "1.0";
$keySecret = "*****";
$baseString = $httpMethod."&". urlencode($url);
$paramString =
"grant_type=client_credentials&".
"oauth_consumer_key=". urlencode($oauthCustomereKey).
"&oauth_nonce=". urlencode($oauthNonce).
"&oauth_signature_method=". urlencode($oauthSignatureMethod).
"&oauth_timestamp=". urlencode($oauthTimestamp).
"&oauth_version=". urlencode($oauthVersion)
;
$baseString = $baseString . "&" . urlencode($paramString);
var_dump($baseString);
$signingKey= urlencode($keySecret) . "&";
$signature = urlencode(
base64_encode(
hash_hmac(
'sha256',
$baseString,
$signingKey,
true
)
)
);
$params = [
"oauth_consumer_key" => $oauthCustomereKey,
"oauth_nonce" => $oauthNonce,
"oauth_signature_method" => $oauthSignatureMethod,
"oauth_timestamp" => $oauthTimestamp,
"oauth_version" => $oauthVersion,
"oauth_signature" => $signature
];
// $lol = 'oauth_consumer_key="' . $oauthCustomereKey . '",oauth_signature_method="'.$oauthSignatureMethod . '",oauth_timestamp="'.$oauthTimestamp.'",oauth_nonce="'.$oauthNonce.'",oauth_version="'.$oauthVersion.'",oauth_signature="'.$signature.'"';
/* This will give you the proper encoded string to include in your Authorization header */
$params = http_build_query($params, null, ',', PHP_QUERY_RFC3986);
$authorization = "Authorization: OAuth " . $params;
var_dump($authorization);
if(!$curl = curl_init()){
exit;
}
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"Content-Type : application/x-www-form-urlencoded",
$authorization));
$token = curl_exec($curl);
curl_close($curl);
return $token;
Result basestring (dump on line 87):
string(253) "POST&https%3A%2F%2Faccount.api.here.com%2Foauth2%2Ftoken&grant_type%3Dclient_credentials%26oauth_consumer_key%3D********%26oauth_nonce%3D1468397107%26oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1605523226%26oauth_version%3D1.0"
And on the doc here we have this example... it look the same:
POST
&https%3A%2F%2Faccount.api.here.com%2Foauth2%2Ftoken
&grant_type=client_credentials%26oauth_consumer_key%3Daccess-key-id-1234%26oauth_nonce%3DLIIpk4%26
oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1456945283%26oauth_version%3D1.0
FIXED
Finally... after 2 days...
There are 2 errors on the code above:
The parameter $data to CURLOPT_POSTFIELDS
Oauth 1.0 wants the double quotes.
So change:
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
With
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
This is strange for me, because with curl I use http_build_query with GET request and not POST, where we can use $data directly like array.
And delete:
$params = http_build_query($params, null, ',', PHP_QUERY_RFC3986);
And write the query with your beautifuls hand because $params doesn't have double quote.
I have used following code for getting amazon product data and all products are getting in xml but product stock is not there in xml content.
Can anyone guide me for how to get product stock information.
<?php
define('AWS_ACCESS_KEY_ID', 'my-access-key');
define('AWS_SECRET_ACCESS_KEY', 'my-secret-key');
define('AMAZON_ASSOC_TAG', 'my-associate-tag');
function amazon_get_signed_url($searchTerm)
{
$base_url = "http://ecs.amazonaws.com/onca/xml";
$params = array( 'AWSAccessKeyId' => AWS_ACCESS_KEY_ID, 'AssociateTag' => AMAZON_ASSOC_TAG, 'Version' => "2010-11-01", 'Operation' => "ItemLookup", 'Service' => "AWSECommerceService", 'ResponseGroup' => "ItemAttributes", 'ItemId'=> $searchTerm);
if(empty($params['AssociateTag']))
{
unset($params['AssociateTag']);
}
// Add the Timestamp
$params['Timestamp'] = gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());
// Sort the URL parameters
$url_parts = array();
foreach(array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
// Construct the string to sign
$url_string = implode("&", $url_parts);
$string_to_sign = "GET\necs.amazonaws.com\n/onca/xml\n" . $url_string;
// Sign the request
$signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE);
// Base64 encode the signature and make it URL safe
$signature = urlencode(base64_encode($signature));
$url = $base_url . '?' . $url_string . "&Signature=" . $signature;
return ($url);
}
$getthis = 'B004XIE6WI'; /*---- Product ASIN-----*/
$show = amazon_get_signed_url($getthis);
$ch = curl_init($show);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$c = curl_exec($ch);
$xml = simplexml_load_string($c);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
echo "<pre>";
print_r($array);
echo "</pre>";
?>
Amazon Product Api does not provide stock information. A similar question was asked here: How to get remaining stock from Product Advertising API (AWS)
I'm trying to get the inventory of my fulfillment using the PHP API of the MWS. When I use the parameters given by amazon on the scratchpad I get the answer perfectly, but when I try using my code it says that the signature doesn't match, what am I doing wrong?
<?php
$base_url = "https://mws.amazonservices.co.uk/FulfillmentInventory/2010-10-01";
$method = "POST";
$host = "mws.amazonservices.co.uk";
$uri = "/FulfillmentInventory/2010-10-01";
function amazon_xml() {
$params = array(
'AWSAccessKeyId' => "123456788",
'Action' => "ListInventorySupply",
'SellerId' => "234234123412341",
'SignatureVersion' => "2",
//'Timestamp'=> gmdate("Y-m-d\TH:i:s.Z", time()),
'Timestamp'=> gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
'Version'=> "2010-10-01",
'SignatureMethod' => "HmacSHA256",
'SellerSkus.member.1' => '1EU-AMZ-FIRE-TV-MOUNT');
// Sort the URL parameters
$url_parts = array();
foreach(array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
// Construct the string to sign
$url_string = implode("&", $url_parts);
$string_to_sign = "POST\nmws.amazonservices.co.uk\n/FulfillmentInventory/2010-10-01\n" . $url_string;
echo $string_to_sign."<br/>";
// Sign the request
$signature = hash_hmac("sha256", $string_to_sign, 'sdgsdfgsdfgsdgsdgsdg', TRUE);
echo $signature."<br />";
// Base64 encode the signature and make it URL safe
$signature = urlencode(base64_encode($signature));
echo $signature."<br />";
$url = "https://mws.amazonservices.co.uk/FulfillmentInventory/2010-10-01" . '?' . $url_string . "&Signature=" . $signature;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
echo "La respuesta es ".$response;
$parsed_xml = simplexml_load_string($response);
//return ($parsed_xml);
echo $parsed_xml;
}
amazon_xml();
?>
You appear to be sorting your $url_parts array by value, where you should be sorting it by key.
ksort($url_parts);
I cannot see any other systematic problem in your code. Another point where my code differs from yours though, is that mine uses a Merchant parameter instead of SellerId - I have not checked if using SellerId actually works as well.
I know that the question related to this topic has been asked many times and i have read all but still not able to solve my problem. Here is my code...
<?php
define('AWS_ACCESS_KEY_ID','xxxxx');
define('AWS_SECRET_ACCESS_KEY','xxxxx');
define('MERCHANT_ID','xxxxx');
define('MARKETPLACE_ID','xxxxxx');
$file = 'test.xml';
$feed = '
<?xml version="1.0" encoding="UTF-8"?>
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.02</DocumentVersion>
<MerchantIdentifier>Mystore</MerchantIdentifier>
</Header>
<MessageType>OrderFulfillment</MessageType>
<Message>
<MessageID>123456</MessageID>
<OrderFulfillment>
<AmazonOrderID>123-1234567-1234567</AmazonOrderID>
<MerchantFulfillmentID>1474290171</MerchantFulfillmentID>
<FulfillmentDate>2016-09-19T12:23:41+00:00</FulfillmentDate>
<FulfillmentData>
<CarrierCode>FedEx</CarrierCode>
<ShippingMethod>FedEx</ShippingMethod>
<ShipperTrackingNumber>1111111</ShipperTrackingNumber>
</FulfillmentData>
</OrderFulfillment>
</Message>
</AmazonEnvelope>
';
$feedHandle = #fopen($file, 'w');
fwrite($feedHandle, trim($feed));
rewind($feedHandle);
$params = array(
'AWSAccessKeyId' => AWS_ACCESS_KEY_ID,
'Action' => "SubmitFeed",
'Merchant' => MERCHANT_ID,
'SignatureVersion' => "2",
'Timestamp'=> gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time()),
'Version'=> "2009-01-01",
'SignatureMethod' => "HmacSHA256",
'FeedType' => '_POST_ORDER_FULFILLMENT_DATA_',
'MarketplaceIdList.Id.1' => MARKETPLACE_ID,
'PurgeAndReplace' => 'false',
);
$url_parts = array();
foreach(array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
$url_string = implode("&", $url_parts);
$string_to_sign = "POST\nmws.amazonservices.com\n/Feeds/2009-01-01\n" . $url_string;
// Sign the request
$signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE);
$signature = urlencode(base64_encode($signature));
$url = "https://mws.amazonservices.com/Feeds/2009-01-01" . '?' . $url_string . "&Signature=" . $signature;
$md5 = base64_encode(md5(trim($feed), true));
$httpHeader=array();
$httpHeader[]='Transfer-Encoding: chunked';
$httpHeader[]='Content-Type: application/x-www-form-urlencoded; charset=utf-8';
$httpHeader[]='Content-MD5: ' . $md5;
$httpHeader[]='Expect:';
$httpHeader[]='Accept:';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_USERAGENT, '<MWS_SubmitFeed>/<1.02> (Language=PHP/' . phpversion() . ')');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_INFILE, $feedHandle);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
curl_setopt($ch, CURLOPT_POST, true);
$response = curl_exec($ch);
var_dump($response);
?>
When I submit the request I am getting the following error:
SenderContentMD5DoesNotMatchthe Content-MD5 HTTP header you passed for your feed did not match the Content-MD5 we calculated for your feed4f0c5178-8971-4322-ba85-aed0bfe81bd0
Actually i am updating the order status on MWS.
Would be appreciated if anyone sort out the problem or point out that where i am going to wrong.
You are doing a trim on the xml and then calculating the md5. Whereas the amazon is not doing any trim on the xml that you send. Hence the mismatch. Remove that trim() from there.
I got the Solution.
Remove the trim() from these lines suggested by Sabuj Hassan and modify the hash generating code:
fwrite($feedHandle, trim($feed));
to
fwrite($feedHandle, $feed);
and
$md5 = base64_encode(md5(trim($feed), true));
to
$md5 = base64_encode(md5(stream_get_contents($feedHandle), true));
Replace trim($feed) to stream_get_contents($feedHandle), it will generate the correct hash for content-md5.
Note: stream_get_contents($feedHandle) is mentioned in amazon's php library.
I keep getting an invalid date range response from my request. I am not sure what is wrong. I have all the parameters and a valid ReportID.
$params = array(
'AWSAccessKeyId' => AWS_ACCESS_KEY_ID,
'Action' => "GetReport",
'SellerId' => MERCHANT_ID,
'SignatureMethod' => "HmacSHA256",
'SignatureVersion' => "2",
'Timestamp' => $timestamp,
'Version'=> "2009-01-01",
'Marketplace' => MARKETPLACE_ID,
'ReportId' => $reportID
);
// Sort the URL parameters
$url_parts = array();
foreach(array_keys($params) as $key)
$url_parts[] = $key . "=" . str_replace('%7E', '~', rawurlencode($params[$key]));
sort($url_parts);
// Construct the string to sign
$url_string = implode("&", $url_parts);
$string_to_sign = "GET\nmws.amazonservices.com\n/Reports/2009-01-01\n" . $url_string;
// Sign the request
$signature = hash_hmac("sha256", $string_to_sign, AWS_SECRET_ACCESS_KEY, TRUE);
// Base64 encode the signature and make it URL safe
$signature = urlencode(base64_encode($signature));
$url = "https://mws.amazonservices.com/Reports/2009-01-01" . '?' . $url_string . "&Signature=" . $signature;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$response = curl_exec($ch);
print_r($response);
The output I get back is Invalid Date Range
Does it work through Amazon's scratchpad? I just tried a GetReport operation and it came back just fine. Of course no date range is needed because you're trying to get back a specific report by id. I usually go to the scratchpad as a quick and easy way to get info from MWS.
My POST looks like this:
Well after contacting Amazon this is what is came down to. When I requested the report using the RequestReport Action I supplied an invalid Date Range. So the report itself return Invalid Date Range as the content of the report.