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

时间:2011-04-26 16:02:32

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

我正在尝试使用以下代码在亚马逊网络服务示例代码页中搜索亚马逊产品数据库

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

并收到以下错误

  

请求必须包含参数   签名。

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

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

THX

3 个答案:

答案 0 :(得分:3)

我转录了this vb代码,它适用于我

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

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

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

<xs:element minOccurs="0" maxOccurs="unbounded" name="ImageSets">

并替换为

<xs:element minOccurs="0" maxOccurs="1" name="ImageSets">

添加以下内容,您需要手动引用一些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);

答案 1 :(得分:2)

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

你这样称呼它:

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

上述链接中的SOAP调用必须有类似的。

答案 2 :(得分:1)

尝试这个..我希望它会有所帮助..我尝试它有效..请与他人分享。

下载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。)行为标记 - &gt; endpointBehaviors标记 - &gt;行为标签 - &gt; signingBehavior标签;   分配accessKeyId和secretKey值。 (3。)绑定标记 - &gt; 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 {...}到公共ImageSet [] ImageSets {...}

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

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