C# //将AWSAccessKeyId和时间戳添加到请求中。 sortedMap[“AWSAccessKeyId”]=this.akid; sortedMap[“Timestamp”]=this.GetTimestamp(); //获取规范查询字符串 字符串canonicalQS=this.constructionCanonicalQueryString(sortedMap); //派生需要签名的字节。 StringBuilder=新的StringBuilder(); builder.Append(请求\方法) .Append(“\n”) .Append(this.endPoint) .Append(“\n”) .Append(请求\ URI) .Append(“\n”) .附加(规范); 字符串stringToSign=builder.ToString(); 字节[]toSign=Encoding.UTF8.GetBytes(stringToSign); //计算签名并转换为Base64。 字节[]sigBytes=signer.ComputeHash(toSign); 字符串签名=Convert.ToBase64String(sigBytes); //现在构造完整的URL并返回给调用者。 StringBuilder qsBuilder=新的StringBuilder(); qsBuilder.Append(“http://”) .Append(this.endPoint) .Append(请求\ URI) .附加(“?”) .Append(canonicalQS) .Append(“&Signature=”) .附加(此.RFC3986(签名)); 返回qsBuilder.ToString(); } /* *以查询字符串的形式对请求进行签名。 * *此方法返回要使用的完整URL。修改返回的URL *无论如何,签名无效,亚马逊将拒绝这些请求。 */ 公共字符串符号(字符串查询字符串) { IDictionary请求=this.CreateDictionary(queryString); 返回此。签名(请求); } /* *亚马逊要求的IS0 8601格式的当前时间 */ 私有字符串GetTimestamp() { DateTime currentTime=DateTime.UtcNow; 字符串时间戳=currentTime.ToString(“yyyy-MM-ddTHH:MM:ssZ”); 返回时间戳; } /* *亚马逊要求按照RFC 3986进行百分比编码(URL编码)。 * *这是必要的,因为.NET的HttpUtility.UrlEncode不进行编码 *根据上述标准。此外,.NET还返回小写编码 *默认情况下,Amazon需要大写编码。 */ 私有字符串PercentEncoderRFC3986(字符串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=新StringBuilder(str); for(int i=0;i

C# //将AWSAccessKeyId和时间戳添加到请求中。 sortedMap[“AWSAccessKeyId”]=this.akid; sortedMap[“Timestamp”]=this.GetTimestamp(); //获取规范查询字符串 字符串canonicalQS=this.constructionCanonicalQueryString(sortedMap); //派生需要签名的字节。 StringBuilder=新的StringBuilder(); builder.Append(请求\方法) .Append(“\n”) .Append(this.endPoint) .Append(“\n”) .Append(请求\ URI) .Append(“\n”) .附加(规范); 字符串stringToSign=builder.ToString(); 字节[]toSign=Encoding.UTF8.GetBytes(stringToSign); //计算签名并转换为Base64。 字节[]sigBytes=signer.ComputeHash(toSign); 字符串签名=Convert.ToBase64String(sigBytes); //现在构造完整的URL并返回给调用者。 StringBuilder qsBuilder=新的StringBuilder(); qsBuilder.Append(“http://”) .Append(this.endPoint) .Append(请求\ URI) .附加(“?”) .Append(canonicalQS) .Append(“&Signature=”) .附加(此.RFC3986(签名)); 返回qsBuilder.ToString(); } /* *以查询字符串的形式对请求进行签名。 * *此方法返回要使用的完整URL。修改返回的URL *无论如何,签名无效,亚马逊将拒绝这些请求。 */ 公共字符串符号(字符串查询字符串) { IDictionary请求=this.CreateDictionary(queryString); 返回此。签名(请求); } /* *亚马逊要求的IS0 8601格式的当前时间 */ 私有字符串GetTimestamp() { DateTime currentTime=DateTime.UtcNow; 字符串时间戳=currentTime.ToString(“yyyy-MM-ddTHH:MM:ssZ”); 返回时间戳; } /* *亚马逊要求按照RFC 3986进行百分比编码(URL编码)。 * *这是必要的,因为.NET的HttpUtility.UrlEncode不进行编码 *根据上述标准。此外,.NET还返回小写编码 *默认情况下,Amazon需要大写编码。 */ 私有字符串PercentEncoderRFC3986(字符串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=新StringBuilder(str); for(int i=0;i,c#,amazon-web-services,C#,Amazon Web Services,您可以从Amazon下载此示例 如果您使用SOAP(在本例中),那么获得所需信息将比使用REST简单得多 我不认为在这种情况下使用REST比使用SOAP调用更简单,SOAP调用在C#中返回一个格式良好的对象,您可以在其中获取所有信息 //Product Advertising API, ItemLookup: http://docs.amazonwebservices.com/AWSECommerceService/2010-10-01/DG/ItemLookup.html Sprightl

您可以从Amazon下载此示例

如果您使用SOAP(在本例中),那么获得所需信息将比使用REST简单得多

我不认为在这种情况下使用REST比使用SOAP调用更简单,SOAP调用在C#中返回一个格式良好的对象,您可以在其中获取所有信息
//Product Advertising API, ItemLookup: http://docs.amazonwebservices.com/AWSECommerceService/2010-10-01/DG/ItemLookup.html

SprightlySoftAWS.REST MyREST = new SprightlySoftAWS.REST();

