2010-11-10 15 views
8

Debo haber revisado 10 proyectos diferentes de C# de muestra que están desactualizados y que ya no funcionan.Amazon Product API: ¿hay algún ejemplo válido y actualizado en C#?

Todo lo que busco es una forma de recuperar la información de un libro basado en un ISBN o título.

El sitio de Amazon Web Service es un pantano absolutamente miserable.

Actualización:

he conseguido utilizar this como punto de partida, y se han completado con éxito una petición básica. Continuaré buscando otros recursos que estén actualizados que puedan entrar en otros escenarios detallados.

+3

Buena pregunta, nombre de usuario incorrecto. –

+1

Gracias señor. Creo que es un nombre apropiado, dado lo malo que soy un codificador. – asfsadf

+1

Bueno, no realmente, da la impresión de que el esfuerzo de alguien para ayudarlo será una pérdida de tiempo. Prueba "guruturd". Muchas U's, eso es genial y aún insinúa tu experiencia. –

Respuesta

2

Hace un tiempo, escribí una biblioteca cliente para comunicarme con los servicios ECS (A2S) de Amazon. Parece que Amazon odia a sus desarrolladores y sigue cambiando el nombre y el marco de su servicio. Bueno, mi cliente ahora está completamente roto por Recent API Changes.

Su mejor opción sería mirar sus muestras here.

Buena suerte con esto. Su API es enorme y obsoleta por la experiencia que tuve, pero eso fue hace dos años. Me da la impresión de que realmente atienden a los desarrolladores para sus servicios empresariales, no a los A2S gratuitos.

+0

Estoy recibiendo solo "El servidor remoto devolvió una respuesta inesperada: (400) Solicitud incorrecta". errores hasta el momento, más un elemento hijo no válido 'signingBehavior'. – asfsadf

3

El componente de AWS de SprightlySoft para .NET le permite interactuar con todos los servicios de Amazon, incluida la API de publicidad de productos. Aquí hay un código de muestra para buscar un ISBN. Obtenga el componente gratis en 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

He estado luchando con esto también (y también estoy en la etapa de aprendizaje).

Lo que encontré que mejor funcionó fue utilizar la API REST, y luego analizar los resultados con Linq a XML en un objeto de resultados personalizado con el que pude trabajar. Disculpe el largo código de pegar (no estoy seguro en el protocolo con eso en esta placa) pero pensé que lo querría todo. Gran parte de esto proviene de una de las muestras de Amazon, pero el sitio no está organizado, así que estoy luchando por encontrarlo nuevamente.

// 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

se puede descargar este ejemplo de Amazon Product Advertising API Signed Requests Sample Code - C# SOAP WCF 4.0

si utiliza jabón (en este caso) que será mucho más sencillo para que usted pueda obtener la información que necesita de utilizar REST.

No creo que usar REST en este caso sea más simple que usar las llamadas SOAP que en C# devuelve un objeto bien formado en el que puede obtener toda la información que necesita sobre el producto sin toda la codificación adicional. Supongo que todos están usando REST hoy en día porque está de moda, solo lo uso cuando es más simple de integrar. En el caso de la API de Amazon Product Advertising, prefiero usar la API de SOAP.

Cuestiones relacionadas