通过 Java/SOAP 的亚马逊产品广告 API
Posted
技术标签:
【中文标题】通过 Java/SOAP 的亚马逊产品广告 API【英文标题】:Amazon Product Advertising API through Java/SOAP 【发布时间】:2012-01-10 07:23:06 【问题描述】:我一直在使用亚马逊的产品广告 API,但我无法获得通过并提供数据的请求。我一直在努力解决这个问题:http://docs.amazonwebservices.com/AWSECommerceService/2011-08-01/GSG/ 和这个:Amazon Product Advertising API signed request with Java
这是我的代码。我使用以下代码生成了 SOAP 绑定:http://docs.amazonwebservices.com/AWSECommerceService/2011-08-01/GSG/YourDevelopmentEnvironment.html#Java
在 Classpath 上,我只有:commons-codec.1.5.jar
import com.ECS.client.jax.AWSECommerceService;
import com.ECS.client.jax.AWSECommerceServicePortType;
import com.ECS.client.jax.Item;
import com.ECS.client.jax.ItemLookup;
import com.ECS.client.jax.ItemLookupRequest;
import com.ECS.client.jax.ItemLookupResponse;
import com.ECS.client.jax.ItemSearchResponse;
import com.ECS.client.jax.Items;
public class Client
public static void main(String[] args)
String secretKey = <my-secret-key>;
String awsKey = <my-aws-key>;
System.out.println("API Test started");
AWSECommerceService service = new AWSECommerceService();
service.setHandlerResolver(new AwsHandlerResolver(
secretKey)); // important
AWSECommerceServicePortType port = service.getAWSECommerceServicePort();
// Get the operation object:
com.ECS.client.jax.ItemSearchRequest itemRequest = new com.ECS.client.jax.ItemSearchRequest();
// Fill in the request object:
itemRequest.setSearchIndex("Books");
itemRequest.setKeywords("Star Wars");
// itemRequest.setVersion("2011-08-01");
com.ECS.client.jax.ItemSearch ItemElement = new com.ECS.client.jax.ItemSearch();
ItemElement.setAWSAccessKeyId(awsKey);
ItemElement.getRequest().add(itemRequest);
// Call the Web service operation and store the response
// in the response object:
com.ECS.client.jax.ItemSearchResponse response = port
.itemSearch(ItemElement);
String r = response.toString();
System.out.println("response: " + r);
for (Items itemList : response.getItems())
System.out.println(itemList);
for (Item item : itemList.getItem())
System.out.println(item);
System.out.println("API Test stopped");
这是我回来的内容。我希望看到亚马逊上的一些星球大战书籍被倾倒到我的控制台上:-/:
API Test started
response: com.ECS.client.jax.ItemSearchResponse@7a6769ea
com.ECS.client.jax.Items@1b5ac06e
API Test stopped
我做错了什么(请注意,第二个 for 循环中没有“项目”被打印出来,因为它是空的)?如何解决此问题或获取相关错误信息?
【问题讨论】:
【参考方案1】:我不使用 SOAP API,但您的 Bounty 要求并没有说明它必须使用 SOAP,只是您想调用 Amazon 并获得结果。因此,我将使用 REST API 发布这个工作示例,它至少可以满足您的要求:
我想要一些可以访问亚马逊服务器并返回结果的工作示例代码
您需要下载以下内容以满足签名要求:
http://associates-amazon.s3.amazonaws.com/signed-requests/samples/amazon-product-advt-api-sample-java-query.zip
解压缩并获取com.amazon.advertising.api.sample.SignedRequestsHelper.java
文件并将其直接放入您的项目中。此代码用于签署请求。
您还需要从以下下载 Apache Commons Codec 1.3 并将其添加到您的类路径中,即添加到您项目的库中。请注意,这是唯一适用于上述类的 Codec 版本 (SignedRequestsHelper
)
http://archive.apache.org/dist/commons/codec/binaries/commons-codec-1.3.zip
现在您可以复制并粘贴以下内容,确保将 your.pkg.here
替换为正确的包名称,并替换 SECRET
和 KEY
属性:
package your.pkg.here;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Main
private static final String SECRET_KEY = "<YOUR_SECRET_KEY>";
private static final String AWS_KEY = "<YOUR_KEY>";
public static void main(String[] args)
SignedRequestsHelper helper = SignedRequestsHelper.getInstance("ecs.amazonaws.com", AWS_KEY, SECRET_KEY);
Map<String, String> params = new HashMap<String, String>();
params.put("Service", "AWSECommerceService");
params.put("Version", "2009-03-31");
params.put("Operation", "ItemLookup");
params.put("ItemId", "1451648537");
params.put("ResponseGroup", "Large");
String url = helper.sign(params);
try
Document response = getResponse(url);
printResponse(response);
catch (Exception ex)
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
private static Document getResponse(String url) throws ParserConfigurationException, IOException, SAXException
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(url);
return doc;
private static void printResponse(Document doc) throws TransformerException, FileNotFoundException
Transformer trans = TransformerFactory.newInstance().newTransformer();
Properties props = new Properties();
props.put(OutputKeys.INDENT, "yes");
trans.setOutputProperties(props);
StreamResult res = new StreamResult(new StringWriter());
DOMSource src = new DOMSource(doc);
trans.transform(src, res);
String toString = res.getWriter().toString();
System.out.println(toString);
如您所见,这比 SOAP API 更易于设置和使用。如果您对使用 SOAP API 没有特定要求,那么我强烈建议您改用 REST API。
使用 REST API 的一个缺点是结果不会为您解组到对象中。这可以通过基于 wsdl 创建所需的类来解决。
【讨论】:
我必须添加 params.put("AssociateTag","th0426-20") 才能让它工作,但是谢谢.. 肯定有一些进展。 不完全是我想要的,但我会给你分数,因为它让我朝着正确的方向前进。 我忘记了新的 Associate 标签要求。很高兴我能帮上忙。 @JonathanSpooner 使用此代码我如何解析输出并检索单个值?即,如果我只想要标题和定价? @Tukajo 提示:文档包含所有元素;)【参考方案2】:这最终起作用了(我必须将我的 associateTag 添加到请求中):
public class Client
public static void main(String[] args)
String secretKey = "<MY_SECRET_KEY>";
String awsKey = "<MY AWS KEY>";
System.out.println("API Test started");
AWSECommerceService service = new AWSECommerceService();
service.setHandlerResolver(new AwsHandlerResolver(secretKey)); // important
AWSECommerceServicePortType port = service.getAWSECommerceServicePort();
// Get the operation object:
com.ECS.client.jax.ItemSearchRequest itemRequest = new com.ECS.client.jax.ItemSearchRequest();
// Fill in the request object:
itemRequest.setSearchIndex("Books");
itemRequest.setKeywords("Star Wars");
itemRequest.getResponseGroup().add("Large");
// itemRequest.getResponseGroup().add("Images");
// itemRequest.setVersion("2011-08-01");
com.ECS.client.jax.ItemSearch ItemElement = new com.ECS.client.jax.ItemSearch();
ItemElement.setAWSAccessKeyId(awsKey);
ItemElement.setAssociateTag("th0426-20");
ItemElement.getRequest().add(itemRequest);
// Call the Web service operation and store the response
// in the response object:
com.ECS.client.jax.ItemSearchResponse response = port
.itemSearch(ItemElement);
String r = response.toString();
System.out.println("response: " + r);
for (Items itemList : response.getItems())
System.out.println(itemList);
for (Item itemObj : itemList.getItem())
System.out.println(itemObj.getItemAttributes().getTitle()); // Title
System.out.println(itemObj.getDetailPageURL()); // Amazon URL
System.out.println("API Test stopped");
【讨论】:
【参考方案3】:看起来响应对象没有覆盖 toString(),所以如果它包含某种错误响应,简单地打印它不会告诉你错误响应是什么。您需要查看 api 以了解响应对象中返回的字段并单独打印这些字段。要么您会收到一条明显的错误消息,要么您必须返回他们的文档以尝试找出问题所在。
【讨论】:
是的,看看您是否可以使用 tcpmon 或类似工具来检查来自 Amazon 的 XML 响应。然后您就可以在他们的 XML 中看到完整的错误消息。【参考方案4】:您需要调用 Item 对象的 get 方法来检索其详细信息,例如:
for (Item item : itemList.getItem())
System.out.println(item.getItemAttributes().getTitle()); //Title of item
System.out.println(item.getDetailPageURL()); // Amazon URL
//etc
如果有任何错误,您可以通过调用 getErrors() 来获取它们
if (response.getOperationRequest().getErrors() != null)
System.out.println(response.getOperationRequest().getErrors().getError().get(0).getMessage());
【讨论】:
感谢您的输入,但是“response.getOperationRequest()”和“itemList.getItem()”都是空的,所以没有打印出来... :-\ 这可能是因为您没有为请求(see Amazon Product API Docs) 指定响应组。您可以通过以下方式在请求中添加响应组:itemRequest.getResponseGroup().add("Large"); itemRequest.getResponseGroup().add("Images");
以上是关于通过 Java/SOAP 的亚马逊产品广告 API的主要内容,如果未能解决你的问题,请参考以下文章
可以通过亚马逊产品广告 API 检索 Kindle 电子书的实际价格吗?