2016-10-29 9 views
0

Фон
Система аутентификации ETrade позволяет мне создать RequestToken, а затем выполнить URL-адрес авторизации, который открывает страницу ETrade. Пользователь регистрируется для авторизации активности в своей учетной записи. Они получают булавку, которую они вводят в мое приложение. Я вызываю ExchangeRequestTokenForAccessToken с помощью RequestToken и Pin. Затем мы выключены.ETAP API автоматической проверки подлинности

Вопрос
Проблема в том, что я создаю службу, которая работает непрерывно в фоновом режиме. Пользователю не будет входа в систему. И наоборот, я не буду делать какие-либо сделки. Просто хрусткие цифры, ища акции, соответствующие определенным критериям. Я не могу понять, как заставить это работать без присмотра.

Спасибо, Брэд.

+0

Токен заканчивается в полночь, если не установлен иначе. Но вы можете назвать etrade и запросить постоянные токены, после чего они истекают через 30 дней. Не рекомендуется использовать для торгов и т. Д. В процессе аутентификации не требуется никаких изменений кода. Только проецирование, когда они истекают, и побуждая их возобновить их. – BWhite

ответ

1

Раньше я использовал серию WebRequests и вручную добавлял заголовки для имитации страниц авторизации. Это работало до года назад, когда ETrade усложняла свои заголовки тем, что, по-видимому, отслеживает информацию. Теперь я использую http://watin.org/ для входа в систему и для удаления кода Auth.

Слоппи код выглядит следующим образом:

  using WatiN.Core; // IE Automation 
... 
      // verify current thread in STA. 

      Settings.Instance.MakeNewIeInstanceVisible = false; 

      var ieStaticInstanceHelper = new IEStaticInstanceHelper(); 
      Settings.AutoStartDialogWatcher = false; 

      using (ieStaticInstanceHelper.IE = new IE()) 
      { 
       string authCode = ""; 
       ieStaticInstanceHelper.IE.GoTo(GetAuthorizationLink()); 

       if (ieStaticInstanceHelper.IE.ContainsText("Scheduled System Maintenance")) 
       { 
        throw new ApplicationException("eTrade down for maintenance."); 
       } 

       TextField user = ieStaticInstanceHelper.IE.TextField(Find.ByName("USER")); 

       TextField pass = ieStaticInstanceHelper.IE.TextField(Find.ById("txtPassword")); 

       TextField pass2 = ieStaticInstanceHelper.IE.TextField(Find.ByName("PASSWORD")); 

       Button btn = ieStaticInstanceHelper.IE.Button(Find.ByClass("log-on-btn")); 
       Button btnAccept = ieStaticInstanceHelper.IE.Button(Find.ByValue("Accept")); 


       TextField authCodeBox = ieStaticInstanceHelper.IE.TextField(Find.First()); 

       if (user != null && pass != null && btn != null && 
        user.Exists && pass2.Exists && btn.Exists) 
       { 
        user.Value = username; 
        pass2.Value = password; 
        btn.Click(); 
       } 

       btnAccept.WaitUntilExists(30); 
       btnAccept.Click(); 

       authCodeBox.WaitUntilExists(30); 
       authCode = authCodeBox.Value; 

       SavePin(authCode); 
      } 
+0

Это была большая помощь. Поскольку WatiN и ETrade изменились, я опубликовал обновленную версию этого ниже. – BWhite

1

Текущая версия кода Брэда Мелтона. WatiN изменился и больше не содержит функцию IE.AttachToIE. Итак, IEStaticInstanceHelper теперь называется StaticBrowserInstanceHelper, но этот код трудно найти, поэтому я включил его здесь.

class StaticBrowserInstanceHelper<T> where T : Browser { 
    private Browser _browser; 
    private int _browserThread; 
    private string _browserHwnd; 

    public Browser Browser { 
     get { 
      int currentThreadId = GetCurrentThreadId(); 
      if (currentThreadId != _browserThread) { 
       _browser = Browser.AttachTo<T>(Find.By("hwnd", _browserHwnd)); 
       _browserThread = currentThreadId; 
      } 
      return _browser; 
     } 
     set { 
      _browser = value; 
      _browserHwnd = _browser.hWnd.ToString(); 
      _browserThread = GetCurrentThreadId(); 
     } 
    } 

    private int GetCurrentThreadId() { 
     return Thread.CurrentThread.GetHashCode(); 
    } 
} 

Имена страниц ETrade также изменились. У них их несколько. На всех страницах входа, которые я проверил, всегда было поле USER и поле PASSWORD, но кнопки входа в систему имели разные имена, которые выглядели хрупкими. Поэтому, если это не сработает, это первое, что я проверил. Во-вторых, если я перейду непосредственно на страницу auth, он предложит войти в систему, но затем он часто не доходит до страницы auth. Я получил более последовательные результаты, перейдя на домашнюю страницу для входа в систему, а затем перейдя на страницу авторизации.

static public string GetPin(string username, string password, string logonLink, string authLink) { 
     // Settings.Instance.MakeNewIeInstanceVisible = false; 

     var StaticInstanceHelper = new StaticBrowserInstanceHelper<IE>(); 
     Settings.AutoStartDialogWatcher = false; 

     // This code doesn't always handle it well when IE is already running, but it won't be in my case. You may need to attach to existing, depending on your context. 
     using (StaticInstanceHelper.Browser = new IE(logonLink)) { 
      string authCode = ""; 

      // Browser reference was failing because IE hadn't started up yet. 
      // I'm in the background, so I don't care how long it takes. 
      // You may want to do a WaitFor to make it snappier. 
      Thread.Sleep(5000); 
      if (StaticInstanceHelper.Browser.ContainsText("Scheduled System Maintenance")) { 
       throw new ApplicationException("eTrade down for maintenance."); 
      } 

      TextField user = StaticInstanceHelper.Browser.TextField(Find.ByName("USER")); 

      TextField pass2 = StaticInstanceHelper.Browser.TextField(Find.ByName("PASSWORD")); 

      // Class names of the Logon and Logoff buttons vary by page, so I find by text. Seems likely to be more stable. 
      Button btnLogOn = StaticInstanceHelper.Browser.Button(Find.ByText("Log On")); 
      Element btnLogOff = StaticInstanceHelper.Browser.Element(Find.ByText("Log Off")); 
      Button btnAccept = StaticInstanceHelper.Browser.Button(Find.ByValue("Accept")); 

      TextField authCodeBox = StaticInstanceHelper.Browser.TextField(Find.First()); 

      if (user != null && btnLogOn != null && 
       user.Exists && pass2.Exists && btnLogOn.Exists) { 
       user.Value = username; 
       pass2.Value = password; 
       btnLogOn.Click(); 
      } 

      Thread.Sleep(1000); 
      if (StaticInstanceHelper.Browser.ContainsText("Scheduled System Maintenance")) { 
       Element btnContinue = StaticInstanceHelper.Browser.Element(Find.ByName("continueButton")); 
       if (btnContinue.Exists) 
        btnContinue.Click(); 
      } 
      btnLogOff.WaitUntilExists(30); 

      // Here we go, finally. 
      StaticInstanceHelper.Browser.GoTo(authLink); 
      btnAccept.WaitUntilExists(30); 
      btnAccept.Click(); 

      authCodeBox.WaitUntilExists(30); 
      authCode = authCodeBox.Value; 
      StaticInstanceHelper.Browser.Close(); 

      return authCode; 
     } 
    } 

Возможность автоматизировать его, как это означает, что я больше не забочусь о том, как долго действует токен. Спасибо, BradM!