steve faleiro 1 Posted October 29, 2021 (edited) Using: + Delphi 10.2.3 Tokyo + IPWorks SSL and IPWorks Encrypt components I am trying to use the Amazon MWS API from Delphi to get a list of orders, but am unsuccessful in making the request to Amazon MWS. Its mandatory that I use IPWorks components, as required by my client. The response from the API says that the signature is not correct: Quote <Error> <Type>Sender</Type> <Code>SignatureDoesNotMatch</Code> <Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message> </Error> Obviously the issue has something to do with calculating the signature, encoding it to Base64, or something wrong with the request itself. I think its the encoding to Base64 that is not working for me. Maybe something to do with Delphi Unicode and UTF-8 encoding. I've spent a whole day trying to figure this out and am stuck, so am posting it here. I hope someone can help. Below is my code: On the form I have 2 components: TipwHTTP and 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))); // 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; I would really appreciate if someone can help me solve this. -Steve Edited October 29, 2021 by steve faleiro Share this post Link to post
Wagner Landgraf 43 Posted October 29, 2021 Maybe you can check the source code of the AWS SDK for Delphi, more specifically the AWS Signer unit, and see how it compares to yours and spot any possible difference in algorithm? Share this post Link to post
Guest Posted October 29, 2021 Those components come with free support (unprioritized, albeit), [i may be wrong]. Did you contact /n software about this specific problem? Share this post Link to post
steve faleiro 1 Posted October 29, 2021 50 minutes ago, Dany Marmur said: Those components come with free support (unprioritized, albeit), [i may be wrong]. Did you contact /n software about this specific problem? Its nothing to do with the components. There is an error in the code in building the HTTP request. Something to do with character encoding (Unicode vs UTF8). Share this post Link to post
steve faleiro 1 Posted October 30, 2021 I've still not found the answer. I've now posted 2 questions on StackOverflow. If anyone has experience in this area or has solved this problem before, please reply there (or here). https://stackoverflow.com/questions/69768072/delphi-calculating-amazon-mws-signature https://stackoverflow.com/questions/69781720/delphi-amazon-mws-api-how-do-derive-the-base64-hmac-from-the-sha-256-hmac TIA! Share this post Link to post
steve faleiro 1 Posted October 30, 2021 On 10/29/2021 at 3:50 PM, Wagner Landgraf said: Maybe you can check the source code of the AWS SDK for Delphi, more specifically the AWS Signer unit, and see how it compares to yours and spot any possible difference in algorithm? I've checked but its a huge library, and I'm unable to find the answer from there. Share this post Link to post