Skip to content
This repository has been archived by the owner on Sep 29, 2023. It is now read-only.

Added feature to create third party access tokens #968

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions lib/PayPal/Auth/OAuthTokenCredential.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class OAuthTokenCredential extends PayPalResourceModel
*
* @var string $clientId
*/
private $clientId;
private $clientId;

/**
* Client secret as obtained from the developer portal
Expand Down Expand Up @@ -75,17 +75,26 @@ class OAuthTokenCredential extends PayPalResourceModel
*/
private $cipher;

/**
* The encrypted account number of the merchant on whose behalf the transaction is being done
*
* @var Subject
*/
private $subject;

/**
* Construct
*
* @param string $clientId client id obtained from the developer portal
* @param string $clientSecret client secret obtained from the developer portal
* @param null|string $subject subject used to create Third Party Token
*/
public function __construct($clientId, $clientSecret)
public function __construct($clientId, $clientSecret, $subject = null)
{
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->cipher = new Cipher($this->clientSecret);
$this->subject = $subject;
}

/**
Expand All @@ -108,6 +117,16 @@ public function getClientSecret()
return $this->clientSecret;
}

/**
* Get the subject used to create Third Party Access Token
*
* @return string
*/
public function getSubject()
{
return $this->subject;
}

/**
* Get AccessToken
*
Expand All @@ -121,8 +140,9 @@ public function getAccessToken($config)
if ($this->accessToken && (time() - $this->tokenCreateTime) < ($this->tokenExpiresIn - self::$expiryBufferTime)) {
return $this->accessToken;
}

// Check for persisted data first
$token = AuthorizationCache::pull($config, $this->clientId);
$token = AuthorizationCache::pull($config, $this->clientId, $this->subject);
if ($token) {
// We found it
// This code block is for backward compatibility only.
Expand All @@ -135,7 +155,7 @@ public function getAccessToken($config)

// Case where we have an old unencrypted cache file
if (!array_key_exists('accessTokenEncrypted', $token)) {
AuthorizationCache::push($config, $this->clientId, $this->encrypt($this->accessToken), $this->tokenCreateTime, $this->tokenExpiresIn);
AuthorizationCache::push($config, $this->clientId, $this->encrypt($this->accessToken), $this->tokenCreateTime, $this->tokenExpiresIn, $this->subject);
} else {
$this->accessToken = $this->decrypt($token['accessTokenEncrypted']);
}
Expand All @@ -158,7 +178,7 @@ public function getAccessToken($config)
if ($this->accessToken == null) {
// Get a new one by making calls to API
$this->updateAccessToken($config);
AuthorizationCache::push($config, $this->clientId, $this->encrypt($this->accessToken), $this->tokenCreateTime, $this->tokenExpiresIn);
AuthorizationCache::push($config, $this->clientId, $this->encrypt($this->accessToken), $this->tokenCreateTime, $this->tokenExpiresIn, $this->subject);
}

return $this->accessToken;
Expand Down Expand Up @@ -267,6 +287,11 @@ private function generateAccessToken($config, $refreshToken = null)
$params['grant_type'] = 'refresh_token';
$params['refresh_token'] = $refreshToken;
}

if ($this->subject != null && $refreshToken == null) {
$params['target_subject'] = $this->subject;
}

$payload = http_build_query($params);
$response = $this->getToken($config, $this->clientId, $this->clientSecret, $payload);

Expand Down
12 changes: 7 additions & 5 deletions lib/PayPal/Cache/AuthorizationCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class AuthorizationCache
* @param string $clientId
* @return mixed|null
*/
public static function pull($config = null, $clientId = null)
public static function pull($config = null, $clientId = null, $subject = null)
{
// Return if not enabled
if (!self::isEnabled($config)) {
Expand All @@ -26,14 +26,15 @@ public static function pull($config = null, $clientId = null)

$tokens = null;
$cachePath = self::cachePath($config);
$cacheKey = $subject == null ? $clientId : $clientId . "." . $subject;
if (file_exists($cachePath)) {
// Read from the file
$cachedToken = file_get_contents($cachePath);
if ($cachedToken && JsonValidator::validate($cachedToken, true)) {
$tokens = json_decode($cachedToken, true);
if ($clientId && is_array($tokens) && array_key_exists($clientId, $tokens)) {
if ($cacheKey && is_array($tokens) && array_key_exists($cacheKey, $tokens)) {
// If client Id is found, just send in that data only
return $tokens[$clientId];
return $tokens[$cacheKey];
} elseif ($clientId) {
// If client Id is provided, but no key in persisted data found matching it.
return null;
Expand All @@ -53,7 +54,7 @@ public static function pull($config = null, $clientId = null)
* @param $tokenExpiresIn
* @throws \Exception
*/
public static function push($config = null, $clientId, $accessToken, $tokenCreateTime, $tokenExpiresIn)
public static function push($config = null, $clientId, $accessToken, $tokenCreateTime, $tokenExpiresIn, $subject=null)
{
// Return if not enabled
if (!self::isEnabled($config)) {
Expand All @@ -70,8 +71,9 @@ public static function push($config = null, $clientId, $accessToken, $tokenCreat
// Reads all the existing persisted data
$tokens = self::pull();
$tokens = $tokens ? $tokens : array();
$cacheKey = $subject == null ? $clientId : $clientId . "." . $subject;
if (is_array($tokens)) {
$tokens[$clientId] = array(
$tokens[$cacheKey] = array(
'clientId' => $clientId,
'accessTokenEncrypted' => $accessToken,
'tokenCreateTime' => $tokenCreateTime,
Expand Down
31 changes: 31 additions & 0 deletions tests/PayPal/Test/Auth/OAuthTokenCredentialTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,37 @@ public function testGetAccessTokenUnit()
$this->assertNotNull($result);
}

public function testGetAccessTokenWithSubjectUnit()
{
$config = array(
'mode' => 'sandbox',
'cache.enabled' => true,
'cache.FileName' => AuthorizationCacheTest::CACHE_FILE
);
$cred = new OAuthTokenCredential('clientId', 'clientSecret', 'subject');

//{"clientId":{"clientId":"clientId","accessToken":"accessToken","tokenCreateTime":1421204091,"tokenExpiresIn":288000000}}
AuthorizationCache::push($config, 'clientId', $cred->encrypt('accessTokenWithSubject'), 1421204091, 288000000, 'subject');
AuthorizationCache::push($config, 'clientId', $cred->encrypt('accessToken1'), 1421204091, 288000000);

$apiContext = new ApiContext($cred);
$apiContext->setConfig($config);
$this->assertEquals('clientId', $cred->getClientId());
$this->assertEquals('clientSecret', $cred->getClientSecret());
$this->assertEquals('subject', $cred->getSubject());
$result = $cred->getAccessToken($config);
$this->assertEquals('accessTokenWithSubject', $result);

$cred = new OAuthTokenCredential('clientId', 'clientSecret');
$apiContext = new ApiContext($cred);
$apiContext->setConfig($config);
$this->assertEquals('clientId', $cred->getClientId());
$this->assertEquals('clientSecret', $cred->getClientSecret());
$this->assertNull($cred->getSubject());
$result = $cred->getAccessToken($config);
$this->assertEquals('accessToken1', $result);
}

public function testGetAccessTokenUnitMock()
{
$config = array(
Expand Down