Аутентификация аутентификации ETrade API

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

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

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

api,oauth,windows-services,etrade-api,

0

Ответов: 2


1 принят

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

Sloppy code выглядит так:

            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);
            }

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!

API, OAuth, окна-услуги, ETrade-апи,