Skip to content

Instantly share code, notes, and snippets.

@chrischattin
Last active March 18, 2019 18:15
Show Gist options
  • Save chrischattin/f84616295d55fc6587a04e0762b994d6 to your computer and use it in GitHub Desktop.
Save chrischattin/f84616295d55fc6587a04e0762b994d6 to your computer and use it in GitHub Desktop.
Get an `access code` without running a webserver or interacting with a browser. Makes interacting with the Web API remotely more convenient.
import requests
import json
from urllib.parse import unquote
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
API_KEY = '*******' # Also called the `client_id`
SECRET_KEY = '*******'
REDIRECT_URI = 'http://localhost:8080' # Arbitrary for headless.
BASE_URL = 'https://sim-api.tradestation.com/v2'
USERNAME = "*******"
PASSWORD = "*******"
#
# Security questions and answers...
#
QUESTION_ONE = "*******"
QUESTION_TWO = "*******"
QUESTION_THREE = "*******"
ANSWER_ONE = "*******"
ANSWER_TWO = "*******"
ANSWER_THREE = "*******"
#
# Once we have the auth code, we can exchange it for the refresh token and access token.
#
def get_token_response(access_code):
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
post_data = {
'grant_type': 'authorization_code',
'client_id': API_KEY,
'client_secret': SECRET_KEY,
'redirect_uri': REDIRECT_URI,
'code': access_code
}
r = requests.post(f'{BASE_URL}/Security/Authorize', headers=headers, data=post_data)
try:
return r.json()
except:
return sys.exc_info()[0]
#
# Start Selenium...
#
options = Options()
options.headless = True
driver = webdriver.Firefox(options=options)
auth_url = f"{BASE_URL}/authorize?redirect_uri={REDIRECT_URI}&client_id={API_KEY}&response_type=code"
try:
driver.get(auth_url)
elem = driver.find_element_by_name("username")
elem.clear()
elem.send_keys(USERNAME)
elem = driver.find_element_by_name("password")
elem.clear()
elem.send_keys(PASSWORD)
driver.find_element_by_id("btnLogin").click()
elem = driver.find_element_by_name("ucQuestionAndAnswer$txtAnswer")
elem.clear()
if QUESTION_ONE in driver.page_source:
elem.send_keys(ANSWER_ONE)
elif QUESTION_TWO in driver.page_source:
elem.send_keys(ANSWER_TWO)
elif QUESTION_THREE in driver.page_source:
elem.send_keys(ANSWER_THREE)
else:
print("Uh oh...") # Should probabaly raise exception here.
driver.find_element_by_id("ucQuestionAndAnswer_btnLogin").click()
#
# Lol. If you know a better way to do this, please let me know.
#
except Exception as e:
s = unquote(e.msg) # `e.msg` is in UTF-8, using `unquote` just makes it easier to read/find the start of the access_code from the error message. Not necessary, however.
a, b = s.find("code="), s.find("&c=UTF-8")
access_code = (s[a+5:b]) # The `+5` here is just the length of the string you used to `find` the start of the access_code.
token_response = get_token_response(access_code)
refresh_token = token_response['refresh_token']
access_token = token_response['access_token']
print("--- Token Response ---")
print(token_response)
print("--- Access Code ---")
print(access_code)
print("--- Access Token ---")
print(access_token)
print("--- Refresh Token ---")
print(refresh_token)
driver.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment