该指南旨在帮助使用亚马逊联盟Product Advertising API的开发人员快速上手,开发出一个可以运行的样例程序。该指南的目标读者是对WebService、RESTful Service有一定了解的Java开发人员。
主要步骤:
- 注册亚马逊联盟账号;
- 注册联盟开发者账号;
- 修改并调试样例程序。
注册亚马逊联盟账号
访问亚马逊联盟网站http://associates.amazon.cn,确保选择地区为“中国”,点击“免费加入”按钮,会跳转到登录注册页面,这里可以直接使用你已经注册过的亚马逊(中国)账号,或者新注册一个账号。
下一步进入向导页面,第一步“帐户信息”中选择或新加一个地址,第二步“我的网站模式”照实填(是的,你需要有一个网站,从导购网站到博客都可以),第三步完成即可。提示添加付款信息,输入一张有效银行卡即可,这一步骤以后做也行。
保持登录状态进入联盟管理界面。比如你在第二步中输入的网站ID为“MyWebsite”,那你的默认跟踪ID将为“mywebsite-23”。跟踪ID又叫Associate Tag,用于在用户实际购买过程中识别你的账号,以保证在发生购买时给你分配提成。点击主页左侧“跟踪代码管理”,可以添加额外的跟踪ID,比如“mywebsite-channel1”,点击“搜索”(其实就是创建),会生成“mywebsite-channel1-23”(如果跟已有的重名会生成其他后缀)。
注册联盟开发者账号
登录到联盟管理界面中,点击“Product Advertising API”页签,会跳转到Product Advertising API的介绍页面。基本上这个页面里所有链接都是有用的,但你可以先点击右边的“现在注册按钮”。这里会跳转到美国亚马逊网站的登录注册界面,注意亚马逊美国和亚马逊中国的账号体系是互相独立的,这里可以用你已经注册过的亚马逊美国账号,或新注册一个(可以使用与亚马逊中国相同的邮箱,也可以不同)。进入第二步,账户信息,这次界面是英文的,填英文或直接填中文都可以,记得下面“Check here to indicate……”要打勾,还有输入正确的图片验证码,点击“完成注册”。
在成功界面,点击“管理您的帐户”链接,跳转到管理页面,在“访问标识”栏,点击“点击这里”,你会发现你跳转到了高大上的AWS亚马逊云的管理页面上。如果有“Attention”提示,不用管它,勾选“I understand”,点击“Continue”即可关闭提示。在“Access Credentials”章节的“Access Keys”标签下,你会看到你的“Access Key ID”是一串字母数字(20个字符),点击“Secret Access Key”列对应的“Show”链接,会弹一个提示框,里面会显示另一串字母数字(40个字符),这就是之后会用的Secret Key。因为超过多少时间后就不能在查看Secret Key了,建议把这对Access Key ID和Secret Key记录在一个安全的地方。
修改并调试样例程序
回到“管理您的帐户”页面,点击左边的“示例代码”,会来到一个列表页面,里边有各种语言的样例程序,比如node.js、PHP、Ruby、C#、Perl、Java,我们比较关心Java。点击“Product Advertising API Signed Requests Sample Code – Java REST/QUERY”,再点击“Download”下载程序包。Java SOAP的样例也是可以用的,但相比而言REST这个版本更简单些。需要注意的是,经笔者测试,截止到14年3月,在北京联通网络访问AWS系列站点有时会有些慢甚至打不开,挂上香港或国外代理服务器即可恢复正常(API接口调用则不存在这个问题)。
将下载的amazon-product-advt-api-sample-java-query.zip解压,在Eclipse里新建一个普通Java工程,把src目录拷贝进去。然后你会发现工程缺少依赖类库无法编译,去Apache网站http://commons.apache.org/proper/commons-codec/下载一个commons-codec.jar,1.3版本以上即可,放到项目lib目录中,并加入Build Path,编译就应该通过了。
com.amazon.advertising.api.sample.SignedRequestsHelper这个类没有什么要改的,用于生产环境都可以。但com.amazon.advertising.api.sample.ItemLookupSample类里有一些需要调整的地方:
- Endpoint(即API所在的服务器URL)修改为亚马逊中国的服务器。别找了,截止到14年3月的版本,注释里都没列中国,但从在线文档(Anatomy of a REST Request)可以找到,CN的Endpoint包括:
http://webservices.amazon.cn/onca/xml
https://webservices.amazon.cn/onca/xml - 添加一个Associate Tag常量,并作为参数传到API里去。这个就是你一开始注册的联盟账号里的跟踪ID,没有这个是算不了钱的。
- 修改AWS_ACCESS_KEY_ID和AWS_SECRET_KEY为上一章注册的开发者账号中所提供的那对Access Key ID和Secret Key。
- 调整API Version参数,样例中的“2009-03-31”版本已经过期,修改为“2011-08-01”。
- 样例中的ITEM_ID是美国的商品,改成中国的“B00D2J9ETE”。
执行ItemLookupSample,Run as Java Application。正确的话,会在Console控制台里打出“Signed Title is “Kindle Fire HDX平板电脑””的字样。程序会调用API两次,其实只是为了演示SignedRequestsHelper.sign()方法的两种重载。
如果程序报错,尝试把Console里打出来的“Signed Request is http://webservices.amazon.cn/onca/xml?AWSAccessKeyId=……”那行里的URL复制下来并在浏览器打开,观察返回的XML即可发现问题,比如认证失败、参数无效之类的错误,都会有提示。
为了大家方便,笔者把自己修改版本的SignedRequestsHelper附在文章最后,替换即可。
基于这个样例程序,相信大家已经可以快速上手,下一步可以查看官方Developer Guide文档(在线查看或下载离线PDF),开发更多的业务功能,同时也建议大家将API返回XML的解析处理做的更强壮更灵活些。
声明:本文中涉及到的样例程序版权归亚马逊所有,笔者的修改仅为展示API能力,笔者不对其中产生的任何bug负责。
附录
笔者的ItemLookupSample.java源码
public class ItemLookupSample { /** * Your associate tag, as taken from Associate administration page. */ private static final String ASSOCIATE_TAG = "YOUR_ASSOCIATE_TAG_HERE"; /** * Your AWS Access Key ID, as taken from the AWS Your Account page. */ private static final String AWS_ACCESS_KEY_ID = "YOUR_ACCESS_KEY_ID_HERE"; /** * Your AWS Secret Key corresponding to the above ID, as taken from the AWS * Your Account page. */ private static final String AWS_SECRET_KEY = "YOUR_SECRET_KEY_HERE"; /** * Use one of the following end-points, according to the region you are * interested in: * * US: ecs.amazonaws.com * CA: ecs.amazonaws.ca * UK: ecs.amazonaws.co.uk * DE: ecs.amazonaws.de * FR: ecs.amazonaws.fr * JP: ecs.amazonaws.jp * CN: webservices.amazon.cn */ private static final String ENDPOINT = "webservices.amazon.cn"; /** * The Item ID to lookup. The value below was selected for the US locale. * You can choose a different value if this value does not work in the * locale of your choice. */ private static final String ITEM_ID = "B00D2J9ETE"; public static void main(String[] args) { // Set up the signed requests helper SignedRequestsHelper helper; try { helper = SignedRequestsHelper.getInstance(ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY); } catch (Exception e) { e.printStackTrace(); return; } String requestUrl = null; String title = null; // The helper can sign requests in two forms - map form and string form. // Here is an example in map form, where the request parameters are stored in a map. System.out.println("Map form example:"); Map<String, String> params = new HashMap<String, String>(); params.put("Service", "AWSECommerceService"); params.put("Version", "2011-08-01"); params.put("AssociateTag", ASSOCIATE_TAG); params.put("Operation", "ItemLookup"); params.put("ItemId", ITEM_ID); params.put("ResponseGroup", "Small"); requestUrl = helper.sign(params); System.out.println("Signed Request is " + requestUrl); title = fetchTitle(requestUrl); System.out.println("Signed Title is \"" + title + "\""); System.out.println(); //Here is an example with string form, where the requests parameters have already been concatenated // into a query string. System.out.println("String form example:"); String queryString = "Service=AWSECommerceService&Version=2011-08-01&AssociateTag=" + ASSOCIATE_TAG + "&Operation=ItemLookup&ResponseGroup=Small&ItemId=" + ITEM_ID; requestUrl = helper.sign(queryString); System.out.println("Request is " + requestUrl); title = fetchTitle(requestUrl); System.out.println("Title is \"" + title + "\""); System.out.println(); } /** * Utility function to fetch the response from the service and extract the * title from the XML. */ private static String fetchTitle(String requestUrl) { String title = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(requestUrl); Node titleNode = doc.getElementsByTagName("Title").item(0); title = titleNode.getTextContent(); } catch (Exception e) { throw new RuntimeException(e); } return title; } }
关于IAM
笔者也有在研究亚马逊的AWS,里边有一套IAM服务,非常方便账户权限的管理,比如我可以创建一个账号,只给它S3的权限,其他服务就访问不了,别人冒用了这个用户的认证信息,也不会造成比S3之外更多的影响。如果能使用IAM用户为联盟API提供认证,会更加方便些,但经过一番调研,结论是,截止到14年3月笔者撰文时,IAM不支持联盟API:
http://stackoverflow.com/questions/9689357/is-it-possible-to-generate-an-aws-access-key-via-iam-for-use-with-the-product-ad