Sol Stein
Sol Stein

Reputation: 656

Amazon Product Affiliate REST API Integration

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

Answers (1)

live2
live2

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

Related Questions