public void BuildPKCEAuthUrl() { using (var handler = new HttpClientHandler { UseCookies = false, AllowAutoRedirect = false }) using (var httpClient = new HttpClient(handler)) // httpClient lifetime is handled by caller - client should be kept for duration of SaxoClient lifetime { var config = new SaxoClientOptions { // Set the appkey to whatever value is stores in the secrets manager AppKey = _configuration["SaxoClient:AppKey"], }; Assert.NotEmpty(config.AppKey); using (var saxoClient = new SaxoClient( _loggerFactory.CreateLogger <SaxoClient>(), Options.Create(config), httpClient)) { var authUri = saxoClient.GetPKCEAuthUrl(); _logger.LogInformation("Got the authentication Uri: {uri}", authUri); Assert.StartsWith(config.AuthenticationUrl, authUri); Assert.Contains(config.AppKey, authUri); Assert.Contains(saxoClient.CodeVerifier, authUri); Assert.Contains("S256", authUri); Assert.Contains(Uri.EscapeDataString(saxoClient.RedirectUrl), authUri); } } }
static void Main(string[] args) { _ = args; try { Init(); _logger.LogInformation("initialization complete"); foreach (var tz in TimeZoneInfo.GetSystemTimeZones()) { _logger.LogInformation("'{id}' '{name}' '{caption}' ({baseOffset})", tz.Id, tz.StandardName, tz.DisplayName, tz.BaseUtcOffset); } var getTokenTask = _saxoClient.GetPKCEApiToken(_cts.Token); _logger.LogInformation("Redirect listener listening on {redirectUrl}", _saxoClient.RedirectUrl); var authUri = _saxoClient.GetPKCEAuthUrl(); _logger.LogInformation("Waiting for external callback from Uri {uri}", authUri); getTokenTask.Wait(); _logger.LogInformation("Authenticated, access token expires in: {expires}, refresh token: {refresh} expires in: {refreshExpires}", _saxoClient.ApiToken.ExpiresIn, _saxoClient.ApiToken.RefreshToken, _saxoClient.ApiToken.RefreshTokenExpiresIn); // Next things to do: get instrument info: https://gateway.saxobank.com/sim/openapi/ref/v1/instruments?AssetTypes=Stock // Get prices for a list of instruments: https://gateway.saxobank.com/sim/openapi/trade/v1/infoprices/list?AccountKey=iX5VtUtBMBQDzOl1Z5px1Q==&Uics=2047,1311,2046,17749,16&AssetType=FxSpot&Amount=100000&FieldGroups=DisplayAndFormat,Quote Console.ReadLine(); } catch (Exception ex) { _logger.LogError(ex, "Uncaught exception"); throw; } finally { Cleanup(); } }