2016-10-29 3 views
0

背景
ETrade認証システムでは、RequestTokenを作成してからAuthorization URLを実行すると、ETradeページが開きます。 ユーザーは自分のアカウントでアクティビティを認証するためにログインします。 ピンを受け取って、アプリに入力します。 RequestTokenとピンを使ってExchangeRequestTokenForAccessTokenを呼び出します。 それから私たちは離れて走っています。ETrade API無人認証

質問
問題は、バックグラウンドで連続して実行されるサービスを作成することです。ログインするユーザーはいません。逆に、私は取引をしません。ちょうど数字を集め、特定の基準を満たす株式を探します。 これを無人で動作させる方法を理解できません。

ありがとう、Brad。

+0

トークンは真夜中に有効期限が切れます。 etradeを呼び出して永続トークンを要求すると、30日後に有効期限が切れます。取引などに使用することはお勧めしません。認証プロセスでコードを変更する必要はありません。有効期限が切れると予測し、更新を促す。 – BWhite

答えて

1

以前は、一連のWebRequestsを使用し、手動でヘッダを追加して認証ページをシミュレートしました。これはETradeが情報を追跡しているようなものでヘッダーを複雑にする約1年前まで機能しました。 http://watin.org/を使用してログインし、認証コードを削除します。

  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フィールドがありましたが、ログインボタンにはさまざまな名前があり、壊れやすいように見えました。もしこれがうまくいかなければ、それが私がチェックする最初のことです。 第2に、私が認証ページに直接行くと、ログインを促しますが、頻繁に認証ページに行くことはありません。 ホームページにアクセスしてログインし、認証ページに行くと、より一貫した結果が得られます。このようにそれを自動化することができること

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!