3

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

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

并得到以下错误

请求必须包含参数签名。

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

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

谢谢

4

3 回答 3

3

我转录了这个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);
于 2013-12-07T15:43:03.337 回答
2

REST 有一个帮助程序类,称为 SignedRequestHelper。

你这样称呼它:

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

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

于 2011-04-26T19:38:02.820 回答
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.)行为标签 -> 端点行为标签 -> 行为标签 -> 签名行为标签;分配 accessKeyId 和 secretKey 值。 (3.) bindings 标签 -> basicHttpBinding 标签;(可选)删除除 AWSECommerceServiceBindingNoTransport 和 AWSECommerceServiceBindingTransport 之外的绑定标签。 (4.)客户标签;删除除 AWSECommerceServiceBindingTransport 之外的终端节点标签。

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

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

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

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

于 2012-05-24T08:49:10.460 回答