Delphi — расчет подписи Amazon MWS

Использование: компоненты Delphi 10.2.3 Tokyo IPWorks SSL и IPWorks Encrypt

Я пытаюсь использовать API Amazon MWS от Delphi для получения списка заказов, но не могу отправить запрос в Amazon MWS. Я обязательно использую компоненты IPWorks, как того требует мой клиент. Ответ от API говорит, что подпись неверна:

Отправитель Рассчитанная нами подпись запроса не соответствует предоставленной вами подписи. Проверьте свой секретный ключ доступа 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;

Я был бы очень признателен, если бы кто-нибудь помог мне решить эту проблему.

-Стив

0 ответов

Другие вопросы по тегам