2010-11-10 26 views
8

Tôi phải chạy qua 10 dự án mẫu C# khác nhau đã lỗi thời và không hoạt động nữa.API sản phẩm của Amazon - có bất kỳ ví dụ hợp lệ, cập nhật nào trong C# không?

Tất cả những gì tôi theo sau là cách để lấy lại thông tin sách dựa trên ISBN hoặc tiêu đề.

Trang web Amazon Web Service là một hành vi cực kỳ khốn khổ.

Cập nhật:

tôi đã quản lý để sử dụng this như là một điểm khởi đầu, và đã hoàn thành một yêu cầu cơ bản. Tôi sẽ tiếp tục tìm kiếm các tài nguyên khác được cập nhật có thể đi vào một số tình huống chi tiết khác.

+3

Câu hỏi hay, tên người dùng không hợp lệ. –

+1

Cảm ơn ngài. Tôi nghĩ rằng đó là một cái tên thích hợp, được đưa ra như thế nào xấu của một coder tôi. – asfsadf

+1

Vâng, không thực sự, nó làm cho ấn tượng rằng nỗ lực của bất cứ ai để giúp bạn sẽ là một sự lãng phí thời gian của họ. Hãy thử "guruturd". Rất nhiều của U, đó là mát mẻ và vẫn còn gợi ý về chuyên môn của bạn. –

Trả lời

2

Một thời gian ngắn, tôi đã viết thư viện khách hàng để liên lạc với các dịch vụ ECS (A2S) của Amazon. Dường như Amazon ghét nhà phát triển của họ và tiếp tục thay đổi tên và khuôn khổ dịch vụ của họ. Vâng, khách hàng của tôi hiện đã bị hỏng hoàn toàn vì Recent API Changes.

Đặt cược tốt nhất của bạn là xem mẫu của chúng here.

Chúc bạn may mắn với điều này. API của họ rất lớn và lỗi thời từ trải nghiệm tôi có, nhưng đó là hai năm trước. Tôi có ấn tượng rằng họ thực sự phục vụ cho các nhà phát triển cho các dịch vụ doanh nghiệp của họ, không phải là A2S miễn phí.

+0

Tôi chỉ nhận được "Máy chủ từ xa đã trả về phản hồi không mong muốn: (400) Yêu cầu không hợp lệ". lỗi cho đến nay, cộng với phần tử con không hợp lệ 'signingBehavior.' – asfsadf

3

Thành phần AWDE SprightlySoft cho .NET cho phép bạn tương tác với tất cả dịch vụ của Amazon, bao gồm API quảng cáo sản phẩm. Dưới đây là một số mã mẫu để tra cứu ISBN. Nhận thành phần miễn phí tại http://sprightlysoft.com/.

//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); 
} 
1

Tôi đã đấu tranh với điều này (và tôi cũng đang ở giai đoạn học tập).

Điều tôi thấy hiệu quả nhất là sử dụng REST api và sau đó phân tích kết quả bằng LINQ thành XML thành đối tượng kết quả tùy chỉnh mà tôi có thể làm việc. Xin lỗi dán mã dài (không chắc chắn về giao thức với điều đó trên bảng này) nhưng figured bạn muốn tất cả. Phần lớn điều này đến từ một trong những mẫu riêng của Amazon, nhưng có trang web không được tổ chức nên tôi đang cố gắng tìm lại nó.

// 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); 
    } 
} 
0

Bạn có thể tải về ví dụ này từ Amazon Product Advertising API Signed Requests Sample Code - C# SOAP WCF 4.0

Nếu bạn sử dụng SOAP (trong trường hợp này) nó sẽ được đơn giản hơn nhiều cho bạn để có được những thông tin mà bạn cần vì sử dụng REST. Tôi không nghĩ rằng việc sử dụng REST trong trường hợp này đơn giản hơn việc sử dụng các cuộc gọi SOAP trong C# trả về một đối tượng được định dạng tốt, trong đó bạn có thể nhận được tất cả thông tin bạn cần về sản phẩm mà không cần mã hóa thêm. Tôi đoán tất cả mọi người đang sử dụng REST ngày nay vì là hợp thời trang, tôi chỉ sử dụng nó khi đơn giản hơn để tích hợp. Trong trường hợp API quảng cáo sản phẩm Amazon, tôi thà sử dụng api SOAP.

Các vấn đề liên quan