0

使用:Delphi 10.2.3 Tokyo IPWorks SSL 和 IPWorks Encrypt 组件

我正在尝试使用 Delphi 的亚马逊 MWS API 来获取订单列表,但未能成功向亚马逊 MWS 发出请求。根据客户的要求,我必须使用 IPWorks 组件。API 的响应表明签名不正确:

发件人 SignatureDoesNotMatch 我们计算的请求签名与您提供的签名不匹配。检查您的 AWS 秘密访问密钥和签名方法。有关详细信息,请参阅服务文档。

显然,这个问题与计算签名、将其编码为 Base64 或请求本身有问题有关。我认为它对 Base64 的编码对我不起作用。也许与 Delphi Unicode 和 UTF-8 编码有关。

我花了一整天的时间试图弄清楚这一点并且被卡住了,所以我把它贴在这里。我希望有人能帮帮忙。下面是我的代码:

在表单上,​​我有 2 个组件:TipwHTTP 和 TipcHash

object HTTPS: TipwHTTP
  FollowRedirects = frAlways
  SSLCertStore = 'MY'
  OnTransfer = HTTPSTransfer
end

object HashMaker: TipcHash
  Algorithm = haHMACSHA256
  EncodeHash = True
end


function GetISO8601DateTime_URLEncodedStr(const ADateTime: TDateTime): String;
var
  d: String;
  l: Integer;
begin
  d := DateToISO8601(TTimeZone.Local.ToUniversalTime(ADateTime), True);
  l := Length(d);
  d := Copy(d, 1, l - 5) + 'Z'; // remove the milliseconds part

  Result := TNetEncoding.URL.Encode(d);
end;

const
  DOMAIN_NAME = 'https://mws.amazonservices.com/Orders/2013-09-01';
var
  sl: TStringList;
  param, signature, aurl: String;
begin
  sl := TStringList.Create;
  try
    sl.Add('AWSAccessKeyId=' + edtAwsAccessKey.Text); { Index: 0 }
    sl.Add('&Action=ListOrders'); { Index: 1 }
    sl.Add('&CreatedAfter=' + GetISO8601DateTime_URLEncodedStr(dtpOrdersCreatedFrom.Date)); { Index: 2 }
    sl.Add('&MWSAuthToken=' + edtMarketplaceID.Text); { Index: 3 }
    sl.Add('&MarketplaceId.Id.1=' + edtMarketplaceID.Text); { Index: 4 }
    sl.Add('&SellerId=' + edtSellerID.Text); { Index: 5 }
    sl.Add('&SignatureMethod=HmacSHA256'); { Index: 6 }   // <---- Insert Signature here
    sl.Add('&SignatureVersion=2'); { Index: 7 }
    sl.Add('&Timestamp=' + GetISO8601DateTime_URLEncodedStr(Now)); { Index: 8 }
    sl.Add('&Version=2013-09-01'); { Index: 9 }

    param := StringReplace(sl.Text, #13#10, '', [rfReplaceAll]);

    HashMaker.Key := edtSecretKey.Text;
    HashMaker.Algorithm := haHMACSHA256;
    HashMaker.InputMessage := 'POST\n' + 'mws.amazonservices.com\n' + '/Orders/2013-09-01\n' + param;
    HashMaker.ComputeHash;
    signature := HashMaker.HashValue;

    SetStatus('Signature1: ' + signature);

    signature := TNetEncoding.Base64.Encode(TEncoding.UTF8.GetString(BytesOf(signature)));

    signature := TNetEncoding.URL.Encode(signature);

    SetStatus('Signature2: ' + signature);

    sl.Insert(6, '&Signature=' + signature);
    param := StringReplace(sl.Text, #13#10, '', [rfReplaceAll]);

    SetStatus('param: ' + param);

  finally
    sl.Free;
  end;

  with HTTPS do
  begin
    ContentType := 'application/x-www-form-urlencoded; charset=UTF-8';
    Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8';
    Timeout := 0;

    aurl := DOMAIN_NAME + '?' + param;
    Post(aurl);
  end;

end;

如果有人可以帮助我解决这个问题,我将不胜感激。

-史蒂夫

4

0 回答 0