python - headers and oauth in get_quote for E*Trade API using Python3 -
after authorizing application, request access token passing oauth credentials through header. signature , headers generated through code;
api_module = 'oauth' api_restful = 'access_token' if renewal: api_restful = 'renew_access_token' production_url = 'https://etws.etrade.com/{0:s}/{1:s}'.format(api_module, api_restful) oauth_timestamp = int(time.time()) rand_str = lambda n: ''.join([random.choice(string.hexdigits) in range(n)]) oauth_nonce = rand_str(40) key = oauth_consumer_secret + \ '&' + \ quote_plus(oauth_token_secret) base_string = quote_plus('get') + '&' + \ quote_plus('https://etws.etrade.com/oauth/access_token') + '&' + \ quote_plus('oauth_consumer_key={}&'.format(oauth_consumer_key)) + \ quote_plus('oauth_nonce={}&'.format(oauth_nonce)) + \ quote_plus('oauth_signature_method=hmac-sha1&') + \ quote_plus('oauth_timestamp={:d}&'.format(oauth_timestamp)) + \ quote_plus('oauth_token={}&'.format(quote_plus(oauth_token))) + \ quote_plus('oauth_verifier={}'.format(oauth_verification_code)) hashed = hmac.new(key.encode(), base_string.encode(), sha1) oauth_signature = quote_plus(binascii.b2a_base64(hashed.digest())[:-1]) header_string = 'authorization: oauth ' + \ 'realm="",' + \ 'oauth_signature="{}",'.format(oauth_signature) + \ 'oauth_nonce="{}",'.format(quote_plus(oauth_nonce)) + \ 'oauth_signature_method="{}",'.format(oauth_signature_method) + \ 'oauth_consumer_key="{}",'.format(oauth_consumer_key) + \ 'oauth_timestamp="{}",'.format(str(oauth_timestamp)) + \ 'oauth_verifier="{}",'.format(oauth_verification_code) + \ 'oauth_token="{}"'.format(quote_plus(oauth_token)) headers_list.append(header_string) response = curl_get_http(current_url=production_url)
produces these headers;
host: etws.etrade.com accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 connection: keep-alive authorization: oauth realm="", oauth_signature="fzqlbi8lblbgs1clp4eags09yum%3d", oauth_nonce="e447ea1fcfbccf0116fbdc47be8e4aa4cf7e3aab", oauth_signature_method="hmac-sha1", oauth_consumer_key="4b6471c7ee", oauth_timestamp="1501003943", oauth_verifier="o5k2a", oauth_token="bvukv9q7f93oxjbqy%2fzrmoqi0m%3d"
the request returns;
oauth_token=3w3hs5asqpwmr%2fm0h0%2bpwhi%2bo%3d&oauth_token_secret=swvknmgeigkzbn35bwwonw%3d
the key updated replacing old token_secret new token_secret. base string updated new token value , new time stamp , nonce. these new values used generate new signature.
url_quotes = 'https://etws.etrade.com/market/rest/quote/{0:s}?detailflag={1:s}'.format(symbols, flag) oauth_timestamp = int(time.time()) rand_str = lambda n: ''.join([random.choice(string.hexdigits) in range(n)]) oauth_nonce = rand_str(40) key = oauth_consumer_secret + \ '&' + \ oauth_token_secret base_string = quote_plus('get') + '&' + \ quote_plus('https://etws.etrade.com/market/rest/quote') + '&' + \ quote_plus('oauth_consumer_key={}&'.format(oauth_consumer_key)) + \ quote_plus('oauth_nonce={}&'.format(oauth_nonce)) + \ quote_plus('oauth_signature_method=hmac-sha1&') + \ quote_plus('oauth_timestamp={:d}&'.format(oauth_timestamp)) + \ quote_plus('oauth_token={}&'.format(oauth_token)) #+ \ #quote_plus('oauth_verifier={}'.format(oauth_verification_code)) hashed = hmac.new(key.encode(), base_string.encode(), sha1) oauth_signature = quote_plus(binascii.b2a_base64(hashed.digest())[:-1]) header_string = 'authorization: oauth ' + \ 'realm="",' + \ 'oauth_signature="{}",'.format(oauth_signature) + \ 'oauth_nonce="{}",'.format(quote_plus(oauth_nonce)) + \ 'oauth_signature_method="{}",'.format(oauth_signature_method) + \ 'oauth_consumer_key="{}",'.format(oauth_consumer_key) + \ 'oauth_timestamp="{:d}",'.format(oauth_timestamp) + \ 'oauth_verifier="{}",'.format(oauth_verification_code) + \ 'oauth_token="{}"'.format(oauth_token) headers_list.append(header_string) response = curl_get_http(current_url=url_quotes)
changing headers to;
host: etws.etrade.com accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 connection: keep-alive authorization: oauth realm="", oauth_signature="v4xa%2frcktfrsudhw%3d", oauth_nonce="57fcc260f81b2fad95acca69fe07bffcd06d83ab", oauth_signature_method="hmac-sha1", oauth_consumer_key="4b6471c7ee", oauth_timestamp="1501003945", oauth_verifier="o5k2a", oauth_token="3w3hs5asqpwmr%2fm0h0%2bpwhi%2bo%3d"
and get_quote request made;
https://etws.etrade.com/market/rest/quote/tick,er,that,goes,up?detailflag=fundamental
though, instead of quote, oauth problem returned.
<error> <message>oauth_problem=signature_invalid</message> </error>
i have tried passing information in url, returns same error. there procedural errors in request? should new token used without updating signature?
(the posted credentials have been changed protect innocent)
the problem in signature generation.
for url portion, should include full url query string. in example be:
base_string = quote_plus('get') + '&' + \ quote_plus('https://etws.etrade.com/market/rest/quote/tick,er,that,goes,up') + '&' + \
when concatenating oauth parameters should include non-oauth query parameters well. need in sorted order per spec (https://oauth.net/core/1.0a/#anchor13). in case need include detailflag=fundamental first parameter:
quote_plus('detailflag=fundamental&') + \ quote_plus('oauth_consumer_key={}&'.format(oauth_consumer_key)) + \
also, oauth_verifier not needed in header except retrieve access token.
Comments
Post a Comment