java web-services api amazon-web-services amazon

Solicitud firmada de la API de publicidad de productos de Amazon con Java



web-services amazon-web-services (4)

Después de muchas horas de juguetear y leer todo el internet varias veces, simplemente no puedo averiguar cómo firmar solicitudes de uso con la API de publicidad de productos.

Hasta ahora he logrado generar un cliente a partir del archivo WSDL proporcionado. Usé un tutorial de Amazon para esto. Lo puedes encontrar aquí:

Tutorial para generar el cliente del servicio web.

Hasta ahora no hay problemas. Para probar el cliente escribí un pequeño trozo de código. El código está destinado a obtener simplemente información sobre un producto. El producto está especificado por su ASIN.

El código:

package client; import com.ECS.client.jax.AWSECommerceService; import com.ECS.client.jax.AWSECommerceServicePortType; import com.ECS.client.jax.ItemLookup; import com.ECS.client.jax.ItemLookupResponse; import com.ECS.client.jax.ItemLookupRequest; public class Client { public static void main(String[] args) { System.out.println("API Test startet"); AWSECommerceService service = new AWSECommerceService(); AWSECommerceServicePortType port = service.getAWSECommerceServicePort(); ItemLookupRequest itemLookup = new ItemLookupRequest(); itemLookup.setIdType("ASIN"); itemLookup.getItemId().add("B000RE216U"); ItemLookup lookup = new ItemLookup(); lookup.setAWSAccessKeyId("<mykeyishere>"); lookup.getRequest().add(itemLookup); ItemLookupResponse response = port.itemLookup(lookup); String r = response.toString(); System.out.println("response: " + r); System.out.println("API Test stopped"); } }

Como puede ver, no hay ninguna parte donde firme la solicitud. He trabajado en muchas de las clases utilizadas y no he encontrado ningún método para firmar la solicitud.

Entonces, ¿cómo firmar una solicitud?

En realidad encontré algo en la documentación: solicitar autenticación

Pero ellos no usan su propia API. Las soluciones propuestas son más o menos solo para uso manual. Así que busqué en las clases de clientes para saber si podía obtener la URL de solicitud y poner todas las partes necesarias para iniciar sesión en mi solicitud. Pero no hay tales métodos.

Espero que alguien pueda señalar lo que estoy haciendo mal.

Esto es lo que hice para resolver el problema. Todo el crédito es para Jon y los chicos de los foros de Amazon.

Antes de describir lo que hice, aquí hay un enlace a la publicación que me ayudó a resolver el problema: Publicación de foro en los foros de Amazon .

Descargué el awshandlerresolver.java que está vinculado en la publicación. Que modifiqué mi propio código para que se vea así:

package client; import com.ECS.client.jax.AWSECommerceService; import com.ECS.client.jax.AWSECommerceServicePortType; import com.ECS.client.jax.ItemLookup; import com.ECS.client.jax.ItemLookupResponse; import com.ECS.client.jax.ItemLookupRequest; public class Client { public static void main(String[] args) { System.out.println("API Test startet"); AWSECommerceService service = new AWSECommerceService(); service.setHandlerResolver(new AwsHandlerResolver("<Secret Key>")); // important AWSECommerceServicePortType port = service.getAWSECommerceServicePort(); ItemLookupRequest itemLookup = new ItemLookupRequest(); itemLookup.setIdType("ASIN"); itemLookup.getItemId().add("B000RE216U"); ItemLookup lookup = new ItemLookup(); lookup.setAWSAccessKeyId("<Access Key>"); // important lookup.getRequest().add(itemLookup); ItemLookupResponse response = port.itemLookup(lookup); String r = response.toString(); System.out.println("response: " + r); System.out.println("API Test stopped"); } }

La impresión al final es más o menos inútil. Pero funciona. También utilicé el enlace WSDL Jon para generar un nuevo cliente de servicio web. Acabo de cambiar las URL en el tutorial que publiqué en mi pregunta.


Esta discusión y la publicación relacionada de Amazon me ayudaron a que el cliente trabajara. Dicho esto, sentí que la solución podría mejorarse con respecto a lo siguiente:

  1. No se recomienda configurar los manejadores de servicios web en el código. Se recomienda un archivo de configuración XML y una anotación correspondiente de @HandlerChain.
  2. No se requiere un SOAPHandler en este caso, LogicalHandler haría muy bien. Un SOAPHandler tiene más alcance que un LogicalHandler y, cuando se trata de código, más acceso no siempre es bueno.
  3. Rellenar la generación de firmas, agregar un Nodo e imprimir la solicitud en un controlador parece demasiado. Estos podrían separarse por separación de responsabilidad y facilidad de prueba. Un enfoque sería agregar el Nodo mediante una transformación XSLT para que el manejador pueda permanecer ajeno a la lógica de transformación. Luego se podría encadenar otro controlador que simplemente imprime la solicitud. Example

Hice esto en primavera está funcionando bien.

package com.bookbub.application; import com.ECS.client.jax.*; import com.ECS.client.jax.ItemSearch; import javax.xml.ws.Holder; import java.math.BigInteger; import java.util.List; public class TestClient { private static final String AWS_ACCESS_KEY_ID = "AI*****2Y7Z****DIHQ"; private static final String AWS_SECRET_KEY = "lIm*****dJuiy***YA+g/vnj/Ix*****Oeu"; private static final String ASSOCIATE_TAG = "****-**"; public static void main(String[] args) { TestClient ist = new TestClient(); ist.runSearch(); } public void runSearch() { AWSECommerceService service = new AWSECommerceService(); service.setHandlerResolver(new AwsHandlerResolver(AWS_SECRET_KEY)); AWSECommerceServicePortType port = service.getAWSECommerceServicePort(); ItemSearchRequest request = new ItemSearchRequest(); request.setSearchIndex("Books"); request.setKeywords("java web services up and running oreilly"); ItemSearch search = new ItemSearch(); search.getRequest().add(request); search.setAWSAccessKeyId(AWS_ACCESS_KEY_ID); Holder<OperationRequest> operation_request =null; Holder<List<Items>> items = new Holder<List<Items>>(); port.itemSearch( search.getMarketplaceDomain(), search.getAWSAccessKeyId(), search.getAssociateTag(), search.getXMLEscaping(), search.getValidate(), search.getShared(), search.getRequest(), operation_request, items); java.util.List<Items> result = items.value; BigInteger totalPages = result.get(0).getTotalResults(); System.out.println(totalPages); for (int i = 0; i < result.get(0).getItem().size(); ++i) { Item myItem = result.get(0).getItem().get(i); System.out.print(myItem.getASIN()); System.out.print(", "); System.out.println(myItem.getDetailPageURL()); System.out.print(", "); System.out.println(myItem.getSmallImage() == null ? "" : myItem.getSmallImage().getURL()); } } }


Prueba esto después de crear el servicio.

service.setHandlerResolver(new AwsHandlerResolver(my_AWS_SECRET_KEY));

Necesitará this clase y this archivo jar para agregar como referencia a su proyecto, ya que AwsHandlerResolver utiliza la codificación Base64.

Deberá cambiar el nombre del archivo AwsHandlerResolver al nombre de la clase, ya que el nombre del archivo está en minúscula.

Creo que el resto del código que tienes está bien.

El WSDL es http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl


También podría lograr los mismos resultados de monetización con la API IntentBrite