Amazon Product Advertising API使用Java签署了请求

经过几个小时的修补和阅读整个互联网几次,我无法弄清楚如何签署使用Product Advertising API的请求。

到目前为止,我设法从提供的WSDL文件生成客户端。 我使用了亚马逊的教程。 你可以在这里找到它:

生成Web服务客户端的教程

到目前为止没有问题。 为了测试客户端,我写了一小段代码。 该代码旨在简单地获取有关产品的一些信息。 该产品由其ASIN指定。

代码:

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(""); lookup.getRequest().add(itemLookup); ItemLookupResponse response = port.itemLookup(lookup); String r = response.toString(); System.out.println("response: " + r); System.out.println("API Test stopped"); } } 

如您所见,我没有签署请求的部分。 我已经通过了很多使用过的类,并没有找到签署请求的方法。

那么,如何签署请求?

我实际上在文档中找到了一些东西: 请求身份validation

但他们不使用自己的API。 所提出的解决方案或多或少仅供手动使用。 所以我查看了客户端类,以便了解我是否可以获取请求URL并将自己请求签名所需的所有部分放入其中。 但是没有这样的方法。

我希望有人可以指出我做错了什么。


这就是我为解决问题所做的工作。 所有的功劳归功于乔恩和亚马逊论坛的人。

在我概述我做了什么之前,这里有一个链接到post,它帮助我解决了这个问题: 亚马逊论坛上的论坛post 。

我下载了post中链接的awshandlerresolver.java。 比我修改自己的代码所以它看起来像这样:

 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("")); // important AWSECommerceServicePortType port = service.getAWSECommerceServicePort(); ItemLookupRequest itemLookup = new ItemLookupRequest(); itemLookup.setIdType("ASIN"); itemLookup.getItemId().add("B000RE216U"); ItemLookup lookup = new ItemLookup(); lookup.setAWSAccessKeyId(""); // 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"); } } 

最后的印刷品或多或少都没用。 但它的确有效。 我还使用WSDL Jon链接来生成一个新的Web服务客户端。 我刚刚在我的问题中发布的教程中更改了URL。

在创建服务后尝试此操作

 service.setHandlerResolver(new AwsHandlerResolver(my_AWS_SECRET_KEY)); 

您将需要此类和此 jar文件作为AwsHandlerResolver使用Base64编码的项目的引用添加。

您需要将AwsHandlerResolver文件重命名为类的名称,因为文件名全为小写。

我认为你拥有的其余代码很好。

WSDL是http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl

这个讨论和相关的亚马逊post帮助我让客户工作。 话虽如此,我觉得解决方案可以改进以下方面:

  1. 不鼓励在代码中设置WebService处理程序。 建议使用XML配置文件和相应的@HandlerChain注释。
  2. 在这种情况下不需要SOAPHandler,LogicalHandler就可以了。 SOAPHandler具有比LogicalHandler更多的范围,当涉及到代码时,更多访问并不总是好的。
  3. 填充签名生成,添加节点并在一个处理程序中打印请求似乎有点太多了。 这些可以分开来分离责任和易于测试。 一种方法是使用XSLT转换添加节点,以便处理程序可以保持对转换逻辑的遗忘。 然后可以链接另一个处理程序,它只打印请求。 例

我在spring这样做,它工作正常。

 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 operation_request =null; Holder> items = new Holder>(); port.itemSearch( search.getMarketplaceDomain(), search.getAWSAccessKeyId(), search.getAssociateTag(), search.getXMLEscaping(), search.getValidate(), search.getShared(), search.getRequest(), operation_request, items); java.util.List 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()); } } } 

您也可以使用IntentBrite API实现相同的货币化结果