Reputation: 656
I am trying to integrate with the Amazon Product Affiliate REST API, I refuse to use the SOAP integration, and please don't bring up the Soap here, I want to use REST, I am using the latest API version, which is 08/01/2013 I followed the documentation, and somehow I get always back a 403 forbidden error, I have looked all over the place, and the only thing I saw was, ppl angry about the outdated samples on Amazon, so I am getting frustrated not getting my integration work, here are the specs that I use.
VS 2015 Console Application targeting .NET 4.5.2 Amazon Api version 08/01/2013
and here is my code base.
I have a class called AmazonRestService which has all properties needed for an ItemLookup,
in the constructor i set some properties which is the default for every request, then i have a method called SignAmazonRequest which takes an AmazonRestService as an argument, and i check all fields that has a value, i fill up the string that will need to be signed,
public class AmazonRestService
{
public string Url { get; set; }
public string Operation { get; set; }
public string AWSAccessKeyId { get; set; }
public string SecretKey { get; set; }
public string AssociateTag { get; set; }
public string ItemId { get; set; }
public string IdType { get; set; }
public string[] ResponseGroup { get; set; }
public string Timestamp { get; set; }
public string Signature { get; set; }
public string Version { get; set; }
public AmazonRestService()
{
Url = "http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&";
AWSAccessKeyId = "XXXXXXXXXXXXXXXXXXXXX";
AssociateTag = "xxxx-xx";
SecretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
Version = "2013-08-01";
}
public AmazonRestService SignAmazonRequest(AmazonRestService service)
{
var stringToSign = "";
stringToSign = stringToSign + "AssociateTag=" + service.AssociateTag;
if (!string.IsNullOrEmpty(service.Operation))
{
stringToSign = stringToSign + "&Operation=" + service.Operation;
}
if (!string.IsNullOrEmpty(service.ItemId))
{
stringToSign = stringToSign + "&ItemId=" + service.ItemId;
}
if (!string.IsNullOrEmpty(service.IdType))
{
stringToSign = stringToSign + "&IdType=" + service.IdType;
}
if (service.ResponseGroup.Length > 0)
{
stringToSign = stringToSign + "&ResponseGroup=";
var lastResponse = service.ResponseGroup.Last();
foreach (var response in service.ResponseGroup)
{
stringToSign = stringToSign + response;
if (response != lastResponse)
{
stringToSign = stringToSign + ",";
}
}
}
stringToSign = stringToSign + "&Version=" + service.Version;
stringToSign = stringToSign + "&AWSAccessKeyId=" + service.AWSAccessKeyId + "&Timestamp=" + service.Timestamp;
stringToSign = stringToSign.Replace(",", "%2C");
stringToSign = stringToSign.Replace(":", "%3A");
service.Url = service.Url + stringToSign;
stringToSign = stringToSign + "&Service=AWSECommerceService";
service.Signature = HmacSha256.SignAmazonRequest(service.SecretKey, stringToSign);
service.Url = service.Url + "&Signature=" + service.Signature;
return service;
}
}
once the string is ready to be signed, i call a static mehod on a different class called HmacSha256.SignAmazonRequest where i pass my secretKey and the string to be signed,
public static class HmacSha256
{
public static string SignAmazonRequest(string secretKey, string request)
{
var stringToSign = PrepareSignatureEncryption(request);
var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
var hmacSha256 = new HMACSHA256(secretKeyBytes);
var hashBytes = hmacSha256.ComputeHash(bytesToSign);
return Convert.ToBase64String(hashBytes).Replace("+", "%2B").Replace("=", "%3D");
}
private static string PrepareSignatureEncryption(string request)
{
var header = "GET" + Environment.NewLine
+ "webservices.amazon.com" + Environment.NewLine
+ "/once/xml" + Environment.NewLine;
var result = header + request;
return result;
}
}
inside the SignAmazonRequest method, i first prepare the string as amazon wants it to be,
i have a private helper method called PrepareSignatureEncryption it takes the string to be signed as an argument, and returns a ready formatted string as amazon shows in their documentation, then convert the string to bytes, i convert the secret key to bytes, generating an HMACSHA256 based on the secret key bytes, with that i compute a hash for the string to sign, i return the bytes converted to base64 string,
now with all that, here is my code in the static void main.
class Program
{
static void Main(string[] args)
{
var restService = new AmazonRestService();
restService.Operation = "ItemLookup";
restService.IdType = "ASIN";
restService.ItemId = "ASINTOLOOKUP";
restService.ResponseGroup = new string[] { "BrowseNodes", "Images", "ItemAttributes", "Offers", "Reviews", "SalesRank" };
var signedRequest = restService.SignAmazonRequest(restService);
Console.WriteLine(signedRequest.Url);
Console.ReadLine();
try
{
var request = WebRequest.Create(signedRequest.Url);
var response = request.GetResponse();
var doc = new XmlDocument();
doc.Load(response.GetResponseStream());
doc.Save("C:/data.xml");
}
catch (Exception ex)
{
var msg = ex.Message;
}
}
}
i am following this documentation.
any idea where i go wrong?
Upvotes: 0
Views: 832
Reputation: 4275
The Documentation of Amazon is bad. But you can use this library Nager.AmazonProductAdvertising is available on nuget and github
PM> Install-Package Nager.AmazonProductAdvertising
Example
var authentication = new AmazonAuthentication();
authentication.AccessKey = "accesskey";
authentication.SecretKey = "secretkey";
var wrapper = new AmazonWrapper(authentication, AmazonEndpoint.US);
var result = wrapper.Search("canon eos", AmazonSearchIndex.Electronics, AmazonResponseGroup.Large);
Upvotes: 0