2017-07-25 59 views
0

授权我的应用程序后,通过将oauth凭证传递给标头来请求访问令牌。签名和头文件是通过这段代码生成的;使用Python3的E * Trade API的get_quote中的标头和oauth

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) for i 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) 

产生这些标题;

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" 

请求返回;

oauth_token=3W3hs5aSQPwMR%2FM0H0%2BPWhI%2Bo%3D&oauth_token_secret=SWvknmgEIgKzbN35bwwoNw%3D 

通过用新的token_secret替换旧的token_secret来更新密钥。基础字符串也用新的标记值以及新的时间戳和随机数更新。这些新值用于生成新签名。

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) for i 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) 

将标题更改为;

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" 

并且发出get_quote请求;

https://etws.etrade.com/market/rest/quote/TICK,ER,THAT,GOES,UP?detailFlag=FUNDAMENTAL 

虽然不是报价,但返回了oauth问题。

<Error> 
<message>oauth_problem=signature_invalid</message> 
</Error> 

我试过在URL中传递信息,但它返回相同的错误。请求中是否存在程序错误?是否应该使用新的令牌而不更新签名?

(已过帐凭证已被更改,以保护无辜)

+0

[编辑]您的问题,并显示您的代码从'OAuthSession'和'request.post(...)。 – stovfl

回答

1

的问题是在签名生成。

对于URL部分,应该包含完整的URL直到查询字符串。在这个例子中,它将是:

base_string = quote_plus('GET') + '&' + \ 
      quote_plus('https://etws.etrade.com/market/rest/quote/TICK,ER,THAT,GOES,UP') + '&' + \ 

当连接oauth参数时,您还应该包含所有非Oauth查询参数。他们需要按照规格排序(https://oauth.net/core/1.0a/#anchor13)。在这种情况下,你需要包括detailFlag =根本性作为你的第一个参数:

quote_plus('detailFlag=FUNDAMENTAL&') + \ 
quote_plus('oauth_consumer_key={}&'.format(oauth_consumer_key)) + \ 

而且,不需要在标题中oauth_verifier除了检索访问令牌。

+0

我不会将参数包含到基本字符串中。谢谢!起初它不起作用,我再次阅读了OAuth Core 1.0a和[RFC3986],以确保我没有再次忽略某些东西。最后,我在基本字符串中找到尾随符号。我删除了单个字符,并看到引号!明天我会讨论XML与JSON,但感谢您的帮助。 – jsfa11