我正在尝试与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;
}
}
}

我知道哪里出错了?
答案 0 :(得分:0)
亚马逊的文档很糟糕。但您可以使用此库Nager.AmazonProductAdvertising可在nuget和github上找到
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);