delphi - 在 Delphi 2007 中对 Amazon 进行 HTTPS POST 调用

标签 delphi amazon-mws

我们使用亚马逊产品广告 API 在他们的网站上重新定价。对于那些不知道它的人来说,它基本上可以让您查询 Amazon 数据库,而无需执行诸如抓取网页之类的耗时操作。它对我们非常有效,或者已经。他们现在正在为卖家解散这个 API,并将我们转移到他们的 MWS 服务上的新 API。

据我所知,这些电话略有不同。两个明显的区别是 PA API 使用 HTTP 和 GET,而 MWS 使用 HTTPS 和 POST。

我不完全确定 Amazon 文档中的示例是否正确,因为它们给出了创建为哈希签名 URL 请求的示例。这是我们过去在使用 GET 方法的 PA-API 上成功执行此操作的方式。但是你可以为 POST 做到这一点吗?我不认为这是可能的,尽管我可能是错的,这当然是例子所暗示的。

无论如何,创建签名 URL 不起作用!所以我决定在 Delphi 中使用某种较低级别的 HTTPS POST。

我在这里搜索过,有几个不同的例子,但我无法让它们中的任何一个正常工作。一些示例似乎使用了 INDY 10,不幸的是我们被困在了 INDY 9 上(出于兼容性原因)。我还查看了 WININET 包装类型函数,但除了异常或错误之外,我无法返回结果。

所以这就是为什么我在这里寻求帮助。

如何使用 Delphi 对 Amazon MWS 进行格式正确的调用?我尝试过以下页面的示例:

How to make an HTTPS POST request in Delphi?

等等等等所有我能找到的!

但是我收到了“错误请求”之类的错误(异常(exception))。

我曾尝试使用 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 的开发人员指南:

https://images-na.ssl-images-amazon.com/images/G/02/mwsportal/doc/en_US/bde/MWSDeveloperGuide._V161846143_.pdf

这是我们将使用的 API 的特定部分(取代当前的产品广告 API):

https://images-na.ssl-images-amazon.com/images/G/02/mwsportal/doc/en_US/bde/MWSDeveloperGuide._V161846143_.pdf

这里最基本的函数是 GetServiceStatus 函数。它不需要任何参数。但是,它仍然需要使用来自亚马逊的凭证(卖家 ID、MWS 访问 key 和 key (用于生成签名)进行身份验证和“签名”)。我的感觉是,如果我可以使用最简单的功能,那么休息会随之而来。但身份验证的问题是使找到解决方案如此困难的原因。没有测试帐户。而且时间戳(因此调用的签名)到期了几分钟。

还有一个“迁移指南”:

https://images-na.ssl-images-amazon.com/images/G/02/mwsportal/doc/en_US/products/MWSProductsApiMigrationGuide._V140058392_.pdf

但是这个文档确实包含一些错误。例如,终点不正确。

我的最新代码包括 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 获取信息,但它没有显示来自软件的任何流量,但它必须与亚马逊通信才能获得“400 错误请求”错误。奇怪的。

最佳答案

我会使用 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 库...

关于delphi - 在 Delphi 2007 中对 Amazon 进行 HTTPS POST 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9279089/

相关文章:

delphi - Delphi XE2 Firemonkey的Align属性设置为alScale如何影响坐标系?

delphi - 在 Windows 7 中看不到性能对象

amazon-mws - 亚马逊订单确认 feed

php - 在 PHP 中运行异步函数的最有效方法是什么?

c# - 连接到亚马逊商城网络服务

delphi - 有限元Delphi库

delphi 2009 unicode + ansi问题

sql-server - 在 SQL Server 中创建 USER 生成错误 : SUBQUERY RETURNED MORE THAN 1 VALUE

django - XML 向亚马逊 MWS 提交得很好,但价格没有更新

api - 亚马逊 MWS 暂存器访问被拒绝