Amazon Product Affiliate REST API集成

时间:2016-03-04 15:05:18

标签: c# api rest amazon-web-services

我正在尝试与Amazon Product Affiliate REST API集成,我拒绝使用SOAP集成,请不要在这里调出Soap,我想使用REST,我使用的是最新的API版本,这是08/01/2013我按照文档,不知怎的,我总是回到403禁止错误,我已经看了遍地,我唯一看到的是,对亚马逊过时的样品感到生气,所以我没有让我的集成工作感到沮丧,这是我使用的规范。

VS 2015 面向.NET 4.5.2的控制台应用程序 亚马逊Api版本08/01/2013

这是我的代码库。

我有一个名为AmazonRestService的类 它具有ItemLookup所需的所有属性,

在构造函数中我设置了一些属性,这是每个请求的默认属性,然后我有一个名为SignAmazonRequest的方法 将AmazonRestService作为参数,我检查所有具有值的字段,我填写需要签名的字符串,



 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;

        }

    }




一旦字符串准备好被签名,我就在另一个名为HmacSha256.SignAmazonRequest的类上调用静态方法 我传递secretKey和要签名的字符串,



    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;
        }
    }




在SignAmazonRequest方法中,我首先按照亚马逊想要的那样准备字符串,

我有一个名为PrepareSignatureEncryption的私有帮助方法 它将字符串作为参数进行签名,并返回一个准备好格式化的字符串,如amazon在其文档中所示, 然后将字符串转换为字节, 我将密钥转换为字节, 根据密钥字节生成HMACSHA256, 用它来计算要签名的字符串的哈希值, 我返回转换为base64字符串的字节,

现在有了这一切,这是我在静态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;
            }
        }
    }




我关注this documentation

我知道哪里出错了?

1 个答案:

答案 0 :(得分:0)

亚马逊的文档很糟糕。但您可以使用此库Nager.AmazonProductAdvertising可在nugetgithub上找到

PM> Install-Package Nager.AmazonProductAdvertising

示例

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);