我们使用亚马逊产品广告API在其网站上进行重新定价。对于那些不知道它的人来说,基本上可以让你在不需要花费大量时间来处理网页的情况下与Amazon数据库进行交互。它对我们很有用,或者有效。他们现在正在为卖家解散这个API,并将他们转移到他们的MWS服务上的新API。
就我所见,这些电话略有不同。两个明显的区别是PA API使用HTTP和GET,而MWS使用HTTPS和POST。
我不完全确定亚马逊文档中的示例是正确的,因为它们提供了创建哈希签名URL请求的示例。这就是我们在使用GET方法的PA-API上成功完成它的方式。但你能为POST做到这一点吗?我不认为这是可能的,虽然我可能是错的,这肯定是示例所暗示的。
无论如何,创建签名的URL不起作用!所以我决定在Delphi中使用某种低级别的HTTPS POST。
我在这里搜索过,有几个不同的例子,但我不能让它们中的任何一个正常工作。一些示例似乎使用了INDY 10,遗憾的是我们在INDY 9上遇到了(出于兼容性原因)。我还查看了WININET包装器类型函数,但除了异常或错误之外我无法获得结果。
这就是为什么我在这里寻求帮助。
如何使用Delphi对亚马逊MWS进行正确格式化的调用?我尝试了以下网页中的示例:
How to make an HTTPS POST request in Delphi?
等等我能找到的所有等等!但我收到的错误就像'错误的请求'(例外)。
我曾尝试使用Fiddler(如其他地方所建议的)来查看正在发生的事情,但还不能完全了解它(尽管我可以在其中编写一个有效的调用!)
所以我正在寻找一些指针或方向。我真的不想升级INDY或添加新库。我宁愿保持现状并使用我现有的东西。我们正在使用D2007。
为了说明需要什么,我需要进行这种调用(GetServiceStatus
是最简单的):
POST /Products/2011-10-01?AWSAccessKeyId=<ACCESSKEY>
&Action=GetServiceStatus
&SellerId=<SELLERID>
&SignatureVersion=2
&Timestamp=2012-02-14T13%3A26%3A42Z
&Version=2011-10-01
&Signature=dtAvv595blmv%2FnV0h2Yr5bCGzKYXid0hkOuCmZOb3bc%3D
&SignatureMethod=HmacSHA256
到此终点:
https://mws.amazonservices.co.uk/Products/2011-10-01
我认为我的问题出现在我尝试的所有示例中,我不知道如何正确设置调用,这可能是我收到错误请求错误的原因。
因此,非常感谢一个简单的解决方案!
文档链接和观察:
这是API的开发者指南:
这是我们将使用的API的特定部分(取代当前的产品广告API):
这里最基本的功能是GetServiceStatus函数。它不需要参数。但是,它仍然需要使用来自亚马逊的凭证进行身份验证和“签名”(卖家ID,MWS访问密钥和密钥(用于生成签名)。我的感觉是,如果我能够获得最简单的功能,那么休息将会跟进。但是,身份验证的问题使得找到解决方案变得非常困难。没有测试帐户。而且时间戳(以及呼叫的签名)也会过期,只需几分钟。
还有一个“迁移指南”:
但是这个文档确实包含一些错误。例如,结束点不正确。
我的最新代码包括ssl,cookie经理等:
var
LHTTP : TIdHTTP;
IdSSLIOHandlerSocket : TIdSSLIOHandlerSocket;
IdCookieManager : TIdCookieManager;
LParams : TStringList;
LResponse : string;
begin
IdCookieManager:=TIdCookieManager.Create(self);
IdSSLIOHandlerSocket:=TIdSSLIOHandlerSocket.Create(self);
with IdSSLIOHandlerSocket do begin
SSLOptions.Method := sslvSSLv3;
end;
LHTTP := TIdHTTP.Create(Self);
with LHTTP do begin
CookieManager:=IdCookieManager;
AllowCookies:=true;
IOHandler:=IdSSLIOHandlerSocket;
Request.ContentType:='text/xml';
Port:=443;
HandleRedirects:=true;
Host:='mws.amazonservices.co.uk';
ProtocolVersion:=pv1_1
end;
LParams := TStringList.Create;
try
LParams.Add('AWSAccessKeyId=<ACCESSKEY>');
LParams.Add('Action=GetServiceStatus');
LParams.Add('SellerId=<SELLERID>)');
LParams.Add('SignatureVersion=2');
LParams.Add('Timestamp=2012-02-15T13%3A00%3A07Z');
LParams.Add('Version=2011-10-01');
LParams.Add('Signature=viPlDAbzEBwlTAwq4hNaZi%2Fa1Klf7qIXIP%2BKUsOcJTI%3D');
LParams.Add('SignatureMethod=HmacSHA256');
LResponse:=LHTTP.Post('https://mws.amazonservices.co.uk/Products/2011-10-01?', LParams);
ShowMessage( LResponse );
except
on E: Exception do
ShowMessage('ouch! ' + E.Message );
end;
LHTTP.Free;
IdSSLIOHandlerSocket.Free;
IdCookieManager.Free;
end;
这是基于亚马逊期望根据其暂存器获得的内容。最后的用户代理是可选的,不是必需的,也不是签名过程的一部分:
POST /Products/2011-10-01?AWSAccessKeyId=<ACCESSID>
&Action=GetServiceStatus
&SellerId=<SELLERID>
&SignatureVersion=2
&Timestamp=2012-02-15T13%3A00%3A07Z
&Version=2011-10-01
&Signature=viPlDAbzEBwlTAwq4hNaZi%2Fa1Klf7qIXIP%2BKUsOcJTI%3D
&SignatureMethod=HmacSHA256 HTTP/1.1
Host: mws.amazonservices.co.uk
x-amazon-user-agent: AmazonJavascriptScratchpad/1.0 (Language=Javascript)
Content-Type: text/xml
我试图从Fiddler获取信息,但它没有显示来自软件的任何流量,但它必须与Amazon通信以获得“400错误请求”错误。奇
答案 0 :(得分:4)
我会使用TIdHTTP,在HTTPOptions中使用您的凭据(如果适用)进行设置,然后执行:
procedure ...
var
LHTTP: TIdHTTP;
LParams: TStringList;
LResponse: string;
begin
LHTTP := TIdHTTTP.Create;
LParams := TStringList.Create;
try
// setup params, basically you're doing key-value pairs that will be encoded in the post
// as KEY1=VALUE1&key2=value2&KEY3=value3, etc.
// in the URL, stuff after ? are parameters
// you don't have to worry about encoding parameters, indy will do it for you
LParams['AWSAccessKeyId'] := '<ACCESSKEY>';
LParams['Action'] := 'GetServiceStatus';
LParams['SellerId'] := '<SELLERID>'
LParams['SignatureVersion'] := '2';
// adjust timestamp
LParams['Timestamp'] := '2012-02-14T13%3A26%3A42Z';
LParams['Version'] := '2011-10-01'
// adjust signature...
LParams['Signature'] := 'dtAvv595blmv%2FnV0h2Yr5bCGzKYXid0hkOuCmZOb3bc%3D';
LParams['SignatureMethod'] := 'HmacSHA256';
LResponse := LHTTP.Post('https://mws.amazonservices.co.uk/Products/2011-10-01', LParams);
ShowMessage( LResponse );
except
on E: Exception do
ShowMessage('ouch! ' + E.Message );
end;
end;
我认为您需要将“/ Products / 2011-10-01”替换为您搜索的日期,即“/ Products / 2012-02-14”等等......
此外,如果我没有弄错,则需要SSL库...
答案 1 :(得分:1)
只是为了让每个人都知道我放弃了尝试获得这个工作的POST解决方案 - 我因为无法接近结果而浪费太多编程时间而感到非常沮丧。
相反,我回到了基础,我已经更改了字符串以签署GET而不是POST,然后创建了一个参数化的URL,然后我调用它来获取XML结果。
也许不是技术上或美学上最好的解决方案,但是,嘿,它有效!
但感谢eveyone的帮助和建议,感谢。
答案 2 :(得分:1)
只是为了让你知道,我与这个问题分享了你的痛苦,最终转到了GET格式,最后阅读了手册
使用自然字节顺序按参数名称对UTF-8查询字符串组件进行排序。参数可以 来自GET URI或POST主体(当Content-Type为application / x-www-form-urlencoded时)。
如果您在标题中设置了上述内容类型,则可以使用