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

Commit

Permalink
Enabling Future Payments
Browse files Browse the repository at this point in the history
- Added feature to create future payments
- Updated Authentication model to retrieve long lived refresh token
- Updated Documentation
- Updated Sample
  • Loading branch information
japatel committed Oct 6, 2014
1 parent 49b80f7 commit cea8981
Show file tree
Hide file tree
Showing 5 changed files with 303 additions and 23 deletions.
48 changes: 48 additions & 0 deletions lib/PayPal/Api/FuturePayment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace PayPal\Api;

use PayPal\Common\PPModel;
use PayPal\Rest\ApiContext;
use PayPal\Transport\PPRestCall;

/**
* Class FuturePayment
*
* @package PayPal\Api
*/
class FuturePayment extends Payment
{

/**
* Extends the Payment object to create future payments
*
* @param null $apiContext
* @param $correlationId
* @return $this
*/
public function create($apiContext = null, $correlationId = null) {
if ($apiContext == null) {
$apiContext = new ApiContext(self::$credential);
}
if (($correlationId == null || trim($correlationId) == "")) {
throw new \InvalidArgumentException("correlationId cannot be null or empty");
}
$payLoad = $this->toJSON();
$call = new PPRestCall($apiContext);
$json = $call->execute(
array('PayPal\Rest\RestHandler'),
"/v1/payments/payment",
"POST",
$payLoad,
[
'Paypal-Application-Correlation-Id' => $correlationId,
'PAYPAL-CLIENT-METADATA-ID' => $correlationId
]
);
$this->fromJson($json);

return $this;

}
}
16 changes: 8 additions & 8 deletions lib/PayPal/Api/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Payment extends PPModel implements IResource
/**
* @var
*/
private static $credential;
protected static $credential;

/**
* Set Credential
Expand Down Expand Up @@ -467,14 +467,14 @@ public static function all($params, $apiContext = null)
$payLoad = "";

$allowedParams = array(
'count' => 1,
'start_id' => 1,
'count' => 1,
'start_id' => 1,
'start_index' => 1,
'start_time' => 1,
'end_time' => 1,
'payee_id' => 1,
'sort_by' => 1,
'sort_order' => 1,
'start_time' => 1,
'end_time' => 1,
'payee_id' => 1,
'sort_by' => 1,
'sort_order' => 1,
);

if ($apiContext == null) {
Expand Down
87 changes: 72 additions & 15 deletions lib/PayPal/Auth/OAuthTokenCredential.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
<?php
/**
* Oauth Token credential
*/

namespace PayPal\Auth;

use PayPal\Common\PPUserAgent;
use PayPal\Core\PPConnectionManager;
use PayPal\Core\PPConstants;
use PayPal\Core\PPHttpConfig;
use PayPal\Core\PPHttpConnection;
use PayPal\Core\PPLoggingManager;
use PayPal\Exception\PPConfigurationException;
use PayPal\Rest\RestHandler;
Expand Down Expand Up @@ -49,7 +46,7 @@ class OAuthTokenCredential
/**
* Generated Access Token
*
* @var $accessToken
* @var string $accessToken
*/
private $accessToken;

Expand Down Expand Up @@ -95,26 +92,64 @@ public function getAccessToken($config)
// We use a buffer time when checking for token expiry to account
// for API call delays and any delay between the time the token is
// retrieved and subsequently used
if ($this->accessToken != null && (time() - $this->tokenCreateTime) > ($this->tokenExpiresIn - self::$expiryBufferTime)) {
if (
$this->accessToken != null &&
(time() - $this->tokenCreateTime) > ($this->tokenExpiresIn - self::$expiryBufferTime)
) {
$this->accessToken = null;
}

// If accessToken is Null, obtain a new token
if ($this->accessToken == null) {
$this->_generateAccessToken($config);
$this->updateAccessToken($config);
}

return $this->accessToken;
}

/**
* Generates a new access token
* Get a Refresh Token from Authorization Code
*
* @param $config
* @param $authorizationCode
* @return string|null
*/
public function getRefreshToken($config, $authorizationCode) //Which comes from Mobile.
{
$payload =
"grant_type=authorization_code&code=".
$authorizationCode.
"&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=token";
$jsonResponse = $this->getToken($config, $payload);

if ($jsonResponse != null && isset($jsonResponse["refresh_token"])) {
return $jsonResponse['refresh_token'];
}
}

/**
* Updates Access Token based on given input
*
* @return null
* @param $config
* @param string|null $refreshToken
* @return string
*/
public function updateAccessToken($config, $refreshToken = null)
{
$this->generateAccessToken($config, $refreshToken);
return $this->accessToken;
}

