【问题】
别人问的:
我看了您的如下文章,范例中的Browse Node IDs返回的都是amazon.com的资料。我要返回amazon.cn的资料,我用了帮助文档中CN的Browse Node IDs,但是报:“80207071(一个ID)is not a valid value for BrowseNodeId. Please change this value and retry your request.”。 |
即,尝试去访问amazon的中国的部分,即CN,即amazon的术语中的endpoint是cn。
【解决过程】
1.参考:
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/CHAP_WhatsNew.html
得知,当前用的,虽然不是最新的2011-08-02:
【记录】寻找AWSECommerceService的最新版本
但是,是比较新的,2011-08-01,其已经如上所述:
|
即,已经支持CN了。
2.用了默认的US的.com:
private static void cn_browseNodeLookupTest() { string _awsApiVersion = "2011-08-01"; string _awsDestination_cn = "ecs.amazonaws.com"; SignedRequestHelper helper_cn = new SignedRequestHelper( awsAccessKeyId, awsSecretKey, awsAssociateTag, _awsDestination_cn); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = _awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper_cn.Sign(reqDict); //WebRequest request = HttpWebRequest.Create(requestUrl); //WebResponse response = request.GetResponse(); //XmlDocument doc = new XmlDocument(); //doc.Load(response.GetResponseStream()); XmlDocument xmlDoc = new XmlDocument(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); req.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader sr; string charset = "UTF-8"; Encoding htmlEncoding = Encoding.GetEncoding(charset); sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string respHtml = sr.ReadToEnd(); sr.Close(); resp.Close(); xmlDoc.LoadXml(respHtml); System.Console.WriteLine(xmlDoc.InnerXml); }
返回xml是:
<BrowseNodeLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01"> <OperationRequest> <RequestId>c7fada9f-13da-4312-bcfb-10c16eb3d035</RequestId> <Arguments> <Argument Name="Operation" Value="BrowseNodeLookup"/> <Argument Name="Service" Value="AWSECommerceService"/> <Argument Name="Signature" Value="bD9/dUvxjPx63vIUHs+WeksSj9MPJUQ0fsLMlFiLbfE="/> <Argument Name="AssociateTag" Value="xxx"/> <Argument Name="Version" Value="2011-08-01"/> <Argument Name="BrowseNodeId" Value="80207071"/> <Argument Name="AWSAccessKeyId" Value="xxx"/> <Argument Name="Timestamp" Value="2013-06-22T07:39:39Z"/> <Argument Name="ResponseGroup" Value="BrowseNodeInfo"/> </Arguments> <RequestProcessingTime>0.011964</RequestProcessingTime> </OperationRequest> <BrowseNodes> <Request> <IsValid>True</IsValid> <BrowseNodeLookupRequest> <BrowseNodeId>80207071</BrowseNodeId> <ResponseGroup>BrowseNodeInfo</ResponseGroup> </BrowseNodeLookupRequest> <Errors> <Error> <Code>AWS.InvalidParameterValue</Code> <Message>80207071 is not a valid value for BrowseNodeId. Please change this value and retry your request.</Message> </Error> </Errors> </Request> </BrowseNodes> </BrowseNodeLookupResponse>
即,和预期的一样,是无效的id。
3.又去试了试,用.cn的:
private static void cn_browseNodeLookupTest() { string _awsApiVersion = "2011-08-01"; string _awsDestination_cn = "ecs.amazonaws.cn"; SignedRequestHelper helper_cn = new SignedRequestHelper( awsAccessKeyId, awsSecretKey, awsAssociateTag, _awsDestination_cn); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = _awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper_cn.Sign(reqDict); //WebRequest request = HttpWebRequest.Create(requestUrl); //WebResponse response = request.GetResponse(); //XmlDocument doc = new XmlDocument(); //doc.Load(response.GetResponseStream()); XmlDocument xmlDoc = new XmlDocument(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); req.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader sr; string charset = "UTF-8"; Encoding htmlEncoding = Encoding.GetEncoding(charset); sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string respHtml = sr.ReadToEnd(); sr.Close(); resp.Close(); xmlDoc.LoadXml(respHtml); System.Console.WriteLine(xmlDoc.InnerXml); }
结果更离谱,返回是看不懂的html内容:
<html><head></head><script type="text/javascript"> var s=String(window.location.href); var host=escape(s.substring(7,s.indexOf(‘/’,7))); var ref=escape(document.referrer); var su = s+"&host="+host+"&refer="+ref+"&server="+pp; s = escape(s); function loadfr(){ document.getElementById("fr1").src = sa+"3.htm?AIMT="+su; } function refreshPage(){ document.location = sa+"2.htm?AIMT="+su; } if (self.location == top.location){ document.location= sa+"1.htm?AIMT="+su; } else { refreshPage(); }</script><frameset rows="*,0"><frame id="main" src=""> <frame id="fr1" src=""></frameset><body></body></html> |
而不是xml,所以也会导致后面的:
xmlDoc.LoadXml(respHtml); |
报错的。
4.再去参考:
去试试那个
|
代码是:
private static void cn_browseNodeLookupTest() { string _awsApiVersion = "2011-08-01"; //string _awsDestination_cn = "ecs.amazonaws.com"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/AnatomyOfaRESTRequest.html#EndpointsandWebServices string _awsDestination_cn = "webservices.amazon.cn"; SignedRequestHelper helper_cn = new SignedRequestHelper( awsAccessKeyId, awsSecretKey, awsAssociateTag, _awsDestination_cn); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = _awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper_cn.Sign(reqDict); //WebRequest request = HttpWebRequest.Create(requestUrl); //WebResponse response = request.GetResponse(); //XmlDocument doc = new XmlDocument(); //doc.Load(response.GetResponseStream()); XmlDocument xmlDoc = new XmlDocument(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); req.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader sr; string charset = "UTF-8"; Encoding htmlEncoding = Encoding.GetEncoding(charset); sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string respHtml = sr.ReadToEnd(); sr.Close(); resp.Close(); xmlDoc.LoadXml(respHtml); System.Console.WriteLine(xmlDoc.InnerXml); }
结果是就可以了:
<BrowseNodeLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01"> <OperationRequest> <RequestId>88394147-043d-4a5f-bb9d-6958b61b9da8</RequestId> <Arguments> <Argument Name="Operation" Value="BrowseNodeLookup"/> <Argument Name="Service" Value="AWSECommerceService"/> <Argument Name="Signature" Value="ovanQqg0HvvAD0d6qdANILaOwQANGBvjmhCKgtpl/kQ="/> <Argument Name="AssociateTag" Value="xxx"/> <Argument Name="Version" Value="2011-08-01"/> <Argument Name="BrowseNodeId" Value="80207071"/> <Argument Name="AWSAccessKeyId" Value="xxx"/> <Argument Name="Timestamp" Value="2013-06-22T07:42:31Z"/> <Argument Name="ResponseGroup" Value="BrowseNodeInfo"/> </Arguments> <RequestProcessingTime>0.001642</RequestProcessingTime> </OperationRequest> <BrowseNodes> <Request> <IsValid>True</IsValid> <BrowseNodeLookupRequest> <BrowseNodeId>80207071</BrowseNodeId> <ResponseGroup>BrowseNodeInfo</ResponseGroup> </BrowseNodeLookupRequest> </Request> <BrowseNode> <BrowseNodeId>80207071</BrowseNodeId> <Name>大家电</Name> <Children> <BrowseNode> <BrowseNodeId>80208071</BrowseNodeId> <Name>类别</Name> <IsCategoryRoot>1</IsCategoryRoot> </BrowseNode> <BrowseNode> <BrowseNodeId>80209071</BrowseNodeId> <Name>特色</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81230071</BrowseNodeId> <Name>推荐分类</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81231071</BrowseNodeId> <Name>Self Service</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81232071</BrowseNodeId> <Name>筛选</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>83190071</BrowseNodeId> <Name>Archive</Name> </BrowseNode> </Children> </BrowseNode> </BrowseNodes> </BrowseNodeLookupResponse>
不光是可以正常返回对应的BrowseNodeId,而且也是对应的中文的。
5.另外,顺带也去测了测2011-08-02版本的API:
private static void cn_browseNodeLookupTest() { //string _awsApiVersion = "2011-08-01"; //【记录】寻找AWSECommerceService的最新版本 //http://www.crifan.com/find_awsecommerceservice_latest_version //http://aws.amazon.com/releasenotes/Product-Advertising-API/7764190151051019 string _awsApiVersion = "2011-08-02"; //string _awsDestination_cn = "ecs.amazonaws.com"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/AnatomyOfaRESTRequest.html#EndpointsandWebServices string _awsDestination_cn = "webservices.amazon.cn"; SignedRequestHelper helper_cn = new SignedRequestHelper( awsAccessKeyId, awsSecretKey, awsAssociateTag, _awsDestination_cn); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = _awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper_cn.Sign(reqDict); //WebRequest request = HttpWebRequest.Create(requestUrl); //WebResponse response = request.GetResponse(); //XmlDocument doc = new XmlDocument(); //doc.Load(response.GetResponseStream()); XmlDocument xmlDoc = new XmlDocument(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); req.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader sr; string charset = "UTF-8"; Encoding htmlEncoding = Encoding.GetEncoding(charset); sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string respHtml = sr.ReadToEnd(); sr.Close(); resp.Close(); xmlDoc.LoadXml(respHtml); System.Console.WriteLine(xmlDoc.InnerXml); }
结果是
<BrowseNodeLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01"> <OperationRequest> <RequestId>333bac99-0f9b-40b1-8182-1335ccd84c18</RequestId> <Arguments> <Argument Name="Operation" Value="BrowseNodeLookup"/> <Argument Name="Service" Value="AWSECommerceService"/> <Argument Name="Signature" Value="GrlWTbhkfwnAYQm4ui7+9BZLDoBclX89ZDZZmU3YZ6Q="/> <Argument Name="AssociateTag" Value="xxx"/> <Argument Name="Version" Value="2011-08-02"/> <Argument Name="BrowseNodeId" Value="80207071"/> <Argument Name="AWSAccessKeyId" Value="xxx"/> <Argument Name="Timestamp" Value="2013-06-22T07:45:44Z"/> <Argument Name="ResponseGroup" Value="BrowseNodeInfo"/> </Arguments> <RequestProcessingTime>0.002016</RequestProcessingTime> </OperationRequest> <BrowseNodes> <Request> <IsValid>True</IsValid> <BrowseNodeLookupRequest> <BrowseNodeId>80207071</BrowseNodeId> <ResponseGroup>BrowseNodeInfo</ResponseGroup> </BrowseNodeLookupRequest> </Request> <BrowseNode> <BrowseNodeId>80207071</BrowseNodeId> <Name>大家电</Name> <Children> <BrowseNode> <BrowseNodeId>80208071</BrowseNodeId> <Name>类别</Name> <IsCategoryRoot>1</IsCategoryRoot> </BrowseNode> <BrowseNode> <BrowseNodeId>80209071</BrowseNodeId> <Name>特色</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81230071</BrowseNodeId> <Name>推荐分类</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81231071</BrowseNodeId> <Name>Self Service</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>81232071</BrowseNodeId> <Name>筛选</Name> </BrowseNode> <BrowseNode> <BrowseNodeId>83190071</BrowseNodeId> <Name>Archive</Name> </BrowseNode> </Children> </BrowseNode> </BrowseNodes> </BrowseNodeLookupResponse>
即,和以前用2011-08-02访问.com的效果一样:
虽然你用的是2011-08-02,但是返回结果却是2011-08-01,直接被服务器无视了。。。
【总结】
如果想要正常访问对应的CN版本的AWS的API的话,则要:
1.使用正确的endpoint,此处对于CN的是:
http://webservices.amazon.cn/onca/xml |
或:
https://webservices.amazon.cn/onca/xml |
注意:
(1)之前参考官网的代码,用的是(估计是旧的)基于
ecs.amazonaws.com |
而改成CN版本的:
ecs.amazonaws.cn |
结果是无效的。
最新的值,都还是参考官网最新的,关于各种endpoint的解释
中的:
|
2.然后再用最新的API,此处即2011-08-01。
注意:
(1)即使你用,我之前去调查到的:
【记录】寻找AWSECommerceService的最新版本
最新的2011-08-02,结果服务器也不认,还是返回给你2011-08-01的结果。
3. 此处附上完整的代码:
(1)SignedRequestHelper.cs
/*
* [Function]
* Implement Amazon AWS API, focus on ItemLookup, ItemSearch, BrowseNodeLookup
* code based on:
* Product Advertising API Signed Requests Sample Code - C# REST/QUERY
* http://aws.amazon.com/code/Product-Advertising-API/2480
* ->
* http://associates-amazon.s3.amazonaws.com/signed-requests/samples/amazon-product-advt-api-sample-csharp-query.zip
*
* [Author]
* Crifan Li
*
* [Date]
* 2013-06-13
*
* [Contact]
* http://www.crifan.com/contact_me/
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Security.Cryptography;
namespace AmazonProductAdvtApi
{
class SignedRequestHelper
{
private string endPoint;
private string akid;
//added by Crifan Li
//https://affiliate-program.amazon.co.uk/gp/advertising/api/detail/api-changes.html?ie=UTF8&pf_rd_t=501&ref_=amb_link_83388313_2&pf_rd_m=A3P5ROKL5A1OLE&pf_rd_p=&pf_rd_s=assoc-center-1&pf_rd_r=&pf_rd_i=assoc-api-detail-2-v2
//Product Advertising API Change Details
//Associate Tag Parameter: Every request made to the API should include a valid Associate Tag. Any request that does not contain a valid Associate Tag will be rejected with an appropriate error message. For details on the Associate Tag parameter, please refer to our Developer guide.
//-> must add this Associate Tag, otherwise will return:
//<Error>
// <Code>AWS.MissingParameters</Code>
// <Message>Your request is missing required parameters. Required parameters include AssociateTag.</Message>
//</Error>
private string associateTag;
private byte[] secret;
private HMAC signer;
private const string REQUEST_URI = "/onca/xml";
private const string REQUEST_METHOD = "GET";
/*
* Use this constructor to create the object. The AWS credentials are available on
* http://aws.amazon.com
*
* The destination is the service end-point for your application:
* US: ecs.amazonaws.com
* JP: ecs.amazonaws.jp
* UK: ecs.amazonaws.co.uk
* DE: ecs.amazonaws.de
* FR: ecs.amazonaws.fr
* CA: ecs.amazonaws.ca
*/
public SignedRequestHelper(string awsAccessKeyId, string awsSecretKey, string awsAssociateTag, string destination)
{
this.endPoint = destination.ToLower();
this.akid = awsAccessKeyId;
//added by Crifan Li
this.associateTag = awsAssociateTag;
this.secret = Encoding.UTF8.GetBytes(awsSecretKey);
this.signer = new HMACSHA256(this.secret);
}
/*
* Sign a request in the form of a Dictionary of name-value pairs.
*
* This method returns a complete URL to use. Modifying the returned URL
* in any way invalidates the signature and Amazon will reject the requests.
*/
public string Sign(IDictionary<string, string> request)
{
// Use a SortedDictionary to get the parameters in naturual byte order, as
// required by AWS.
ParamComparer pc = new ParamComparer();
SortedDictionary<string, string> sortedMap = new SortedDictionary<string, string>(request, pc);
// Add the AWSAccessKeyId and Timestamp to the requests.
sortedMap["AWSAccessKeyId"] = this.akid;
//added by Crifan Li
sortedMap["AssociateTag"] = this.associateTag;
sortedMap["Timestamp"] = this.GetTimestamp();
// Get the canonical query string
string canonicalQS = this.ConstructCanonicalQueryString(sortedMap);
// Derive the bytes needs to be signed.
StringBuilder builder = new StringBuilder();
builder.Append(REQUEST_METHOD)
.Append("\n")
.Append(this.endPoint)
.Append("\n")
.Append(REQUEST_URI)
.Append("\n")
.Append(canonicalQS);
string stringToSign = builder.ToString();
byte[] toSign = Encoding.UTF8.GetBytes(stringToSign);
// Compute the signature and convert to Base64.
byte[] sigBytes = signer.ComputeHash(toSign);
string signature = Convert.ToBase64String(sigBytes);
// now construct the complete URL and return to caller.
StringBuilder qsBuilder = new StringBuilder();
qsBuilder.Append("http://")
.Append(this.endPoint)
.Append(REQUEST_URI)
.Append("?")
.Append(canonicalQS)
.Append("&Signature=")
.Append(this.PercentEncodeRfc3986(signature));
return qsBuilder.ToString();
}
/*
* Sign a request in the form of a query string.
*
* This method returns a complete URL to use. Modifying the returned URL
* in any way invalidates the signature and Amazon will reject the requests.
*/
public string Sign(string queryString)
{
IDictionary<string, string> request = this.CreateDictionary(queryString);
return this.Sign(request);
}
/*
* Current time in IS0 8601 format as required by Amazon
*/
private string GetTimestamp()
{
DateTime currentTime = DateTime.UtcNow;
string timestamp = currentTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
return timestamp;
}
/*
* Percent-encode (URL Encode) according to RFC 3986 as required by Amazon.
*
* This is necessary because .NET's HttpUtility.UrlEncode does not encode
* according to the above standard. Also, .NET returns lower-case encoding
* by default and Amazon requires upper-case encoding.
*/
private string PercentEncodeRfc3986(string str)
{
str = HttpUtility.UrlEncode(str, System.Text.Encoding.UTF8);
str = str.Replace("'", "%27").Replace("(", "%28").Replace(")", "%29").Replace("*", "%2A").Replace("!", "%21").Replace("%7e", "~").Replace("+", "%20");
StringBuilder sbuilder = new StringBuilder(str);
for (int i = 0; i < sbuilder.Length; i++)
{
if (sbuilder[i] == '%')
{
if (Char.IsLetter(sbuilder[i + 1]) || Char.IsLetter(sbuilder[i + 2]))
{
sbuilder[i + 1] = Char.ToUpper(sbuilder[i + 1]);
sbuilder[i + 2] = Char.ToUpper(sbuilder[i + 2]);
}
}
}
return sbuilder.ToString();
}
/*
* Convert a query string to corresponding dictionary of name-value pairs.
*/
private IDictionary<string, string> CreateDictionary(string queryString)
{
Dictionary<string, string> map = new Dictionary<string, string>();
string[] requestParams = queryString.Split('&');
for (int i = 0; i < requestParams.Length; i++)
{
if (requestParams[i].Length < 1)
{
continue;
}
char[] sep = { '=' };
string[] param = requestParams[i].Split(sep, 2);
for (int j = 0; j < param.Length; j++)
{
param[j] = HttpUtility.UrlDecode(param[j], System.Text.Encoding.UTF8);
}
switch (param.Length)
{
case 1:
{
if (requestParams[i].Length >= 1)
{
if (requestParams[i].ToCharArray()[0] == '=')
{
map[""] = param[0];
}
else
{
map[param[0]] = "";
}
}
break;
}
case 2:
{
if (!string.IsNullOrEmpty(param[0]))
{
map[param[0]] = param[1];
}
}
break;
}
}
return map;
}
/*
* Consttuct the canonical query string from the sorted parameter map.
*/
private string ConstructCanonicalQueryString(SortedDictionary<string, string> sortedParamMap)
{
StringBuilder builder = new StringBuilder();
if (sortedParamMap.Count == 0)
{
builder.Append("");
return builder.ToString();
}
foreach (KeyValuePair<string, string> kvp in sortedParamMap)
{
builder.Append(this.PercentEncodeRfc3986(kvp.Key));
builder.Append("=");
builder.Append(this.PercentEncodeRfc3986(kvp.Value));
builder.Append("&");
}
string canonicalString = builder.ToString();
canonicalString = canonicalString.Substring(0, canonicalString.Length - 1);
return canonicalString;
}
}
/*
* To help the SortedDictionary order the name-value pairs in the correct way.
*/
class ParamComparer : IComparer<string>
{
public int Compare(string p1, string p2)
{
return string.CompareOrdinal(p1, p2);
}
}
}
(2)ItemLookupSample.cs
/* * [Function] * Implement Amazon AWS API, focus on ItemLookup, ItemSearch, BrowseNodeLookup * code based on: * Product Advertising API Signed Requests Sample Code - C# REST/QUERY * http://aws.amazon.com/code/Product-Advertising-API/2480 * -> * http://associates-amazon.s3.amazonaws.com/signed-requests/samples/amazon-product-advt-api-sample-csharp-query.zip * * [Author] * Crifan Li * * [Date] * 2013-06-20 * * [Contact] * http://www.crifan.com/contact_me/ */ using System; using System.Collections.Generic; using System.Text; using System.Net; using System.IO; using System.Xml; using System.Xml.XPath; namespace AmazonProductAdvtApi { class ItemLookupSample { //【记录】申请AWS的AWSAccessKeyId(AWS Access Key ID) //http://www.crifan.com/apply_aws_access_key_id/ private const string awsAccessKeyId = "change to your access key id"; private const string awsSecretKey = "change to your secret key"; private const string awsAssociateTag = "change to your associate tag"; private const string awsDestination = "ecs.amazonaws.com"; //【记录】寻找AWSECommerceService的最新版本 //http://www.crifan.com/find_awsecommerceservice_latest_version //http://aws.amazon.com/releasenotes/Product-Advertising-API/7764190151051019 //private const string awsApiVersion = "2011-08-02"; private const string awsApiVersion = "2011-08-01"; //private const string NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/2009-03-31"; //private const string NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/2011-08-01"; private const string NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/" + awsApiVersion; //private const string ITEM_ID = "0545010225"; //private const string ITEM_ID = "B0083PWAPW"; //<Item> // <ASIN>B0083PWAPW</ASIN> // <ParentASIN>B008GGCAVM</ParentASIN> //</Item> private const string ITEM_ID = "B008GGCAVM"; private static void itemSearchTest(SignedRequestHelper helper) { /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = awsApiVersion; reqDict["Operation"] = "ItemSearch"; //reqDict["SearchIndex"] = "None"; reqDict["SearchIndex"] = "HomeGarden"; reqDict["ResponseGroup"] = "ItemIds"; //Home & Kitchen -> Heating, Cooling & Air Quality -> Air Conditioners & Accessories -> Energy Star Qualified //reqDict["BrowseNodeId"] = "3737761"; reqDict["BrowseNode"] = "3737761"; reqDict["ItemPage"] = "6"; String requestUrl = helper.Sign(reqDict); WebRequest request = HttpWebRequest.Create(requestUrl); WebResponse response = request.GetResponse(); XmlDocument doc = new XmlDocument(); doc.Load(response.GetResponseStream()); //for debug System.Console.WriteLine(doc.InnerXml); } private static void browseNodeLookupTest(SignedRequestHelper helper) { /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //2619525011 -> Appliances //reqDict["BrowseNodeId"] = "2619525011"; //<BrowseNodeId>2619525011</BrowseNodeId> //<Name>Appliances</Name> //<Children> // <BrowseNode> // <BrowseNodeId>2619526011</BrowseNodeId> // <Name>Categories</Name> // <IsCategoryRoot>1</IsCategoryRoot> // </BrowseNode> //reqDict["BrowseNodeId"] = "2619526011"; //<Children> // <BrowseNode> // <BrowseNodeId>3737671</BrowseNodeId> // <Name>Air Conditioners</Name> // </BrowseNode> //reqDict["BrowseNodeId"] = "3737671"; //<BrowseNode> // <BrowseNodeId>3737671</BrowseNodeId> // <Name>Air Conditioners & Accessories</Name> // <Children> // <BrowseNode> // <BrowseNodeId>3737761</BrowseNodeId> // <Name>Energy Star Qualified</Name> // </BrowseNode> //reqDict["BrowseNodeId"] = "3737761"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper.Sign(reqDict); WebRequest request = HttpWebRequest.Create(requestUrl); WebResponse response = request.GetResponse(); XmlDocument doc = new XmlDocument(); doc.Load(response.GetResponseStream()); //for debug System.Console.WriteLine(doc.InnerXml); } private static void cn_browseNodeLookupTest() { string _awsApiVersion = "2011-08-01"; //【记录】寻找AWSECommerceService的最新版本 //http://www.crifan.com/find_awsecommerceservice_latest_version //http://aws.amazon.com/releasenotes/Product-Advertising-API/7764190151051019 //string _awsApiVersion = "2011-08-02"; //string _awsDestination_cn = "ecs.amazonaws.com"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/AnatomyOfaRESTRequest.html#EndpointsandWebServices string _awsDestination_cn = "webservices.amazon.cn"; SignedRequestHelper helper_cn = new SignedRequestHelper( awsAccessKeyId, awsSecretKey, awsAssociateTag, _awsDestination_cn); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; reqDict["Version"] = _awsApiVersion; reqDict["Operation"] = "BrowseNodeLookup"; //http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html //for CN: Appliances -> 80207071 reqDict["BrowseNodeId"] = "80207071"; reqDict["ResponseGroup"] = "BrowseNodeInfo"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; requestUrl = helper_cn.Sign(reqDict); //WebRequest request = HttpWebRequest.Create(requestUrl); //WebResponse response = request.GetResponse(); //XmlDocument doc = new XmlDocument(); //doc.Load(response.GetResponseStream()); XmlDocument xmlDoc = new XmlDocument(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestUrl); req.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); StreamReader sr; string charset = "UTF-8"; Encoding htmlEncoding = Encoding.GetEncoding(charset); sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string respHtml = sr.ReadToEnd(); sr.Close(); resp.Close(); xmlDoc.LoadXml(respHtml); System.Console.WriteLine(xmlDoc.InnerXml); } public static void Main() { SignedRequestHelper helper = new SignedRequestHelper(awsAccessKeyId, awsSecretKey, awsAssociateTag, awsDestination); //itemSearchTest(helper); //browseNodeLookupTest(helper); cn_browseNodeLookupTest(); /* * Here is an ItemLookup example where the request is stored as a dictionary. */ IDictionary<string, string> reqDict = new Dictionary<string, String>(); reqDict["Service"] = "AWSECommerceService"; //r1["Version"] = "2009-03-31"; //r1["Version"] = "2009-03-31"; //reqDict["Version"] = "2011-08-02"; reqDict["Version"] = "2011-08-01"; reqDict["Operation"] = "ItemLookup"; reqDict["IdType"] = "ASIN"; //reqDict["ItemId"] = ITEM_ID; string asin = "B004ZGN6MY"; //string asin = "B00008OE6I"; reqDict["ItemId"] = asin; //reqDict["ResponseGroup"] = "Small"; //reqDict["ResponseGroup"] = "OfferSummary"; //reqDict["ResponseGroup"] = "ItemAttributes"; //reqDict["ResponseGroup"] = "VariationSummary"; //reqDict["ResponseGroup"] = "Variations"; reqDict["ResponseGroup"] = "Accessories"; /* * The helper supports two forms of requests - dictionary form and query string form. */ String requestUrl; String title; requestUrl = helper.Sign(reqDict); title = FetchTitle(requestUrl); System.Console.WriteLine("Method 1: ItemLookup Dictionary form."); System.Console.WriteLine("Title is \"" + title + "\""); System.Console.WriteLine(); } private static string FetchTitle(string url) { try { WebRequest request = HttpWebRequest.Create(url); WebResponse response = request.GetResponse(); XmlDocument doc = new XmlDocument(); doc.Load(response.GetResponseStream()); //for debug System.Console.WriteLine(doc.InnerXml); XmlNodeList errorMessageNodes = doc.GetElementsByTagName("Message", NAMESPACE); if (errorMessageNodes != null && errorMessageNodes.Count > 0) { String message = errorMessageNodes.Item(0).InnerText; return "Error: " + message + " (but signature worked)"; } XmlNode titleNode = doc.GetElementsByTagName("Title", NAMESPACE).Item(0); string title = titleNode.InnerText; response.Close(); return title; } catch (Exception e) { System.Console.WriteLine("Caught Exception: " + e.Message); System.Console.WriteLine("Stack Trace: " + e.StackTrace); } return null; } } }
然后换成自己的awsAccessKeyId,awsSecretKey,awsAssociateTag,直接拿去用即可。
原文http://www.crifan.com/how_to_use_amzon_aws_api_cn_version/