Enabled Caching of Access Tokens

- Updated AuthTokenCredential to store access token in file storage
- Updated samples to include the configuration to disable/enable caching
This commit is contained in:
japatel
2014-12-02 14:53:14 -06:00
parent 6cf15ab4bf
commit ddd1a2ddf6
8 changed files with 170 additions and 20 deletions

3
.gitignore vendored
View File

@@ -15,3 +15,6 @@ atlassian-ide-plugin.xml
# Composer # Composer
vendor vendor
composer.lock composer.lock
# Project
var

View File

@@ -133,6 +133,28 @@ There are two kinds of tests that we include in our sdk package. Unit tests, and
## Developer Notes ## Developer Notes
### Caching - Performance Improvement
PayPal API SDK now has the ability to cache Access Tokens for multiple request uses. Generally, an access token is valid for approximately 15 min to 8 hours based on security settings by PayPal. However, by default PHP requests a new access token each time a new process/request is made in your website. To re-use the access token, we enabled cache storage via file under /var/auth.cache.
To enable this, you need to configure by updating the configuration settings in your sdk_config.ini file or dynamic values as shown below:
Please visit our [sample sdk_config.ini](https://github.com/paypal/PayPal-PHP-SDK/blob/master/sample/sdk_config.ini)
```
;Caching Configuration
[cache]
; If Cache is enabled, it stores the access token retrieved from ClientId and Secret from the
; server into a file provided in constant $CACHE_PATH in PayPal/Cache/AuthorizationCache.
; If the value is set to 'true', it would try to create a file and store the information.
; For any other value, it would disable it
; Please note, this is a very good performance improvement, and we would encourage you to
; set this up properly to reduce the number of calls, to almost 50% on normal use cases
; PLEASE NOTE: You may need to provide proper write permissions to /var directory under PayPal-PHP-SDK on
; your hosting server
cache.enabled=true
```
##### PLEASE NOTE: You may need to provide proper write permissions to /var directory under PayPal-PHP-SDK on your hosting server
### API Model Constructor ### API Model Constructor
You can intialize the API objects by passing JSON string or Array representation of object to the constructor. E.g.: You can intialize the API objects by passing JSON string or Array representation of object to the constructor. E.g.:

View File

@@ -2,6 +2,8 @@
namespace PayPal\Auth; namespace PayPal\Auth;
use PayPal\Cache\AuthorizationCache;
use PayPal\Common\PPModel;
use PayPal\Common\PPUserAgent; use PayPal\Common\PPUserAgent;
use PayPal\Common\ResourceModel; use PayPal\Common\ResourceModel;
use PayPal\Core\PPConstants; use PayPal\Core\PPConstants;
@@ -10,12 +12,15 @@ use PayPal\Core\PPHttpConnection;
use PayPal\Core\PPLoggingManager; use PayPal\Core\PPLoggingManager;
use PayPal\Exception\PPConfigurationException; use PayPal\Exception\PPConfigurationException;
use PayPal\Rest\RestHandler; use PayPal\Rest\RestHandler;
use PayPal\Validation\JsonValidator;
/** /**
* Class OAuthTokenCredential * Class OAuthTokenCredential
*/ */
class OAuthTokenCredential extends ResourceModel class OAuthTokenCredential extends ResourceModel
{ {
public static $CACHE_PATH = '/../../../var/auth.cache';
/** /**
* Private Variable * Private Variable
* *
@@ -107,6 +112,15 @@ class OAuthTokenCredential extends ResourceModel
*/ */
public function getAccessToken($config) public function getAccessToken($config)
{ {
// Check for persisted data first
$token = AuthorizationCache::pull($config, $this->clientId);
if ($token) {
// We found it
$this->accessToken = $token['accessToken'];
$this->tokenCreateTime = $token['tokenCreateTime'];
$this->tokenExpiresIn = $token['tokenExpiresIn'];
}
// Check if Access Token is not null and has not expired. // Check if Access Token is not null and has not expired.
// The API returns expiry time as a relative time unit // The API returns expiry time as a relative time unit
// We use a buffer time when checking for token expiry to account // We use a buffer time when checking for token expiry to account
@@ -121,12 +135,15 @@ class OAuthTokenCredential extends ResourceModel
// If accessToken is Null, obtain a new token // If accessToken is Null, obtain a new token
if ($this->accessToken == null) { if ($this->accessToken == null) {
// Get a new one by making calls to API
$this->updateAccessToken($config); $this->updateAccessToken($config);
AuthorizationCache::push($config, $this->clientId, $this->accessToken, $this->tokenCreateTime, $this->tokenExpiresIn);
} }
return $this->accessToken; return $this->accessToken;
} }
/** /**
* Get a Refresh Token from Authorization Code * Get a Refresh Token from Authorization Code
* *

View File

@@ -0,0 +1,94 @@
<?php
namespace PayPal\Cache;
use PayPal\Core\PPConfigManager;
use PayPal\Validation\JsonValidator;
abstract class AuthorizationCache
{
public static $CACHE_PATH = '/../../../var/auth.cache';
/**
* A pull method which would read the persisted data based on clientId.
* If clientId is not provided, an array with all the tokens would be passed.
*
* @param array|null $config
* @param string $clientId
* @return mixed|null
*/
public static function pull($config = null, $clientId = null)
{
// Return if not enabled
if (!self::isEnabled($config)) { return null; }
$tokens = null;
if (file_exists(__DIR__ . self::$CACHE_PATH)) {
// Read from the file
$cachedToken = file_get_contents(__DIR__ . self::$CACHE_PATH);
if ($cachedToken && JsonValidator::validate($cachedToken, true)) {
$tokens = json_decode($cachedToken, true);
if ($clientId && is_array($tokens) && array_key_exists($clientId, $tokens)) {
// If client Id is found, just send in that data only
return $tokens[$clientId];
} else if ($clientId) {
// If client Id is provided, but no key in persisted data found matching it.
return null;
}
}
}
return $tokens;
}
/**
* Persists the data into a cache file provided in $CACHE_PATH
*
* @param array|null $config
* @param $clientId
* @param $accessToken
* @param $tokenCreateTime
* @param $tokenExpiresIn
*/
public static function push($config = null, $clientId, $accessToken, $tokenCreateTime, $tokenExpiresIn)
{
// Return if not enabled
if (!self::isEnabled($config)) { return; }
if (!is_dir(dirname(__DIR__ . self::$CACHE_PATH))) {
if (mkdir(dirname(__DIR__ . self::$CACHE_PATH), 0755, true) == false) {
return;
}
}
// Reads all the existing persisted data
$tokens = self::pull();
$tokens = $tokens ? $tokens : array();
if (is_array($tokens)) {
$tokens[$clientId] = array(
'clientId' => $clientId,
'accessToken' => $accessToken,
'tokenCreateTime' => $tokenCreateTime,
'tokenExpiresIn' => $tokenExpiresIn
);
}
file_put_contents(__DIR__ . self::$CACHE_PATH, json_encode($tokens));
}
/**
* Determines from the Configuration if caching is currently enabled/disabled
*
* @param $config
* @return bool
*/
public static function isEnabled($config)
{
$config = ($config && is_array($config)) ? $config : PPConfigManager::getInstance()->getConfigHashmap();
if (array_key_exists("cache.enabled", $config)) {
$value = $config['cache.enabled'];
return (trim($value) == 'true') ? true : false;
}
return false;
}
}

View File

@@ -12,7 +12,7 @@ class PPConstants
{ {
const SDK_NAME = 'PayPal-PHP-SDK'; const SDK_NAME = 'PayPal-PHP-SDK';
const SDK_VERSION = '0.15.1'; const SDK_VERSION = '0.16.0';
const REST_SANDBOX_ENDPOINT = "https://api.sandbox.paypal.com/"; const REST_SANDBOX_ENDPOINT = "https://api.sandbox.paypal.com/";
const OPENID_REDIRECT_SANDBOX_URL = "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect"; const OPENID_REDIRECT_SANDBOX_URL = "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect";

View File

@@ -1,5 +1,9 @@
PayPal PHP SDK release notes PayPal PHP SDK release notes
============================ ============================
v0.16.0
----
* Enabled Caching Abilities for Access Tokens
v0.15.1 v0.15.1
---- ----
* Enabled Deleting Billing Plans * Enabled Deleting Billing Plans

View File

@@ -40,6 +40,14 @@ return $apiContext;
*/ */
function getApiContext($clientId, $clientSecret) function getApiContext($clientId, $clientSecret)
{ {
// Register the sdk_config.ini file in current directory
// as the configuration source.
/*
if(!defined("PP_CONFIG_PATH")) {
define("PP_CONFIG_PATH", __DIR__);
}
*/
// ### Api context // ### Api context
// Use an ApiContext object to authenticate // Use an ApiContext object to authenticate
@@ -60,7 +68,6 @@ function getApiContext($clientId, $clientSecret)
// Comment this line out and uncomment the PP_CONFIG_PATH // Comment this line out and uncomment the PP_CONFIG_PATH
// 'define' block if you want to use static file // 'define' block if you want to use static file
// based configuration // based configuration
$apiContext->setConfig( $apiContext->setConfig(
array( array(
'mode' => 'sandbox', 'mode' => 'sandbox',
@@ -68,17 +75,10 @@ function getApiContext($clientId, $clientSecret)
'log.LogEnabled' => true, 'log.LogEnabled' => true,
'log.FileName' => '../PayPal.log', 'log.FileName' => '../PayPal.log',
'log.LogLevel' => 'FINE', 'log.LogLevel' => 'FINE',
'validation.level' => 'log' 'validation.level' => 'log',
'cache.enabled' => 'true'
) )
); );
/*
// Register the sdk_config.ini file in current directory
// as the configuration source.
if(!defined("PP_CONFIG_PATH")) {
define("PP_CONFIG_PATH", __DIR__);
}
*/
return $apiContext; return $apiContext;
} }

View File

@@ -1,13 +1,11 @@
;## This is an example configuration file for the SDK.
;## The sample scripts configure the SDK dynamically
;## but you can choose to go for file based configuration
;## in simpler apps (See bootstrap.php for more).
[Account] [Account]
acct1.ClientId = AYSq3RDGsmBLJE-otTkBtM-jBRd1TCQwFf9RGfwddNXWz0uFU9ztymylOhRS acct1.ClientId = AYSq3RDGsmBLJE-otTkBtM-jBRd1TCQwFf9RGfwddNXWz0uFU9ztymylOhRS
acct1.ClientSecret = EGnHDxD_qRPdaLdZz8iCr8N7_MzF-YHPTkjs6NKYQvQSBngp4PTTVWkPZRbL acct1.ClientSecret = EGnHDxD_qRPdaLdZz8iCr8N7_MzF-YHPTkjs6NKYQvQSBngp4PTTVWkPZRbL
## This is an example configuration file for the SDK.
## The sample scripts configure the SDK dynamically
## but you can choose to go for file based configuration
## in simpler apps (See bootstrap.php for more).
;Connection Information ;Connection Information
[Http] [Http]
http.ConnectionTimeOut = 30 http.ConnectionTimeOut = 30
@@ -16,11 +14,11 @@ http.Retry = 1
;Service Configuration ;Service Configuration
[Service] [Service]
mode=sandbox ; can be set to sandbox / live ; can be set to sandbox / live
mode = sandbox
;Logging Information ;Logging Information
[Log] [Log]
log.LogEnabled=true log.LogEnabled=true
; When using a relative path, the log file is created ; When using a relative path, the log file is created
@@ -42,4 +40,16 @@ log.LogLevel=FINE
; 'log' : logs the error message to logger only (default) ; 'log' : logs the error message to logger only (default)
; 'strict' : throws a php notice message ; 'strict' : throws a php notice message
; 'disable' : disable the validation ; 'disable' : disable the validation
validation.level=strict validation.level=log
;Caching Configuration
[cache]
; If Cache is enabled, it stores the access token retrieved from ClientId and Secret from the
; server into a file provided in constant $CACHE_PATH in PayPal/Cache/AuthorizationCache.
; If the value is set to 'true', it would try to create a file and store the information.
; For any other value, it would disable it
; Please note, this is a very good performance improvement, and we would encourage you to
; set this up properly to reduce the number of calls, to almost 50% on normal use cases
; PLEASE NOTE: You may need to provide proper write permissions to /var directory under PayPal-PHP-SDK on
; your hosting server
cache.enabled=true