/**
* Retrieves the token based on the input configuration
*
* @param [] $config
* @param string $payload
* @return mixed
* @throws PPConfigurationException
* @throws \PayPal\Exception\PPConnectionException
*/
private function _generateAccessToken($config)
private function getToken($config, $payload)
{
$base64ClientID = base64_encode($this->clientId . ":" . $this->clientSecret);
$headers = array(
Expand All @@ -126,20 +161,40 @@ private function _generateAccessToken($config)
$httpConfiguration = $this->getOAuthHttpConfiguration($config);
$httpConfiguration->setHeaders($headers);

$connection = PPConnectionManager::getInstance()->getConnection($httpConfiguration, $config);
$res = $connection->execute("grant_type=client_credentials");
$connection = new PPHttpConnection($httpConfiguration, $config);
$res = $connection->execute($payload);
$jsonResponse = json_decode($res, true);

if ($jsonResponse == null || !isset($jsonResponse["access_token"]) || !isset($jsonResponse["expires_in"])) {
$this->accessToken = null;
$this->tokenExpiresIn = null;
$this->logger->warning("Could not generate new Access token. Invalid response from server: " . $jsonResponse);
$this->logger->warning(
"Could not generate new Access token. Invalid response from server: " . $jsonResponse
);
} else {
$this->accessToken = $jsonResponse["access_token"];
$this->tokenExpiresIn = $jsonResponse["expires_in"];
}

$this->tokenCreateTime = time();
return $jsonResponse;
}


/**
* Generates a new access token
*
* @param [] $config
* @return null
*/
private function generateAccessToken($config, $refreshToken = null)
{
$payload = "grant_type=client_credentials";
if ($refreshToken != null) {
// If the refresh token is provided, it would get access token using refresh token
// Used for Future Payments
$payload = "grant_type=refresh_token&refresh_token=$refreshToken";
}
$this->getToken($config, $payload);

return $this->accessToken;
}
Expand Down Expand Up @@ -170,7 +225,9 @@ private function getOAuthHttpConfiguration($config)
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');
throw new PPConfigurationException(
'You must set one of service.endpoint or mode parameters in your configuration'
);
}