String RequestURL;
RequestURL = "https://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&Operation=ItemLookup&Version=2010-10-01";
RequestURL += "&AWSAccessKeyId=" + System.Uri.EscapeDataString(AWSAccessKeyId) + "&SignatureVersion=2&SignatureMethod=HmacSHA256&Timestamp=" + Uri.EscapeDataString(DateTime.UtcNow.ToString("yyyy-MM-dd\\THH:mm:ss.fff\\Z"));
RequestURL += "&ItemId=9781904233657";
RequestURL += "&IdType=ISBN";
RequestURL += "&SearchIndex=Books";

String RequestMethod;
RequestMethod = "GET";

String SignatureValue;
SignatureValue = MyREST.GetSignatureVersion2Value(RequestURL, RequestMethod, "", AWSSecretAccessKey);

RequestURL += "&Signature=" + System.Uri.EscapeDataString(SignatureValue);

Boolean RetBool;
RetBool = MyREST.MakeRequest(RequestURL, RequestMethod, null);

System.Diagnostics.Debug.Print("");
System.Diagnostics.Debug.Print(MyREST.LogData);
System.Diagnostics.Debug.Print("");

String ResponseMessage = "";

if (RetBool == true)
{
    System.Xml.XmlDocument MyXmlDocument;
    System.Xml.XmlNamespaceManager MyXmlNamespaceManager;
    System.Xml.XmlNode MyXmlNode;
    System.Xml.XmlNodeList MyXmlNodeList;

    MyXmlDocument = new System.Xml.XmlDocument();
    MyXmlDocument.LoadXml(MyREST.ResponseString);

    MyXmlNamespaceManager = new System.Xml.XmlNamespaceManager(MyXmlDocument.NameTable);
    MyXmlNamespaceManager.AddNamespace("amz", "http://webservices.amazon.com/AWSECommerceService/2010-10-01");

    MyXmlNodeList = MyXmlDocument.SelectNodes("amz:ItemLookupResponse/amz:Items/amz:Item", MyXmlNamespaceManager);

    if (MyXmlNodeList.Count == 0)
    {
        ResponseMessage = "No items found.";
    }
    else
    {
        foreach (System.Xml.XmlNode ItemXmlNode in MyXmlNodeList)
        {
            MyXmlNode = ItemXmlNode.SelectSingleNode("amz:ItemAttributes/amz:Title", MyXmlNamespaceManager);
            ResponseMessage += "Title = " + MyXmlNode.InnerText;

            ResponseMessage += Environment.NewLine;
        }
    }

    MessageBox.Show(ResponseMessage);
}
else
{
    ResponseMessage = MyREST.ResponseStringFormatted;

    MessageBox.Show(ResponseMessage);
}
// custom class for result item
public class AmazonBookSearchResult
{
    public string ASIN;
    public string Author;
    public string Title;
    public Uri DetailPageURL;
    public Uri AllCustomerReviews;
}

// I call this with the search terms, returns an IEnumerable of results
public class ItemLookup
{
    private const string MY_AWS_ACCESS_KEY_ID = "YOUR KEY";
    private const string MY_AWS_SECRET_KEY = "YOUR KEY";
    private const string DESTINATION = "ecs.amazonaws.com";

    private const string NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/2009-03-31";

    public static IEnumerable<AmazonBookSearchResult> AmazonItemLookup(string category, string browseNode, string keyWords)
    {
        SignedRequestHelper helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
        String requestUrl;

        IDictionary<string, string> r1 = new Dictionary<string, String>();
        r1["Service"] = "AWSECommerceService";
        r1["Version"] = "2009-03-31";
        r1["Operation"] = "ItemSearch";
        r1["ResponseGroup"] = "ItemAttributes";
        r1["SearchIndex"] = category;
        r1["Keywords"] = keyWords;

        requestUrl = helper.Sign(r1);
        XmlDocument xmlDoc = sendRequest(requestUrl);
        XDocument doc = XDocument.Load(new XmlNodeReader(xmlDoc));

        XNamespace ns = "http://webservices.amazon.com/AWSECommerceService/2009-03-31";
        IEnumerable<AmazonBookSearchResult> result =
            from items in doc.Element(ns + "ItemSearchResponse").Elements(ns + "Items").Elements(ns + "Item")
            select new AmazonBookSearchResult
            {
                ASIN = (string)items.Element(ns + "ASIN")
            };

        int count = doc.Element(ns + "ItemSearchResponse").Elements(ns + "Items").Elements(ns + "Item").Count();

        return result;

    } // end Lookup()

    // this is just taken from the amazon sample
    private static XmlDocument sendRequest(string url)
    {
        try
        {
            WebRequest request = HttpWebRequest.Create(url);
            WebResponse response = request.GetResponse();
            XmlDocument doc = new XmlDocument();
            doc.Load(response.GetResponseStream());

            XmlNodeList errorMessageNodes = doc.GetElementsByTagName("Message", NAMESPACE);
            if (errorMessageNodes != null && errorMessageNodes.Count > 0)
            {
                String message = errorMessageNodes.Item(0).InnerText;
                throw new Exception("Error " + message);
            }

            return doc;
        }
        catch (Exception e)
        {
            System.Console.WriteLine("Caught Exception: " + e.Message);
            System.Console.WriteLine("Stack Trace: " + e.StackTrace);
        }

        return null;
    }// end FetchTitle()
}

class SignedRequestHelper
{
    private string endPoint;
    private string akid;
    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 destination)
    {
        this.endPoint = destination.ToLower();
        this.akid = awsAccessKeyId;
        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;
        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);
    }
}