【问题标题】:Amazon Product Advertising API Signing Issues亚马逊产品广告 API 签名问题
【发布时间】:2011-04-26 16:02:32
【问题描述】:

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

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

并得到以下错误

请求必须包含参数 签名。

亚马逊文档并不清楚如何签署请求。

知道如何让它工作吗???

谢谢

【问题讨论】:

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


【解决方案1】:

我转录了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);

【讨论】:

    【解决方案2】:

    有一个用于 REST 的帮助器类,称为 SignedRequestHelper。

    你这样称呼它:

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

    上述链接中的 SOAP 调用肯定有类似的。

    【讨论】:

    • 谁能告诉我从哪里得到这个SignedRequestHelper 课程?在 C#...
    【解决方案3】:

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

    在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.) 行为标签 -> 端点行为标签 -> 行为标签 -> 签名行为标签; 分配 accessKeyId 和 secretKey 值。 (3.) 绑定标签 -> basicHttpBinding 标签; (可选的) 删除除 AWSECommerceServiceBindingNoTransport 之外的绑定标签 和 AWSECommerceServiceBindingTransport。 (4.) 客户标签; 删除 AWSECommerceServiceBindingTransport 以外的端点标签。

    program.cs: 添加 itemSearch.AssociateTag = ConfigurationManager.AppSettings["associateTag"];在 ItemSearchResponse 响应之前 = amazonClient.ItemSearch(itemSearch);

    reference.cs:(使用 Visual Studio 在服务引用文件夹中打开文件) 更改 private ImageSet[][] imageSetsField;私有 ImageSet[] imageSetsField; 更改 public ImageSet[][] ImageSets {...} 为 public ImageSet[] ImageSets {...}

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多