/// <summary> /// Request a new authentication token given the current refresh token /// </summary> /// <param name="preAuthenticateCallback">Method called just prior to authentication request</param> /// <param name="accessTokenExpiryCallback">Method called to pass token expiry once authenticated</param> /// <returns></returns> public async Task Authenticate(string refreshToken = "") { HttpResponseMessage resp; if (refreshToken != "") { _auth.refresh_token = refreshToken; } try { resp = await authClient.GetAsync(string.Format("https://login.questrade.com/oauth2/token?grant_type=refresh_token&refresh_token={0}", _auth.refresh_token)); if (resp.IsSuccessStatusCode) { PostAuthentication(resp); } else { UnsuccessfulAuthArgs arg = new UnsuccessfulAuthArgs(); arg.resp = resp; OnUnsuccessfulAuthentication(typeof(Questrade), arg); } } catch (HttpRequestException ex) { APIGetErrorArg arg = new APIGetErrorArg(); arg.httpRequestException = ex; OnHttpGetError(this, arg); //Raise http exception event } }
/// <summary> /// Exchanges code from redirect URL parameter for an access token. Read more at https://www.questrade.com/api/documentation/authorization /// </summary> /// <param name="clientId"></param> /// <param name="redirectURL"></param> /// <param name="code"></param> /// <param name="preAuthenticateCallback"></param> /// <param name="accessTokenExpiryCallback"></param> /// <returns></returns> public async Task CodeToAccessToken(string clientId, string redirectURL, string code) { try { string req = string.Format("https://login.questrade.com/oauth2/token?client_id={0}&code={1}&grant_type=authorization_code&redirect_uri={2}", clientId, code, redirectURL); var resp = await authClient.GetAsync(req); if (resp.IsSuccessStatusCode) { PostAuthentication(resp); } else { UnsuccessfulAuthArgs arg = new UnsuccessfulAuthArgs(); arg.resp = resp; OnUnsuccessfulAuthentication(this, arg); } } catch (HttpRequestException ex) { APIGetErrorArg arg = new APIGetErrorArg(); arg.httpRequestException = ex; OnHttpGetError(this, arg); //Raise http exception event } }
/// <summary> /// Method used to make a GET call to Questrade API /// </summary> /// <typeparam name="T">Return type</typeparam> /// <param name="client">Authenticated http client</param> /// <param name="requestUri">Request URIm</param> /// <returns></returns> private APIReturn <T> ApiGet <T>(HttpClient client, string requestUri, CancellationToken token = default(CancellationToken)) { APIReturn <T> apiReturn = new APIReturn <T>(); try { token.ThrowIfCancellationRequested(); var resp = client.GetAsync(requestUri, token).Result;//, token); if (!token.IsCancellationRequested) { //Parse rate limit headers System.Collections.Generic.IEnumerable <string> RemainIEnum; bool hasRateLimitRemain = resp.Headers.TryGetValues("X-RateLimit-Remaining", out RemainIEnum); System.Collections.Generic.IEnumerable <string> RateResetIEnum; bool hasRateReset = resp.Headers.TryGetValues("X-RateLimit-Reset", out RateResetIEnum); int numAPICallsRemain; if (hasRateLimitRemain && hasRateReset) { int.TryParse(((string[])RemainIEnum)[0], out numAPICallsRemain); int ResetUnixTime; int.TryParse(((string[])RateResetIEnum)[0], out ResetUnixTime); System.DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); apiReturn.RateReset = dt.AddSeconds(ResetUnixTime).ToLocalTime(); apiReturn.NumCallsLeft = numAPICallsRemain; } //Error parse string respStr = resp.Content.ReadAsStringAsync().Result; if (respStr.Contains("message")) { apiReturn.isSuccess = false; ParseErrorAndRaiseEvent(resp); } else { apiReturn.isSuccess = true; apiReturn.q_obj = JsonToObject <T>(resp.Content.ReadAsStringAsync().Result); } return(apiReturn); } else { return(default(APIReturn <T>)); } } catch (HttpRequestException ex) { APIGetErrorArg arg = new APIGetErrorArg(); arg.httpRequestException = ex; OnHttpGetError(this, arg); //Raise http exception event return(apiReturn); } }