亚马逊产品广告API签名问题

我正在尝试使用以下代码在amazon web services示例代码页中搜索亚马逊产品数据库

AWSECommerceService ecs = new AWSECommerceService(); // Create ItemSearch wrapper ItemSearch search = new ItemSearch(); search.AssociateTag = "ABC"; search.AWSAccessKeyId = "XYZ"; // Create a request object ItemSearchRequest request = new ItemSearchRequest(); // Fill request object with request parameters request.ResponseGroup = new string[] { "ItemAttributes" }; // Set SearchIndex and Keywords request.SearchIndex = "All"; request.Keywords = "The Shawshank Redemption"; // Set the request on the search wrapper search.Request = new ItemSearchRequest[] { request }; try { //Send the request and store the response //in response ItemSearchResponse response = ecs.ItemSearch(search); gvRes.DataSource = response.Items; } catch (Exception ex) { divContent.InnerText = ex.Message; } 

并得到以下错误

请求必须包含参数Signature。

和amazon文档不清楚如何签署请求。

任何想法如何让它工作???

谢谢

有一个名为SignedRequestHelper的REST辅助类。

你这样称呼它:

 SignedRequestHelper helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION); requestUrl = helper.Sign(querystring); 

在上面的链接中,SOAP调用必须有类似的一个。

我转录了这个 vb代码,它对我有用

添加服务引用并将其命名为Amazon

 http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl 

进入托管项目的文件夹,打开服务引用文件夹并打开Reference.cs,然后将[] []的所有实例替换为[],然后打开AWSECommerceService.wsdl并查找

  

并替换为

  

添加以下内容,您需要手动引用一些dll

 using System.Security.Cryptography; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.ServiceModel.Description; using System.Text.RegularExpressions; using System.Xml; using System.IO; using System.Runtime.Serialization; using AmazonApiTest.Amazon; //instead of AmazonApiTest use your project name 

首先是各种接口实现

 public class AmazonSigningMessageInspector : IClientMessageInspector { private string accessKeyId = ""; private string secretKey = ""; public AmazonSigningMessageInspector(string accessKeyId, string secretKey) { this.accessKeyId = accessKeyId; this.secretKey = secretKey; } public Object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) { string operation = Regex.Match(request.Headers.Action, "[^/]+$").ToString(); DateTime now = DateTime.UtcNow; String timestamp = now.ToString("yyyy-MM-ddTHH:mm:ssZ"); String signMe = operation + timestamp; Byte[] bytesToSign = Encoding.UTF8.GetBytes(signMe); Byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey); HMAC hmacSha256 = new HMACSHA256(secretKeyBytes); Byte[] hashBytes = hmacSha256.ComputeHash(bytesToSign); String signature = Convert.ToBase64String(hashBytes); request.Headers.Add(new AmazonHeader("AWSAccessKeyId", accessKeyId)); request.Headers.Add(new AmazonHeader("Timestamp", timestamp)); request.Headers.Add(new AmazonHeader("Signature", signature)); return null; } void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message Message, Object correlationState) { } } public class AmazonSigningEndpointBehavior : IEndpointBehavior { private string accessKeyId = ""; private string secretKey = ""; public AmazonSigningEndpointBehavior(string accessKeyId, string secretKey) { this.accessKeyId = accessKeyId; this.secretKey = secretKey; } public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) { clientRuntime.ClientMessageInspectors.Add(new AmazonSigningMessageInspector(accessKeyId, secretKey)); } public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatched) { } public void Validate(ServiceEndpoint serviceEndpoint) { } public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParemeters) { } } public class AmazonHeader : MessageHeader { private string m_name; private string value; public AmazonHeader(string name, string value) { this.m_name = name; this.value = value; } public override string Name { get { return m_name; } } public override string Namespace { get { return "http://security.amazonaws.com/doc/2007-01-01/"; } } protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteString(value); } } 

现在你以这种方式使用生成的代码

 ItemSearch search = new ItemSearch(); search.AssociateTag = "YOUR ASSOCIATE TAG"; search.AWSAccessKeyId = "YOUR AWS ACCESS KEY ID"; ItemSearchRequest req = new ItemSearchRequest(); req.ResponseGroup = new string[] { "ItemAttributes" }; req.SearchIndex = "Books"; req.Author = "Lansdale"; req.Availability = ItemSearchRequestAvailability.Available; search.Request = new ItemSearchRequest[]{req}; Amazon.AWSECommerceServicePortTypeClient amzwc = new Amazon.AWSECommerceServicePortTypeClient(); amzwc.ChannelFactory.Endpoint.EndpointBehaviors.Add(new AmazonSigningEndpointBehavior("ACCESS KEY", "SECRET KEY")); ItemSearchResponse resp = amzwc.ItemSearch(search); foreach (Item item in resp.Items[0].Item) Console.WriteLine(item.ItemAttributes.Author[0] + " - " + item.ItemAttributes.Title); 

尝试这个..我希望它会帮助..我尝试它的工作..请与他人分享。

下载http://www.falconwebtech.com/post/Using-WCF-and-SOAP-to-Send-Amazon-Product-Advertising-API-Signed-Requests上的示例代码

我们需要更新服务引用,在app.config,program.cs和reference.cs上做一点改动。

app.config 🙁 1.) appSettings标签; 分配accessKeyId和secretKey值,添加。 (2.)行为标签 – > endpointBehaviors标签 – >行为标签 – > signingBehavior标签; 分配accessKeyId和secretKey值。 (3.) bindings tag – > basicHttpBinding标签; (可选)删除除AWSECommerceServiceBindingNoTransport和AWSECommerceServiceBindingTransport之外的绑定标记。 (4.)客户标签; 删除除AWSECommerceServiceBindingTransport之外的端点标记。

program.cs: add itemSearch.AssociateTag = ConfigurationManager.AppSettings [“associateTag”]; 在ItemSearchResponse response = amazonClient.ItemSearch(itemSearch)之前;

reference.cs 🙁使用visual studio在服务引用文件夹中打开文件) 更改私有ImageSet [] [] imageSetsField; 私人ImageSet [] imageSetsField; public ImageSet [] [] ImageSets {…}更改为public ImageSet [] ImageSets {…}

最后我们可以运行我们的程序,它会工作。 祝好运..

nb:会有1个警告(无效的子元素签名行为),我想我们可以忽略它,或者如果你有任何解决方案请分享.. ^^ v ..