【问题标题】:Amazon Product Affiliate REST API Integration亚马逊产品附属 REST API 集成
【发布时间】:2016-03-04 15:05:17
【问题描述】:

我正在尝试与 Amazon Product Affiliate REST API 集成,我拒绝使用 SOAP 集成,请不要在此处提出 Soap,我要使用 REST,我使用的是最新的 API 版本,是 2013 年 8 月 1 日,我按照文档进行操作,不知何故,我总是返回 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 的私有辅助方法 它将要签名的字符串作为参数,并返回一个准备好的格式化字符串,如亚马逊在其文档中显示的那样, 然后将字符串转换为字节, 我将密钥转换为字节, 根据密钥字节生成 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

知道我哪里出错了吗?

【问题讨论】:

  • 我尝试了webservices.amazon.com/scratchpad/index.html,一切正常,我试图在我的代码中获取它,具有相同的时间戳,并且一切看起来与暂存器上的完全一样,按字节排序,并且签名仍然不同,有人对此有所了解吗?

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


【解决方案1】:

亚马逊的文档很糟糕。但是你可以使用这个库 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 2017-08-11
    • 2013-08-04
    • 2013-07-06
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    相关资源
    最近更新 更多