paypal/sdk-core-dotnet — pull request #31 by freeboarder (2014-03-18 11:10:26+00:00)
Title: Bugfix in OAuthTokenCredential.GetAccessToken and two useful new properties

OAuthTokenCredential.GetAccessToken has a nasty but that caused an already existing access token never to be considered as expired or expiring. The check for an expired or expiring access token used DateTime.Now.Millisecond (as well as GenerateOAuthToken used this to store the milliseconds when a token was created). Problem with this is that DateTime.Now.Millisecond only stores the millisecond *component* of the time. new DateTime(2014, 1, 1, 10, 0, 0, 500) and DateTime(2014, 12, 31, 23, 23, 59, 500) both result in 500 for example. Because the millisecond value could maximal be 999, the result of (current milliseconds - milliseconds when starting / 1000) could never be greater than the usual 28800 seconds TTL minus the gap od 120 seconds.
My solution was to store the actual date when a token was created:

private string GenerateOAuthToken(string base64ClientId)
{
...
lastAccessTokenCreationDate = DateTime.Now;
return generatedToken;
}

... and then use that for checking an expired or expiring token:

public string GetAccessToken()
{
....
double elapsedSeconds = (DateTime.Now - lastAccessTokenCreationDate).TotalSeconds;
if (elapsedSeconds > secondsToExpire - accessTokenExpirationCheckSafetyGapSeconds)
{
....
}

I also added two properties for developers who want to get information about the lifetime and specify the safety gap:

private int accessTokenExpirationCheckSafetyGapSeconds = 120;
///

/// Returns the lifetime of a created access token as returned by PayPal in seconds.
/// Is only set after an access token was created.
///

public int AccessTokenLifetimeInSeconds
{
get
{
return secondsToExpire;
}
}

///

/// Safety gap when checking the expiration of an already created access token in seconds.
/// The expiration must not ly in the past of now - the safety gap.
///

public int AccessTokenExpirationCheckSafetyGapSeconds
{
get
{
return accessTokenExpirationCheckSafetyGapSeconds;
}
set
{
accessTokenExpirationCheckSafetyGapSeconds = value;
}
}