forked from LiveCarta/PayPal-PHP-SDK
Enabling Future Payments
- Added feature to create future payments - Updated Authentication model to retrieve long lived refresh token - Updated Documentation - Updated Sample
This commit is contained in:
48
lib/PayPal/Api/FuturePayment.php
Normal file
48
lib/PayPal/Api/FuturePayment.php
Normal file
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class Payment extends PPModel implements IResource
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private static $credential;
|
||||
protected static $credential;
|
||||
|
||||
/**
|
||||
* Set Credential
|
||||
@@ -467,14 +467,14 @@ class Payment extends PPModel implements IResource
|
||||
$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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -49,7 +46,7 @@ class OAuthTokenCredential
|
||||
/**
|
||||
* Generated Access Token
|
||||
*
|
||||
* @var $accessToken
|
||||
* @var string $accessToken
|
||||
*/
|
||||
private $accessToken;
|
||||
|
||||
@@ -95,26 +92,64 @@ class OAuthTokenCredential
|
||||
// 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
|
||||
*
|
||||
* @return null
|
||||
* @param $authorizationCode
|
||||
* @return string|null
|
||||
*/
|
||||
private function _generateAccessToken($config)
|
||||
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
|
||||
*
|
||||
* @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 getToken($config, $payload)
|
||||
{
|
||||
$base64ClientID = base64_encode($this->clientId . ":" . $this->clientSecret);
|
||||
$headers = array(
|
||||
@@ -126,20 +161,40 @@ class OAuthTokenCredential
|
||||
$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;
|
||||
}
|
||||
@@ -170,7 +225,9 @@ class OAuthTokenCredential
|
||||
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), '/');
|
||||
|
||||
70
sample/doc/payments/CreateFuturePayment.html
Normal file
70
sample/doc/payments/CreateFuturePayment.html
Normal file
@@ -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"><?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 'paypal'.</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>->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>->setCurrency(<span class="hljs-string">"USD"</span>)
|
||||
->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>->setAmount(<span class="hljs-variable">$amount</span>)
|
||||
->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>->setReturnUrl(<span class="hljs-string">"$baseUrl/ExecutePayment.php?success=true"</span>)
|
||||
->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 'sale'</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>->setIntent(<span class="hljs-string">"authorize"</span>)
|
||||
->setPayer(<span class="hljs-variable">$payer</span>)
|
||||
->setRedirectUrls(<span class="hljs-variable">$redirectUrls</span>)
|
||||
->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>->getCredential()->getRefreshToken(<span class="hljs-variable">$apiContext</span>->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>->getCredential()->updateAccessToken(<span class="hljs-variable">$apiContext</span>->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 'create' 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>->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>->getMessage() . PHP_EOL;
|
||||
var_dump(<span class="hljs-variable">$ex</span>->getData());
|
||||
<span class="hljs-keyword">exit</span>(<span class="hljs-number">1</span>);
|
||||
}
|
||||
<span class="hljs-preprocessor">?></span>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Future payments</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Created payment:
|
||||
<span class="hljs-preprocessor"><?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-variable">$payment</span>->getId();<span class="hljs-preprocessor">?></span>
|
||||
</div>
|
||||
<pre><span class="hljs-preprocessor"><?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-variable">$payment</span>->toJSON(JSON_PRETTY_PRINT);<span class="hljs-preprocessor">?></span></pre>
|
||||
<a href=<span class="hljs-string">'../index.html'</span>>Back</a>
|
||||
</body>
|
||||
</html></div></div></div></div></body></html>
|
||||
105
sample/payments/CreateFuturePayment.php
Normal file
105
sample/payments/CreateFuturePayment.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
// # Create Payment using PayPal as payment method
|
||||
// This sample code demonstrates how you can process a
|
||||
// PayPal Account based Payment.
|
||||
// API used: /v1/payments/payment
|
||||
|
||||
require __DIR__ . '/../bootstrap.php';
|
||||
use PayPal\Api\Amount;
|
||||
use PayPal\Api\Details;
|
||||
use PayPal\Api\Item;
|
||||
use PayPal\Api\ItemList;
|
||||
use PayPal\Api\Payer;
|
||||
use PayPal\Api\Payment;
|
||||
use PayPal\Api\RedirectUrls;
|
||||
use PayPal\Api\Transaction;
|
||||
session_start();
|
||||
|
||||
// ### Payer
|
||||
// A resource representing a Payer that funds a payment
|
||||
// For paypal account payments, set payment method
|
||||
// to 'paypal'.
|
||||
$payer = new Payer();
|
||||
$payer->setPaymentMethod("paypal");
|
||||
|
||||
// ### Amount
|
||||
// Lets you specify a payment amount.
|
||||
// You can also specify additional details
|
||||
// such as shipping, tax.
|
||||
$amount = new Amount();
|
||||
$amount->setCurrency("USD")
|
||||
->setTotal("0.17");
|
||||
|
||||
// ### Transaction
|
||||
// A transaction defines the contract of a
|
||||
// payment - what is the payment for and who
|
||||
// is fulfilling it.
|
||||
$transaction = new Transaction();
|
||||
$transaction->setAmount($amount)
|
||||
->setDescription("Payment description");
|
||||
|
||||
// ### Redirect urls
|
||||
// Set the urls that the buyer must be redirected to after
|
||||
// payment approval/ cancellation.
|
||||
$baseUrl = getBaseUrl();
|
||||
$redirectUrls = new RedirectUrls();
|
||||
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
|
||||
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
|
||||
|
||||
// ### Payment
|
||||
// A Payment Resource; create one using
|
||||
// the above types and intent set to 'sale'
|
||||
$payment = new Payment();
|
||||
$payment->setIntent("authorize")
|
||||
->setPayer($payer)
|
||||
->setRedirectUrls($redirectUrls)
|
||||
->setTransactions(array($transaction));
|
||||
|
||||
// ### Get Refresh Token
|
||||
// You need to get a permanent refresh token from the authorization code, retrieved from the mobile sdk.
|
||||
|
||||
// authorization code from mobile sdk
|
||||
$authorizationCode = 'EF4Ds2Wv1JbHiU_UuhR5v-ftTbeJD03RBX-Zjg9pLCAhdLqLeRR6YSKTNsrbQGX7lFoZ3SxwFyxADEZbBOxpn023W9SA0JzSQAy-9eLdON5eDPAyMyKlHyNVS2DqBR2iWVfQGfudbd9MDoRxMEjIZbY';
|
||||
|
||||
// correlation id from mobile sdk
|
||||
$correlationId = '123123456';
|
||||
|
||||
try {
|
||||
// Exchange authorization_code for long living refresh token. You should store
|
||||
// it in a database for later use
|
||||
$refreshToken = $apiContext->getCredential()->getRefreshToken($apiContext->getConfig(), $authorizationCode);
|
||||
|
||||
// Update the access token in apiContext
|
||||
$apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refreshToken);
|
||||
|
||||
// ### Create Future Payment
|
||||
// Create a payment by calling the 'create' method
|
||||
// passing it a valid apiContext.
|
||||
// (See bootstrap.php for more on `ApiContext`)
|
||||
// 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.
|
||||
$payment->create($apiContext, $correlationId);
|
||||
|
||||
} catch (PayPal\Exception\PPConnectionException $ex) {
|
||||
echo "Exception: " . $ex->getMessage() . PHP_EOL;
|
||||
var_dump($ex->getData());
|
||||
exit(1);
|
||||
}
|
||||
?>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Future payments</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
Created payment:
|
||||
<?php echo $payment->getId();?>
|
||||
</div>
|
||||
<pre><?php echo $payment->toJSON(JSON_PRETTY_PRINT);?></pre>
|
||||
<a href='../index.html'>Back</a>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user