[英]Amazon Product Advertising API Signing Issues
我正在嘗試使用以下代碼在亞馬遜網絡服務示例代碼頁中搜索亞馬遜產品數據庫
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文檔不清楚如何簽署請求。
任何想法如何讓它工作???
謝謝
我轉錄了這個 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);
有一個名為SignedRequestHelper的REST輔助類。
你這樣稱呼它:
SignedRequestHelper helper =
new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
requestUrl = helper.Sign(querystring);
在上面的鏈接中,SOAP調用必須有類似的一個。
嘗試這個...我希望它會幫助..我嘗試它的工作..請與他人分享。
我們需要更新服務引用,在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 ..
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.