Reputation: 1567
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:
Sender
SignatureDoesNotMatch
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.
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)));
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;
I would really appreciate if someone can help me solve this.
-Steve
Upvotes: 0
Views: 231