It is nasty to debug Amazon MWS Feed submissions because whatever you might be doing wrong Ama just returns the same senseless error message:
<Error>
<Type>Sender</Type>
<Code>InvalidParameterValue</Code>
<Message>Either Action or Operation query parameter must be present.</Message>
</Error>
I am 100% positive that I build StringToSign correctly as well as calculate HMAC-SHA256, etc. It took me a few weeks to collect and adopt a stack of useful functions for hashing, signing, base64ing, etc. MWS requests. Written in pure Pascal they were all tested on Orders and Products APIs.
Now when it comes to Feeds API I am stuck on the above error. All parameters are equal to those generated by MWS Scratchpad. I tested the submission StringToSign generated by MWS Scratchpad, but no luck.
What I noticed so far: there is a difference between the number/values of headers generated by MWS Scratchpad and my app.
The Scratchpad generates the following headers (it least they are displayed):
Host: mws.amazonservices.ca
x-amazon-user-agent: AmazonJavascriptScratchpad/1.0 (Language=Javascript)
Content-Type: text/xml
My app uses Indy (in XE4) TIdHTTP to make a request. When Amazon returns the above error, Request.RawHeaders.Text
contains the following:
Content-Length: 251
x-amazon-user-agent: MyApp/1.1(Language=Delphi;Platform=Windows7)
Content-Type: text/xml
Host: mws.amazonservices.ca
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: MyApp/1.1(Language=Delphi;Platform=Windows7)
Looks like the extra the headers are added to Request
object by default. My first question is: can those extra headers theoretically influence on the behavior? I.e. can they be the showstoppers?
My second question: is there any option to mofidy the list of default heades in Indy HTTP.Request
? To go on with the debugging I would rather exclude extra headers to see if the request works.
UPDATE: (SignedString)
AWSAccessKeyId=<AWSAccessKeyId>
&Action=GetFeedSubmissionList
&Merchant=<MerchantId>
&SignatureMethod=HmacSHA256
&SignatureVersion=2
&Timestamp=2015-07-26T09%3A04%3A59Z
&Version=2009-01-01
&Signature=1OI0PVgL3uh5sFXxjCzaaWEwGmW6h5e0dgLUFkPgoXg%3D
UPDATE: (Complete HTTP Request/Response provided by TIdLogFile
)
Stat Connected.
Sent 28.07.2015 12:28:11:
POST / HTTP/1.1<EOL>
Content-Type: text/xml; charset=us-ascii<EOL>
Content-Length: 279<EOL>
x-amazon-user-agent: MyAppNameAndVer<EOL>
Host: mws.amazonservices.ca<EOL>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<EOL>
Accept-Encoding: identity<EOL>
User-Agent: Mozilla/3.0 (compatible; Indy Library)<EOL><EOL>
Sent 28.07.2015 12:28:11:
AWSAccessKeyId=<AWSAccessKeyId>
&Action=GetFeedSubmissionList
&MWSAuthToken=<AWSAuthToken>
&Merchant=<MerchantId>
&SignatureMethod=HmacSHA256
&SignatureVersion=2
&Timestamp=2015-07-28T10%3A28%3A09Z
&Version=2009-01-01
&Signature=I6euLIiVDzjZ8bbdtF840K0TJCkGh4NrUbQPtQtu78A%3D
Recv 28.07.2015 12:28:11:
HTTP/1.1 400 Bad Request<EOL>
Date: Tue, 28 Jul 2015 10:28:10 GMT<EOL>
Server: AmazonMWS<EOL>
x-mws-request-id: 7e63280d-1db5-4d10-af40-587747d032a8<EOL>
x-mws-timestamp: 2015-07-28T10:28:11.048Z<EOL>
x-mws-response-context: OmAlguEmW20QT07uIdb9d25xkX+JSS7uFr1rDvXIoqXMvbUFzUMt1b5Xl2WzDaJszbwr25N/J4c=<EOL>
Content-Type: text/xml<EOL>
Content-Length: 324<EOL>
Vary: User-Agent<EOL>
nnCoection: close<EOL><EOL>
<?xml version="1.0"?><LF><ErrorResponse xmlns="https://mws.amazonservices.com/"><LF> <Error><LF> <Type>Sender</Type><LF> <Code>InvalidParameterValue</Code><LF> <Message>Either Action or Operation query parameter must be present.</Message><LF> </Error><LF> <RequestID>7e63280d-1db5-4d10-af40-587747d032a8</RequestID><LF></ErrorResponse><LF>
Stat Disconnected.
Please note: I formatted the response for your convenience adding CRs after <EOL>
Confusing nnCoection
header is explained here: Cneonction and nnCoection HTTP headers
My question is now resolved. Below is my way to thank people not breaking the Community standards ;-)
Days := 1;
repeat
IsSuccessful := DebugAmazonFeedSubmissionProc;
Inc(Days);
until IsSuccessful or (Days = 14);
if not IsSuccessful then
begin
AskTheGods(@StackOverflow);
Sleep(1000); // ...wake up and drink a cup'o'tea :)
Expert := TRemyLebeau.Create('delphi');
try
Expert.ReviewTheCode;
Expert.GetTheJobDone;
finally
// You may dispose the instance here,
// but the Class is one of the most valuable assets of the Community.
// Thank you, Remy!
end;
end;