$baseEndpoint = rtrim(trim($baseEndpoint), '/');
Expand Down
70 changes: 70 additions & 0 deletions sample/doc/payments/CreateFuturePayment.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!DOCTYPE html><html lang="en"><head><title>payments/CreateFuturePayment</title></head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><meta name="groc-relative-root" content="../"><meta name="groc-document-path" content="payments/CreateFuturePayment"><meta name="groc-project-path" content="sample/payments/CreateFuturePayment.php"><link rel="stylesheet" type="text/css" media="all" href="../assets/style.css"><script type="text/javascript" src="../assets/behavior.js"></script><body><div id="meta"><div class="file-path">sample/payments/CreateFuturePayment.php</div></div><div id="document"><div class="segment"><div class="code"><div class="wrapper"><span class="hljs-preprocessor">&lt;?php</span></div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h1 id="create-payment-using-paypal-as-payment-method">Create Payment using PayPal as payment method</h1>
<p>This sample code demonstrates how you can process a
PayPal Account based Payment.
API used: /v1/payments/payment</p></div></div><div class="code"><div class="wrapper"><span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/../bootstrap.php'</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Amount</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Details</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Item</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">ItemList</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Payer</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Payment</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">RedirectUrls</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PayPal</span>\<span class="hljs-title">Api</span>\<span class="hljs-title">Transaction</span>;
session_start();</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="payer">Payer</h3>
<p>A resource representing a Payer that funds a payment
For paypal account payments, set payment method
to &#39;paypal&#39;.</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$payer</span> = <span class="hljs-keyword">new</span> Payer();
<span class="hljs-variable">$payer</span>-&gt;setPaymentMethod(<span class="hljs-string">"paypal"</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="amount">Amount</h3>
<p>Lets you specify a payment amount.
You can also specify additional details
such as shipping, tax.</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$amount</span> = <span class="hljs-keyword">new</span> Amount();
<span class="hljs-variable">$amount</span>-&gt;setCurrency(<span class="hljs-string">"USD"</span>)
-&gt;setTotal(<span class="hljs-string">"0.17"</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="transaction">Transaction</h3>
<p>A transaction defines the contract of a
payment - what is the payment for and who
is fulfilling it. </p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$transaction</span> = <span class="hljs-keyword">new</span> Transaction();
<span class="hljs-variable">$transaction</span>-&gt;setAmount(<span class="hljs-variable">$amount</span>)
-&gt;setDescription(<span class="hljs-string">"Payment description"</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="redirect-urls">Redirect urls</h3>
<p>Set the urls that the buyer must be redirected to after
payment approval/ cancellation.</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$baseUrl</span> = getBaseUrl();
<span class="hljs-variable">$redirectUrls</span> = <span class="hljs-keyword">new</span> RedirectUrls();
<span class="hljs-variable">$redirectUrls</span>-&gt;setReturnUrl(<span class="hljs-string">"$baseUrl/ExecutePayment.php?success=true"</span>)
-&gt;setCancelUrl(<span class="hljs-string">"$baseUrl/ExecutePayment.php?success=false"</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="payment">Payment</h3>
<p>A Payment Resource; create one using
the above types and intent set to &#39;sale&#39;</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$payment</span> = <span class="hljs-keyword">new</span> Payment();
<span class="hljs-variable">$payment</span>-&gt;setIntent(<span class="hljs-string">"authorize"</span>)
-&gt;setPayer(<span class="hljs-variable">$payer</span>)
-&gt;setRedirectUrls(<span class="hljs-variable">$redirectUrls</span>)
-&gt;setTransactions(<span class="hljs-keyword">array</span>(<span class="hljs-variable">$transaction</span>));</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="get-refresh-token">Get Refresh Token</h3>
<p>You need to get a permanent refresh token from the authorization code, retrieved from the mobile sdk.</p></div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>authorization code from mobile sdk</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$authorizationCode</span> = <span class="hljs-string">'EF4Ds2Wv1JbHiU_UuhR5v-ftTbeJD03RBX-Zjg9pLCAhdLqLeRR6YSKTNsrbQGX7lFoZ3SxwFyxADEZbBOxpn023W9SA0JzSQAy-9eLdON5eDPAyMyKlHyNVS2DqBR2iWVfQGfudbd9MDoRxMEjIZbY'</span>;</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>correlation id from mobile sdk</p></div></div><div class="code"><div class="wrapper"><span class="hljs-variable">$correlationId</span> = <span class="hljs-string">'123123456'</span>;

<span class="hljs-keyword">try</span> {</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>Exchange authorization_code for long living refresh token. You should store
it in a database for later use</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-variable">$refreshToken</span> = <span class="hljs-variable">$apiContext</span>-&gt;getCredential()-&gt;getRefreshToken(<span class="hljs-variable">$apiContext</span>-&gt;getConfig(), <span class="hljs-variable">$authorizationCode</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><p>Update the access token in apiContext</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-variable">$apiContext</span>-&gt;getCredential()-&gt;updateAccessToken(<span class="hljs-variable">$apiContext</span>-&gt;getConfig(), <span class="hljs-variable">$refreshToken</span>);</div></div></div><div class="segment"><div class="comments "><div class="wrapper"><h3 id="create-future-payment">Create Future Payment</h3>
<p>Create a payment by calling the &#39;create&#39; method
passing it a valid apiContext.
(See bootstrap.php for more on <code>ApiContext</code>)
The return object contains the state and the
url to which the buyer must be redirected to
for payment approval
Please note that currently future payments works only with Paypal as a funding instrument.</p></div></div><div class="code"><div class="wrapper"> <span class="hljs-variable">$payment</span>-&gt;create(<span class="hljs-variable">$apiContext</span>, <span class="hljs-variable">$correlationId</span>);

} <span class="hljs-keyword">catch</span> (PayPal\<span class="hljs-keyword">Exception</span>\PPConnectionException <span class="hljs-variable">$ex</span>) {
<span class="hljs-keyword">echo</span> <span class="hljs-string">"Exception: "</span> . <span class="hljs-variable">$ex</span>-&gt;getMessage() . PHP_EOL;
var_dump(<span class="hljs-variable">$ex</span>-&gt;getData());
<span class="hljs-keyword">exit</span>(<span class="hljs-number">1</span>);
}
<span class="hljs-preprocessor">?&gt;</span>

&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Future payments&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div&gt;
Created payment:
<span class="hljs-preprocessor">&lt;?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-variable">$payment</span>-&gt;getId();<span class="hljs-preprocessor">?&gt;</span>
&lt;/div&gt;
&lt;pre&gt;<span class="hljs-preprocessor">&lt;?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-variable">$payment</span>-&gt;toJSON(JSON_PRETTY_PRINT);<span class="hljs-preprocessor">?&gt;</span>&lt;/pre&gt;
&lt;a href=<span class="hljs-string">'../index.html'</span>&gt;Back&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</div></div></div></div></body></html>
Loading

0 comments on commit cea8981

Please sign in to comment.