From 20038e7525fd8534a8efa3d8165b0f2f7b8c91b6 Mon Sep 17 00:00:00 2001 From: japatel Date: Wed, 17 Dec 2014 15:36:41 -0600 Subject: [PATCH] Configurable Headers for All Requests to PayPal - Allows adding additional headers to every call to PayPal APIs. - Refactored OAuthTokenCredential to share code for making Rest Calls - SDK Config to add headers with http.headers.* syntax - Fixes #193 --- lib/PayPal/Auth/OAuthTokenCredential.php | 72 +++++----------- lib/PayPal/Core/PPConstants.php | 2 +- lib/PayPal/Rest/ApiContext.php | 20 +++++ lib/PayPal/Rest/OauthHandler.php | 105 +++++++++++++++++++++++ lib/PayPal/Rest/RestHandler.php | 5 ++ release_notes.md | 6 ++ sample/bootstrap.php | 8 +- sample/sdk_config.ini | 4 + 8 files changed, 170 insertions(+), 52 deletions(-) create mode 100644 lib/PayPal/Rest/OauthHandler.php diff --git a/lib/PayPal/Auth/OAuthTokenCredential.php b/lib/PayPal/Auth/OAuthTokenCredential.php index 2e43df9..52e1232 100644 --- a/lib/PayPal/Auth/OAuthTokenCredential.php +++ b/lib/PayPal/Auth/OAuthTokenCredential.php @@ -3,16 +3,13 @@ namespace PayPal\Auth; use PayPal\Cache\AuthorizationCache; -use PayPal\Common\PPModel; -use PayPal\Common\PPUserAgent; use PayPal\Common\ResourceModel; -use PayPal\Core\PPConstants; use PayPal\Core\PPHttpConfig; use PayPal\Core\PPHttpConnection; use PayPal\Core\PPLoggingManager; use PayPal\Exception\PPConfigurationException; -use PayPal\Rest\RestHandler; -use PayPal\Validation\JsonValidator; +use PayPal\Handler\IPPHandler; +use PayPal\Rest\ApiContext; /** * Class OAuthTokenCredential @@ -21,6 +18,12 @@ class OAuthTokenCredential extends ResourceModel { public static $CACHE_PATH = '/../../../var/auth.cache'; + + /** + * @var string Default Auth Handler + */ + public static $AUTH_HANDLER = 'PayPal\Rest\OauthHandler'; + /** * Private Variable * @@ -192,6 +195,8 @@ class OAuthTokenCredential extends ResourceModel * Retrieves the token based on the input configuration * * @param array $config + * @param string $clientId + * @param string $clientSecret * @param string $payload * @return mixed * @throws PPConfigurationException @@ -199,17 +204,20 @@ class OAuthTokenCredential extends ResourceModel */ private function getToken($config, $clientId, $clientSecret, $payload) { - $base64ClientID = base64_encode($clientId . ":" . $clientSecret); - $headers = array( - "User-Agent" => PPUserAgent::getValue(PPConstants::SDK_NAME, PPConstants::SDK_VERSION), - "Authorization" => "Basic " . $base64ClientID, - "Accept" => "*/*" - ); + $httpConfig = new PPHttpConfig(null, 'POST'); - $httpConfiguration = self::getOAuthHttpConfiguration($config); - $httpConfiguration->setHeaders($headers); + $handlers = array(self::$AUTH_HANDLER); - $connection = new PPHttpConnection($httpConfiguration, $config); + /** @var IPPHandler $handler */ + foreach ($handlers as $handler) { + if (!is_object($handler)) { + $fullHandler = "\\" . (string)$handler; + $handler = new $fullHandler(new ApiContext($this)); + } + $handler->handle($httpConfig, $payload, array('clientId' => $clientId, 'clientSecret' => $clientSecret)); + } + + $connection = new PPHttpConnection($httpConfig, $config); $res = $connection->execute($payload); $response = json_decode($res, true); @@ -249,40 +257,4 @@ class OAuthTokenCredential extends ResourceModel return $this->accessToken; } - - /** - * Get HttpConfiguration object for OAuth API - * - * @param array $config - * - * @return PPHttpConfig - * @throws \PayPal\Exception\PPConfigurationException - */ - private static function getOAuthHttpConfiguration($config) - { - if (isset($config['oauth.EndPoint'])) { - $baseEndpoint = $config['oauth.EndPoint']; - } else if (isset($config['service.EndPoint'])) { - $baseEndpoint = $config['service.EndPoint']; - } else if (isset($config['mode'])) { - switch (strtoupper($config['mode'])) { - case 'SANDBOX': - $baseEndpoint = PPConstants::REST_SANDBOX_ENDPOINT; - break; - case 'LIVE': - $baseEndpoint = PPConstants::REST_LIVE_ENDPOINT; - break; - default: - throw new PPConfigurationException('The mode config parameter must be set to either sandbox/live'); - } - } else { - throw new PPConfigurationException( - 'You must set one of service.endpoint or mode parameters in your configuration' - ); - } - - $baseEndpoint = rtrim(trim($baseEndpoint), '/'); - - return new PPHttpConfig($baseEndpoint . "/v1/oauth2/token", "POST"); - } } diff --git a/lib/PayPal/Core/PPConstants.php b/lib/PayPal/Core/PPConstants.php index 8f6ebf1..8241486 100644 --- a/lib/PayPal/Core/PPConstants.php +++ b/lib/PayPal/Core/PPConstants.php @@ -12,7 +12,7 @@ class PPConstants { const SDK_NAME = 'PayPal-PHP-SDK'; - const SDK_VERSION = '0.16.0'; + const SDK_VERSION = '0.16.1'; const REST_SANDBOX_ENDPOINT = "https://api.sandbox.paypal.com/"; const OPENID_REDIRECT_SANDBOX_URL = "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect"; diff --git a/lib/PayPal/Rest/ApiContext.php b/lib/PayPal/Rest/ApiContext.php index a99ee47..3c8a81e 100644 --- a/lib/PayPal/Rest/ApiContext.php +++ b/lib/PayPal/Rest/ApiContext.php @@ -58,6 +58,26 @@ class ApiContext return $this->credential; } + public function getRequestHeaders() + { + $result = PPConfigManager::getInstance()->get('http.headers'); + $headers = array(); + foreach ($result as $header => $value) { + $headerName = ltrim($header, 'http.headers'); + $headers[$headerName] = $value; + } + return $headers; + } + + public function addRequestHeader($name, $value) + { + // Determine if the name already has a 'http.headers' prefix. If not, add one. + if (!(substr($name, 0, strlen('http.headers')) === 'http.headers')) { + $name = 'http.headers.' . $name; + } + PPConfigManager::getInstance()->addConfigs(array($name => $value)); + } + /** * Get Request ID * diff --git a/lib/PayPal/Rest/OauthHandler.php b/lib/PayPal/Rest/OauthHandler.php new file mode 100644 index 0000000..1e80557 --- /dev/null +++ b/lib/PayPal/Rest/OauthHandler.php @@ -0,0 +1,105 @@ +apiContext = $apiContext; + } + + /** + * @param PPHttpConfig $httpConfig + * @param string $request + * @param mixed $options + * @return mixed|void + * @throws PPConfigurationException + * @throws PPInvalidCredentialException + * @throws PPMissingCredentialException + */ + public function handle($httpConfig, $request, $options) + { + $config = $this->apiContext->getConfig(); + + $httpConfig->setUrl( + rtrim(trim($this->_getEndpoint($config)), '/') . + (isset($options['path']) ? $options['path'] : '') + ); + + $headers = array( + "User-Agent" => PPUserAgent::getValue(PPConstants::SDK_NAME, PPConstants::SDK_VERSION), + "Authorization" => "Basic " . base64_encode($options['clientId'] . ":" . $options['clientSecret']), + "Accept" => "*/*" + ); + $httpConfig->setHeaders($headers); + + // Add any additional Headers that they may have provided + $headers = $this->apiContext->getRequestHeaders(); + foreach ($headers as $key => $value) { + $httpConfig->addHeader($key, $value); + } + } + + /** + * Get HttpConfiguration object for OAuth API + * + * @param array $config + * + * @return PPHttpConfig + * @throws \PayPal\Exception\PPConfigurationException + */ + private static function _getEndpoint($config) + { + if (isset($config['oauth.EndPoint'])) { + $baseEndpoint = $config['oauth.EndPoint']; + } else if (isset($config['service.EndPoint'])) { + $baseEndpoint = $config['service.EndPoint']; + } else if (isset($config['mode'])) { + switch (strtoupper($config['mode'])) { + case 'SANDBOX': + $baseEndpoint = PPConstants::REST_SANDBOX_ENDPOINT; + break; + case 'LIVE': + $baseEndpoint = PPConstants::REST_LIVE_ENDPOINT; + break; + default: + throw new PPConfigurationException('The mode config parameter must be set to either sandbox/live'); + } + } else { + throw new PPConfigurationException( + 'You must set one of service.endpoint or mode parameters in your configuration' + ); + } + + $baseEndpoint = rtrim(trim($baseEndpoint), '/') . "/v1/oauth2/token"; + + return $baseEndpoint; + } +} diff --git a/lib/PayPal/Rest/RestHandler.php b/lib/PayPal/Rest/RestHandler.php index 3e060f4..f8c858a 100644 --- a/lib/PayPal/Rest/RestHandler.php +++ b/lib/PayPal/Rest/RestHandler.php @@ -84,6 +84,11 @@ class RestHandler implements IPPHandler if ($httpConfig->getMethod() == 'POST' || $httpConfig->getMethod() == 'PUT') { $httpConfig->addHeader('PayPal-Request-Id', $this->apiContext->getRequestId()); } + // Add any additional Headers that they may have provided + $headers = $this->apiContext->getRequestHeaders(); + foreach ($headers as $key => $value) { + $httpConfig->addHeader($key, $value); + } } /** diff --git a/release_notes.md b/release_notes.md index c9a4989..7b88e49 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,5 +1,11 @@ PayPal PHP SDK release notes ============================ +v0.16.1 +---- +* Configurable Headers for all requests to PayPal +* Allows adding additional headers to every call to PayPal APIs +* SDK Config to add headers with http.headers.* syntax + v0.16.0 ---- * Enabled Webhook Management Capabilities diff --git a/sample/bootstrap.php b/sample/bootstrap.php index eedbfe0..f52220f 100644 --- a/sample/bootstrap.php +++ b/sample/bootstrap.php @@ -62,6 +62,11 @@ function getApiContext($clientId, $clientSecret) ) ); + // Partner Attribution Id + // Use this header if you are a PayPal partner. Specify a unique BN Code to receive revenue attribution. To learn more or to request a BN Code, contact your Partner Manager or visit the PayPal Partner Portal . + + $apiContext->addRequestHeader('PayPal-Partner-Attribution-Id', '123123123'); + // #### SDK configuration @@ -76,7 +81,8 @@ function getApiContext($clientId, $clientSecret) 'log.FileName' => '../PayPal.log', 'log.LogLevel' => 'FINE', 'validation.level' => 'log', - 'cache.enabled' => 'true' + 'cache.enabled' => 'true', + // 'http.headers.PayPal-Partner-Attribution-Id' => '123123123' ) ); diff --git a/sample/sdk_config.ini b/sample/sdk_config.ini index 530e76e..54a6a5a 100644 --- a/sample/sdk_config.ini +++ b/sample/sdk_config.ini @@ -10,6 +10,10 @@ acct1.ClientSecret = EGnHDxD_qRPdaLdZz8iCr8N7_MzF-YHPTkjs6NKYQvQSBngp4PTTVWkPZRb [Http] http.ConnectionTimeOut = 30 http.Retry = 1 + +; Adding HTTP Headers to each request sent to PayPal APIs +;http.headers.PayPal-Partner-Attribution-Id = 123123123 + ;http.Proxy=http://[username:password]@hostname[:port] ;Service Configuration