Back again. I have successfully learned how to sign my GET requests for the E*TRADE API, but now I am up to POST requests for placing orders.
I build the order and use a REST POST to send the request.
The string to encode for the signature is the same as what I am using for GET of my account information and market data, except instead of "GET" at the start is replaced by "POST".
The string to encode for the signature is:
POST&%20https%3A%2F%2Fapi.etrade.com%2Fv1%2Faccounts%2F{accountkeyredacted}%2Forders%2Fpreview&oauth_consumer_key%3D{keyredacted}3%26oauth_nonce%3D762480b2bdbae095aff70d8c2da908ab%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1691173914%26oauth_token%3D{tokenredacted}%253D
In addition to setting the Authorization header I set the Content-Type header to appllication/xml
I tried adding "Content-Type=application/xml" to the base string for the signature.
From another similar question I saw something about oauth_body_hash="". Do I need to hash the entire xml body of the order? If so how to you add the entire body of the request to the signature.
I tried showing code but I couldn't post it because of an error saying I had too much code.
I have tried to add oauth_body_hash. In the POST I use with TDAmeritrade (and with E*Trade) I am posting a stream. So I use the same stream to create the body to hash.
var
bodyText: string;
DataStream: TMemoryStream;
begin
DataStream := TMemoryStream.Create;
try
Body.SaveToStream(DataStream);
DataStream.Seek(0, 0);
bodyText := ReadStreamAsString(DataStream);
finally
DataStream.Free;
end;
FKey := URIEncode(etrade_consumer_secret) + '&';
if AccessSecret <> '' then
FKey := FKey + URIEncode(AccessSecret)
else if TokenSecret <> '' then
FKey := FKey + URIEncode(TokenSecret);
OutputDebugString(FKey);
FBodySignature := TNetEncoding.Base64.EncodeBytesToString(THashSHA1.GetHMACAsBytes(bodyText, FKey));
and I add it to the base string that I hash
if FBodySignature <> '' then
Data.Add('oauth_body_hash=' + URIEncode(FBodySignature));
and to the header
result := format('oauth_signature="%s",' +
'oauth_nonce="%s",' +
'oauth_body_hash="%s",' +
'oauth_signature_method="HMAC-SHA1",' +
'oauth_consumer_key="%s",' +
'oauth_timestamp="%s",' +
'oauth_token="%s"',
[SignatureEncoded, Nonce, UriEncode(FbodySignature), UriEncode(ConsumerKey), Timestamp, URIEncode(Token)]);
Still signature invalid.
I tried adding the oauth_body_hash just to the header but not to the main signature. Doesn't work either.
I looked at the python example and it has the following headers:
# Add parameters and header information
headers = {"Content-Type": "application/xml", "consumerKey": config["DEFAULT"]["CONSUMER_KEY"]}
I added my consumerKey as a header. No difference.