This commit is contained in:
Tim Bendt
2025-11-25 00:16:35 -05:00
commit 6b9ef7ca55
6757 changed files with 1003748 additions and 0 deletions

View File

@@ -0,0 +1 @@
github: [barryvdh]

View File

@@ -0,0 +1,49 @@
name: "PHPUnit tests"
on:
pull_request:
push:
branches:
- "master"
jobs:
phpunit:
name: "PHPUnit tests"
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
dependencies:
- "lowest"
- "highest"
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
operating-system:
- "ubuntu-latest"
steps:
- name: "Checkout"
uses: "actions/checkout@v2"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "pcov"
php-version: "${{ matrix.php-version }}"
ini-values: memory_limit=-1
tools: composer:v2
- name: "Install lowest dependencies"
if: ${{ matrix.dependencies == 'lowest' }}
run: "composer update --prefer-lowest --no-interaction --no-progress --no-suggest"
- name: "Install highest dependencies"
if: ${{ matrix.dependencies == 'highest' }}
run: "composer update --no-interaction --no-progress --no-suggest"
- name: "Tests"
run: "vendor/bin/phpunit"

20
system/vendor/omnipay/common/LICENSE vendored Executable file
View File

@@ -0,0 +1,20 @@
Copyright (c) Adrian Macneil
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

62
system/vendor/omnipay/common/UPGRADE.md vendored Executable file
View File

@@ -0,0 +1,62 @@
## Upgrade apps from 2.x to 3.x
- The `redirect()` method no longer calls `exit()` after sending the content. This is up to the developer now.
- It is now possible to use `setAmountInteger(integer $value)` and `setMoney(Money $money)`
- HTTPPlug is used. Guzzle will be installed when using `omnipay/omnipay`, otherwise you need to require your own implementation (see http://docs.php-http.org/en/latest/clients.html)
- The package is renamed from `omnipay/omnipay` to `league/omnipay` and no longer installs all gateways by default.
## Upgrade Gateways from 2.x to 3.x
The primary difference is the HTTP Client. We are now using HTTPlug (http://httplug.io/) but rely on our own interface.
### Breaking
- Change typehint from Guzzle ClientInterface to `Omnipay\Common\Http\ClientInterface`
- `$client->get('..')`/`$client->post('..')` etc are removed, you can call `$client->request('GET', '')`.
- No need to call `$request->send()`, requests are sent directly.
- Instead of `$client->createRequest(..)` you can create+send the request directly with `$client->request(..)`.
- When sending a JSON body, convert the body to a string with `json_encode()` and set the correct Content-Type.
- The response is a PSR-7 Response object. You can call `$response->getBody()->getContents()` to get the body as a string.
- `$response->json()` and `$response->xml()` are gone, but you can implement the logic directly.
- An HTTP Client is no longer added by default by `omnipay/common`, but `omnipay/omnipay` will add Guzzle.
Gateways should not rely on Guzzle or other clients directly.
- `$body` should be a string (eg. `http_build_query($data)` or `json_encode($data)` instead of just `$data`).
- The `$headers` parameters should be an `array` (not `null`, but can be empty)
Examples:
```php
// V2 XML:
$response = $this->httpClient->post($this->endpoint, null, $data)->send();
$result = $httpResponse->xml();
// V3 XML:
$response = $this->httpClient->request('POST', $this->endpoint, [], http_build_query($data));
$result = simplexml_load_string($httpResponse->getBody()->getContents());
```
```php
// Example JSON request:
$response = $this->httpClient->request('POST', $this->endpoint, [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
], json_encode($data));
$result = json_decode($response->getBody()->getContents(), true);
```
#### Testing
PHPUnit is upgraded to PHPUnit 6. Common issues:
- `setExpectedException()` is removed
```php
// PHPUnit 5:
$this->setExpectedException($class, $message);
// PHPUnit 6:
$this->expectException($class);
$this->expectExceptionMessage($message);
```
- Tests that do not perform any assertions, will be marked as risky. This can be avoided by annotating them with ` @doesNotPerformAssertions`
- You should remove the `Mockery\Adapter\Phpunit\TestListener` in phpunit.xml.dist

74
system/vendor/omnipay/common/composer.json vendored Executable file
View File

@@ -0,0 +1,74 @@
{
"name": "omnipay/common",
"type": "library",
"description": "Common components for Omnipay payment processing library",
"keywords": [
"gateway",
"merchant",
"omnipay",
"pay",
"payment",
"purchase"
],
"homepage": "https://github.com/thephpleague/omnipay-common",
"license": "MIT",
"authors": [
{
"name": "Adrian Macneil",
"email": "adrian@adrianmacneil.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
},
{
"name": "Jason Judge",
"email": "jason.judge@consil.co.uk"
},
{
"name": "Del"
},
{
"name": "Omnipay Contributors",
"homepage": "https://github.com/thephpleague/omnipay-common/contributors"
}
],
"autoload": {
"psr-4": { "Omnipay\\Common\\" : "src/Common" },
"classmap": ["src/Omnipay.php"]
},
"autoload-dev": {
"psr-4": { "Omnipay\\Common\\" : "tests/Common" },
"classmap": ["tests/OmnipayTest.php"]
},
"require": {
"php": "^7.2|^8",
"php-http/client-implementation": "^1",
"php-http/message": "^1.5",
"php-http/message-factory": "^1.1",
"php-http/discovery": "^1.14",
"symfony/http-foundation": "^2.1|^3|^4|^5|^6",
"moneyphp/money": "^3.1|^4.0.3"
},
"require-dev": {
"omnipay/tests": "^4.1",
"php-http/mock-client": "^1",
"php-http/guzzle7-adapter": "^1",
"squizlabs/php_codesniffer": "^3.5"
},
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev"
}
},
"suggest": {
"league/omnipay": "The default Omnipay package provides a default HTTP Adapter."
},
"scripts": {
"test": "phpunit",
"check-style": "phpcs -p --standard=PSR2 src/",
"fix-style": "phpcbf -p --standard=PSR2 src/"
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -0,0 +1,74 @@
<?php
namespace Omnipay\Common\Http;
use function GuzzleHttp\Psr7\str;
use Http\Client\HttpClient;
use Http\Discovery\HttpClientDiscovery;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Message\RequestFactory;
use Omnipay\Common\Http\Exception\NetworkException;
use Omnipay\Common\Http\Exception\RequestException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
class Client implements ClientInterface
{
/**
* The Http Client which implements `public function sendRequest(RequestInterface $request)`
* Note: Will be changed to PSR-18 when released
*
* @var HttpClient
*/
private $httpClient;
/**
* @var RequestFactory
*/
private $requestFactory;
public function __construct($httpClient = null, RequestFactory $requestFactory = null)
{
$this->httpClient = $httpClient ?: HttpClientDiscovery::find();
$this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find();
}
/**
* @param $method
* @param $uri
* @param array $headers
* @param string|array|resource|StreamInterface|null $body
* @param string $protocolVersion
* @return ResponseInterface
* @throws \Http\Client\Exception
*/
public function request(
$method,
$uri,
array $headers = [],
$body = null,
$protocolVersion = '1.1'
) {
$request = $this->requestFactory->createRequest($method, $uri, $headers, $body, $protocolVersion);
return $this->sendRequest($request);
}
/**
* @param RequestInterface $request
* @return ResponseInterface
* @throws \Http\Client\Exception
*/
private function sendRequest(RequestInterface $request)
{
try {
return $this->httpClient->sendRequest($request);
} catch (\Http\Client\Exception\NetworkException $networkException) {
throw new NetworkException($networkException->getMessage(), $request, $networkException);
} catch (\Exception $exception) {
throw new RequestException($exception->getMessage(), $request, $exception);
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Omnipay\Common\Http;
use Omnipay\Common\Http\Exception\NetworkException;
use Omnipay\Common\Http\Exception\RequestException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
interface ClientInterface
{
/**
* Creates a new PSR-7 request.
*
* @param string $method
* @param string|UriInterface $uri
* @param array $headers
* @param resource|string|StreamInterface|null $body
* @param string $protocolVersion
*
* @throws RequestException when the HTTP client is passed a request that is invalid and cannot be sent.
* @throws NetworkException if there is an error with the network or the remote server cannot be reached.
*
* @return ResponseInterface
*/
public function request(
$method,
$uri,
array $headers = [],
$body = null,
$protocolVersion = '1.1'
);
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Omnipay\Common\Http;
use Psr\Http\Message\RequestInterface;
use Throwable;
abstract class Exception extends \RuntimeException
{
/** @var RequestInterface */
protected $request;
public function __construct($message, RequestInterface $request, $previous = null)
{
$this->request = $request;
parent::__construct($message, 0, $previous);
}
/**
* Returns the request.
*
* The request object MAY be a different object from the one passed to ClientInterface::sendRequest()
*
* @return RequestInterface
*/
public function getRequest()
{
return $this->request;
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Omnipay\Common\Http\Exception;
use Omnipay\Common\Http\Exception;
class NetworkException extends Exception
{
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Omnipay\Common\Http\Exception;
use Omnipay\Common\Http\Exception;
class RequestException extends Exception
{
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Omnipay\Common;
use Omnipay\Common\Exception\InvalidRequestException;
use Symfony\Component\HttpFoundation\ParameterBag;
trait ParametersTrait
{
/**
* Internal storage of all of the parameters.
*
* @var ParameterBag
*/
protected $parameters;
/**
* Set one parameter.
*
* @param string $key Parameter key
* @param mixed $value Parameter value
* @return $this
*/
protected function setParameter($key, $value)
{
$this->parameters->set($key, $value);
return $this;
}
/**
* Get one parameter.
*
* @param string $key Parameter key
* @return mixed A single parameter value.
*/
protected function getParameter($key)
{
return $this->parameters->get($key);
}
/**
* Get all parameters.
*
* @return array An associative array of parameters.
*/
public function getParameters()
{
return $this->parameters->all();
}
/**
* Initialize the object with parameters.
*
* If any unknown parameters passed, they will be ignored.
*
* @param array $parameters An associative array of parameters
* @return $this.
*/
public function initialize(array $parameters = [])
{
$this->parameters = new ParameterBag;
Helper::initialize($this, $parameters);
return $this;
}
/**
* Validate the request.
*
* This method is called internally by gateways to avoid wasting time with an API call
* when the request is clearly invalid.
*
* @param string ... a variable length list of required parameters
* @throws InvalidRequestException
*/
public function validate(...$args)
{
foreach ($args as $key) {
$value = $this->parameters->get($key);
if (! isset($value)) {
throw new InvalidRequestException("The $key parameter is required");
}
}
}
}

View File

@@ -0,0 +1,351 @@
<?php
/**
* Base payment gateway class
*/
namespace Omnipay\Common;
use Guzzle\Http\ClientInterface;
use Guzzle\Http\Client as HttpClient;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
/**
* Base payment gateway class
*
* This abstract class should be extended by all payment gateways
* throughout the Omnipay system. It enforces implementation of
* the GatewayInterface interface and defines various common attibutes
* and methods that all gateways should have.
*
* Example:
*
* <code>
* // Initialise the gateway
* $gateway->initialize(...);
*
* // Get the gateway parameters.
* $parameters = $gateway->getParameters();
*
* // Create a credit card object
* $card = new CreditCard(...);
*
* // Do an authorisation transaction on the gateway
* if ($gateway->supportsAuthorize()) {
* $gateway->authorize(...);
* } else {
* throw new \Exception('Gateway does not support authorize()');
* }
* </code>
*
* For further code examples see the *omnipay-example* repository on github.
*
* @see GatewayInterface
*/
abstract class AbstractGateway implements GatewayInterface
{
/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*/
protected $parameters;
/**
* @var \Guzzle\Http\ClientInterface
*/
protected $httpClient;
/**
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $httpRequest;
/**
* Create a new gateway instance
*
* @param ClientInterface $httpClient A Guzzle client to make API calls with
* @param HttpRequest $httpRequest A Symfony HTTP request object
*/
public function __construct(ClientInterface $httpClient = null, HttpRequest $httpRequest = null)
{
$this->httpClient = $httpClient ?: $this->getDefaultHttpClient();
$this->httpRequest = $httpRequest ?: $this->getDefaultHttpRequest();
$this->initialize();
}
/**
* Get the short name of the Gateway
*
* @return string
*/
public function getShortName()
{
return Helper::getGatewayShortName(get_class($this));
}
/**
* Initialize this gateway with default parameters
*
* @param array $parameters
* @return $this
*/
public function initialize(array $parameters = array())
{
$this->parameters = new ParameterBag;
// set default parameters
foreach ($this->getDefaultParameters() as $key => $value) {
if (is_array($value)) {
$this->parameters->set($key, reset($value));
} else {
$this->parameters->set($key, $value);
}
}
Helper::initialize($this, $parameters);
return $this;
}
/**
* @return array
*/
public function getDefaultParameters()
{
return array();
}
/**
* @return array
*/
public function getParameters()
{
return $this->parameters->all();
}
/**
* @param string $key
* @return mixed
*/
public function getParameter($key)
{
return $this->parameters->get($key);
}
/**
* @param string $key
* @param mixed $value
* @return $this
*/
public function setParameter($key, $value)
{
$this->parameters->set($key, $value);
return $this;
}
/**
* @return boolean
*/
public function getTestMode()
{
return $this->getParameter('testMode');
}
/**
* @param boolean $value
* @return $this
*/
public function setTestMode($value)
{
return $this->setParameter('testMode', $value);
}
/**
* @return string
*/
public function getCurrency()
{
return strtoupper($this->getParameter('currency'));
}
/**
* @param string $value
* @return $this
*/
public function setCurrency($value)
{
return $this->setParameter('currency', $value);
}
/**
* Supports Authorize
*
* @return boolean True if this gateway supports the authorize() method
*/
public function supportsAuthorize()
{
return method_exists($this, 'authorize');
}
/**
* Supports Complete Authorize
*
* @return boolean True if this gateway supports the completeAuthorize() method
*/
public function supportsCompleteAuthorize()
{
return method_exists($this, 'completeAuthorize');
}
/**
* Supports Capture
*
* @return boolean True if this gateway supports the capture() method
*/
public function supportsCapture()
{
return method_exists($this, 'capture');
}
/**
* Supports Purchase
*
* @return boolean True if this gateway supports the purchase() method
*/
public function supportsPurchase()
{
return method_exists($this, 'purchase');
}
/**
* Supports Complete Purchase
*
* @return boolean True if this gateway supports the completePurchase() method
*/
public function supportsCompletePurchase()
{
return method_exists($this, 'completePurchase');
}
/**
* Supports Refund
*
* @return boolean True if this gateway supports the refund() method
*/
public function supportsRefund()
{
return method_exists($this, 'refund');
}
/**
* Supports Void
*
* @return boolean True if this gateway supports the void() method
*/
public function supportsVoid()
{
return method_exists($this, 'void');
}
/**
* Supports AcceptNotification
*
* @return boolean True if this gateway supports the acceptNotification() method
*/
public function supportsAcceptNotification()
{
return method_exists($this, 'acceptNotification');
}
/**
* Supports CreateCard
*
* @return boolean True if this gateway supports the create() method
*/
public function supportsCreateCard()
{
return method_exists($this, 'createCard');
}
/**
* Supports DeleteCard
*
* @return boolean True if this gateway supports the delete() method
*/
public function supportsDeleteCard()
{
return method_exists($this, 'deleteCard');
}
/**
* Supports UpdateCard
*
* @return boolean True if this gateway supports the update() method
*/
public function supportsUpdateCard()
{
return method_exists($this, 'updateCard');
}
/**
* Create and initialize a request object
*
* This function is usually used to create objects of type
* Omnipay\Common\Message\AbstractRequest (or a non-abstract subclass of it)
* and initialise them with using existing parameters from this gateway.
*
* Example:
*
* <code>
* class MyRequest extends \Omnipay\Common\Message\AbstractRequest {};
*
* class MyGateway extends \Omnipay\Common\AbstractGateway {
* function myRequest($parameters) {
* $this->createRequest('MyRequest', $parameters);
* }
* }
*
* // Create the gateway object
* $gw = Omnipay::create('MyGateway');
*
* // Create the request object
* $myRequest = $gw->myRequest($someParameters);
* </code>
*
* @see \Omnipay\Common\Message\AbstractRequest
* @param string $class The request class name
* @param array $parameters
* @return \Omnipay\Common\Message\AbstractRequest
*/
protected function createRequest($class, array $parameters)
{
$obj = new $class($this->httpClient, $this->httpRequest);
return $obj->initialize(array_replace($this->getParameters(), $parameters));
}
/**
* Get the global default HTTP client.
*
* @return HttpClient
*/
protected function getDefaultHttpClient()
{
return new HttpClient(
'',
array(
'curl.options' => array(CURLOPT_CONNECTTIMEOUT => 60),
)
);
}
/**
* Get the global default HTTP request.
*
* @return HttpRequest
*/
protected function getDefaultHttpRequest()
{
return HttpRequest::createFromGlobals();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Bad Method Call Exception
*/
class BadMethodCallException extends \BadMethodCallException implements OmnipayException
{
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Invalid Credit Card Exception
*
* Thrown when a credit card is invalid or missing required fields.
*/
class InvalidCreditCardException extends \Exception implements OmnipayException
{
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Invalid Request Exception
*
* Thrown when a request is invalid or missing required fields.
*/
class InvalidRequestException extends \Exception implements OmnipayException
{
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Invalid Response exception.
*
* Thrown when a gateway responded with invalid or unexpected data (for example, a security hash did not match).
*/
class InvalidResponseException extends \Exception implements OmnipayException
{
public function __construct($message = "Invalid response from payment gateway", $code = 0, $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Omnipay Exception marker interface
*/
interface OmnipayException
{
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Omnipay\Common\Exception;
/**
* Runtime Exception
*/
class RuntimeException extends \RuntimeException implements OmnipayException
{
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* Omnipay Gateway Factory class
*/
namespace Omnipay\Common;
use Guzzle\Http\ClientInterface;
use Omnipay\Common\Exception\RuntimeException;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
/**
* Omnipay Gateway Factory class
*
* This class abstracts a set of gateways that can be independently
* registered, accessed, and used.
*
* Note that static calls to the Omnipay class are routed to this class by
* the static call router (__callStatic) in Omnipay.
*
* Example:
*
* <code>
* // Create a gateway for the PayPal ExpressGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('ExpressGateway');
* </code>
*
* @see Omnipay\Omnipay
*/
class GatewayFactory
{
/**
* Internal storage for all available gateways
*
* @var array
*/
private $gateways = array();
/**
* All available gateways
*
* @return array An array of gateway names
*/
public function all()
{
return $this->gateways;
}
/**
* Replace the list of available gateways
*
* @param array $gateways An array of gateway names
*/
public function replace(array $gateways)
{
$this->gateways = $gateways;
}
/**
* Register a new gateway
*
* @param string $className Gateway name
*/
public function register($className)
{
if (!in_array($className, $this->gateways)) {
$this->gateways[] = $className;
}
}
/**
* Automatically find and register all officially supported gateways
*
* @return array An array of gateway names
*/
public function find()
{
foreach ($this->getSupportedGateways() as $gateway) {
$class = Helper::getGatewayClassName($gateway);
if (class_exists($class)) {
$this->register($gateway);
}
}
ksort($this->gateways);
return $this->all();
}
/**
* Create a new gateway instance
*
* @param string $class Gateway name
* @param ClientInterface|null $httpClient A Guzzle HTTP Client implementation
* @param HttpRequest|null $httpRequest A Symfony HTTP Request implementation
* @throws RuntimeException If no such gateway is found
* @return GatewayInterface An object of class $class is created and returned
*/
public function create($class, ClientInterface $httpClient = null, HttpRequest $httpRequest = null)
{
$class = Helper::getGatewayClassName($class);
if (!class_exists($class)) {
throw new RuntimeException("Class '$class' not found");
}
return new $class($httpClient, $httpRequest);
}
/**
* Get a list of supported gateways which may be available
*
* @return array
*/
public function getSupportedGateways()
{
$package = json_decode(file_get_contents(__DIR__.'/../../../composer.json'), true);
return $package['extra']['gateways'];
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* Payment gateway interface
*/
namespace Omnipay\Common;
/**
* Payment gateway interface
*
* This interface class defines the standard functions that any
* Omnipay gateway needs to define.
*
* @see AbstractGateway
*
* @method \Omnipay\Common\Message\RequestInterface authorize(array $options = array()) (Optional method)
* Authorize an amount on the customers card
* @method \Omnipay\Common\Message\RequestInterface completeAuthorize(array $options = array()) (Optional method)
* Handle return from off-site gateways after authorization
* @method \Omnipay\Common\Message\RequestInterface capture(array $options = array()) (Optional method)
* Capture an amount you have previously authorized
* @method \Omnipay\Common\Message\RequestInterface purchase(array $options = array()) (Optional method)
* Authorize and immediately capture an amount on the customers card
* @method \Omnipay\Common\Message\RequestInterface completePurchase(array $options = array()) (Optional method)
* Handle return from off-site gateways after purchase
* @method \Omnipay\Common\Message\RequestInterface refund(array $options = array()) (Optional method)
* Refund an already processed transaction
* @method \Omnipay\Common\Message\RequestInterface void(array $options = array()) (Optional method)
* Generally can only be called up to 24 hours after submitting a transaction
* @method \Omnipay\Common\Message\RequestInterface createCard(array $options = array()) (Optional method)
* The returned response object includes a cardReference, which can be used for future transactions
* @method \Omnipay\Common\Message\RequestInterface updateCard(array $options = array()) (Optional method)
* Update a stored card
* @method \Omnipay\Common\Message\RequestInterface deleteCard(array $options = array()) (Optional method)
* Delete a stored card
*/
interface GatewayInterface
{
/**
* Get gateway display name
*
* This can be used by carts to get the display name for each gateway.
*/
public function getName();
/**
* Get gateway short name
*
* This name can be used with GatewayFactory as an alias of the gateway class,
* to create new instances of this gateway.
*/
public function getShortName();
/**
* Define gateway parameters, in the following format:
*
* array(
* 'username' => '', // string variable
* 'testMode' => false, // boolean variable
* 'landingPage' => array('billing', 'login'), // enum variable, first item is default
* );
*/
public function getDefaultParameters();
/**
* Initialize gateway with parameters
*/
public function initialize(array $parameters = array());
/**
* Get all gateway parameters
*
* @return array
*/
public function getParameters();
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* Helper class
*/
namespace Omnipay\Common;
use InvalidArgumentException;
/**
* Helper class
*
* This class defines various static utility functions that are in use
* throughout the Omnipay system.
*/
class Helper
{
/**
* Convert a string to camelCase. Strings already in camelCase will not be harmed.
*
* @param string $str The input string
* @return string camelCased output string
*/
public static function camelCase($str)
{
$str = self::convertToLowercase($str);
return preg_replace_callback(
'/_([a-z])/',
function ($match) {
return strtoupper($match[1]);
},
$str
);
}
/**
* Convert strings with underscores to be all lowercase before camelCase is preformed.
*
* @param string $str The input string
* @return string The output string
*/
protected static function convertToLowercase($str)
{
$explodedStr = explode('_', $str);
if (count($explodedStr) > 1) {
foreach ($explodedStr as $value) {
$lowercasedStr[] = strtolower($value);
}
$str = implode('_', $lowercasedStr);
}
return $str;
}
/**
* Validate a card number according to the Luhn algorithm.
*
* @param string $number The card number to validate
* @return boolean True if the supplied card number is valid
*/
public static function validateLuhn($number)
{
$str = '';
foreach (array_reverse(str_split($number)) as $i => $c) {
$str .= $i % 2 ? $c * 2 : $c;
}
return array_sum(str_split($str)) % 10 === 0;
}
/**
* Initialize an object with a given array of parameters
*
* Parameters are automatically converted to camelCase. Any parameters which do
* not match a setter on the target object are ignored.
*
* @param mixed $target The object to set parameters on
* @param array $parameters An array of parameters to set
*/
public static function initialize($target, $parameters)
{
if (is_array($parameters)) {
foreach ($parameters as $key => $value) {
$method = 'set'.ucfirst(static::camelCase($key));
if (method_exists($target, $method)) {
$target->$method($value);
}
}
}
}
/**
* Resolve a gateway class to a short name.
*
* The short name can be used with GatewayFactory as an alias of the gateway class,
* to create new instances of a gateway.
*/
public static function getGatewayShortName($className)
{
if (0 === strpos($className, '\\')) {
$className = substr($className, 1);
}
if (0 === strpos($className, 'Omnipay\\')) {
return trim(str_replace('\\', '_', substr($className, 8, -7)), '_');
}
return '\\'.$className;
}
/**
* Resolve a short gateway name to a full namespaced gateway class.
*
* Class names beginning with a namespace marker (\) are left intact.
* Non-namespaced classes are expected to be in the \Omnipay namespace, e.g.:
*
* \Custom\Gateway => \Custom\Gateway
* \Custom_Gateway => \Custom_Gateway
* Stripe => \Omnipay\Stripe\Gateway
* PayPal\Express => \Omnipay\PayPal\ExpressGateway
* PayPal_Express => \Omnipay\PayPal\ExpressGateway
*
* @param string $shortName The short gateway name
* @return string The fully namespaced gateway class name
*/
public static function getGatewayClassName($shortName)
{
if (0 === strpos($shortName, '\\')) {
return $shortName;
}
// replace underscores with namespace marker, PSR-0 style
$shortName = str_replace('_', '\\', $shortName);
if (false === strpos($shortName, '\\')) {
$shortName .= '\\';
}
return '\\Omnipay\\'.$shortName.'Gateway';
}
/**
* Convert an amount into a float.
* The float datatype can then be converted into the string
* format that the remote gateway requies.
*
* @var string|int|float $value The value to convert.
* @throws InvalidArgumentException on a validation failure.
* @return float The amount converted to a float.
*/
public static function toFloat($value)
{
if (!is_string($value) && !is_int($value) && !is_float($value)) {
throw new InvalidArgumentException('Data type is not a valid decimal number.');
}
if (is_string($value)) {
// Validate generic number, with optional sign and decimals.
if (!preg_match('/^[-]?[0-9]+(\.[0-9]*)?$/', $value)) {
throw new InvalidArgumentException('String is not a valid decimal number.');
}
}
return (float)$value;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Issuer
*/
namespace Omnipay\Common;
/**
* Issuer
*
* This class abstracts some functionality around card issuers used in the
* Omnipay system.
*/
class Issuer
{
/**
* The identifier of the issuer.
*
* @var string
*/
protected $id;
/**
* The full name of the issuer.
*
* @var string
*/
protected $name;
/**
* The ID of a payment method that the issuer belongs to.
*
* @see PaymentMethod
*
* @var string
*/
protected $paymentMethod;
/**
* Create a new Issuer
*
* @see PaymentMethod
*
* @param string $id The identifier of this issuer
* @param string $name The name of this issuer
* @param string|null $paymentMethod The ID of a payment method this issuer belongs to
*/
public function __construct($id, $name, $paymentMethod = null)
{
$this->id = $id;
$this->name = $name;
$this->paymentMethod = $paymentMethod;
}
/**
* The identifier of this issuer
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* The name of this issuer
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* The ID of a payment method this issuer belongs to
*
* @see PaymentMethod
*
* @return string
*/
public function getPaymentMethod()
{
return $this->paymentMethod;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* Cart Item
*/
namespace Omnipay\Common;
use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Cart Item
*
* This class defines a single cart item in the Omnipay system.
*
* @see ItemInterface
*/
class Item implements ItemInterface
{
/**
* @var \Symfony\Component\HttpFoundation\ParameterBag
*/
protected $parameters;
/**
* Create a new item with the specified parameters
*
* @param array|null $parameters An array of parameters to set on the new object
*/
public function __construct($parameters = null)
{
$this->initialize($parameters);
}
/**
* Initialize this item with the specified parameters
*
* @param array|null $parameters An array of parameters to set on this object
* @return $this Item
*/
public function initialize($parameters = null)
{
$this->parameters = new ParameterBag;
Helper::initialize($this, $parameters);
return $this;
}
public function getParameters()
{
return $this->parameters->all();
}
protected function getParameter($key)
{
return $this->parameters->get($key);
}
protected function setParameter($key, $value)
{
$this->parameters->set($key, $value);
return $this;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return $this->getParameter('name');
}
/**
* Set the item name
*/
public function setName($value)
{
return $this->setParameter('name', $value);
}
/**
* {@inheritDoc}
*/
public function getDescription()
{
return $this->getParameter('description');
}
/**
* Set the item description
*/
public function setDescription($value)
{
return $this->setParameter('description', $value);
}
/**
* {@inheritDoc}
*/
public function getQuantity()
{
return $this->getParameter('quantity');
}
/**
* Set the item quantity
*/
public function setQuantity($value)
{
return $this->setParameter('quantity', $value);
}
/**
* {@inheritDoc}
*/
public function getPrice()
{
return $this->getParameter('price');
}
/**
* Set the item price
*/
public function setPrice($value)
{
return $this->setParameter('price', $value);
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Cart Item Bag
*/
namespace Omnipay\Common;
/**
* Cart Item Bag
*
* This class defines a bag (multi element set or array) of single cart items
* in the Omnipay system.
*
* @see Item
*/
class ItemBag implements \IteratorAggregate, \Countable
{
/**
* Item storage
*
* @see Item
*
* @var array
*/
protected $items;
/**
* Constructor
*
* @param array $items An array of items
*/
public function __construct(array $items = array())
{
$this->replace($items);
}
/**
* Return all the items
*
* @see Item
*
* @return array An array of items
*/
public function all()
{
return $this->items;
}
/**
* Replace the contents of this bag with the specified items
*
* @see Item
*
* @param array $items An array of items
*/
public function replace(array $items = array())
{
$this->items = array();
foreach ($items as $item) {
$this->add($item);
}
}
/**
* Add an item to the bag
*
* @see Item
*
* @param ItemInterface|array $item An existing item, or associative array of item parameters
*/
public function add($item)
{
if ($item instanceof ItemInterface) {
$this->items[] = $item;
} else {
$this->items[] = new Item($item);
}
}
/**
* Returns an iterator for items
*
* @return \ArrayIterator An \ArrayIterator instance
*/
public function getIterator()
{
return new \ArrayIterator($this->items);
}
/**
* Returns the number of items
*
* @return int The number of items
*/
public function count()
{
return count($this->items);
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Cart Item interface
*/
namespace Omnipay\Common;
/**
* Cart Item interface
*
* This interface defines the functionality that all cart items in
* the Omnipay system are to have.
*/
interface ItemInterface
{
/**
* Name of the item
*/
public function getName();
/**
* Description of the item
*/
public function getDescription();
/**
* Quantity of the item
*/
public function getQuantity();
/**
* Price of the item
*/
public function getPrice();
}

View File

@@ -0,0 +1,694 @@
<?php
/**
* Abstract Request
*/
namespace Omnipay\Common\Message;
use Guzzle\Http\ClientInterface;
use Omnipay\Common\CreditCard;
use Omnipay\Common\Currency;
use Omnipay\Common\Exception\InvalidRequestException;
use Omnipay\Common\Exception\RuntimeException;
use Omnipay\Common\Helper;
use Omnipay\Common\ItemBag;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use InvalidArgumentException;
/**
* Abstract Request
*
* This abstract class implements RequestInterface and defines a basic
* set of functions that all Omnipay Requests are intended to include.
*
* Requests of this class are usually created using the createRequest
* function of the gateway and then actioned using methods within this
* class or a class that extends this class.
*
* Example -- creating a request:
*
* <code>
* class MyRequest extends \Omnipay\Common\Message\AbstractRequest {};
*
* class MyGateway extends \Omnipay\Common\AbstractGateway {
* function myRequest($parameters) {
* $this->createRequest('MyRequest', $parameters);
* }
* }
*
* // Create the gateway object
* $gw = Omnipay::create('MyGateway');
*
* // Create the request object
* $myRequest = $gw->myRequest($someParameters);
* </code>
*
* Example -- validating and sending a request:
*
* <code>
* try {
* $myRequest->validate();
* $myResponse = $myRequest->send();
* } catch (InvalidRequestException $e) {
* print "Something went wrong: " . $e->getMessage() . "\n";
* }
* // now do something with the $myResponse object, test for success, etc.
* </code>
*
* @see RequestInterface
* @see AbstractResponse
*/
abstract class AbstractRequest implements RequestInterface
{
/**
* The request parameters
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*/
protected $parameters;
/**
* The request client.
*
* @var \Guzzle\Http\ClientInterface
*/
protected $httpClient;
/**
* The HTTP request object.
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $httpRequest;
/**
* An associated ResponseInterface.
*
* @var ResponseInterface
*/
protected $response;
/**
* @var bool
*/
protected $zeroAmountAllowed = true;
/**
* @var bool
*/
protected $negativeAmountAllowed = false;
/**
* Create a new Request
*
* @param ClientInterface $httpClient A Guzzle client to make API calls with
* @param HttpRequest $httpRequest A Symfony HTTP request object
*/
public function __construct(ClientInterface $httpClient, HttpRequest $httpRequest)
{
$this->httpClient = $httpClient;
$this->httpRequest = $httpRequest;
$this->initialize();
}
/**
* Initialize the object with parameters.
*
* If any unknown parameters passed, they will be ignored.
*
* @param array $parameters An associative array of parameters
*
* @return $this
* @throws RuntimeException
*/
public function initialize(array $parameters = array())
{
if (null !== $this->response) {
throw new RuntimeException('Request cannot be modified after it has been sent!');
}
$this->parameters = new ParameterBag;
Helper::initialize($this, $parameters);
return $this;
}
/**
* Get all parameters as an associative array.
*
* @return array
*/
public function getParameters()
{
return $this->parameters->all();
}
/**
* Get a single parameter.
*
* @param string $key The parameter key
* @return mixed
*/
protected function getParameter($key)
{
return $this->parameters->get($key);
}
/**
* Set a single parameter
*
* @param string $key The parameter key
* @param mixed $value The value to set
* @return AbstractRequest Provides a fluent interface
* @throws RuntimeException if a request parameter is modified after the request has been sent.
*/
protected function setParameter($key, $value)
{
if (null !== $this->response) {
throw new RuntimeException('Request cannot be modified after it has been sent!');
}
$this->parameters->set($key, $value);
return $this;
}
/**
* Gets the test mode of the request from the gateway.
*
* @return boolean
*/
public function getTestMode()
{
return $this->getParameter('testMode');
}
/**
* Sets the test mode of the request.
*
* @param boolean $value True for test mode on.
* @return AbstractRequest
*/
public function setTestMode($value)
{
return $this->setParameter('testMode', $value);
}
/**
* Validate the request.
*
* This method is called internally by gateways to avoid wasting time with an API call
* when the request is clearly invalid.
*
* @param string ... a variable length list of required parameters
* @throws InvalidRequestException
*/
public function validate()
{
foreach (func_get_args() as $key) {
$value = $this->parameters->get($key);
if (! isset($value)) {
throw new InvalidRequestException("The $key parameter is required");
}
}
}
/**
* Get the card.
*
* @return CreditCard
*/
public function getCard()
{
return $this->getParameter('card');
}
/**
* Sets the card.
*
* @param CreditCard $value
* @return AbstractRequest Provides a fluent interface
*/
public function setCard($value)
{
if ($value && !$value instanceof CreditCard) {
$value = new CreditCard($value);
}
return $this->setParameter('card', $value);
}
/**
* Get the card token.
*
* @return string
*/
public function getToken()
{
return $this->getParameter('token');
}
/**
* Sets the card token.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setToken($value)
{
return $this->setParameter('token', $value);
}
/**
* Get the card reference.
*
* @return string
*/
public function getCardReference()
{
return $this->getParameter('cardReference');
}
/**
* Sets the card reference.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setCardReference($value)
{
return $this->setParameter('cardReference', $value);
}
/**
* Convert an amount into a float.
*
* @var string|int|float $value The value to convert.
* @throws InvalidRequestException on any validation failure.
* @return float The amount converted to a float.
*/
public function toFloat($value)
{
try {
return Helper::toFloat($value);
} catch (InvalidArgumentException $e) {
// Throw old exception for legacy implementations.
throw new InvalidRequestException($e->getMessage(), $e->getCode(), $e);
}
}
/**
* Validates and returns the formated amount.
*
* @throws InvalidRequestException on any validation failure.
* @return string The amount formatted to the correct number of decimal places for the selected currency.
*/
public function getAmount()
{
$amount = $this->getParameter('amount');
if ($amount !== null) {
// Don't allow integers for currencies that support decimals.
// This is for legacy reasons - upgrades from v0.9
if ($this->getCurrencyDecimalPlaces() > 0) {
if (is_int($amount) || (is_string($amount) && false === strpos((string) $amount, '.'))) {
throw new InvalidRequestException(
'Please specify amount as a string or float, '
. 'with decimal places (e.g. \'10.00\' to represent $10.00).'
);
};
}
$amount = $this->toFloat($amount);
// Check for a negative amount.
if (!$this->negativeAmountAllowed && $amount < 0) {
throw new InvalidRequestException('A negative amount is not allowed.');
}
// Check for a zero amount.
if (!$this->zeroAmountAllowed && $amount === 0.0) {
throw new InvalidRequestException('A zero amount is not allowed.');
}
// Check for rounding that may occur if too many significant decimal digits are supplied.
$decimal_count = strlen(substr(strrchr(sprintf('%.8g', $amount), '.'), 1));
if ($decimal_count > $this->getCurrencyDecimalPlaces()) {
throw new InvalidRequestException('Amount precision is too high for currency.');
}
return $this->formatCurrency($amount);
}
}
/**
* Sets the payment amount.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setAmount($value)
{
return $this->setParameter('amount', $value);
}
/**
* Get the payment amount as an integer.
*
* @return integer
*/
public function getAmountInteger()
{
return (int) round($this->getAmount() * $this->getCurrencyDecimalFactor());
}
/**
* Get the payment currency code.
*
* @return string
*/
public function getCurrency()
{
return $this->getParameter('currency');
}
/**
* Sets the payment currency code.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setCurrency($value)
{
if ($value !== null) {
$value = strtoupper($value);
}
return $this->setParameter('currency', $value);
}
/**
* Get the payment currency number.
*
* @return integer
*/
public function getCurrencyNumeric()
{
if ($currency = Currency::find($this->getCurrency())) {
return $currency->getNumeric();
}
}
/**
* Get the number of decimal places in the payment currency.
*
* @return integer
*/
public function getCurrencyDecimalPlaces()
{
if ($currency = Currency::find($this->getCurrency())) {
return $currency->getDecimals();
}
return 2;
}
private function getCurrencyDecimalFactor()
{
return pow(10, $this->getCurrencyDecimalPlaces());
}
/**
* Format an amount for the payment currency.
*
* @return string
*/
public function formatCurrency($amount)
{
return number_format(
$amount,
$this->getCurrencyDecimalPlaces(),
'.',
''
);
}
/**
* Get the request description.
*
* @return string
*/
public function getDescription()
{
return $this->getParameter('description');
}
/**
* Sets the request description.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setDescription($value)
{
return $this->setParameter('description', $value);
}
/**
* Get the transaction ID.
*
* The transaction ID is the identifier generated by the merchant website.
*
* @return string
*/
public function getTransactionId()
{
return $this->getParameter('transactionId');
}
/**
* Sets the transaction ID.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setTransactionId($value)
{
return $this->setParameter('transactionId', $value);
}
/**
* Get the transaction reference.
*
* The transaction reference is the identifier generated by the remote
* payment gateway.
*
* @return string
*/
public function getTransactionReference()
{
return $this->getParameter('transactionReference');
}
/**
* Sets the transaction reference.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setTransactionReference($value)
{
return $this->setParameter('transactionReference', $value);
}
/**
* A list of items in this order
*
* @return ItemBag|null A bag containing items in this order
*/
public function getItems()
{
return $this->getParameter('items');
}
/**
* Set the items in this order
*
* @param ItemBag|array $items An array of items in this order
* @return AbstractRequest
*/
public function setItems($items)
{
if ($items && !$items instanceof ItemBag) {
$items = new ItemBag($items);
}
return $this->setParameter('items', $items);
}
/**
* Get the client IP address.
*
* @return string
*/
public function getClientIp()
{
return $this->getParameter('clientIp');
}
/**
* Sets the client IP address.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setClientIp($value)
{
return $this->setParameter('clientIp', $value);
}
/**
* Get the request return URL.
*
* @return string
*/
public function getReturnUrl()
{
return $this->getParameter('returnUrl');
}
/**
* Sets the request return URL.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setReturnUrl($value)
{
return $this->setParameter('returnUrl', $value);
}
/**
* Get the request cancel URL.
*
* @return string
*/
public function getCancelUrl()
{
return $this->getParameter('cancelUrl');
}
/**
* Sets the request cancel URL.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setCancelUrl($value)
{
return $this->setParameter('cancelUrl', $value);
}
/**
* Get the request notify URL.
*
* @return string
*/
public function getNotifyUrl()
{
return $this->getParameter('notifyUrl');
}
/**
* Sets the request notify URL.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setNotifyUrl($value)
{
return $this->setParameter('notifyUrl', $value);
}
/**
* Get the payment issuer.
*
* This field is used by some European gateways, and normally represents
* the bank where an account is held (separate from the card brand).
*
* @return string
*/
public function getIssuer()
{
return $this->getParameter('issuer');
}
/**
* Set the payment issuer.
*
* This field is used by some European gateways, and normally represents
* the bank where an account is held (separate from the card brand).
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setIssuer($value)
{
return $this->setParameter('issuer', $value);
}
/**
* Get the payment issuer.
*
* This field is used by some European gateways, which support
* multiple payment providers with a single API.
*
* @return string
*/
public function getPaymentMethod()
{
return $this->getParameter('paymentMethod');
}
/**
* Set the payment method.
*
* This field is used by some European gateways, which support
* multiple payment providers with a single API.
*
* @param string $value
* @return AbstractRequest Provides a fluent interface
*/
public function setPaymentMethod($value)
{
return $this->setParameter('paymentMethod', $value);
}
/**
* Send the request
*
* @return ResponseInterface
*/
public function send()
{
$data = $this->getData();
return $this->sendData($data);
}
/**
* Get the associated Response.
*
* @return ResponseInterface
*/
public function getResponse()
{
if (null === $this->response) {
throw new RuntimeException('You must call send() before accessing the Response!');
}
return $this->response;
}
}

View File

@@ -0,0 +1,224 @@
<?php
/**
* Abstract Response
*/
namespace Omnipay\Common\Message;
use Omnipay\Common\Exception\RuntimeException;
use Symfony\Component\HttpFoundation\RedirectResponse as HttpRedirectResponse;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
/**
* Abstract Response
*
* This abstract class implements ResponseInterface and defines a basic
* set of functions that all Omnipay Requests are intended to include.
*
* Objects of this class or a subclass are usually created in the Request
* object (subclass of AbstractRequest) as the return parameters from the
* send() function.
*
* Example -- validating and sending a request:
*
* <code>
* $myResponse = $myRequest->send();
* // now do something with the $myResponse object, test for success, etc.
* </code>
*
* @see ResponseInterface
*/
abstract class AbstractResponse implements ResponseInterface
{
/**
* The embodied request object.
*
* @var RequestInterface
*/
protected $request;
/**
* The data contained in the response.
*
* @var mixed
*/
protected $data;
/**
* Constructor
*
* @param RequestInterface $request the initiating request.
* @param mixed $data
*/
public function __construct(RequestInterface $request, $data)
{
$this->request = $request;
$this->data = $data;
}
/**
* Get the initiating request object.
*
* @return RequestInterface
*/
public function getRequest()
{
return $this->request;
}
/**
* Is the response successful?
*
* @return boolean
*/
public function isPending()
{
return false;
}
/**
* Does the response require a redirect?
*
* @return boolean
*/
public function isRedirect()
{
return false;
}
/**
* Is the response a transparent redirect?
*
* @return boolean
*/
public function isTransparentRedirect()
{
return false;
}
/**
* Is the transaction cancelled by the user?
*
* @return boolean
*/
public function isCancelled()
{
return false;
}
/**
* Get the response data.
*
* @return mixed
*/
public function getData()
{
return $this->data;
}
/**
* Response Message
*
* @return null|string A response message from the payment gateway
*/
public function getMessage()
{
return null;
}
/**
* Response code
*
* @return null|string A response code from the payment gateway
*/
public function getCode()
{
return null;
}
/**
* Gateway Reference
*
* @return null|string A reference provided by the gateway to represent this transaction
*/
public function getTransactionReference()
{
return null;
}
/**
* Get the transaction ID as generated by the merchant website.
*
* @return string
*/
public function getTransactionId()
{
return null;
}
/**
* Automatically perform any required redirect
*
* This method is meant to be a helper for simple scenarios. If you want to customize the
* redirection page, just call the getRedirectUrl() and getRedirectData() methods directly.
*
* @codeCoverageIgnore
*
* @return void
*/
public function redirect()
{
$this->getRedirectResponse()->send();
exit;
}
/**
* @return HttpRedirectResponse
*/
public function getRedirectResponse()
{
if (!$this instanceof RedirectResponseInterface || !$this->isRedirect()) {
throw new RuntimeException('This response does not support redirection.');
}
if ('GET' === $this->getRedirectMethod()) {
return HttpRedirectResponse::create($this->getRedirectUrl());
} elseif ('POST' === $this->getRedirectMethod()) {
$hiddenFields = '';
foreach ($this->getRedirectData() as $key => $value) {
$hiddenFields .= sprintf(
'<input type="hidden" name="%1$s" value="%2$s" />',
htmlentities($key, ENT_QUOTES, 'UTF-8', false),
htmlentities($value, ENT_QUOTES, 'UTF-8', false)
)."\n";
}
$output = '<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Redirecting...</title>
</head>
<body onload="document.forms[0].submit();">
<form action="%1$s" method="post">
<p>Redirecting to payment page...</p>
<p>
%2$s
<input type="submit" value="Continue" />
</p>
</form>
</body>
</html>';
$output = sprintf(
$output,
htmlentities($this->getRedirectUrl(), ENT_QUOTES, 'UTF-8', false),
$hiddenFields
);
return HttpResponse::create($output);
}
throw new RuntimeException('Invalid redirect method "'.$this->getRedirectMethod().'".');
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Fetch Issuers Response interface
*/
namespace Omnipay\Common\Message;
/**
* Fetch Issuers Response interface
*
* This interface class defines the functionality of a response
* that is a "fetch issuers" response. It extends the ResponseInterface
* interface class with some extra functions relating to the
* specifics of a response to fetch the issuers from the gateway.
* This happens when the gateway needs the customer to choose a
* card issuer.
*
* @see ResponseInterface
* @see Omnipay\Common\Issuer
*/
interface FetchIssuersResponseInterface extends ResponseInterface
{
/**
* Get the returned list of issuers.
*
* These represent banks which the user must choose between.
*
* @return \Omnipay\Common\Issuer[]
*/
public function getIssuers();
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Fetch Payment Methods Response interface
*/
namespace Omnipay\Common\Message;
/**
* Fetch Payment Methods Response interface
*
* This interface class defines the functionality of a response
* that is a "fetch payment method" response. It extends the ResponseInterface
* interface class with some extra functions relating to the
* specifics of a response to fetch the payment method from the gateway.
* This happens when the gateway needs the customer to choose a
* payment method.
*
* @see ResponseInterface
* @see Omnipay\Common\PaymentMethod
*/
interface FetchPaymentMethodsResponseInterface extends ResponseInterface
{
/**
* Get the returned list of payment methods.
*
* These represent separate payment methods which the user must choose between.
*
* @return \Omnipay\Common\PaymentMethod[]
*/
public function getPaymentMethods();
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* Message Interface
*/
namespace Omnipay\Common\Message;
/**
* Message Interface
*
* This interface class defines the standard functions that any Omnipay message
* interface needs to be able to provide.
*/
interface MessageInterface
{
/**
* Get the raw data array for this message. The format of this varies from gateway to
* gateway, but will usually be either an associative array, or a SimpleXMLElement.
*
* @return mixed
*/
public function getData();
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Omnipay\Common\Message;
/**
* Incoming notification
*/
interface NotificationInterface extends MessageInterface
{
const STATUS_COMPLETED = 'completed';
const STATUS_PENDING = 'pending';
const STATUS_FAILED = 'failed';
/**
* Gateway Reference
*
* @return string A reference provided by the gateway to represent this transaction
*/
public function getTransactionReference();
/**
* Was the transaction successful?
*
* @return string Transaction status, one of {@see STATUS_COMPLETED}, {@see #STATUS_PENDING},
* or {@see #STATUS_FAILED}.
*/
public function getTransactionStatus();
/**
* Response Message
*
* @return string A response message from the payment gateway
*/
public function getMessage();
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Redirect Response interface
*/
namespace Omnipay\Common\Message;
/**
* Redirect Response interface
*
* This interface class defines the functionality of a response
* that is a redirect response. It extends the ResponseInterface
* interface class with some extra functions relating to the
* specifics of a redirect response from the gateway.
*
* @see ResponseInterface
*/
interface RedirectResponseInterface extends ResponseInterface
{
/**
* Gets the redirect target url.
*
* @return string
*/
public function getRedirectUrl();
/**
* Get the required redirect method (either GET or POST).
*
* @return string
*/
public function getRedirectMethod();
/**
* Gets the redirect form data array, if the redirect method is POST.
*
* @return array
*/
public function getRedirectData();
/**
* Perform the required redirect.
*
* @return void
*/
public function redirect();
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* Request Interface
*/
namespace Omnipay\Common\Message;
/**
* Request Interface
*
* This interface class defines the standard functions that any Omnipay request
* interface needs to be able to provide. It is an extension of MessageInterface.
*
* @see MessageInterface
*/
interface RequestInterface extends MessageInterface
{
/**
* Initialize request with parameters
* @param array $parameters The parameters to send
*/
public function initialize(array $parameters = array());
/**
* Get all request parameters
*
* @return array
*/
public function getParameters();
/**
* Get the response to this request (if the request has been sent)
*
* @return ResponseInterface
*/
public function getResponse();
/**
* Send the request
*
* @return ResponseInterface
*/
public function send();
/**
* Send the request with specified data
*
* @param mixed $data The data to send
* @return ResponseInterface
*/
public function sendData($data);
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Response interface
*/
namespace Omnipay\Common\Message;
/**
* Response Interface
*
* This interface class defines the standard functions that any Omnipay response
* interface needs to be able to provide. It is an extension of MessageInterface.
*
* @see MessageInterface
*/
interface ResponseInterface extends MessageInterface
{
/**
* Get the original request which generated this response
*
* @return RequestInterface
*/
public function getRequest();
/**
* Is the response successful?
*
* @return boolean
*/
public function isSuccessful();
/**
* Does the response require a redirect?
*
* @return boolean
*/
public function isRedirect();
/**
* Is the transaction cancelled by the user?
*
* @return boolean
*/
public function isCancelled();
/**
* Response Message
*
* @return null|string A response message from the payment gateway
*/
public function getMessage();
/**
* Response code
*
* @return null|string A response code from the payment gateway
*/
public function getCode();
/**
* Gateway Reference
*
* @return null|string A reference provided by the gateway to represent this transaction
*/
public function getTransactionReference();
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Payment Method
*/
namespace Omnipay\Common;
/**
* Payment Method
*
* This class defines a payment method to be used in the Omnipay system.
*
* @see Issuer
*/
class PaymentMethod
{
/**
* The ID of the payment method. Used as the payment method ID in the
* Issuer class.
*
* @see Issuer
*
* @var string
*/
protected $id;
/**
* The full name of the payment method
*
* @var string
*/
protected $name;
/**
* Create a new PaymentMethod
*
* @param string $id The identifier of this payment method
* @param string $name The name of this payment method
*/
public function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
/**
* The identifier of this payment method
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* The name of this payment method
*
* @return string
*/
public function getName()
{
return $this->name;
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Omnipay class
*/
namespace Omnipay;
use Omnipay\Common\GatewayFactory;
/**
* Omnipay class
*
* Provides static access to the gateway factory methods. This is the
* recommended route for creation and establishment of payment gateway
* objects via the standard GatewayFactory.
*
* Example:
*
* <code>
* // Create a gateway for the PayPal ExpressGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('ExpressGateway');
*
* // Initialise the gateway
* $gateway->initialize(...);
*
* // Get the gateway parameters.
* $parameters = $gateway->getParameters();
*
* // Create a credit card object
* $card = new CreditCard(...);
*
* // Do an authorisation transaction on the gateway
* if ($gateway->supportsAuthorize()) {
* $gateway->authorize(...);
* } else {
* throw new \Exception('Gateway does not support authorize()');
* }
* </code>
*
* For further code examples see the *omnipay-example* repository on github.
*
* @method static array all()
* @method static array replace(array $gateways)
* @method static string register(string $className)
* @method static array find()
* @method static array getSupportedGateways()
* @codingStandardsIgnoreStart
* @method static \Omnipay\Common\GatewayInterface create(string $class, \Guzzle\Http\ClientInterface $httpClient = null, \Symfony\Component\HttpFoundation\Request $httpRequest = null)
* @codingStandardsIgnoreEnd
*
* @see Omnipay\Common\GatewayFactory
*/
class Omnipay
{
/**
* Internal factory storage
*
* @var GatewayFactory
*/
private static $factory;
/**
* Get the gateway factory
*
* Creates a new empty GatewayFactory if none has been set previously.
*
* @return GatewayFactory A GatewayFactory instance
*/
public static function getFactory()
{
if (is_null(static::$factory)) {
static::$factory = new GatewayFactory;
}
return static::$factory;
}
/**
* Set the gateway factory
*
* @param GatewayFactory $factory A GatewayFactory instance
*/
public static function setFactory(GatewayFactory $factory = null)
{
static::$factory = $factory;
}
/**
* Static function call router.
*
* All other function calls to the Omnipay class are routed to the
* factory. e.g. Omnipay::getSupportedGateways(1, 2, 3, 4) is routed to the
* factory's getSupportedGateways method and passed the parameters 1, 2, 3, 4.
*
* Example:
*
* <code>
* // Create a gateway for the PayPal ExpressGateway
* $gateway = Omnipay::create('ExpressGateway');
* </code>
*
* @see GatewayFactory
*
* @param string $method The factory method to invoke.
* @param array $parameters Parameters passed to the factory method.
*
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
$factory = static::getFactory();
return call_user_func_array(array($factory, $method), $parameters);
}
}

20
system/vendor/omnipay/paypal/LICENSE vendored Executable file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2012-2013 Adrian Macneil
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

43
system/vendor/omnipay/paypal/composer.json vendored Executable file
View File

@@ -0,0 +1,43 @@
{
"name": "omnipay/paypal",
"type": "library",
"description": "PayPal gateway for Omnipay payment processing library",
"keywords": [
"gateway",
"merchant",
"omnipay",
"pay",
"payment",
"paypal",
"purchase"
],
"homepage": "https://github.com/thephpleague/omnipay-paypal",
"license": "MIT",
"authors": [
{
"name": "Adrian Macneil",
"email": "adrian@adrianmacneil.com"
},
{
"name": "Omnipay Contributors",
"homepage": "https://github.com/thephpleague/omnipay-paypal/contributors"
}
],
"autoload": {
"psr-4": { "Omnipay\\PayPal\\" : "src/" }
},
"require": {
"omnipay/common": "^3"
},
"require-dev": {
"omnipay/tests": "^3",
"squizlabs/php_codesniffer": "^3",
"phpro/grumphp": "^0.14"
},
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"prefer-stable": true
}

15
system/vendor/omnipay/paypal/grumphp.yml vendored Executable file
View File

@@ -0,0 +1,15 @@
parameters:
git_dir: .
bin_dir: vendor/bin
tasks:
phpunit:
config_file: ~
testsuite: ~
group: []
always_execute: false
phpcs:
standard: PSR2
warning_severity: ~
ignore_patterns:
- tests/
triggered_by: [php]

146
system/vendor/omnipay/paypal/makedoc.sh vendored Executable file
View File

@@ -0,0 +1,146 @@
#!/bin/sh
#
# Smart little documentation generator.
# GPL/LGPL
# (c) Del 2015 http://www.babel.com.au/
#
APPNAME='Omnipay PayPal Gateway Module'
CMDFILE=apigen.cmd.$$
DESTDIR=./documents
#
# Find apigen, either in the path or as a local phar file
#
if [ -f apigen.phar ]; then
APIGEN="php apigen.phar"
else
APIGEN=`which apigen`
if [ ! -f "$APIGEN" ]; then
# Search for phpdoc if apigen is not found.
if [ -f phpDocumentor.phar ]; then
PHPDOC="php phpDocumentor.phar"
else
PHPDOC=`which phpdoc`
if [ ! -f "$PHPDOC" ]; then
echo "Neither apigen nor phpdoc is installed in the path or locally, please install one of them"
echo "see http://www.apigen.org/ or http://www.phpdoc.org/"
exit 1
fi
fi
fi
fi
#
# As of version 4 of apigen need to use the generate subcommand
#
if [ ! -z "$APIGEN" ]; then
APIGEN="$APIGEN generate"
fi
#
# Without any arguments this builds the entire system documentation,
# making the cache file first if required.
#
if [ -z "$1" ]; then
#
# Check to see that the cache has been made.
#
if [ ! -f dirlist.cache ]; then
echo "Making dirlist.cache file"
$0 makecache
fi
#
# Build the apigen/phpdoc command in a file.
#
if [ ! -z "$APIGEN" ]; then
echo "$APIGEN --php --tree --title '$APPNAME API Documentation' --destination $DESTDIR/main \\" > $CMDFILE
cat dirlist.cache | while read dir; do
echo "--source $dir \\" >> $CMDFILE
done
echo "" >> $CMDFILE
elif [ ! -z "$PHPDOC" ]; then
echo "$PHPDOC --sourcecode --title '$APPNAME API Documentation' --target $DESTDIR/main --directory \\" > $CMDFILE
cat dirlist.cache | while read dir; do
echo "${dir},\\" >> $CMDFILE
done
echo "" >> $CMDFILE
else
"Neither apigen nor phpdoc are found, how did I get here?"
exit 1
fi
#
# Run the apigen command
#
rm -rf $DESTDIR/main
mkdir -p $DESTDIR/main
. ./$CMDFILE
/bin/rm -f ./$CMDFILE
#
# The "makecache" argument causes the script to just make the cache file
#
elif [ "$1" = "makecache" ]; then
echo "Find application source directories"
find src -name \*.php -print | \
(
while read file; do
grep -q 'class' $file && dirname $file
done
) | sort -u | \
grep -v -E 'config|docs|migrations|phpunit|test|Test|views|web' > dirlist.app
echo "Find vendor source directories"
find vendor -name \*.php -print | \
(
while read file; do
grep -q 'class' $file && dirname $file
done
) | sort -u | \
grep -v -E 'config|docs|migrations|phpunit|codesniffer|test|Test|views' > dirlist.vendor
#
# Filter out any vendor directories for which apigen fails
#
echo "Filter source directories"
mkdir -p $DESTDIR/tmp
cat dirlist.app dirlist.vendor | while read dir; do
if [ ! -z "$APIGEN" ]; then
$APIGEN --quiet --title "Test please ignore" \
--source $dir \
--destination $DESTDIR/tmp && (
echo "Including $dir"
echo $dir >> dirlist.cache
) || (
echo "Excluding $dir"
)
elif [ ! -z "$PHPDOC" ]; then
$PHPDOC --quiet --title "Test please ignore" \
--directory $dir \
--target $DESTDIR/tmp && (
echo "Including $dir"
echo $dir >> dirlist.cache
) || (
echo "Excluding $dir"
)
fi
done
echo "Documentation cache dirlist.cache built OK"
#
# Clean up
#
/bin/rm -rf $DESTDIR/tmp
fi

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Omnipay Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="Mockery\Adapter\Phpunit\TestListener" file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php" />
</listeners>
<filter>
<whitelist>
<directory>./src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,168 @@
<?php
namespace Omnipay\PayPal;
/**
* PayPal Express Class
*/
class ExpressGateway extends ProGateway
{
public function getName()
{
return 'PayPal Express';
}
public function getDefaultParameters()
{
$settings = parent::getDefaultParameters();
$settings['solutionType'] = array('Sole', 'Mark');
$settings['landingPage'] = array('Billing', 'Login');
$settings['brandName'] = '';
$settings['headerImageUrl'] = '';
$settings['logoImageUrl'] = '';
$settings['borderColor'] = '';
return $settings;
}
public function getSolutionType()
{
return $this->getParameter('solutionType');
}
public function setSolutionType($value)
{
return $this->setParameter('solutionType', $value);
}
public function getLandingPage()
{
return $this->getParameter('landingPage');
}
public function setLandingPage($value)
{
return $this->setParameter('landingPage', $value);
}
public function getBrandName()
{
return $this->getParameter('brandName');
}
public function setBrandName($value)
{
return $this->setParameter('brandName', $value);
}
public function getHeaderImageUrl()
{
return $this->getParameter('headerImageUrl');
}
public function getLogoImageUrl()
{
return $this->getParameter('logoImageUrl');
}
public function getBorderColor()
{
return $this->getParameter('borderColor');
}
/**
* Header Image URL (Optional)
*
* URL for the image you want to appear at the top left of the payment page.
* The image has a maximum size of 750 pixels wide by 90 pixels high.
* PayPal recommends that you provide an image that is stored on a secure
* (HTTPS) server.
* If you do not specify an image, the business name displays.
* Character length and limitations: 127 single-byte alphanumeric characters
*/
public function setHeaderImageUrl($value)
{
return $this->setParameter('headerImageUrl', $value);
}
/**
* Logo Image URL (Optional)
*
* URL for the image to appear above the order summary, in place of the
* brand name.
* The recommended size is 190 pixels wide and 60 pixels high.
*/
public function setLogoImageUrl($value)
{
return $this->setParameter('logoImageUrl', $value);
}
/**
* Border Color (Optional)
*
* The color of the border gradient on payment pages.
* Should be a six character hexadecimal code (i.e. C0C0C0).
*/
public function setBorderColor($value)
{
return $this->setParameter('borderColor', $value);
}
public function setSellerPaypalAccountId($value)
{
return $this->setParameter('sellerPaypalAccountId', $value);
}
public function getSellerPaypalAccountId()
{
return $this->getParameter('sellerPaypalAccountId');
}
public function authorize(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressAuthorizeRequest', $parameters);
}
public function completeAuthorize(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressCompleteAuthorizeRequest', $parameters);
}
public function purchase(array $parameters = array())
{
return $this->authorize($parameters);
}
public function completePurchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressCompletePurchaseRequest', $parameters);
}
public function void(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressVoidRequest', $parameters);
}
public function fetchCheckout(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressFetchCheckoutRequest', $parameters);
}
/**
* @return Message\ExpressTransactionSearchRequest
*/
public function transactionSearch(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressTransactionSearchRequest', $parameters);
}
public function order(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressOrderRequest', $parameters);
}
public function completeOrder(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressCompleteOrderRequest', $parameters);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Omnipay\PayPal;
/**
* PayPal Express In-Context Class
*/
class ExpressInContextGateway extends ExpressGateway
{
public function getName()
{
return 'PayPal Express In-Context';
}
public function authorize(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressInContextAuthorizeRequest', $parameters);
}
public function order(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ExpressInContextOrderRequest', $parameters);
}
}

View File

@@ -0,0 +1,356 @@
<?php
/**
* PayPal Abstract Request
*/
namespace Omnipay\PayPal\Message;
use Omnipay\Common\ItemBag;
use Omnipay\PayPal\PayPalItem;
use Omnipay\PayPal\PayPalItemBag;
/**
* PayPal Abstract Request
*
* This class forms the base class for PayPal Express Checkout and Pro Checkout
* requests. These are also known as "Payflow Gateway" requests and also
* "PayPal Classic APIs".
*
* According to the PayPal documentation:
*
* * This is the recommended way to integrate when you want to accept payments
* with a completely customizable solution. This integration method leverages
* the PayPal Payflow Gateway to transmit payments your PayPal Internet Merchant
* Account; it also gives the merchant the flexibility to change payment
* processors without having to re-do their technical integration. When using
* PayPal Payments Pro (Payflow Edition) using Payflow Gateway integration,
* merchants can use Transparent Redirect feature to help manage PCI compliance.
*
* @link https://developer.paypal.com/docs/classic/products/payflow-gateway/
* @link https://developer.paypal.com/docs/classic/express-checkout/gs_expresscheckout/
* @link https://developer.paypal.com/docs/classic/products/ppp-payflow-edition/
* @link https://devtools-paypal.com/integrationwizard/
* @link http://paypal.github.io/sdk/
*/
abstract class AbstractRequest extends \Omnipay\Common\Message\AbstractRequest
{
const API_VERSION = '119.0';
protected $liveEndpoint = 'https://api-3t.paypal.com/nvp';
protected $testEndpoint = 'https://api-3t.sandbox.paypal.com/nvp';
/**
* @var bool
*/
protected $negativeAmountAllowed = true;
public function getUsername()
{
return $this->getParameter('username');
}
public function setUsername($value)
{
return $this->setParameter('username', $value);
}
public function getPassword()
{
return $this->getParameter('password');
}
public function setPassword($value)
{
return $this->setParameter('password', $value);
}
public function getSignature()
{
return $this->getParameter('signature');
}
public function setSignature($value)
{
return $this->setParameter('signature', $value);
}
public function getSubject()
{
return $this->getParameter('subject');
}
public function setSubject($value)
{
return $this->setParameter('subject', $value);
}
public function getSolutionType()
{
return $this->getParameter('solutionType');
}
public function setSolutionType($value)
{
return $this->setParameter('solutionType', $value);
}
public function getLandingPage()
{
return $this->getParameter('landingPage');
}
public function setLandingPage($value)
{
return $this->setParameter('landingPage', $value);
}
public function getHeaderImageUrl()
{
return $this->getParameter('headerImageUrl');
}
public function setHeaderImageUrl($value)
{
return $this->setParameter('headerImageUrl', $value);
}
public function getLogoImageUrl()
{
return $this->getParameter('logoImageUrl');
}
public function setLogoImageUrl($value)
{
return $this->setParameter('logoImageUrl', $value);
}
public function getBorderColor()
{
return $this->getParameter('borderColor');
}
public function setBorderColor($value)
{
return $this->setParameter('borderColor', $value);
}
public function getBrandName()
{
return $this->getParameter('brandName');
}
public function setBrandName($value)
{
return $this->setParameter('brandName', $value);
}
public function getNoShipping()
{
return $this->getParameter('noShipping');
}
public function setNoShipping($value)
{
return $this->setParameter('noShipping', $value);
}
public function getAllowNote()
{
return $this->getParameter('allowNote');
}
public function setAllowNote($value)
{
return $this->setParameter('allowNote', $value);
}
public function getAddressOverride()
{
return $this->getParameter('addressOverride');
}
public function setAddressOverride($value)
{
return $this->setParameter('addressOverride', $value);
}
public function getMaxAmount()
{
return $this->getParameter('maxAmount');
}
public function setMaxAmount($value)
{
return $this->setParameter('maxAmount', $value);
}
public function getTaxAmount()
{
return $this->getParameter('taxAmount');
}
public function setTaxAmount($value)
{
return $this->setParameter('taxAmount', $value);
}
public function getShippingAmount()
{
return $this->getParameter('shippingAmount');
}
public function setShippingAmount($value)
{
return $this->setParameter('shippingAmount', $value);
}
public function getHandlingAmount()
{
return $this->getParameter('handlingAmount');
}
public function setHandlingAmount($value)
{
return $this->setParameter('handlingAmount', $value);
}
public function getShippingDiscount()
{
return $this->getParameter('shippingDiscount');
}
public function setShippingDiscount($value)
{
return $this->setParameter('shippingDiscount', $value);
}
public function getInsuranceAmount()
{
return $this->getParameter('insuranceAmount');
}
public function setInsuranceAmount($value)
{
return $this->setParameter('insuranceAmount', $value);
}
public function getLocaleCode()
{
return $this->getParameter('localeCode');
}
/*
* Used to change the locale of PayPal pages.
* Accepts 2 or 5 character language codes as described here:
* https://developer.paypal.com/docs/classic/express-checkout/integration-guide/ECCustomizing/
*
* If no value/invalid value is passed, the gateway will default it for you
*/
public function setLocaleCode($value)
{
return $this->setParameter('localeCode', $value);
}
public function setCustomerServiceNumber($value)
{
return $this->setParameter('customerServiceNumber', $value);
}
public function getCustomerServiceNumber()
{
return $this->getParameter('customerServiceNumber');
}
public function setSellerPaypalAccountId($value)
{
return $this->setParameter('sellerPaypalAccountId', $value);
}
public function getSellerPaypalAccountId()
{
return $this->getParameter('sellerPaypalAccountId');
}
/**
* The Button Source (BN Code) is for PayPal Partners taking payments for a 3rd party
*/
public function setButtonSource($value)
{
return $this->setParameter('ButtonSource', $value);
}
public function getButtonSource()
{
return $this->getParameter('ButtonSource');
}
protected function getBaseData()
{
$data = array();
$data['VERSION'] = static::API_VERSION;
$data['USER'] = $this->getUsername();
$data['PWD'] = $this->getPassword();
$data['SIGNATURE'] = $this->getSignature();
$data['SUBJECT'] = $this->getSubject();
$bnCode = $this->getButtonSource();
if (!empty($bnCode)) {
$data['BUTTONSOURCE'] = $bnCode;
}
return $data;
}
protected function getItemData()
{
$data = array();
$items = $this->getItems();
if ($items) {
$data["PAYMENTREQUEST_0_ITEMAMT"] = 0;
foreach ($items as $n => $item) {
$data["L_PAYMENTREQUEST_0_NAME$n"] = $item->getName();
$data["L_PAYMENTREQUEST_0_DESC$n"] = $item->getDescription();
$data["L_PAYMENTREQUEST_0_QTY$n"] = $item->getQuantity();
$data["L_PAYMENTREQUEST_0_AMT$n"] = $this->formatCurrency($item->getPrice());
if ($item instanceof PayPalItem) {
$data["L_PAYMENTREQUEST_0_NUMBER$n"] = $item->getCode();
}
$data["PAYMENTREQUEST_0_ITEMAMT"] += $item->getQuantity() * $this->formatCurrency($item->getPrice());
}
$data["PAYMENTREQUEST_0_ITEMAMT"] = $this->formatCurrency($data["PAYMENTREQUEST_0_ITEMAMT"]);
}
return $data;
}
public function sendData($data)
{
$httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), [], http_build_query($data, '', '&'));
return $this->createResponse($httpResponse->getBody()->getContents());
}
protected function getEndpoint()
{
return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
}
protected function createResponse($data)
{
return $this->response = new Response($this, $data);
}
/**
* Set the items in this order
*
* @param ItemBag|array $items An array of items in this order
*/
public function setItems($items)
{
if ($items && !$items instanceof ItemBag) {
$items = new PayPalItemBag($items);
}
return $this->setParameter('items', $items);
}
}

View File

@@ -0,0 +1,189 @@
<?php
/**
* PayPal Abstract REST Request
*/
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Exception\InvalidResponseException;
/**
* PayPal Abstract REST Request
*
* This class forms the base class for PayPal REST requests via the PayPal REST APIs.
*
* A complete REST operation is formed by combining an HTTP method (or “verb”) with
* the full URI to the resource youre addressing. For example, here is the operation
* to create a new payment:
*
* <code>
* POST https://api.paypal.com/v1/payments/payment
* </code>
*
* To create a complete request, combine the operation with the appropriate HTTP headers
* and any required JSON payload.
*
* @link https://developer.paypal.com/docs/api/
* @link https://devtools-paypal.com/integrationwizard/
* @link http://paypal.github.io/sdk/
* @see Omnipay\PayPal\RestGateway
*/
abstract class AbstractRestRequest extends \Omnipay\Common\Message\AbstractRequest
{
const API_VERSION = 'v1';
/**
* Sandbox Endpoint URL
*
* The PayPal REST APIs are supported in two environments. Use the Sandbox environment
* for testing purposes, then move to the live environment for production processing.
* When testing, generate an access token with your test credentials to make calls to
* the Sandbox URIs. When youre set to go live, use the live credentials assigned to
* your app to generate a new access token to be used with the live URIs.
*
* @var string URL
*/
protected $testEndpoint = 'https://api.sandbox.paypal.com';
/**
* Live Endpoint URL
*
* When youre set to go live, use the live credentials assigned to
* your app to generate a new access token to be used with the live URIs.
*
* @var string URL
*/
protected $liveEndpoint = 'https://api.paypal.com';
/**
* PayPal Payer ID
*
* @var string PayerID
*/
protected $payerId = null;
public function getClientId()
{
return $this->getParameter('clientId');
}
public function setClientId($value)
{
return $this->setParameter('clientId', $value);
}
public function getSecret()
{
return $this->getParameter('secret');
}
public function setSecret($value)
{
return $this->setParameter('secret', $value);
}
public function getToken()
{
return $this->getParameter('token');
}
public function setToken($value)
{
return $this->setParameter('token', $value);
}
public function getPayerId()
{
return $this->getParameter('payerId');
}
public function setPayerId($value)
{
return $this->setParameter('payerId', $value);
}
/**
* Get HTTP Method.
*
* This is nearly always POST but can be over-ridden in sub classes.
*
* @return string
*/
protected function getHttpMethod()
{
return 'POST';
}
protected function getEndpoint()
{
$base = $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
return $base . '/' . self::API_VERSION;
}
public function sendData($data)
{
// Guzzle HTTP Client createRequest does funny things when a GET request
// has attached data, so don't send the data if the method is GET.
if ($this->getHttpMethod() == 'GET') {
$requestUrl = $this->getEndpoint() . '?' . http_build_query($data);
$body = null;
} else {
$body = $this->toJSON($data);
$requestUrl = $this->getEndpoint();
}
// Might be useful to have some debug code here, PayPal especially can be
// a bit fussy about data formats and ordering. Perhaps hook to whatever
// logging engine is being used.
// echo "Data == " . json_encode($data) . "\n";
try {
$httpResponse = $this->httpClient->request(
$this->getHttpMethod(),
$this->getEndpoint(),
array(
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $this->getToken(),
'Content-type' => 'application/json',
),
$body
);
// Empty response body should be parsed also as and empty array
$body = (string) $httpResponse->getBody()->getContents();
$jsonToArrayResponse = !empty($body) ? json_decode($body, true) : array();
return $this->response = $this->createResponse($jsonToArrayResponse, $httpResponse->getStatusCode());
} catch (\Exception $e) {
throw new InvalidResponseException(
'Error communicating with payment gateway: ' . $e->getMessage(),
$e->getCode()
);
}
}
/**
* Returns object JSON representation required by PayPal.
* The PayPal REST API requires the use of JSON_UNESCAPED_SLASHES.
*
* Adapted from the official PayPal REST API PHP SDK.
* (https://github.com/paypal/PayPal-PHP-SDK/blob/master/lib/PayPal/Common/PayPalModel.php)
*
* @param int $options http://php.net/manual/en/json.constants.php
* @return string
*/
public function toJSON($data, $options = 0)
{
// Because of PHP Version 5.3, we cannot use JSON_UNESCAPED_SLASHES option
// Instead we would use the str_replace command for now.
// TODO: Replace this code with return json_encode($this->toArray(), $options | 64); once we support PHP >= 5.4
if (version_compare(phpversion(), '5.4.0', '>=') === true) {
return json_encode($data, $options | 64);
}
return str_replace('\\/', '/', json_encode($data, $options));
}
protected function createResponse($data, $statusCode)
{
return $this->response = new RestResponse($this, $data, $statusCode);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Capture Request
*/
class CaptureRequest extends AbstractRequest
{
public function getData()
{
$this->validate('transactionReference', 'amount');
$data = $this->getBaseData();
$data['METHOD'] = 'DoCapture';
$data['AMT'] = $this->getAmount();
$data['CURRENCYCODE'] = $this->getCurrency();
$data['AUTHORIZATIONID'] = $this->getTransactionReference();
$data['COMPLETETYPE'] = 'Complete';
return $data;
}
}

View File

@@ -0,0 +1,195 @@
<?php
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Exception\InvalidRequestException;
use Omnipay\PayPal\Support\InstantUpdateApi\ShippingOption;
use Omnipay\PayPal\Support\InstantUpdateApi\BillingAgreement;
/**
* PayPal Express Authorize Request
*/
class ExpressAuthorizeRequest extends AbstractRequest
{
const DEFAULT_CALLBACK_TIMEOUT = 5;
public function setCallback($callback)
{
return $this->setParameter('callback', $callback);
}
public function getCallback()
{
return $this->getParameter('callback');
}
public function setCallbackTimeout($callbackTimeout)
{
return $this->setParameter('callbackTimeout', $callbackTimeout);
}
public function getCallbackTimeout()
{
return $this->getParameter('callbackTimeout');
}
/**
* @param ShippingOption[] $data
*/
public function setShippingOptions($data)
{
$this->setParameter('shippingOptions', $data);
}
/**
* @return ShippingOption[]
*/
public function getShippingOptions()
{
return $this->getParameter('shippingOptions');
}
/**
* @param BillingAgreement $data
*/
public function setBillingAgreement($data)
{
$this->setParameter('billingAgreement', $data);
}
/**
* @return BillingAgreement
*/
public function getBillingAgreement()
{
return $this->getParameter('billingAgreement');
}
protected function validateCallback()
{
$callback = $this->getCallback();
if (!empty($callback)) {
$shippingOptions = $this->getShippingOptions();
if (empty($shippingOptions)) {
throw new InvalidRequestException(
'When setting a callback for the Instant Update API you must set shipping options'
);
} else {
$hasDefault = false;
foreach ($shippingOptions as $shippingOption) {
if ($shippingOption->isDefault()) {
$hasDefault = true;
continue;
}
}
if (!$hasDefault) {
throw new InvalidRequestException(
'One of the supplied shipping options must be set as default'
);
}
}
}
}
public function getData()
{
$this->validate('amount', 'returnUrl', 'cancelUrl');
$this->validateCallback();
$data = $this->getBaseData();
$data['METHOD'] = 'SetExpressCheckout';
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Authorization';
$data['PAYMENTREQUEST_0_AMT'] = $this->getAmount();
$data['PAYMENTREQUEST_0_CURRENCYCODE'] = $this->getCurrency();
$data['PAYMENTREQUEST_0_INVNUM'] = $this->getTransactionId();
$data['PAYMENTREQUEST_0_DESC'] = $this->getDescription();
// pp express specific fields
$data['SOLUTIONTYPE'] = $this->getSolutionType();
$data['LANDINGPAGE'] = $this->getLandingPage();
$data['RETURNURL'] = $this->getReturnUrl();
$data['CANCELURL'] = $this->getCancelUrl();
$data['HDRIMG'] = $this->getHeaderImageUrl();
$data['BRANDNAME'] = $this->getBrandName();
$data['NOSHIPPING'] = $this->getNoShipping();
$data['ALLOWNOTE'] = $this->getAllowNote();
$data['ADDROVERRIDE'] = $this->getAddressOverride();
$data['LOGOIMG'] = $this->getLogoImageUrl();
$data['CARTBORDERCOLOR'] = $this->getBorderColor();
$data['LOCALECODE'] = $this->getLocaleCode();
$data['CUSTOMERSERVICENUMBER'] = $this->getCustomerServiceNumber();
$callback = $this->getCallback();
if (!empty($callback)) {
$data['CALLBACK'] = $callback;
// callback timeout MUST be included and > 0
$timeout = $this->getCallbackTimeout();
$data['CALLBACKTIMEOUT'] = $timeout > 0 ? $timeout : self::DEFAULT_CALLBACK_TIMEOUT;
// if you're using a callback you MUST set shipping option(s)
$shippingOptions = $this->getShippingOptions();
if (!empty($shippingOptions)) {
foreach ($shippingOptions as $index => $shipping) {
$data['L_SHIPPINGOPTIONNAME' . $index] = $shipping->getName();
$data['L_SHIPPINGOPTIONAMOUNT' . $index] = number_format($shipping->getAmount(), 2);
$data['L_SHIPPINGOPTIONISDEFAULT' . $index] = $shipping->isDefault() ? '1' : '0';
if ($shipping->hasLabel()) {
$data['L_SHIPPINGOPTIONLABEL' . $index] = $shipping->getLabel();
}
}
}
}
$data['MAXAMT'] = $this->getMaxAmount();
$data['PAYMENTREQUEST_0_TAXAMT'] = $this->getTaxAmount();
$data['PAYMENTREQUEST_0_SHIPPINGAMT'] = $this->getShippingAmount();
$data['PAYMENTREQUEST_0_HANDLINGAMT'] = $this->getHandlingAmount();
$data['PAYMENTREQUEST_0_SHIPDISCAMT'] = $this->getShippingDiscount();
$data['PAYMENTREQUEST_0_INSURANCEAMT'] = $this->getInsuranceAmount();
$data['PAYMENTREQUEST_0_SELLERPAYPALACCOUNTID'] = $this->getSellerPaypalAccountId();
$card = $this->getCard();
if ($card) {
$data['PAYMENTREQUEST_0_SHIPTONAME'] = $card->getName();
$data['PAYMENTREQUEST_0_SHIPTOSTREET'] = $card->getAddress1();
$data['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $card->getAddress2();
$data['PAYMENTREQUEST_0_SHIPTOCITY'] = $card->getCity();
$data['PAYMENTREQUEST_0_SHIPTOSTATE'] = $card->getState();
$data['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $card->getCountry();
$data['PAYMENTREQUEST_0_SHIPTOZIP'] = $card->getPostcode();
$data['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $card->getPhone();
$data['EMAIL'] = $card->getEmail();
}
$billingAgreement = $this->getBillingAgreement();
if ($billingAgreement) {
$data['L_BILLINGTYPE0'] = $billingAgreement->getType();
$data['L_BILLINGAGREEMENTDESCRIPTION0'] = $billingAgreement->getDescription();
if ($billingAgreement->hasPaymentType()) {
$data['L_PAYMENTTYPE0'] = $billingAgreement->getPaymentType();
}
if ($billingAgreement->hasCustomAnnotation()) {
$data['L_BILLINGAGREEMENTCUSTOM0'] = $billingAgreement->getCustomAnnotation();
}
}
$data = array_merge($data, $this->getItemData());
return $data;
}
protected function createResponse($data)
{
return $this->response = new ExpressAuthorizeResponse($this, $data);
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Message\RedirectResponseInterface;
/**
* PayPal Express Authorize Response
*/
class ExpressAuthorizeResponse extends Response implements RedirectResponseInterface
{
protected $liveCheckoutEndpoint = 'https://www.paypal.com/cgi-bin/webscr';
protected $testCheckoutEndpoint = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
public function isSuccessful()
{
return false;
}
public function isRedirect()
{
return isset($this->data['ACK']) && in_array($this->data['ACK'], array('Success', 'SuccessWithWarning'));
}
public function getRedirectUrl()
{
return $this->getCheckoutEndpoint().'?'.http_build_query($this->getRedirectQueryParameters(), '', '&');
}
public function getTransactionReference()
{
return isset($this->data['TOKEN']) ? $this->data['TOKEN'] : null;
}
public function getRedirectMethod()
{
return 'GET';
}
public function getRedirectData()
{
return null;
}
protected function getRedirectQueryParameters()
{
return array(
'cmd' => '_express-checkout',
'useraction' => 'commit',
'token' => $this->getTransactionReference(),
);
}
protected function getCheckoutEndpoint()
{
return $this->getRequest()->getTestMode() ? $this->testCheckoutEndpoint : $this->liveCheckoutEndpoint;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Complete Authorize Request
*/
class ExpressCompleteAuthorizeRequest extends AbstractRequest
{
public function getData()
{
$this->validate('amount');
$data = $this->getBaseData();
$data['METHOD'] = 'DoExpressCheckoutPayment';
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Authorization';
$data['PAYMENTREQUEST_0_AMT'] = $this->getAmount();
$data['PAYMENTREQUEST_0_CURRENCYCODE'] = $this->getCurrency();
$data['PAYMENTREQUEST_0_INVNUM'] = $this->getTransactionId();
$data['PAYMENTREQUEST_0_DESC'] = $this->getDescription();
$data['PAYMENTREQUEST_0_NOTIFYURL'] = $this->getNotifyUrl();
$data['MAXAMT'] = $this->getMaxAmount();
$data['PAYMENTREQUEST_0_TAXAMT'] = $this->getTaxAmount();
$data['PAYMENTREQUEST_0_SHIPPINGAMT'] = $this->getShippingAmount();
$data['PAYMENTREQUEST_0_HANDLINGAMT'] = $this->getHandlingAmount();
$data['PAYMENTREQUEST_0_SHIPDISCAMT'] = $this->getShippingDiscount();
$data['PAYMENTREQUEST_0_INSURANCEAMT'] = $this->getInsuranceAmount();
$data['TOKEN'] = $this->getToken() ? $this->getToken() : $this->httpRequest->query->get('token');
$data['PAYERID'] = $this->getPayerID() ? $this->getPayerID() : $this->httpRequest->query->get('PayerID');
$data = array_merge($data, $this->getItemData());
return $data;
}
public function getPayerID()
{
return $this->getParameter('payerID');
}
public function setPayerID($value)
{
return $this->setParameter('payerID', $value);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Complete Order Request
*/
class ExpressCompleteOrderRequest extends ExpressCompleteAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Order';
return $data;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Complete Purchase Request
*/
class ExpressCompletePurchaseRequest extends ExpressCompleteAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Sale';
return $data;
}
protected function createResponse($data)
{
return $this->response = new ExpressCompletePurchaseResponse($this, $data);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Complete Payment Response
*/
class ExpressCompletePurchaseResponse extends ExpressAuthorizeResponse
{
/*
* Is this complete purchase response successful? Will not be successful if it's a redirect response.
*
* @return bool
*/
public function isSuccessful()
{
$success = isset($this->data['ACK']) && in_array($this->data['ACK'], array('Success', 'SuccessWithWarning'));
return !$this->isRedirect() && $success;
}
/**
* The complete purchase response can be in error where it wants to have your customer return to paypal.
*
* @return bool
*/
public function isRedirect()
{
return isset($this->data['L_ERRORCODE0']) && in_array($this->data['L_ERRORCODE0'], array('10486'));
}
/**
* The transaction reference obtained from the purchase() call can't be used to refund a purchase.
*
* @return string
*/
public function getTransactionReference()
{
if ($this->isSuccessful() && isset($this->data['PAYMENTINFO_0_TRANSACTIONID'])) {
return $this->data['PAYMENTINFO_0_TRANSACTIONID'];
}
return parent::getTransactionReference();
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Fetch Checkout Details Request
*/
class ExpressFetchCheckoutRequest extends AbstractRequest
{
public function getData()
{
$this->validate();
$data = $this->getBaseData();
$data['METHOD'] = 'GetExpressCheckoutDetails';
// token can either be specified directly, or inferred from the GET parameters
if ($this->getToken()) {
$data['TOKEN'] = $this->getToken();
} else {
$data['TOKEN'] = $this->httpRequest->query->get('token');
}
return $data;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express In-Context Authorize Request
*/
class ExpressInContextAuthorizeRequest extends ExpressAuthorizeRequest
{
protected function createResponse($data)
{
return $this->response = new ExpressInContextAuthorizeResponse($this, $data);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express In-Context Authorize Response
*/
class ExpressInContextAuthorizeResponse extends ExpressAuthorizeResponse
{
protected $liveCheckoutEndpoint = 'https://www.paypal.com/checkoutnow';
protected $testCheckoutEndpoint = 'https://www.sandbox.paypal.com/checkoutnow';
protected function getRedirectQueryParameters()
{
return array(
'useraction' => 'commit',
'token' => $this->getTransactionReference(),
);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express In-Context Order Request
*/
class ExpressInContextOrderRequest extends ExpressInContextAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Order';
return $data;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Order Request
*/
class ExpressOrderRequest extends ExpressAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['PAYMENTREQUEST_0_PAYMENTACTION'] = 'Order';
return $data;
}
}

View File

@@ -0,0 +1,371 @@
<?php
namespace Omnipay\PayPal\Message;
use DateTime;
/**
* Paypal Express Checkout - Transaction Search
*
* @see https://developer.paypal.com/docs/classic/api/merchant/TransactionSearch_API_Operation_NVP/
* @see https://developer.paypal.com/docs/classic/express-checkout/ht_searchRetrieveTransactionData-curl-etc/
*
* pt_BR:
* @see https://www.paypal-brasil.com.br/desenvolvedores/tutorial/criando-relatorios-customizados-via-api/
*/
class ExpressTransactionSearchRequest extends AbstractRequest
{
public function getData()
{
$data = $this->getBaseData();
$data['METHOD'] = 'TransactionSearch';
$this->validate('startDate');
$data['STARTDATE'] = $this->getStartDate()->format(DateTime::ISO8601);
if ($this->getEndDate()) {
$data['ENDDATE'] = $this->getEndDate()->format(DateTime::ISO8601);
}
if ($this->getSalutation()) {
$data['SALUTATION'] = $this->getSalutation();
}
if ($this->getFirstName()) {
$data['FIRSTNAME'] = $this->getFirstName();
}
if ($this->getMiddleName()) {
$data['MIDDLENAME'] = $this->getMiddleName();
}
if ($this->getLastName()) {
$data['LASTNAME'] = $this->getLastName();
}
if ($this->getSuffix()) {
$data['SUFFIX'] = $this->getSuffix();
}
if ($this->getEmail()) {
$data['EMAIL'] = $this->getEmail();
}
if ($this->getReceiver()) {
$data['RECEIVER'] = $this->getReceiver();
}
if ($this->getReceiptId()) {
$data['RECEIPTID'] = $this->getReceiptId();
}
if ($this->getTransactionId()) {
$data['TRANSACTIONID'] = $this->getTransactionId();
}
if ($this->getInvoiceNumber()) {
$data['INVNUM'] = $this->getInvoiceNumber();
}
if ($this->getCard()) {
$data['ACCT'] = $this->getCard()->getNumber();
}
if ($this->getAuctionItemNumber()) {
$data['AUCTIONITEMNUMBER'] = $this->getAuctionItemNumber();
}
if ($this->getTransactionClass()) {
$data['TRANSACTIONCLASS'] = $this->getTransactionClass();
}
if ($this->getAmount()) {
$this->validate('currency');
$data['AMT'] = $this->getAmount();
$data['CURRENCYCODE'] = $this->getCurrency();
}
if ($this->getStatus()) {
$data['STATUS'] = $this->getStatus();
}
if ($this->getProfileId()) {
$data['PROFILEID'] = $this->getProfileId();
}
return $data;
}
/**
* @return DateTime|null
*/
public function getStartDate()
{
return $this->getParameter('startDate');
}
/**
* @param DateTime|string $date
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setStartDate($date)
{
if (! $date instanceof DateTime) {
$date = new DateTime($date);
}
return $this->setParameter('startDate', $date);
}
/**
* @return DateTime|null
*/
public function getEndDate()
{
return $this->getParameter('endDate');
}
/**
* @param DateTime|string $date
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setEndDate($date)
{
if (! $date instanceof DateTime) {
$date = new DateTime($date);
}
return $this->setParameter('endDate', $date);
}
/**
* @return string
*/
public function getSalutation()
{
return $this->getParameter('salutation');
}
/**
* @param string $salutation
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setSalutation($salutation)
{
return $this->setParameter('salutation', $salutation);
}
/**
* @return string
*/
public function getFirstName()
{
return $this->getParameter('firstName');
}
/**
* @param string $firstName
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setFirstName($firstName)
{
return $this->setParameter('firstName', $firstName);
}
/**
* @return string
*/
public function getMiddleName()
{
return $this->getParameter('middleName');
}
/**
* @param string $middleName
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setMiddleName($middleName)
{
return $this->setParameter('middleName', $middleName);
}
/**
* @return string
*/
public function getLastName()
{
return $this->getParameter('lastName');
}
/**
* @param string $lastName
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setLastName($lastName)
{
return $this->setParameter('lastName', $lastName);
}
/**
* @return string
*/
public function getSuffix()
{
return $this->getParameter('suffix');
}
/**
* @param string $suffix
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setSuffix($suffix)
{
return $this->setParameter('suffix', $suffix);
}
/**
* @return string
*/
public function getEmail()
{
return $this->getParameter('email');
}
/**
* @param string $email
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setEmail($email)
{
return $this->setParameter('email', $email);
}
/**
* @return string
*/
public function getReceiver()
{
return $this->getParameter('receiver');
}
/**
* @param string $receiver
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setReceiver($receiver)
{
return $this->setParameter('receiver', $receiver);
}
/**
* @return string
*/
public function getReceiptId()
{
return $this->getParameter('receiptId');
}
/**
* @param string $receiptId
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setReceiptId($receiptId)
{
return $this->setParameter('receiptId', $receiptId);
}
/**
* @return string
*/
public function getInvoiceNumber()
{
return $this->getParameter('invoiceNumber');
}
/**
* @param string $invoiceNumber
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setInvoiceNumber($invoiceNumber)
{
return $this->setParameter('invoiceNumber', $invoiceNumber);
}
/**
* @return string
*/
public function getAuctionItemNumber()
{
return $this->getParameter('auctionItemNumber');
}
/**
* @param string $auctionItemNumber
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setAuctionItemNumber($auctionItemNumber)
{
return $this->setParameter('auctionItemNumber', $auctionItemNumber);
}
/**
* @return string
*/
public function getTransactionClass()
{
return $this->getParameter('transactionClass');
}
/**
* @param string $transactionClass
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setTransactionClass($transactionClass)
{
return $this->setParameter('transactionClass', $transactionClass);
}
/**
* @return string
*/
public function getStatus()
{
return $this->getParameter('status');
}
/**
* @param string $status
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setStatus($status)
{
return $this->setParameter('status', $status);
}
/**
* @return string
*/
public function getProfileId()
{
return $this->getParameter('profileId');
}
/**
* @param string $profileId
* @return \Omnipay\Common\Message\AbstractRequest
*/
public function setProfileId($profileId)
{
return $this->setParameter('profileId', $profileId);
}
/**
* @return ExpressTransactionSearchResponse
*/
public function createResponse($data)
{
return $this->response = new ExpressTransactionSearchResponse($this, $data);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Message\RequestInterface;
/**
* Response for Transaction Search request
*/
class ExpressTransactionSearchResponse extends Response
{
public function __construct(RequestInterface $request, $data)
{
parent::__construct($request, $data);
$payments = array();
foreach ($this->data as $key => $value) {
if ($this->isSuccessful()
&& preg_match('/(L_)?(?<key>[A-Za-z]+)(?<n>[0-9]+)/', $key, $matches)
) {
$payments[$matches['n']][$matches['key']] = $value;
unset($this->data[$key]);
}
}
$this->data['payments'] = $payments;
}
public function getPayments()
{
return $this->data['payments'];
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Express Void Request
*/
class ExpressVoidRequest extends AbstractRequest
{
public function getData()
{
$this->validate('transactionReference');
$data = $this->getBaseData();
$data['METHOD'] = 'DoVoid';
$data['AUTHORIZATIONID'] = $this->getTransactionReference();
return $data;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Fetch Transaction Request
*/
class FetchTransactionRequest extends AbstractRequest
{
public function getData()
{
$this->validate('transactionReference');
$data = $this->getBaseData();
$data['METHOD'] = 'GetTransactionDetails';
$data['TRANSACTIONID'] = $this->getTransactionReference();
return $data;
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Pro Authorize Request
*/
class ProAuthorizeRequest extends AbstractRequest
{
public function getData()
{
$this->validate('amount', 'card');
$this->getCard()->validate();
$data = $this->getBaseData();
$data['METHOD'] = 'DoDirectPayment';
$data['PAYMENTACTION'] = 'Authorization';
$data['AMT'] = $this->getAmount();
$data['CURRENCYCODE'] = $this->getCurrency();
$data['INVNUM'] = $this->getTransactionId();
$data['DESC'] = $this->getDescription();
// add credit card details
$data['ACCT'] = $this->getCard()->getNumber();
$data['CREDITCARDTYPE'] = $this->getCard()->getBrand();
$data['EXPDATE'] = $this->getCard()->getExpiryDate('mY');
$data['STARTDATE'] = $this->getCard()->getStartDate('mY');
$data['CVV2'] = $this->getCard()->getCvv();
$data['ISSUENUMBER'] = $this->getCard()->getIssueNumber();
$data['IPADDRESS'] = $this->getClientIp();
$data['FIRSTNAME'] = $this->getCard()->getFirstName();
$data['LASTNAME'] = $this->getCard()->getLastName();
$data['EMAIL'] = $this->getCard()->getEmail();
$data['STREET'] = $this->getCard()->getAddress1();
$data['STREET2'] = $this->getCard()->getAddress2();
$data['CITY'] = $this->getCard()->getCity();
$data['STATE'] = $this->getCard()->getState();
$data['ZIP'] = $this->getCard()->getPostcode();
$data['COUNTRYCODE'] = strtoupper($this->getCard()->getCountry());
return $data;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Pro Purchase Request
*/
class ProPurchaseRequest extends ProAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['PAYMENTACTION'] = 'Sale';
return $data;
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Omnipay\PayPal\Message;
/**
* PayPal Refund Request
*/
class RefundRequest extends AbstractRequest
{
public function getData()
{
$this->validate('transactionReference');
$data = $this->getBaseData();
$data['METHOD'] = 'RefundTransaction';
$data['TRANSACTIONID'] = $this->getTransactionReference();
$data['REFUNDTYPE'] = 'Full';
if ($this->getAmount() > 0) {
$data['REFUNDTYPE'] = 'Partial';
$data['AMT'] = $this->getAmount();
$data['CURRENCYCODE'] = $this->getCurrency();
}
return $data;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Message\AbstractResponse;
use Omnipay\Common\Message\RequestInterface;
/**
* PayPal Response
*/
class Response extends AbstractResponse
{
public function __construct(RequestInterface $request, $data)
{
$this->request = $request;
parse_str($data, $this->data);
}
public function isPending()
{
return isset($this->data['PAYMENTINFO_0_PAYMENTSTATUS'])
&& $this->data['PAYMENTINFO_0_PAYMENTSTATUS'] == 'Pending';
}
public function isSuccessful()
{
return isset($this->data['ACK']) && in_array($this->data['ACK'], array('Success', 'SuccessWithWarning'));
}
public function getTransactionReference()
{
foreach (array('REFUNDTRANSACTIONID',
'TRANSACTIONID',
'PAYMENTINFO_0_TRANSACTIONID',
'AUTHORIZATIONID') as $key) {
if (isset($this->data[$key])) {
return $this->data[$key];
}
}
}
public function getMessage()
{
return isset($this->data['L_LONGMESSAGE0']) ? $this->data['L_LONGMESSAGE0'] : null;
}
}

View File

@@ -0,0 +1,366 @@
<?php
/**
* PayPal REST Authorize Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Authorize Request
*
* To collect payment at a later time, first authorize a payment using the /payment resource.
* You can then capture the payment to complete the sale and collect payment.
*
* This looks exactly like a RestPurchaseRequest object except that the intent is
* set to "authorize" (to authorize a payment to be captured later) rather than
* "sale" (which is used to capture a payment immediately).
*
* ### Example
*
* #### Initialize Gateway
*
* <code>
* // Create a gateway for the PayPal RestGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
* </code>
*
* #### Direct Credit Card Authorize
*
* This is for the use case where a customer has presented their
* credit card details and you intend to use the PayPal REST gateway
* for processing a transaction using that credit card data.
*
* This does not require the customer to have a PayPal account.
*
* </code>
* // Create a credit card object
* // DO NOT USE THESE CARD VALUES -- substitute your own
* // see the documentation in the class header.
* $card = new CreditCard(array(
* 'firstName' => 'Example',
* 'lastName' => 'User',
* 'number' => '4111111111111111',
* 'expiryMonth' => '01',
* 'expiryYear' => '2020',
* 'cvv' => '123',
* 'billingAddress1' => '1 Scrubby Creek Road',
* 'billingCountry' => 'AU',
* 'billingCity' => 'Scrubby Creek',
* 'billingPostcode' => '4999',
* 'billingState' => 'QLD',
* ));
*
* // Do an authorisation transaction on the gateway
* $transaction = $gateway->authorize(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* 'description' => 'This is a test authorize transaction.',
* 'card' => $card,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Authorize transaction was successful!\n";
* // Find the authorization ID
* $auth_id = $response->getTransactionReference();
* }
* </code>
*
* Direct credit card payment and related features are restricted in
* some countries.
* As of January 2015 these transactions are only supported in the UK
* and in the USA.
*
* #### PayPal Account Authorization
*
* This is for the use case where the customer intends to pay using their
* PayPal account. Note that no credit card details are provided, instead
* both a return URL and a cancel URL are required.
*
* The optimal solution here is to provide a unique return URL and cancel
* URL per transaction. That way your code will know what transaction is
* being returned or cancelled by PayPal.
*
* So step 1 is to store some transaction data somewhere on your system so
* that you have an ID when your transaction returns. How you do this of
* course depends on what framework, database layer, etc, you are using but
* for this step let's assume that you have a class set up that can save
* a transaction and return the object, and that you can retrieve the ID
* of that saved object using some call like getId() on the object. Most
* ORMs such as Doctrine ORM, Propel or Eloquent will have some methods
* that will allow you to do this or something similar.
*
* <code>
* $transaction = MyClass::saveTransaction($some_data);
* $txn_id = $transaction->getId();
* </code>
*
* Step 2 is to send the purchase request.
*
* </code>
* // Do a purchase transaction on the gateway
* try {
* $transaction = $gateway->authorize(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* 'description' => 'This is a test authorize transaction.',
* 'returnUrl' => 'http://mysite.com/paypal/return/?txn_id=' . $txn_id,
* 'cancelUrl' => 'http://mysite.com/paypal/return/?txn_id=' . $txn_id,
* ));
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway purchase response data == " . print_r($data, true) . "\n";
*
* if ($response->isSuccessful()) {
* echo "Step 2 was successful!\n";
* }
*
* } catch (\Exception $e) {
* echo "Exception caught while attempting authorize.\n";
* echo "Exception type == " . get_class($e) . "\n";
* echo "Message == " . $e->getMessage() . "\n";
* }
* </code>
*
* Step 3 is where your code needs to redirect the customer to the PayPal
* gateway so that the customer can sign in to their PayPal account and
* agree to authorize the payment. The response will implement an interface
* called RedirectResponseInterface from which the redirect URL can be obtained.
*
* How you do this redirect is up to your platform, code or framework at
* this point. For the below example I will assume that there is a
* function called redirectTo() which can handle it for you.
*
* </code>
* if ($response->isRedirect()) {
* // Redirect the customer to PayPal so that they can sign in and
* // authorize the payment.
* echo "The transaction is a redirect";
* redirectTo($response->getRedirectUrl());
* }
* </code>
*
* Step 4 is where the customer returns to your site. This will happen on
* either the returnUrl or the cancelUrl, that you provided in the purchase()
* call.
*
* If the cancelUrl is called then you can assume that the customer has not
* authorized the payment, therefore you can cancel the transaction.
*
* If the returnUrl is called, then you need to complete the transaction via
* a further call to PayPal.
*
* Note this example assumes that the authorize has been successful.
*
* The payer ID and the payment ID returned from the callback after the authorize
* will be passed to the return URL as GET parameters payerId and paymentId
* respectively.
*
* <code>
* $paymentId = $_GET['paymentId'];
* $payerId = $_GET['payerId'];
*
* // Once the transaction has been approved, we need to complete it.
* $transaction = $gateway->completePurchase(array(
* 'payer_id' => $payer_id,
* 'transactionReference' => $sale_id,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* // The customer has successfully paid.
* echo "Step 4 was successful!\n";
* } else {
* // There was an error returned by completePurchase(). You should
* // check the error code and message from PayPal, which may be something
* // like "card declined", etc.
* }
* </code>
*
* #### Note on Handling Error Messages
*
* PayPal account payments are a 2 step process. Firstly the customer needs to
* authorize the payment from PayPal to your application. Secondly, assuming that
* the customer does not have enough balance to pay the invoice from their PayPal
* balance, PayPal needs to transfer the funds from the customer's credit card to
* their PayPal account. This transaction is between PayPal and the customer, and
* not between the customer and you.
*
* If the second transaction fails then a call to completePurchase() will return
* an error. However this error message will be fairly generic. For privacy
* reasons, PayPal will not disclose to the merchant the full reason for the
* failure, they will only disclose this to the customer.
*
* Therefore on a failed completeAuthorize() call you could display an error message
* like this one:
*
* "PayPal failed to process the transaction from your card. For privacy reasons,
* PayPal are unable to disclose to us the reason for this failure. You should try
* a different payment method, a different card within PayPal, or contact PayPal
* support if you need to understand the reason for the failed transaction. PayPal
* may advise you to use a different card if the particular card is rejected
* by the card issuer."
*
* @link https://developer.paypal.com/docs/integration/direct/capture-payment/#authorize-the-payment
* @link https://developer.paypal.com/docs/api/#authorizations
* @link http://bit.ly/1wUQ33R
* @see RestCaptureRequest
* @see RestPurchaseRequest
*/
class RestAuthorizeRequest extends AbstractRestRequest
{
public function getData()
{
$data = array(
'intent' => 'authorize',
'payer' => array(
'payment_method' => 'credit_card',
'funding_instruments' => array()
),
'transactions' => array(
array(
'description' => $this->getDescription(),
'amount' => array(
'total' => $this->getAmount(),
'currency' => $this->getCurrency(),
),
'invoice_number' => $this->getTransactionId()
)
),
'experience_profile_id' => $this->getExperienceProfileId()
);
$items = $this->getItems();
if ($items) {
$itemList = array();
foreach ($items as $n => $item) {
$itemList[] = array(
'name' => $item->getName(),
'description' => $item->getDescription(),
'quantity' => $item->getQuantity(),
'price' => $this->formatCurrency($item->getPrice()),
'currency' => $this->getCurrency()
);
}
$data['transactions'][0]['item_list']["items"] = $itemList;
}
if ($this->getCardReference()) {
$this->validate('amount');
$data['payer']['funding_instruments'][] = array(
'credit_card_token' => array(
'credit_card_id' => $this->getCardReference(),
),
);
} elseif ($this->getCard()) {
$this->validate('amount', 'card');
$this->getCard()->validate();
$data['payer']['funding_instruments'][] = array(
'credit_card' => array(
'number' => $this->getCard()->getNumber(),
'type' => $this->getCard()->getBrand(),
'expire_month' => $this->getCard()->getExpiryMonth(),
'expire_year' => $this->getCard()->getExpiryYear(),
'cvv2' => $this->getCard()->getCvv(),
'first_name' => $this->getCard()->getFirstName(),
'last_name' => $this->getCard()->getLastName(),
'billing_address' => array(
'line1' => $this->getCard()->getAddress1(),
//'line2' => $this->getCard()->getAddress2(),
'city' => $this->getCard()->getCity(),
'state' => $this->getCard()->getState(),
'postal_code' => $this->getCard()->getPostcode(),
'country_code' => strtoupper($this->getCard()->getCountry()),
)
)
);
// There's currently a quirk with the REST API that requires line2 to be
// non-empty if it's present. Jul 14, 2014
$line2 = $this->getCard()->getAddress2();
if (!empty($line2)) {
$data['payer']['funding_instruments'][0]['credit_card']['billing_address']['line2'] = $line2;
}
} else {
$this->validate('amount', 'returnUrl', 'cancelUrl');
unset($data['payer']['funding_instruments']);
$data['payer']['payment_method'] = 'paypal';
$data['redirect_urls'] = array(
'return_url' => $this->getReturnUrl(),
'cancel_url' => $this->getCancelUrl(),
);
}
return $data;
}
/**
* Get the experience profile id
*
* @return string
*/
public function getExperienceProfileId()
{
return $this->getParameter('experienceProfileId');
}
/**
* Set the experience profile id
*
* @param string $value
* @return RestAuthorizeRequest provides a fluent interface.
*/
public function setExperienceProfileId($value)
{
return $this->setParameter('experienceProfileId', $value);
}
/**
* Get transaction description.
*
* The REST API does not currently have support for passing an invoice number
* or transaction ID.
*
* @return string
*/
public function getDescription()
{
$id = $this->getTransactionId();
$desc = parent::getDescription();
if (empty($id)) {
return $desc;
} elseif (empty($desc)) {
return $id;
} else {
return "$id : $desc";
}
}
/**
* Get transaction endpoint.
*
* Authorization of payments is done using the /payment resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/payment';
}
protected function createResponse($data, $statusCode)
{
return $this->response = new RestAuthorizeResponse($this, $data, $statusCode);
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* PayPal REST Authorize Response
*/
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Message\RedirectResponseInterface;
/**
* PayPal REST Authorize Response
*/
class RestAuthorizeResponse extends RestResponse implements RedirectResponseInterface
{
public function isSuccessful()
{
return empty($this->data['error']) && $this->getCode() == 201;
}
public function isRedirect()
{
return $this->getRedirectUrl() !== null;
}
public function getRedirectUrl()
{
if (isset($this->data['links']) && is_array($this->data['links'])) {
foreach ($this->data['links'] as $key => $value) {
if ($value['rel'] == 'approval_url') {
return $value['href'];
}
}
}
return null;
}
/**
* Get the URL to complete (execute) the purchase or agreement.
*
* The URL is embedded in the links section of the purchase or create
* subscription request response.
*
* @return string
*/
public function getCompleteUrl()
{
if (isset($this->data['links']) && is_array($this->data['links'])) {
foreach ($this->data['links'] as $key => $value) {
if ($value['rel'] == 'execute') {
return $value['href'];
}
}
}
return null;
}
public function getTransactionReference()
{
// The transaction reference for a paypal purchase request or for a
// paypal create subscription request ends up in the execute URL
// in the links section of the response.
$completeUrl = $this->getCompleteUrl();
if (empty($completeUrl)) {
return parent::getTransactionReference();
}
$urlParts = explode('/', $completeUrl);
// The last element of the URL should be "execute"
$execute = end($urlParts);
if (!in_array($execute, array('execute', 'agreement-execute'))) {
return parent::getTransactionReference();
}
// The penultimate element should be the transaction reference
return prev($urlParts);
}
/**
* Get the required redirect method (either GET or POST).
*
* @return string
*/
public function getRedirectMethod()
{
return 'GET';
}
/**
* Gets the redirect form data array, if the redirect method is POST.
*
* @return null
*/
public function getRedirectData()
{
return null;
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* PayPal REST Cancel Subscription Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Cancel Subscription Request
*
* Use this call to cancel an agreement after the buyer approves it.
*
* ### Request Data
*
* Pass the agreement id in the URI of a POST call. Also include a description,
* which is the reason for cancelling the subscription.
*
* ### Example
*
* To create the agreement, see the code example in RestCreateSubscriptionRequest.
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a cancel subscription transaction on the gateway
* $transaction = $gateway->cancelSubscription(array(
* 'transactionReference' => $subscription_id,
* 'description' => "Cancelling the agreement.",
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Cancel Subscription transaction was successful!\n";
* }
* </code>
*
* Note that the subscription_id that you get from calling the response's
* getTransactionReference() method at the end of the completeSubscription
* call will be different to the one that you got after calling the response's
* getTransactionReference() method at the end of the createSubscription
* call. The one that you get from completeSubscription is the correct
* one to use going forwards (e.g. for cancelling or updating the subscription).
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-0LN988D3JACS/cancel \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{
* "note": "Canceling the agreement."
* }'
* </code>
*
* @link https://developer.paypal.com/docs/api/#cancel-an-agreement
* @see RestCreateSubscriptionRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestCancelSubscriptionRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference', 'description');
$data = array(
'note' => $this->getDescription(),
);
return $data;
}
/**
* Get transaction endpoint.
*
* Subscriptions are executed using the /billing-agreements resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements/' .
$this->getTransactionReference() . '/cancel';
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* PayPal REST Capture Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Capture Request
*
* Use this resource to capture and process a previously created authorization.
* To use this resource, the original payment call must have the intent set to
* authorize.
*
* To capture payment, make a call to /v1/payments/authorization/{authorization_id}/capture
* with the authorization ID in the URI along with an amount object. For a
* partial capture, you can provide a lower amount. Additionally, you can explicitly
* indicate a final capture (prevent future captures) by setting the is_final_capture
* value to true.
*
* ### Example
*
* Note this example assumes that the authorization has been successful
* and that the authorization ID returned from the authorization is held in $auth_id.
* See RestAuthorizeRequest for the first part of this example transaction:
*
* <code>
* // Once the transaction has been authorized, we can capture it for final payment.
* $transaction = $gateway->capture(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* ));
* $transaction->setTransactionReference($auth_id);
* $response = $transaction->send();
* </code>
*
* @see RestAuthorizeRequest
* @link https://developer.paypal.com/docs/api/#capture-an-authorization
*/
class RestCaptureRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference', 'amount');
return array(
'amount' => array(
'currency' => $this->getCurrency(),
'total' => $this->getAmount(),
),
'is_final_capture' => true,
);
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/authorization/' . $this->getTransactionReference() . '/capture';
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* PayPal REST Complete Purchase Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Complete Purchase Request
*
* Use this message to execute (complete) a PayPal payment that has been
* approved by the payer. You can optionally update transaction information
* when executing the payment by passing in one or more transactions.
*
* This call only works after a buyer has approved the payment using the
* provided PayPal approval URL.
*
* ### Example
*
* The payer ID and the payment ID returned from the callback after the purchase
* will be passed to the return URL as GET parameters payerId and paymentId
* respectively.
*
* See RestPurchaseRequest for the first part of this example transaction:
*
* <code>
* $paymentId = $_GET['paymentId'];
* $payerId = $_GET['payerId'];
*
* // Once the transaction has been approved, we need to complete it.
* $transaction = $gateway->completePurchase(array(
* 'payer_id' => $payerId,
* 'transactionReference' => $paymentId,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* // The customer has successfully paid.
* } else {
* // There was an error returned by completePurchase(). You should
* // check the error code and message from PayPal, which may be something
* // like "card declined", etc.
* }
* </code>
*
* @see RestPurchaseRequest
* @link https://developer.paypal.com/docs/api/#execute-an-approved-paypal-payment
*/
class RestCompletePurchaseRequest extends AbstractRestRequest
{
/**
* Get the raw data array for this message. The format of this varies from gateway to
* gateway, but will usually be either an associative array, or a SimpleXMLElement.
*
* @return mixed
*/
public function getData()
{
$this->validate('transactionReference', 'payerId');
$data = array(
'payer_id' => $this->getPayerId()
);
return $data;
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/payment/' . $this->getTransactionReference() . '/execute';
}
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* PayPal REST Complete Subscription Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Complete Subscription Request
*
* Use this call to execute an agreement after the buyer approves it.
*
* Note: This request is only necessary for PayPal payments. Billing
* agreements for credit card payments execute automatically at the time
* of creation and so this request is not necessary for credit card payments.
*
* ### Request Data
*
* Pass the token in the URI of a POST call to execute the subscription
* agreement after buyer approval. You can find the token in the execute
* link returned by the request to create a billing agreement.
*
* No other data is required.
*
* ### Example
*
* To create the agreement, see the code example in RestCreateSubscriptionRequest.
*
* At the completion of a createSubscription call, the customer should be
* redirected to the redirect URL contained in $response->getRedirectUrl(). Once
* the customer has approved the agreement and be returned to the returnUrl
* in the call. The returnUrl can contain the following code to complete
* the agreement:
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a complete subscription transaction on the gateway
* $transaction = $gateway->completeSubscription(array(
* 'transactionReference' => $subscription_id,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Complete Subscription transaction was successful!\n";
* $subscription_id = $response->getTransactionReference();
* echo "Subscription reference = " . $subscription_id;
* }
* </code>
*
* Note that the subscription_id that you get from calling the response's
* getTransactionReference() method at the end of the completeSubscription
* call will be different to the one that you got after calling the response's
* getTransactionReference() method at the end of the createSubscription
* call. The one that you get from completeSubscription is the correct
* one to use going forwards (e.g. for cancelling or updating the subscription).
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-agreements/EC-0JP008296V451950C/agreement-execute \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{}'
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "id": "I-0LN988D3JACS",
* "links": [
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-0LN988D3JACS",
* "rel": "self",
* "method": "GET"
* }
* ]
* }
* </code>
*
* @link https://developer.paypal.com/docs/api/#execute-an-agreement
* @see RestCreateSubscriptionRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestCompleteSubscriptionRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
$data = array();
return $data;
}
/**
* Get transaction endpoint.
*
* Subscriptions are executed using the /billing-agreements resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements/' .
$this->getTransactionReference() . '/agreement-execute';
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* PayPal REST Create Card Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Create Card Request
*
* PayPal offers merchants a /vault API to store sensitive details
* like credit card related details.
*
* You can currently use the /vault API to store credit card details
* with PayPal instead of storing them on your own server. After storing
* a credit card, you can then pass the credit card id instead of the
* related credit card details to complete a payment.
*
* Direct credit card payment and related features are restricted in
* some countries.
* As of January 2015 these transactions are only supported in the UK
* and in the USA.
*
* Example:
*
* <code>
* // Create a gateway for the PayPal RestGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Create a credit card object
* // DO NOT USE THESE CARD VALUES -- substitute your own
* // see the documentation in the class header.
* $card = new CreditCard(array(
* 'firstName' => 'Example',
* 'lastName' => 'User',
* 'number' => '4111111111111111',
* 'expiryMonth' => '01',
* 'expiryYear' => '2020',
* 'cvv' => '123',
* 'billingAddress1' => '1 Scrubby Creek Road',
* 'billingCountry' => 'AU',
* 'billingCity' => 'Scrubby Creek',
* 'billingPostcode' => '4999',
* 'billingState' => 'QLD',
* ));
*
* // Do a create card transaction on the gateway
* $transaction = $gateway->createCard(array(
* 'card' => $card,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Create card transaction was successful!\n";
* // Find the card ID
* $card_id = $response->getTransactionReference();
* }
* </code>
*
* @link https://developer.paypal.com/docs/api/#vault
* @link https://developer.paypal.com/docs/api/#store-a-credit-card
* @link http://bit.ly/1wUQ33R
*/
class RestCreateCardRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('card');
$this->getCard()->validate();
$data = array(
'number' => $this->getCard()->getNumber(),
'type' => $this->getCard()->getBrand(),
'expire_month' => $this->getCard()->getExpiryMonth(),
'expire_year' => $this->getCard()->getExpiryYear(),
'cvv2' => $this->getCard()->getCvv(),
'first_name' => $this->getCard()->getFirstName(),
'last_name' => $this->getCard()->getLastName(),
'billing_address' => array(
'line1' => $this->getCard()->getAddress1(),
//'line2' => $this->getCard()->getAddress2(),
'city' => $this->getCard()->getCity(),
'state' => $this->getCard()->getState(),
'postal_code' => $this->getCard()->getPostcode(),
'country_code' => strtoupper($this->getCard()->getCountry()),
)
);
// There's currently a quirk with the REST API that requires line2 to be
// non-empty if it's present. Jul 14, 2014
$line2 = $this->getCard()->getAddress2();
if (!empty($line2)) {
$data['billing_address']['line2'] = $line2;
}
return $data;
}
protected function getEndpoint()
{
return parent::getEndpoint() . '/vault/credit-cards';
}
}

View File

@@ -0,0 +1,323 @@
<?php
/**
* PayPal REST Create Plan Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Create Plan Request
*
* PayPal offers merchants a /billing-plans resource for providing billing plans
* to users for recurring payments.
*
* After the billing plan is created, the /billing-agreements resource provides
* billing agreements so that users can agree to be billed for the plans.
*
* You can create an empty billing plan and add a trial period and/or regular
* billing. Alternatively, you can create a fully loaded plan that includes both
* a trial period and regular billing. Note: By default, a created billing plan
* is in a CREATED state. A user cannot subscribe to the billing plan unless it
* has been set to the ACTIVE state.
*
* ### Request Data
*
* In order to create a new billing plan you must submit the following details:
*
* * name (string). Required.
* * description (string). Required.
* * type (string). Allowed values: FIXED, INFINITE. Required.
* * payment_definitions (array)
* * merchant_preferences (object)
*
* ### Example
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a create plan transaction on the gateway
* $transaction = $gateway->createPlan(array(
* 'name' => 'Test Plan',
* 'description' => 'A plan created for testing',
* 'type' => $gateway::BILLING_PLAN_TYPE_FIXED,
* 'paymentDefinitions' => [
* [
* 'name' => 'Monthly Payments for 12 months',
* 'type' => $gateway::PAYMENT_TRIAL,
* 'frequency' => $gateway::BILLING_PLAN_FREQUENCY_MONTH,
* 'frequency_interval' => 1,
* 'cycles' => 12,
* 'amount' => ['value' => 10.00, 'currency' => 'USD'],
* ],
* ],
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Create Plan transaction was successful!\n";
* $plan_id = $response->getTransactionReference();
* echo "Plan reference = " . $plan_id . "\n";
* }
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-plans \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{
* "name": "T-Shirt of the Month Club Plan",
* "description": "Template creation.",
* "type": "fixed",
* "payment_definitions": [
* {
* "name": "Regular Payments",
* "type": "REGULAR",
* "frequency": "MONTH",
* "frequency_interval": "2",
* "amount": {
* "value": "100",
* "currency": "USD"
* },
* "cycles": "12",
* "charge_models": [
* {
* "type": "SHIPPING",
* "amount": {
* "value": "10",
* "currency": "USD"
* }
* },
* {
* "type": "TAX",
* "amount": {
* "value": "12",
* "currency": "USD"
* }
* }
* ]
* }
* ],
* "merchant_preferences": {
* "setup_fee": {
* "value": "1",
* "currency": "USD"
* },
* "return_url": "http://www.return.com",
* "cancel_url": "http://www.cancel.com",
* "auto_bill_amount": "YES",
* "initial_fail_amount_action": "CONTINUE",
* "max_fail_attempts": "0"
* }
* }'
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "id": "P-94458432VR012762KRWBZEUA",
* "state": "CREATED",
* "name": "T-Shirt of the Month Club Plan",
* "description": "Template creation.",
* "type": "FIXED",
* "payment_definitions": [
* {
* "id": "PD-50606817NF8063316RWBZEUA",
* "name": "Regular Payments",
* "type": "REGULAR",
* "frequency": "Month",
* "amount": {
* "currency": "USD",
* "value": "100"
* },
* "charge_models": [
* {
* "id": "CHM-55M5618301871492MRWBZEUA",
* "type": "SHIPPING",
* "amount": {
* "currency": "USD",
* "value": "10"
* }
* },
* {
* "id": "CHM-92S85978TN737850VRWBZEUA",
* "type": "TAX",
* "amount": {
* "currency": "USD",
* "value": "12"
* }
* }
* ],
* "cycles": "12",
* "frequency_interval": "2"
* }
* ],
* "merchant_preferences": {
* "setup_fee": {
* "currency": "USD",
* "value": "1"
* },
* "max_fail_attempts": "0",
* "return_url": "http://www.return.com",
* "cancel_url": "http://www.cancel.com",
* "auto_bill_amount": "YES",
* "initial_fail_amount_action": "CONTINUE"
* },
* "create_time": "2014-07-31T17:41:55.920Z",
* "update_time": "2014-07-31T17:41:55.920Z",
* "links": [
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-plans/P-94458432VR012762KRWBZEUA",
* "rel": "self",
* "method": "GET"
* }
* ]
* }
* </code>
*
* @link https://developer.paypal.com/docs/api/#create-a-plan
* @see Omnipay\PayPal\RestGateway
*/
class RestCreatePlanRequest extends AbstractRestRequest
{
/**
* Get the plan name
*
* @return string
*/
public function getName()
{
return $this->getParameter('name');
}
/**
* Set the plan name
*
* @param string $value
* @return RestCreatePlanRequest provides a fluent interface.
*/
public function setName($value)
{
return $this->setParameter('name', $value);
}
/**
* Get the plan type
*
* @return string
*/
public function getType()
{
return $this->getParameter('type');
}
/**
* Set the plan type
*
* @param string $value either RestGateway::BILLING_PLAN_TYPE_FIXED
* or RestGateway::BILLING_PLAN_TYPE_INFINITE
* @return RestCreatePlanRequest provides a fluent interface.
*/
public function setType($value)
{
return $this->setParameter('type', $value);
}
/**
* Get the plan payment definitions
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#paymentdefinition-object
*/
public function getPaymentDefinitions()
{
return $this->getParameter('paymentDefinitions');
}
/**
* Set the plan payment definitions
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreatePlanRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#paymentdefinition-object
*/
public function setPaymentDefinitions(array $value)
{
return $this->setParameter('paymentDefinitions', $value);
}
/**
* Get the plan merchant preferences
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#merchantpreferences-object
*/
public function getMerchantPreferences()
{
return $this->getParameter('merchantPreferences');
}
/**
* Set the plan merchant preferences
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreatePlanRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#merchantpreferences-object
*/
public function setMerchantPreferences(array $value)
{
return $this->setParameter('merchantPreferences', $value);
}
public function getData()
{
$this->validate('name', 'description', 'type');
$data = array(
'name' => $this->getName(),
'description' => $this->getDescription(),
'type' => $this->getType(),
'payment_definitions' => $this->getPaymentDefinitions(),
'merchant_preferences' => $this->getMerchantPreferences(),
);
return $data;
}
/**
* Get transaction endpoint.
*
* Billing plans are created using the /billing-plans resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-plans';
}
}

View File

@@ -0,0 +1,457 @@
<?php
/**
* PayPal REST Create Subscription Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Create Subscription Request
*
* Use this call to create a billing agreement for the buyer. The response
* for this call includes these HATEOAS links: an approval_url link and an
* execute link. Each returned link includes the token for the agreement.
*
* For PayPal payments:
*
* * After successfully creating the agreement, direct the user to the
* approval_url on the PayPal site so that the user can approve the agreement.
* * Call the execute link to execute the billing agreement.
*
* Note: Billing agreements for credit card payments execute automatically
* when created. There is no need for the user to approve the agreement or
* to execute the agreement.
*
* ### Request Data
*
* Pass the agreement details in the body of a POST call, including the
* following agreement object properties:
*
* * name (string). Required.
* * description (string). Required.
* * start_date (string). Format yyyy-MM-dd z, as defined in ISO8601. Required.
* * agreement_details (array)
* * payer (array). Required
* * shipping_address (array). Should be provided if it is different to the
* default address.
* * override_merchant_preferences (array).
* * override_charge_models (array).
* * plan (array). Required.
*
* ### Example
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a create plan transaction on the gateway
* $transaction = $gateway->createPlan(array(
* 'name' => 'Test Plan',
* 'description' => 'A plan created for testing',
* 'type' => $gateway::BILLING_PLAN_TYPE_FIXED,
* 'paymentDefinitions' => [
* [
* 'name' => 'Monthly Payments for 12 months',
* 'type' => $gateway::PAYMENT_TRIAL,
* 'frequency' => $gateway::BILLING_PLAN_FREQUENCY_MONTH,
* 'frequency_interval' => 1,
* 'cycles' => 12,
* 'amount' => ['value' => 10.00, 'currency' => 'USD'],
* ],
* ],
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Create Plan transaction was successful!\n";
* $plan_id = $response->getTransactionReference();
* echo "Plan reference = " . $plan_id . "\n";
* }
*
* // Do a create subscription transaction on the gateway
* $transaction = $gateway->createSubscription(array(
* 'name' => 'Test Subscription',
* 'description' => 'A subscription created for testing',
* 'startDate' => new \DateTime(), // now
* 'planId' => $plan_id,
* 'payerDetails => ['payment_method' => 'paypal'],
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Create Subscription transaction was successful!\n";
* if ($response->isRedirect()) {
* echo "Response is a redirect\n";
* echo "Redirect URL = " . $response->getRedirectUrl();
* $subscription_id = $response->getTransactionReference();
* echo "Subscription reference = " . $subscription_id;
* }
* }
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-agreements \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{
* "name": "T-Shirt of the Month Club Agreement",
* "description": "Agreement for T-Shirt of the Month Club Plan",
* "start_date": "2015-02-19T00:37:04Z",
* "plan": {
* "id": "P-94458432VR012762KRWBZEUA"
* },
* "payer": {
* "payment_method": "paypal"
* },
* "shipping_address": {
* "line1": "111 First Street",
* "city": "Saratoga",
* "state": "CA",
* "postal_code": "95070",
* "country_code": "US"
* }
* }'
* }'
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "name": "T-Shirt of the Month Club Agreement",
* "description": "Agreement for T-Shirt of the Month Club Plan",
* "plan": {
* "id": "P-94458432VR012762KRWBZEUA",
* "state": "ACTIVE",
* "name": "T-Shirt of the Month Club Plan",
* "description": "Template creation.",
* "type": "FIXED",
* "payment_definitions": [
* {
* "id": "PD-50606817NF8063316RWBZEUA",
* "name": "Regular Payments",
* "type": "REGULAR",
* "frequency": "Month",
* "amount": {
* "currency": "USD",
* "value": "100"
* },
* "charge_models": [
* {
* "id": "CHM-92S85978TN737850VRWBZEUA",
* "type": "TAX",
* "amount": {
* "currency": "USD",
* "value": "12"
* }
* },
* {
* "id": "CHM-55M5618301871492MRWBZEUA",
* "type": "SHIPPING",
* "amount": {
* "currency": "USD",
* "value": "10"
* }
* }
* ],
* "cycles": "12",
* "frequency_interval": "2"
* }
* ],
* "merchant_preferences": {
* "setup_fee": {
* "currency": "USD",
* "value": "1"
* },
* "max_fail_attempts": "0",
* "return_url": "http://www.return.com",
* "cancel_url": "http://www.cancel.com",
* "auto_bill_amount": "YES",
* "initial_fail_amount_action": "CONTINUE"
* }
* },
* "links": [
* {
* "href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-0JP008296V451950C",
* "rel": "approval_url",
* "method": "REDIRECT"
* },
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-agreements/EC-0JP008296V451950C/agreement-execute",
* "rel": "execute",
* "method": "POST"
* }
* ],
* "start_date": "2015-02-19T00:37:04Z"
* }
* </code>
*
* ### Known Issues
*
* PayPal subscription payments cannot be refunded. PayPal is working on this functionality
* for their future API release. In order to refund a PayPal subscription payment, you will
* need to use the PayPal web interface to refund it manually.
*
* @link https://developer.paypal.com/docs/api/#create-an-agreement
* @see RestCreatePlanRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestCreateSubscriptionRequest extends AbstractRestRequest
{
/**
* Get the agreement name
*
* @return string
*/
public function getName()
{
return $this->getParameter('name');
}
/**
* Set the agreement name
*
* @param string $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
*/
public function setName($value)
{
return $this->setParameter('name', $value);
}
/**
* Get the plan ID
*
* @return string
*/
public function getPlanId()
{
return $this->getParameter('planId');
}
/**
* Set the plan ID
*
* @param string $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
*/
public function setPlanId($value)
{
return $this->setParameter('planId', $value);
}
/**
* Get the agreement start date
*
* @return \DateTime
*/
public function getStartDate()
{
return $this->getParameter('startDate');
}
/**
* Set the agreement start date
*
* @param \DateTime $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
*/
public function setStartDate(\DateTime $value)
{
return $this->setParameter('startDate', $value);
}
/**
* Get the agreement details
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#agreementdetails-object
*/
public function getAgreementDetails()
{
return $this->getParameter('agreementDetails');
}
/**
* Set the agreement details
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#agreementdetails-object
*/
public function setAgreementDetails(array $value)
{
return $this->setParameter('agreementDetails', $value);
}
/**
* Get the payer details
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#payer-object
*/
public function getPayerDetails()
{
return $this->getParameter('payerDetails');
}
/**
* Set the payer details
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#payer-object
*/
public function setPayerDetails(array $value)
{
return $this->setParameter('payerDetails', $value);
}
/**
* Get the shipping address
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#address-object
*/
public function getShippingAddress()
{
return $this->getParameter('shippingAddress');
}
/**
* Set the shipping address
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#address-object
*/
public function setShippingAddress(array $value)
{
return $this->setParameter('shippingAddress', $value);
}
/**
* Get preferences to override the plan merchant preferences
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#merchantpreferences-object
*/
public function getMerchantPreferences()
{
return $this->getParameter('merchantPreferences');
}
/**
* Set preferences to override the plan merchant preferences
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#merchantpreferences-object
*/
public function setMerchantPreferences(array $value)
{
return $this->setParameter('merchantPreferences', $value);
}
/**
* Get charge model to override the plan charge model
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @return array
* @link https://developer.paypal.com/docs/api/#overridechargemodel-object
*/
public function getChargeModel()
{
return $this->getParameter('chargeModel');
}
/**
* Set preferences to override the plan merchant preferences
*
* See the class documentation and the PayPal REST API documentation for
* a description of the array elements.
*
* @param array $value
* @return RestCreateSubscriptionRequest provides a fluent interface.
* @link https://developer.paypal.com/docs/api/#merchantpreferences-object
*/
public function setChargeModel(array $value)
{
return $this->setParameter('chargeModel', $value);
}
public function getData()
{
$this->validate('name', 'description', 'startDate', 'payerDetails', 'planId');
$data = array(
'name' => $this->getName(),
'description' => $this->getDescription(),
'start_date' => $this->getStartDate()->format('c'),
'agreement_details' => $this->getAgreementDetails(),
'payer' => $this->getPayerDetails(),
'plan' => array(
'id' => $this->getPlanId(),
),
'shipping_address' => $this->getShippingAddress(),
'override_merchant_preferences' => $this->getMerchantPreferences(),
'override_charge_models' => $this->getChargeModel(),
);
return $data;
}
/**
* Get transaction endpoint.
*
* Subscriptions are created using the /billing-agreements resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements';
}
protected function createResponse($data, $statusCode)
{
return $this->response = new RestAuthorizeResponse($this, $data, $statusCode);
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* PayPal REST Delete Card Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Delete Card Request
*
* PayPal offers merchants a /vault API to store sensitive details
* like credit card related details.
*
* You can currently use the /vault API to store credit card details
* with PayPal instead of storing them on your own server. After storing
* a credit card, you can then pass the credit card id instead of the
* related credit card details to complete a payment.
*
* Direct credit card payment and related features are restricted in
* some countries.
* As of January 2015 these transactions are only supported in the UK
* and in the USA.
*
* Example. This example assumes that the card has already been created
* using a RestCreateCardRequest call and that the card ID has been stored
* in $card_id. See RestCreateCardRequest for the details of the first
* part of this process.
*
* <code>
* $transaction = $gateway->deleteCard();
* $transaction->setCardReference($card_id);
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Gateway deleteCard was successful.\n";
* } else {
* echo "Gateway deleteCard failed.\n";
* }
* </code>
*
* @link https://developer.paypal.com/docs/api/#vault
* @link https://developer.paypal.com/docs/api/#delete-a-stored-credit-card
* @link http://bit.ly/1wUQ33R
* @see RestCreateCardRequest
*/
class RestDeleteCardRequest extends AbstractRestRequest
{
public function getHttpMethod()
{
return 'DELETE';
}
public function getData()
{
$this->validate('cardReference');
return array();
}
public function getEndpoint()
{
return parent::getEndpoint() . '/vault/credit-cards/' . $this->getCardReference();
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* PayPal REST Fetch Purchase Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Fetch Purchase Request
*
* Use this call to get details about payments that have not completed, such
* as payments that are created and approved, or if a payment has failed.
*
* ### Example
*
* See RestPurchaseRequest for the first part of this example transaction:
*
* <code>
* // Fetch the transaction so that details can be found for refund, etc.
* $transaction = $gateway->fetchPurchase();
* $transaction->setTransactionReference($sale_id);
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway fetchTransaction response data == " . print_r($data, true) . "\n";
* </code>
*
* @see RestPurchaseRequest
* @link https://developer.paypal.com/docs/api/#look-up-a-payment-resource
*/
class RestFetchPurchaseRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
return array();
}
/**
* Get HTTP Method.
*
* The HTTP method for fetchTransaction requests must be GET.
* Using POST results in an error 500 from PayPal.
*
* @return string
*/
protected function getHttpMethod()
{
return 'GET';
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/payment/' . $this->getTransactionReference();
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* PayPal REST Fetch Transaction Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Fetch Transaction Request
*
* To get details about completed payments (sale transaction) created by a payment request
* or to refund a direct sale transaction, PayPal provides the /sale resource and related
* sub-resources.
*
* Example -- note this example assumes that the purchase has been successful
* and that the transaction ID returned from the purchase is held in $sale_id.
* See RestPurchaseRequest for the first part of this example transaction:
*
* <code>
* // Fetch the transaction so that details can be found for refund, etc.
* $transaction = $gateway->fetchTransaction();
* $transaction->setTransactionReference($sale_id);
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway fetchTransaction response data == " . print_r($data, true) . "\n";
* </code>
*
* @see RestPurchaseRequest
* @link https://developer.paypal.com/docs/api/#sale-transactions
*/
class RestFetchTransactionRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
return array();
}
/**
* Get HTTP Method.
*
* The HTTP method for fetchTransaction requests must be GET.
* Using POST results in an error 500 from PayPal.
*
* @return string
*/
protected function getHttpMethod()
{
return 'GET';
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/sale/' . $this->getTransactionReference();
}
}

View File

@@ -0,0 +1,242 @@
<?php
/**
* PayPal REST List Plans Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST List Plans Request
*
* Use this call to get a list of plans in any state (CREATED, ACTIVE, etc.).
* The plans returned are the plans made by the merchant making the call.
*
*
* ### Example
*
* #### Initialize Gateway
*
* <code>
* // Create a gateway for the PayPal RestGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
* </code>
*
* #### List all plans that have state CREATED
* <code>
*
* // List all billing plans
* $transaction = $gateway->listPlan([
* 'state' => CREATED,
* ]);
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway listPlan response data == " . print_r($data, true) . "\n";
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v -X GET https://api.sandbox.paypal.com/v1/payments/billing-plans?page_size=3&status=ACTIVE&page=1\
* -H "Content-Type:application/json" \
* -H "Authorization: Bearer Access-Token"
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "total_items": "166",
* "total_pages": "83",
* "plans": [
* {
* "id": "P-7DC96732KA7763723UOPKETA",
* "state": "ACTIVE",
* "name": "Plan with Regular and Trial Payment Definitions",
* "description": "Plan with regular and trial billing payment definitions.",
* "type": "FIXED",
* "create_time": "2017-08-22T04:41:52.836Z",
* "update_time": "2017-08-22T04:41:53.169Z",
* "links": [
* {
* "href": "https://api.sandbox.paypal.com//v1/payments/billing-plans/P-7DC96732KA7763723UOPKETA",
* "rel": "self",
* "method": "GET"
* }
* ]
* },
* {
* "id": "P-1TV69435N82273154UPWDU4I",
* "state": "ACTIVE",
* "name": "Plan with Regular Payment Definition",
* "description": "Plan with one regular payment definition, minimal merchant preferences, and no shipping fee",
* "type": "INFINITE",
* "create_time": "2017-08-22T04:41:55.623Z",
* "update_time": "2017-08-22T04:41:56.055Z",
* "links": [
* {
* "href": "https://api.sandbox.paypal.com//v1/payments/billing-plans/P-1TV69435N82273154UPWDU4I",
* "rel": "self",
* "method": "GET"
* }
* ]
* }
* ],
* "links": [
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-plans?page_size=2&page=1&start=3&status=active",
* "rel": "start",
* "method": "GET"
* },
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-plans?page_size=2&page=0&status=active",
* "rel": "previous_page",
* "method": "GET"
* },
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-plans?page_size=2&page=2&status=active",
* "rel": "next_page",
* "method": "GET"
* },
* {
* "href": "https://api.sandbox.paypal.com/v1/payments/billing-plans?page_size=2&page=82&status=active",
* "rel": "last",
* "method": "GET"
* }
* ]
* }
*
* </code>
*
* @link https://developer.paypal.com/docs/api/payments.billing-plans#plan_list
*/
class RestListPlanRequest extends AbstractRestRequest
{
/**
*
* Get the request page
*
* @return integer
*/
public function getPage()
{
return $this->getParameter('page');
}
/**
* Set the request page
*
* @param integer $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setPage($value)
{
return $this->setParameter('page', $value);
}
/**
* Get the request status
*
* @return string
*/
public function getStatus()
{
return $this->getParameter('status');
}
/**
* Set the request status
*
* @param string $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setStatus($value)
{
return $this->setParameter('status', $value);
}
/**
* Get the request page size
*
* @return string
*/
public function getPageSize()
{
return $this->getParameter('pageSize');
}
/**
* Set the request page size
*
* @param string $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setPageSize($value)
{
return $this->setParameter('pageSize', $value);
}
/**
* Get the request total required
*
* @return string
*/
public function getTotalRequired()
{
return $this->getParameter('totalRequired');
}
/**
* Set the request total required
*
* @param string $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setTotalRequired($value)
{
return $this->setParameter('totalRequired', $value);
}
public function getData()
{
return array(
'page' => $this->getPage(),
'status' => $this->getStatus(),
'page_size' => $this->getPageSize(),
'total_required' => $this->getTotalRequired()
);
}
/**
* Get HTTP Method.
*
* The HTTP method for list plans requests must be GET.
*
* @return string
*/
protected function getHttpMethod()
{
return 'GET';
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-plans';
}
}

View File

@@ -0,0 +1,282 @@
<?php
/**
* PayPal REST List Purchase Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST List Purchase Request
*
* Use this call to get a list of payments in any state (created, approved,
* failed, etc.). The payments returned are the payments made to the merchant
* making the call.
*
* ### Example
*
* See RestPurchaseRequest for the first part of this example transaction:
*
* <code>
* // Make some DateTimes for start and end times
* $start_time = new \DateTime('yesterday');
* $end_time = new \DateTime('now');
*
* // List the transaction so that details can be found for refund, etc.
* $transaction = $gateway->listPurchase(
* 'startTime' => $start_time,
* 'endTime => $end_time
* );
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway listPurchase response data == " . print_r($data, true) . "\n";
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v -X GET https://api.sandbox.paypal.com/v1/payments/payment?
* sort_order=asc&sort_by=update_time \
* -H "Content-Type:application/json" \
* -H "Authorization: Bearer <Access-Token>"
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "payments": [
* {
* "id": "PAY-4D099447DD202993VKEFMRJQ",
* "create_time": "2013-01-31T19:40:22Z",
* "update_time": "2013-01-31T19:40:24Z",
* "state": "approved",
* "intent": "sale",
* "payer": {
* "payment_method": "credit_card",
* "funding_instruments": [
* {
* "credit_card": {
* "type": "visa",
* "number": "xxxxxxxxxxxx0331",
* "expire_month": "10",
* "expire_year": "2018",
* "first_name": "Betsy",
* "last_name": "Buyer",
* "billing_address": {
* "line1": "111 First Street",
* "city": "Saratoga",
* "state": "CA",
* "postal_code": "95070",
* "country_code": "US"
* }
* }
* }
* ]
* },
* "transactions": [
* {
* "amount": {
* "total": "110.54",
* "currency": "USD"
* },
* "description": "This is the payment transaction description.",
* "related_resources": [
* {
* "sale": {
* "id": "1D971400A7097562W",
* "create_time": "2013-01-31T19:40:23Z",
* "update_time": "2013-01-31T19:40:25Z",
* "state": "completed",
* "amount": {
* "total": "110.54",
* "currency": "USD"
* },
* "parent_payment": "PAY-4D099447DD202993VKEFMRJQ",
* "links": [
* {
* "href":
* "https://api.sandbox.paypal.com/v1/payments/sale/1D971400A7097562W",
* "rel": "self",
* "method": "GET"
* },
* {
* "href":
* "https://api.sandbox.paypal.com/v1/payments/sale/1D971400A7097562W/refund",
* "rel": "refund",
* "method": "POST"
* },
* {
* "href":
* "https://api.sandbox.paypal.com/v1/payments/payment/PAY-4D099447DD202993VKEFMRJQ",
* "rel": "parent_payment",
* "method": "GET"
* }
* ]
* }
* }
* ]
* }
* ],
* "links": [
* {
* "href":
* "https://api.sandbox.paypal.com/v1/payments/payment/PAY-4D099447DD202993VKEFMRJQ",
* "rel": "self",
* "method": "GET"
* }
* ]
* }
* ]
* }
* </code>
*
* @see RestPurchaseRequest
* @link https://developer.paypal.com/docs/api/#list-payment-resources
*/
class RestListPurchaseRequest extends AbstractRestRequest
{
/**
* Get the request count
*
* @return integer
*/
public function getCount()
{
return $this->getParameter('count');
}
/**
* Set the request count
*
* @param integer $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setCount($value)
{
return $this->setParameter('count', $value);
}
/**
* Get the request startId
*
* @return string
*/
public function getStartId()
{
return $this->getParameter('startId');
}
/**
* Set the request startId
*
* @param string $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setStartId($value)
{
return $this->setParameter('startId', $value);
}
/**
* Get the request startIndex
*
* @return integer
*/
public function getStartIndex()
{
return $this->getParameter('startIndex');
}
/**
* Set the request startIndex
*
* @param integer $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setStartIndex($value)
{
return $this->setParameter('startIndex', $value);
}
/**
* Get the request startTime
*
* @return string
*/
public function getStartTime()
{
return $this->getParameter('startTime');
}
/**
* Set the request startTime
*
* @param string|\DateTime $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setStartTime($value)
{
if ($value instanceof \DateTime) {
$value->setTimezone(new \DateTimeZone('UTC'));
$value = $value->format('Y-m-d\TH:i:s\Z');
}
return $this->setParameter('startTime', $value);
}
/**
* Get the request endTime
*
* @return string
*/
public function getEndTime()
{
return $this->getParameter('endTime');
}
/**
* Set the request endTime
*
* @param string|\DateTime $value
* @return AbstractRestRequest provides a fluent interface.
*/
public function setEndTime($value)
{
if ($value instanceof \DateTime) {
$value->setTimezone(new \DateTimeZone('UTC'));
$value = $value->format('Y-m-d\TH:i:s\Z');
}
return $this->setParameter('endTime', $value);
}
public function getData()
{
return array(
'count' => $this->getCount(),
'start_id' => $this->getStartId(),
'start_index' => $this->getStartIndex(),
'start_time' => $this->getStartTime(),
'end_time' => $this->getEndTime(),
);
}
/**
* Get HTTP Method.
*
* The HTTP method for listPurchase requests must be GET.
*
* @return string
*/
protected function getHttpMethod()
{
return 'GET';
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/payment';
}
}

View File

@@ -0,0 +1,232 @@
<?php
/**
* PayPal REST Purchase Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Purchase Request
*
* PayPal provides various payment related operations using
* the /payment resource and related sub-resources. Use payment
* for direct credit card payments and PayPal account payments.
* You can also use sub-resources to get payment related details.
*
* Note that a PayPal Purchase Request looks exactly like a PayPal
* Authorize request except that the 'intent' is set to 'sale' for
* immediate payment. This class takes advantage of that by
* extending the RestAuthorizeRequest class and simply over-riding
* the getData() function to set the intent to sale.
*
* ### Example
*
* #### Initialize Gateway
*
* <code>
* // Create a gateway for the PayPal RestGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
* </code>
*
* #### Direct Credit Card Payment
*
* This is for the use case where a customer has presented their
* credit card details and you intend to use the PayPal REST gateway
* for processing a transaction using that credit card data.
*
* This does not require the customer to have a PayPal account.
*
* <code>
* // Create a credit card object
* // DO NOT USE THESE CARD VALUES -- substitute your own
* // see the documentation in the class header.
* $card = new CreditCard(array(
* 'firstName' => 'Example',
* 'lastName' => 'User',
* 'number' => '4111111111111111',
* 'expiryMonth' => '01',
* 'expiryYear' => '2020',
* 'cvv' => '123',
* 'billingAddress1' => '1 Scrubby Creek Road',
* 'billingCountry' => 'AU',
* 'billingCity' => 'Scrubby Creek',
* 'billingPostcode' => '4999',
* 'billingState' => 'QLD',
* ));
*
* // Do a purchase transaction on the gateway
* try {
* $transaction = $gateway->purchase(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* 'description' => 'This is a test purchase transaction.',
* 'card' => $card,
* ));
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway purchase response data == " . print_r($data, true) . "\n";
*
* if ($response->isSuccessful()) {
* echo "Purchase transaction was successful!\n";
* }
* } catch (\Exception $e) {
* echo "Exception caught while attempting authorize.\n";
* echo "Exception type == " . get_class($e) . "\n";
* echo "Message == " . $e->getMessage() . "\n";
* }
* </code>
*
* Direct credit card payment and related features are restricted in
* some countries.
* As of January 2015 these transactions are only supported in the UK
* and in the USA.
*
* #### PayPal Account Payment
*
* This is for the use case where the customer intends to pay using their
* PayPal account. Note that no credit card details are provided, instead
* both a return URL and a cancel URL are required.
*
* The optimal solution here is to provide a unique return URL and cancel
* URL per transaction. That way your code will know what transaction is
* being returned or cancelled by PayPal.
*
* So step 1 is to store some transaction data somewhere on your system so
* that you have an ID when your transaction returns. How you do this of
* course depends on what framework, database layer, etc, you are using but
* for this step let's assume that you have a class set up that can save
* a transaction and return the object, and that you can retrieve the ID
* of that saved object using some call like getId() on the object. Most
* ORMs such as Doctrine ORM, Propel or Eloquent will have some methods
* that will allow you to do this or something similar.
*
* <code>
* $transaction = MyClass::saveTransaction($some_data);
* $txn_id = $transaction->getId();
* </code>
*
* Step 2 is to send the purchase request.
*
* <code>
* // Do a purchase transaction on the gateway
* try {
* $transaction = $gateway->purchase(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* 'description' => 'This is a test purchase transaction.',
* 'returnUrl' => 'http://mysite.com/paypal/return/?txn_id=' . $txn_id,
* 'cancelUrl' => 'http://mysite.com/paypal/return/?txn_id=' . $txn_id,
* ));
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway purchase response data == " . print_r($data, true) . "\n";
*
* if ($response->isSuccessful()) {
* echo "Step 2 was successful!\n";
* }
*
* } catch (\Exception $e) {
* echo "Exception caught while attempting purchase.\n";
* echo "Exception type == " . get_class($e) . "\n";
* echo "Message == " . $e->getMessage() . "\n";
* }
* </code>
*
* Step 3 is where your code needs to redirect the customer to the PayPal
* gateway so that the customer can sign in to their PayPal account and
* agree to authorize the payment. The response will implement an interface
* called RedirectResponseInterface from which the redirect URL can be obtained.
*
* How you do this redirect is up to your platform, code or framework at
* this point. For the below example I will assume that there is a
* function called redirectTo() which can handle it for you.
*
* <code>
* if ($response->isRedirect()) {
* // Redirect the customer to PayPal so that they can sign in and
* // authorize the payment.
* echo "The transaction is a redirect";
* redirectTo($response->getRedirectUrl());
* }
* </code>
*
* Step 4 is where the customer returns to your site. This will happen on
* either the returnUrl or the cancelUrl, that you provided in the purchase()
* call.
*
* If the cancelUrl is called then you can assume that the customer has not
* authorized the payment, therefore you can cancel the transaction.
*
* If the returnUrl is called, then you need to complete the transaction via
* a further call to PayPal.
*
* Note this example assumes that the purchase has been successful.
*
* The payer ID and the payment ID returned from the callback after the purchase
* will be passed to the return URL as GET parameters payerId and paymentId
* respectively.
*
* <code>
* $paymentId = $_GET['paymentId'];
* $payerId = $_GET['payerId'];
*
* // Once the transaction has been approved, we need to complete it.
* $transaction = $gateway->completePurchase(array(
* 'payer_id' => $payer_id,
* 'transactionReference' => $sale_id,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* // The customer has successfully paid.
* echo "Step 4 was successful!\n";
* } else {
* // There was an error returned by completePurchase(). You should
* // check the error code and message from PayPal, which may be something
* // like "card declined", etc.
* }
* </code>
*
* #### Note on Handling Error Messages
*
* PayPal account payments are a 2 step process. Firstly the customer needs to
* authorize the payment from PayPal to your application. Secondly, assuming that
* the customer does not have enough balance to pay the invoice from their PayPal
* balance, PayPal needs to transfer the funds from the customer's credit card to
* their PayPal account. This transaction is between PayPal and the customer, and
* not between the customer and you.
*
* If the second transaction fails then a call to completePurchase() will return
* an error. However this error message will be fairly generic. For privacy
* reasons, PayPal will not disclose to the merchant the full reason for the
* failure, they will only disclose this to the customer.
*
* Therefore on a failed completePurchase() call you could display an error message
* like this one:
*
* "PayPal failed to process the transaction from your card. For privacy reasons,
* PayPal are unable to disclose to us the reason for this failure. You should try
* a different payment method, a different card within PayPal, or contact PayPal
* support if you need to understand the reason for the failed transaction. PayPal
* may advise you to use a different card if the particular card is rejected
* by the card issuer."
*
* @link https://developer.paypal.com/docs/api/#create-a-payment
* @see RestAuthorizeRequest
*/
class RestPurchaseRequest extends RestAuthorizeRequest
{
public function getData()
{
$data = parent::getData();
$data['intent'] = 'sale';
return $data;
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* PayPal REST Reactivate Subscription Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Reactivate Subscription Request
*
* Use this call to reactivate an agreement.
*
* ### Request Data
*
* Pass the agreement id in the URI of a POST call. Also include a description,
* which is the reason for reactivating the subscription.
*
* ### Example
*
* To create the agreement, see the code example in RestCreateSubscriptionRequest.
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a reactivate subscription transaction on the gateway
* $transaction = $gateway->reactivateSubscription(array(
* 'transactionReference' => $subscription_id,
* 'description' => "Reactivating the agreement.",
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Reactivate Subscription transaction was successful!\n";
* }
* </code>
*
* Note that the subscription_id that you get from calling the response's
* getTransactionReference() method at the end of the completeSubscription
* call will be different to the one that you got after calling the response's
* getTransactionReference() method at the end of the createSubscription
* call. The one that you get from completeSubscription is the correct
* one to use going forwards (e.g. for cancelling or updating the subscription).
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-0LN988D3JACS/re-activate \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{
* "note": "Reactivating the agreement."
* }'
* </code>
*
* @link https://developer.paypal.com/docs/api/#reactivate-an-agreement
* @see RestCreateSubscriptionRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestReactivateSubscriptionRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference', 'description');
$data = array(
'note' => $this->getDescription(),
);
return $data;
}
/**
* Get transaction endpoint.
*
* Subscriptions are executed using the /billing-agreements resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements/' .
$this->getTransactionReference() . '/re-activate';
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* PayPal REST Refund Captured Payment Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Refund Captured Payment Request
*
* Use this call to refund a captured payment.
*
* @link https://developer.paypal.com/docs/api/#refund-a-captured-payment
* @see RestAuthorizeRequest
* @see RestCaptureRequest
*/
class RestRefundCaptureRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
return array(
'amount' => array(
'currency' => $this->getCurrency(),
'total' => $this->getAmount(),
),
'description' => $this->getDescription(),
);
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/capture/' . $this->getTransactionReference() . '/refund';
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* PayPal REST Refund Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Refund Request
*
* To get details about completed payments (sale transaction) created by a payment request
* or to refund a direct sale transaction, PayPal provides the /sale resource and related
* sub-resources.
*
* TODO: There might be a problem here, in that refunding a capture requires a different URL.
*
* TODO: Yes I know. The gateway doesn't yet support looking up or refunding captured
* transactions. That will require adding additional message classes because the URLs
* are all different.
*
* A non-zero amount can be provided for the refund using setAmount(), if this is not
* provided (or is zero) then a full refund is made.
*
* Example -- note this example assumes that the purchase has been successful
* and that the transaction ID returned from the purchase is held in $sale_id.
* See RestPurchaseRequest for the first part of this example transaction:
*
* <code>
* $transaction = $gateway->refund(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* ));
* $transaction->setTransactionReference($sale_id);
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Refund transaction was successful!\n";
* $data = $response->getData();
* echo "Gateway refund response data == " . print_r($data, true) . "\n";
* }
* </code>
*
* ### Known Issues
*
* PayPal subscription payments cannot be refunded. PayPal is working on this functionality
* for their future API release. In order to refund a PayPal subscription payment, you will
* need to use the PayPal web interface to refund it manually.
*
* @see RestPurchaseRequest
*/
class RestRefundRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
if ($this->getAmount() > 0) {
return array(
'amount' => array(
'currency' => $this->getCurrency(),
'total' => $this->getAmount(),
),
'description' => $this->getDescription(),
);
} else {
return new \stdClass();
}
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/sale/' . $this->getTransactionReference() . '/refund';
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* PayPal REST Response
*/
namespace Omnipay\PayPal\Message;
use Omnipay\Common\Message\AbstractResponse;
use Omnipay\Common\Message\RequestInterface;
/**
* PayPal REST Response
*/
class RestResponse extends AbstractResponse
{
protected $statusCode;
public function __construct(RequestInterface $request, $data, $statusCode = 200)
{
parent::__construct($request, $data);
$this->statusCode = $statusCode;
}
public function isSuccessful()
{
return empty($this->data['error']) && $this->getCode() < 400;
}
public function getTransactionReference()
{
// This is usually correct for payments, authorizations, etc
if (!empty($this->data['transactions']) && !empty($this->data['transactions'][0]['related_resources'])) {
foreach (array('sale', 'authorization') as $type) {
if (!empty($this->data['transactions'][0]['related_resources'][0][$type])) {
return $this->data['transactions'][0]['related_resources'][0][$type]['id'];
}
}
}
// This is a fallback, but is correct for fetch transaction and possibly others
if (!empty($this->data['id'])) {
return $this->data['id'];
}
return null;
}
public function getMessage()
{
if (isset($this->data['error_description'])) {
return $this->data['error_description'];
}
if (isset($this->data['message'])) {
return $this->data['message'];
}
return null;
}
public function getCode()
{
return $this->statusCode;
}
public function getCardReference()
{
if (isset($this->data['id'])) {
return $this->data['id'];
}
}
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* PayPal REST Search Transaction Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Search Transaction Request
*
* Use this call to search for the transactions within a billing agreement.
* Note that this is not a generic transaction search function -- for that
* see RestListPurchaseRequest. It only searches for transactions within
* a billing agreement.
*
* This should be used on a regular basis to determine the success / failure
* state of transactions on active billing agreements.
*
* ### Example
*
* <code>
* // List the transactions for a billing agreement.
* $transaction = $gateway->listPurchase();
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway listPurchase response data == " . print_r($data, true) . "\n";
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v GET https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-0LN988D3JACS/transactions \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>'
* </code>
*
* ### Response Sample
*
* This is from the PayPal web site:
*
* <code>
* {
* "agreement_transaction_list": [
* {
* "transaction_id": "I-0LN988D3JACS",
* "status": "Created",
* "transaction_type": "Recurring Payment",
* "payer_email": "bbuyer@example.com",
* "payer_name": "Betsy Buyer",
* "time_stamp": "2014-06-09T09:29:36Z",
* "time_zone": "GMT"
* },
* {
* "transaction_id": "928415314Y5640008",
* "status": "Completed",
* "transaction_type": "Recurring Payment",
* "amount": {
* "currency": "USD",
* "value": "1.00"
* },
* "fee_amount": {
* "currency": "USD",
* "value": "-0.33"
* },
* "net_amount": {
* "currency": "USD",
* "value": "0.67"
* },
* "payer_email": "bbuyer@example.com",
* "payer_name": "Betsy Buyer",
* "time_stamp": "2014-06-09T09:42:47Z",
* "time_zone": "GMT"
* },
* {
* "transaction_id": "I-0LN988D3JACS",
* "status": "Suspended",
* "transaction_type": "Recurring Payment",
* "payer_email": "bbuyer@example.com",
* "payer_name": "Betsy Buyer",
* "time_stamp": "2014-06-09T11:18:34Z",
* "time_zone": "GMT"
* },
* {
* "transaction_id": "I-0LN988D3JACS",
* "status": "Reactivated",
* "transaction_type": "Recurring Payment",
* "payer_email": "bbuyer@example.com",
* "payer_name": "Betsy Buyer",
* "time_stamp": "2014-06-09T11:18:48Z",
* "time_zone": "GMT"
* }
* ]
* }
* </code>
*
* ### Known Issues
*
* PayPal subscription payments cannot be refunded. PayPal is working on this functionality
* for their future API release. In order to refund a PayPal subscription payment, you will
* need to use the PayPal web interface to refund it manually.
*
* @see RestCreateSubscriptionRequest
* @link https://developer.paypal.com/docs/api/#search-for-transactions
*/
class RestSearchTransactionRequest extends AbstractRestRequest
{
/**
* Get the agreement ID
*
* @return string
*/
public function getAgreementId()
{
return $this->getParameter('agreementId');
}
/**
* Set the agreement ID
*
* @param string $value
* @return RestSearchTransactionRequest provides a fluent interface.
*/
public function setAgreementId($value)
{
return $this->setParameter('agreementId', $value);
}
/**
* Get the request startDate
*
* @return string
*/
public function getStartDate()
{
return $this->getParameter('startDate');
}
/**
* Set the request startDate
*
* @param string|DateTime $value
* @return RestSearchTransactionRequest provides a fluent interface.
*/
public function setStartDate($value)
{
return $this->setParameter('startDate', is_string($value) ? new \DateTime($value) : $value);
}
/**
* Get the request endDate
*
* @return string
*/
public function getEndDate()
{
return $this->getParameter('endDate');
}
/**
* Set the request endDate
*
* @param string|DateTime $value
* @return RestSearchTransactionRequest provides a fluent interface.
*/
public function setEndDate($value)
{
return $this->setParameter('endDate', is_string($value) ? new \DateTime($value) : $value);
}
public function getData()
{
$this->validate('agreementId', 'startDate', 'endDate');
return array(
'start_date' => $this->getStartDate()->format('Y-m-d'),
'end_date' => $this->getEndDate()->format('Y-m-d'),
);
}
/**
* Get HTTP Method.
*
* The HTTP method for searchTransaction requests must be GET.
*
* @return string
*/
protected function getHttpMethod()
{
return 'GET';
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements/' .
$this->getAgreementId() . '/transactions';
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* PayPal REST Suspend Subscription Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Suspend Subscription Request
*
* Use this call to suspend an agreement.
*
* ### Request Data
*
* Pass the agreement id in the URI of a POST call. Also include a description,
* which is the reason for suspending the subscription.
*
* ### Example
*
* To create the agreement, see the code example in RestCreateSubscriptionRequest.
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Do a suspend subscription transaction on the gateway
* $transaction = $gateway->suspendSubscription(array(
* 'transactionReference' => $subscription_id,
* 'description' => "Suspending the agreement.",
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Suspend Subscription transaction was successful!\n";
* }
* </code>
*
* Note that the subscription_id that you get from calling the response's
* getTransactionReference() method at the end of the completeSubscription
* call will be different to the one that you got after calling the response's
* getTransactionReference() method at the end of the createSubscription
* call. The one that you get from completeSubscription is the correct
* one to use going forwards (e.g. for cancelling or updating the subscription).
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v POST https://api.sandbox.paypal.com/v1/payments/billing-agreements/I-0LN988D3JACS/suspend \
* -H 'Content-Type:application/json' \
* -H 'Authorization: Bearer <Access-Token>' \
* -d '{
* "note": "Suspending the agreement."
* }'
* </code>
*
* @link https://developer.paypal.com/docs/api/#suspend-an-agreement
* @see RestCreateSubscriptionRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestSuspendSubscriptionRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference', 'description');
$data = array(
'note' => $this->getDescription(),
);
return $data;
}
/**
* Get transaction endpoint.
*
* Subscriptions are executed using the /billing-agreements resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-agreements/' .
$this->getTransactionReference() . '/suspend';
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* PayPal REST Token Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Token Request
*
* With each API call, youll need to set request headers, including
* an OAuth 2.0 access token. Get an access token by using the OAuth
* 2.0 client_credentials token grant type with your clientId:secret
* as your Basic Auth credentials.
*
* @link https://developer.paypal.com/docs/integration/direct/make-your-first-call/
* @link https://developer.paypal.com/docs/api/#authentication--headers
*/
class RestTokenRequest extends AbstractRestRequest
{
public function getData()
{
return array('grant_type' => 'client_credentials');
}
protected function getEndpoint()
{
return parent::getEndpoint() . '/oauth2/token';
}
public function sendData($data)
{
$body = $data ? http_build_query($data, '', '&') : null;
$httpResponse = $this->httpClient->request(
$this->getHttpMethod(),
$this->getEndpoint(),
array(
'Accept' => 'application/json',
'Authorization' => 'Basic ' . base64_encode("{$this->getClientId()}:{$this->getSecret()}"),
),
$body
);
// Empty response body should be parsed also as and empty array
$body = (string) $httpResponse->getBody()->getContents();
$jsonToArrayResponse = !empty($body) ? json_decode($body, true) : array();
return $this->response = new RestResponse($this, $jsonToArrayResponse, $httpResponse->getStatusCode());
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* PayPal REST Update Plan Request
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Update Plan Request
*
* You can update the information for an existing billing plan. The state
* of a plan must be active before a billing agreement is created.
*
* ### Request Data
*
* Pass the billing plan id in the URI of a PATCH call, including the replace
* operation in the body. Other operations in the patch_request object will
* throw validation exceptions.
*
* ### Example
*
* To create the billing plan, see the code example in RestCreatePlanRequest.
*
* <code>
* // Create a gateway for the PayPal REST Gateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
*
* // Update the billing plan
* $transaction = $gateway->updatePlan(array(
* 'transactionReference' => $plan_id,
* 'state' => $gateway::BILLING_PLAN_STATE_ACTIVE,
* ));
* $response = $transaction->send();
* if ($response->isSuccessful()) {
* echo "Update Plan transaction was successful!\n";
* }
* </code>
*
* ### Request Sample
*
* This is from the PayPal web site:
*
* <code>
* curl -v -k -X PATCH 'https://api.sandbox.paypal.com/v1/payments/billing-plans/P-94458432VR012762KRWBZEUA' \
* -H "Content-Type: application/json" \
* -H "Authorization: Bearer <Access-Token>" \
* -d '[
* {
* "path": "/",
* "value": {
* "state": "ACTIVE"
* },
* "op": "replace"
* }
* ]'
* </code>
*
* ### Response
*
* Returns the HTTP status of 200 if the call is successful.
*
* @link https://developer.paypal.com/docs/api/#update-a-plan
* @see RestCreateSubscriptionRequest
* @see Omnipay\PayPal\RestGateway
*/
class RestUpdatePlanRequest extends AbstractRestRequest
{
/**
* Get the plan state
*
* @return string
*/
public function getState()
{
return $this->getParameter('state');
}
/**
* Set the plan state
*
* @param string $value
* @return RestUpdatePlanRequest provides a fluent interface.
*/
public function setState($value)
{
return $this->setParameter('state', $value);
}
public function getData()
{
$this->validate('transactionReference', 'state');
$data = array(array(
'path' => '/',
'value' => array(
'state' => $this->getState(),
),
'op' => 'replace'
));
return $data;
}
/**
* Get transaction endpoint.
*
* Billing plans are managed using the /billing-plans resource.
*
* @return string
*/
protected function getEndpoint()
{
return parent::getEndpoint() . '/payments/billing-plans/' . $this->getTransactionReference();
}
protected function getHttpMethod()
{
return 'PATCH';
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* PayPal REST Void an authorization
*/
namespace Omnipay\PayPal\Message;
/**
* PayPal REST Void an authorization
*
* Use this call to void a previously authorized payment.
* Note: A fully captured authorization cannot be voided.
*
* @link https://developer.paypal.com/docs/api/#void-an-authorization
* @see RestAuthorizeRequest
*/
class RestVoidRequest extends AbstractRestRequest
{
public function getData()
{
$this->validate('transactionReference');
}
public function getEndpoint()
{
return parent::getEndpoint() . '/payments/authorization/' . $this->getTransactionReference() . '/void';
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Paypal Item
*/
namespace Omnipay\PayPal;
use Omnipay\Common\Item;
/**
* Class PayPalItem
*
* @package Omnipay\PayPal
*/
class PayPalItem extends Item
{
/**
* {@inheritDoc}
*/
public function getCode()
{
return $this->getParameter('code');
}
/**
* Set the item code
*/
public function setCode($value)
{
return $this->setParameter('code', $value);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* PayPal Item bag
*/
namespace Omnipay\PayPal;
use Omnipay\Common\ItemBag;
use Omnipay\Common\ItemInterface;
/**
* Class PayPalItemBag
*
* @package Omnipay\PayPal
*/
class PayPalItemBag extends ItemBag
{
/**
* Add an item to the bag
*
* @see Item
*
* @param ItemInterface|array $item An existing item, or associative array of item parameters
*/
public function add($item)
{
if ($item instanceof ItemInterface) {
$this->items[] = $item;
} else {
$this->items[] = new PayPalItem($item);
}
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Omnipay\PayPal;
use Omnipay\Common\AbstractGateway;
/**
* PayPal Pro Class
*/
class ProGateway extends AbstractGateway
{
public function getName()
{
return 'PayPal Pro';
}
public function getDefaultParameters()
{
return array(
'username' => '',
'password' => '',
'signature' => '',
'testMode' => false,
);
}
public function getUsername()
{
return $this->getParameter('username');
}
public function setUsername($value)
{
return $this->setParameter('username', $value);
}
public function getPassword()
{
return $this->getParameter('password');
}
public function setPassword($value)
{
return $this->setParameter('password', $value);
}
public function getSignature()
{
return $this->getParameter('signature');
}
public function setSignature($value)
{
return $this->setParameter('signature', $value);
}
public function authorize(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ProAuthorizeRequest', $parameters);
}
public function purchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\ProPurchaseRequest', $parameters);
}
public function capture(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\CaptureRequest', $parameters);
}
public function refund(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RefundRequest', $parameters);
}
public function fetchTransaction(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\FetchTransactionRequest', $parameters);
}
}

View File

@@ -0,0 +1,717 @@
<?php
/**
* PayPal Pro Class using REST API
*/
namespace Omnipay\PayPal;
use Omnipay\Common\AbstractGateway;
use Omnipay\PayPal\Message\ProAuthorizeRequest;
use Omnipay\PayPal\Message\CaptureRequest;
use Omnipay\PayPal\Message\RefundRequest;
/**
* PayPal Pro Class using REST API
*
* This class forms the gateway class for PayPal REST requests via the PayPal REST APIs.
*
* The PayPal API uses HTTP verbs and a RESTful endpoint structure. OAuth 2.0 is used
* as the API Authorization framework. Request and response payloads are formatted as JSON.
*
* The PayPal REST APIs are supported in two environments. Use the Sandbox environment
* for testing purposes, then move to the live environment for production processing.
* When testing, generate an access token with your test credentials to make calls to
* the Sandbox URIs. When youre set to go live, use the live credentials assigned to
* your app to generate a new access token to be used with the live URIs.
*
* ### Test Mode
*
* In order to use this for testing in sandbox mode you will need at least two sandbox
* test accounts. One will need to be a business account, and one will need to be a
* personal account with credit card details. To create these you will need to go to
* the sandbox accounts section of the PayPal developer dashboard, here:
* https://developer.paypal.com/webapps/developer/applications/accounts
* On that page click "Create Account" and follow the prompts. When you are creating the
* Personal account, ensure that it is created with a credit card -- either Visa or
* MasterCard or one of the other types. When you are testing in the sandbox, use the
* credit card details you will receive for this Personal account rather than any other
* commonly used test credit card numbers (e.g. visa card 4111111111111111 or 4444333322221111
* both of which will result in Error 500 / INTERNAL_SERVICE_ERROR type errors from the
* PayPal gateway).
*
* With each API call, youll need to set request headers, including an OAuth 2.0
* access token. Get an access token by using the OAuth 2.0 client_credentials token
* grant type with your clientId:secret as your Basic Auth credentials. For more
* information, see Make your first call (link). This class sets all of the headers
* associated with the API call for you, including making preliminary calls to create
* or update the OAuth 2.0 access token before each call you make, if required. All
* you need to do is provide the clientId and secret when you initialize the gateway,
* or use the set*() calls to set them after creating the gateway object.
*
* ### Credentials
*
* To create production and sandbox credentials for your PayPal account:
*
* * Log into your PayPal account.
* * Navigate to your Sandbox accounts at https://developer.paypal.com/webapps/developer/applications/accounts
* to ensure that you have a valid sandbox account to use for testing. If you don't already have a sandbox
* account, one can be created on this page. You will actually need 2 accounts, a personal account and a
* business account, the business account is the one you need to use for creating API applications.
* * Check your account status on https://developer.paypal.com/webapps/developer/account/status to ensure
* that it is valid for live transactions.
* * Navigate to the My REST apps page: https://developer.paypal.com/webapps/developer/applications/myapps
* * Click *Create App*
* * On the next page, enter an App name and select the sandbox account to use, then click *Create app*.
* * On the next page the sandbox account, endpoint, Client ID and Secret should be displayed.
* Record these. The Sandbox account should match the one that you selected on the previous
* page, and the sandbox endpoint should be ai.sandbox.paypal.com
* * Adjacent to *Live credentials* click *Show* to display your live credentials. The endpoint
* for these should be api.paypal.com, there should also be a Client ID and Secret.
*
* You can create additional REST APIs apps for other websites -- because the webhooks are
* stored per app then it pays to have one API app per website that you are using (and an
* additional one for things like command line testing, etc).
*
* ### Example
*
* #### Initialize Gateway
*
* <code>
* // Create a gateway for the PayPal RestGateway
* // (routes to GatewayFactory::create)
* $gateway = Omnipay::create('PayPal_Rest');
*
* // Initialise the gateway
* $gateway->initialize(array(
* 'clientId' => 'MyPayPalClientId',
* 'secret' => 'MyPayPalSecret',
* 'testMode' => true, // Or false when you are ready for live transactions
* ));
* </code>
*
* #### Direct Credit Card Payment
*
* <code>
* // Create a credit card object
* // DO NOT USE THESE CARD VALUES -- substitute your own
* // see the documentation in the class header.
* $card = new CreditCard(array(
* 'firstName' => 'Example',
* 'lastName' => 'User',
* 'number' => '4111111111111111',
* 'expiryMonth' => '01',
* 'expiryYear' => '2020',
* 'cvv' => '123',
* 'billingAddress1' => '1 Scrubby Creek Road',
* 'billingCountry' => 'AU',
* 'billingCity' => 'Scrubby Creek',
* 'billingPostcode' => '4999',
* 'billingState' => 'QLD',
* ));
*
* // Do a purchase transaction on the gateway
* try {
* $transaction = $gateway->purchase(array(
* 'amount' => '10.00',
* 'currency' => 'AUD',
* 'description' => 'This is a test purchase transaction.',
* 'card' => $card,
* ));
* $response = $transaction->send();
* $data = $response->getData();
* echo "Gateway purchase response data == " . print_r($data, true) . "\n";
*
* if ($response->isSuccessful()) {
* echo "Purchase transaction was successful!\n";
* }
* } catch (\Exception $e) {
* echo "Exception caught while attempting authorize.\n";
* echo "Exception type == " . get_class($e) . "\n";
* echo "Message == " . $e->getMessage() . "\n";
* }
* </code>
*
* ### Dashboard
*
* Once you have processed some payments you can go to the PayPal sandbox site,
* at https://www.sandbox.paypal.com/ and log in with the email address and password
* of your PayPal sandbox business test account. You will then see the result
* of those transactions on the "My recent activity" list under the My Account
* tab.
*
* @link https://developer.paypal.com/docs/api/
* @link https://devtools-paypal.com/integrationwizard/
* @link http://paypal.github.io/sdk/
* @link https://developer.paypal.com/docs/integration/direct/rest_api_payment_country_currency_support/
* @link https://developer.paypal.com/docs/faq/
* @link https://developer.paypal.com/docs/integration/direct/make-your-first-call/
* @link https://developer.paypal.com/docs/integration/web/accept-paypal-payment/
* @link https://developer.paypal.com/docs/api/#authentication--headers
* @see Omnipay\PayPal\Message\AbstractRestRequest
*/
class RestGateway extends AbstractGateway
{
// Constants used in plan creation
const BILLING_PLAN_TYPE_FIXED = 'FIXED';
const BILLING_PLAN_TYPE_INFINITE = 'INFINITE';
const BILLING_PLAN_FREQUENCY_DAY = 'DAY';
const BILLING_PLAN_FREQUENCY_WEEK = 'WEEK';
const BILLING_PLAN_FREQUENCY_MONTH = 'MONTH';
const BILLING_PLAN_FREQUENCY_YEAR = 'YEAR';
const BILLING_PLAN_STATE_CREATED = 'CREATED';
const BILLING_PLAN_STATE_ACTIVE = 'ACTIVE';
const BILLING_PLAN_STATE_INACTIVE = 'INACTIVE';
const BILLING_PLAN_STATE_DELETED = 'DELETED';
const PAYMENT_TRIAL = 'TRIAL';
const PAYMENT_REGULAR = 'REGULAR';
public function getName()
{
return 'PayPal REST';
}
public function getDefaultParameters()
{
return array(
'clientId' => '',
'secret' => '',
'token' => '',
'testMode' => false,
);
}
//
// Tokens -- methods to set up, store and retrieve the OAuth 2.0 access token.
//
// @link https://developer.paypal.com/docs/api/#authentication--headers
//
/**
* Get OAuth 2.0 client ID for the access token.
*
* Get an access token by using the OAuth 2.0 client_credentials
* token grant type with your clientId:secret as your Basic Auth
* credentials.
*
* @return string
*/
public function getClientId()
{
return $this->getParameter('clientId');
}
/**
* Set OAuth 2.0 client ID for the access token.
*
* Get an access token by using the OAuth 2.0 client_credentials
* token grant type with your clientId:secret as your Basic Auth
* credentials.
*
* @param string $value
* @return RestGateway provides a fluent interface
*/
public function setClientId($value)
{
return $this->setParameter('clientId', $value);
}
/**
* Get OAuth 2.0 secret for the access token.
*
* Get an access token by using the OAuth 2.0 client_credentials
* token grant type with your clientId:secret as your Basic Auth
* credentials.
*
* @return string
*/
public function getSecret()
{
return $this->getParameter('secret');
}
/**
* Set OAuth 2.0 secret for the access token.
*
* Get an access token by using the OAuth 2.0 client_credentials
* token grant type with your clientId:secret as your Basic Auth
* credentials.
*
* @param string $value
* @return RestGateway provides a fluent interface
*/
public function setSecret($value)
{
return $this->setParameter('secret', $value);
}
/**
* Get OAuth 2.0 access token.
*
* @param bool $createIfNeeded [optional] - If there is not an active token present, should we create one?
* @return string
*/
public function getToken($createIfNeeded = true)
{
if ($createIfNeeded && !$this->hasToken()) {
$response = $this->createToken()->send();
if ($response->isSuccessful()) {
$data = $response->getData();
if (isset($data['access_token'])) {
$this->setToken($data['access_token']);
$this->setTokenExpires(time() + $data['expires_in']);
}
}
}
return $this->getParameter('token');
}
/**
* Create OAuth 2.0 access token request.
*
* @return \Omnipay\PayPal\Message\RestTokenRequest
*/
public function createToken()
{
return $this->createRequest('\Omnipay\PayPal\Message\RestTokenRequest', array());
}
/**
* Set OAuth 2.0 access token.
*
* @param string $value
* @return RestGateway provides a fluent interface
*/
public function setToken($value)
{
return $this->setParameter('token', $value);
}
/**
* Get OAuth 2.0 access token expiry time.
*
* @return integer
*/
public function getTokenExpires()
{
return $this->getParameter('tokenExpires');
}
/**
* Set OAuth 2.0 access token expiry time.
*
* @param integer $value
* @return RestGateway provides a fluent interface
*/
public function setTokenExpires($value)
{
return $this->setParameter('tokenExpires', $value);
}
/**
* Is there a bearer token and is it still valid?
*
* @return bool
*/
public function hasToken()
{
$token = $this->getParameter('token');
$expires = $this->getTokenExpires();
if (!empty($expires) && !is_numeric($expires)) {
$expires = strtotime($expires);
}
return !empty($token) && time() < $expires;
}
/**
* Create Request
*
* This overrides the parent createRequest function ensuring that the OAuth
* 2.0 access token is passed along with the request data -- unless the
* request is a RestTokenRequest in which case no token is needed. If no
* token is available then a new one is created (e.g. if there has been no
* token request or the current token has expired).
*
* @param string $class
* @param array $parameters
* @return \Omnipay\PayPal\Message\AbstractRestRequest
*/
public function createRequest($class, array $parameters = array())
{
if (!$this->hasToken() && $class != '\Omnipay\PayPal\Message\RestTokenRequest') {
// This will set the internal token parameter which the parent
// createRequest will find when it calls getParameters().
$this->getToken(true);
}
return parent::createRequest($class, $parameters);
}
//
// Payments -- Create payments or get details of one or more payments.
//
// @link https://developer.paypal.com/docs/api/#payments
//
/**
* Create a purchase request.
*
* PayPal provides various payment related operations using the /payment
* resource and related sub-resources. Use payment for direct credit card
* payments and PayPal account payments. You can also use sub-resources
* to get payment related details.
*
* @link https://developer.paypal.com/docs/api/#create-a-payment
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestPurchaseRequest
*/
public function purchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestPurchaseRequest', $parameters);
}
/**
* Fetch a purchase request.
*
* Use this call to get details about payments that have not completed,
* such as payments that are created and approved, or if a payment has failed.
*
* @link https://developer.paypal.com/docs/api/#look-up-a-payment-resource
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestFetchPurchaseRequest
*/
public function fetchPurchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestFetchPurchaseRequest', $parameters);
}
/**
* List purchase requests.
*
* Use this call to get a list of payments in any state (created, approved,
* failed, etc.). The payments returned are the payments made to the merchant
* making the call.
*
* @link https://developer.paypal.com/docs/api/#list-payment-resources
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestListPurchaseRequest
*/
public function listPurchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestListPurchaseRequest', $parameters);
}
/**
* Completes a purchase request.
*
* @link https://developer.paypal.com/docs/api/#execute-an-approved-paypal-payment
* @param array $parameters
* @return Message\AbstractRestRequest
*/
public function completePurchase(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCompletePurchaseRequest', $parameters);
}
// TODO: Update a payment resource https://developer.paypal.com/docs/api/#update-a-payment-resource
//
// Authorizations -- Capture, reauthorize, void and look up authorizations.
//
// @link https://developer.paypal.com/docs/api/#authorizations
// @link https://developer.paypal.com/docs/integration/direct/capture-payment/
//
/**
* Create an authorization request.
*
* To collect payment at a later time, first authorize a payment using the /payment resource.
* You can then capture the payment to complete the sale and collect payment.
*
* @link https://developer.paypal.com/docs/integration/direct/capture-payment/#authorize-the-payment
* @link https://developer.paypal.com/docs/api/#authorizations
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestAuthorizeRequest
*/
public function authorize(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestAuthorizeRequest', $parameters);
}
/**
* Void an authorization.
*
* To to void a previously authorized payment.
*
* @link https://developer.paypal.com/docs/api/#void-an-authorization
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestVoidRequest
*/
public function void(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestVoidRequest', $parameters);
}
/**
* Capture an authorization.
*
* Use this resource to capture and process a previously created authorization.
* To use this resource, the original payment call must have the intent set to
* authorize.
*
* @link https://developer.paypal.com/docs/api/#capture-an-authorization
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCaptureRequest
*/
public function capture(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCaptureRequest', $parameters);
}
// TODO: Authorizations with payment_method == paypal.
/**
* Refund a Captured Payment
*
* To refund captured payments (authorization transaction) created by a authorize request.
*
* @link https://developer.paypal.com/docs/api/#refund-a-captured-payment
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestRefundCaptureRequest
*/
public function refundCapture(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestRefundCaptureRequest', $parameters);
}
//
// Sale Transactions -- Get and refund completed payments (sale transactions).
// @link https://developer.paypal.com/docs/api/#sale-transactions
//
/**
* Fetch a Sale Transaction
*
* To get details about completed payments (sale transaction) created by a payment request
* or to refund a direct sale transaction, PayPal provides the /sale resource and related
* sub-resources.
*
* @link https://developer.paypal.com/docs/api/#sale-transactions
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestFetchTransactionRequest
*/
public function fetchTransaction(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestFetchTransactionRequest', $parameters);
}
/**
* Refund a Sale Transaction
*
* To get details about completed payments (sale transaction) created by a payment request
* or to refund a direct sale transaction, PayPal provides the /sale resource and related
* sub-resources.
*
* @link https://developer.paypal.com/docs/api/#sale-transactions
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestRefundRequest
*/
public function refund(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestRefundRequest', $parameters);
}
//
// Vault: Store customer credit cards securely.
//
// @link https://developer.paypal.com/docs/api/#vault
//
/**
* Store a credit card in the vault
*
* You can currently use the /vault API to store credit card details
* with PayPal instead of storing them on your own server. After storing
* a credit card, you can then pass the credit card id instead of the
* related credit card details to complete a payment.
*
* @link https://developer.paypal.com/docs/api/#store-a-credit-card
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCreateCardRequest
*/
public function createCard(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCreateCardRequest', $parameters);
}
/**
* Delete a credit card from the vault.
*
* Updating a card in the vault is no longer supported -- see
* http://stackoverflow.com/questions/20858910/paypal-rest-api-update-a-stored-credit-card
* Therefore the only way to update a card is to remove it using deleteCard and
* then re-add it using createCard.
*
* @link https://developer.paypal.com/docs/api/#delete-a-stored-credit-card
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestDeleteCardRequest
*/
public function deleteCard(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestDeleteCardRequest', $parameters);
}
//
// Billing Plans and Agreements -- Set up recurring payments.
// @link https://developer.paypal.com/docs/api/#billing-plans-and-agreements
//
/**
* Create a billing plan.
*
* You can create an empty billing plan and add a trial period and/or regular
* billing. Alternatively, you can create a fully loaded plan that includes
* both a trial period and regular billing. Note: By default, a created billing
* plan is in a CREATED state. A user cannot subscribe to the billing plan
* unless it has been set to the ACTIVE state.
*
* @link https://developer.paypal.com/docs/api/#create-a-plan
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCreatePlanRequest
*/
public function createPlan(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCreatePlanRequest', $parameters);
}
/**
* Update a billing plan.
*
* You can update the information for an existing billing plan. The state of a plan
* must be active before a billing agreement is created.
*
* @link https://developer.paypal.com/docs/api/#update-a-plan
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestUpdatePlanRequest
*/
public function updatePlan(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestUpdatePlanRequest', $parameters);
}
// TODO: Retrieve a plan
/**
* List billing plans.
*
* Use this call to get a list of plans in any state (CREATED, ACTIVE, etc.).
* The plans returned are the plans made by the merchant making the call.
*
* @link https://developer.paypal.com/docs/api/payments.billing-plans#plan_list
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestListPlanRequest
*/
public function listPlan(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestListPlanRequest', $parameters);
}
/**
* Create a subscription.
*
* Use this call to create a billing agreement for the buyer.
*
* @link https://developer.paypal.com/docs/api/#create-an-agreement
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCreateSubscriptionRequest
*/
public function createSubscription(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCreateSubscriptionRequest', $parameters);
}
/**
* Complete (execute) a subscription.
*
* Use this call to execute an agreement after the buyer approves it.
*
* @link https://developer.paypal.com/docs/api/#execute-an-agreement
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCompleteSubscriptionRequest
*/
public function completeSubscription(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCompleteSubscriptionRequest', $parameters);
}
/**
* Cancel a subscription.
*
* Use this call to cancel an agreement.
*
* @link https://developer.paypal.com/docs/api/#cancel-an-agreement
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCancelSubscriptionRequest
*/
public function cancelSubscription(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestCancelSubscriptionRequest', $parameters);
}
/**
* Suspend a subscription.
*
* Use this call to suspend an agreement.
*
* @link https://developer.paypal.com/docs/api/#suspend-an-agreement
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestSuspendSubscriptionRequest
*/
public function suspendSubscription(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestSuspendSubscriptionRequest', $parameters);
}
/**
* Reactivate a suspended subscription.
*
* Use this call to reactivate or un-suspend an agreement.
*
* @link https://developer.paypal.com/docs/api/#reactivate-an-agreement
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestReactivateSubscriptionRequest
*/
public function reactivateSubscription(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestReactivateSubscriptionRequest', $parameters);
}
/**
* Search for transactions.
*
* Use this call to search for the transactions within a billing agreement.
* Note that this is not a generic transaction search function -- for that
* see RestListPurchaseRequest. It only searches for transactions within
* a billing agreement.
*
* This should be used on a regular basis to determine the success / failure
* state of transactions on active billing agreements.
*
* @link https://developer.paypal.com/docs/api/#search-for-transactions
* @param array $parameters
* @return \Omnipay\PayPal\Message\RestCompleteSubscriptionRequest
*/
public function searchTransaction(array $parameters = array())
{
return $this->createRequest('\Omnipay\PayPal\Message\RestSearchTransactionRequest', $parameters);
}
// TODO: Update an agreement
// TODO: Retrieve an agreement
// TODO: Set outstanding agreement amounts
// TODO: Bill outstanding agreement amounts
}

View File

@@ -0,0 +1,97 @@
<?php
namespace Omnipay\PayPal\Support\InstantUpdateApi;
use Omnipay\Common\Exception\InvalidRequestException;
class BillingAgreement
{
/**
* Billing agreement types for single or recurring payment
*
* @var array
*/
protected $types = array(
'single' => 'MerchantInitiatedBillingSingleAgreement',
'recurring' => 'MerchantInitiatedBilling',
);
/** @var string */
private $type;
/** @var string */
private $description;
/** @var string */
private $paymentType;
/** @var string */
private $customAnnotation;
/**
* @param bool $recurring L_BILLINGTYPE0
* @param string $description L_BILLINGAGREEMENTDESCRIPTION0
* @param null|string $paymentType L_PAYMENTTYPE0
* @param null|string $customAnnotation L_BILLINGAGREEMENTCUSTOM0
* @throws \Exception
*/
public function __construct($recurring, $description, $paymentType = null, $customAnnotation = null)
{
if (!$recurring && !is_null($paymentType) && !in_array($paymentType, array('Any', 'InstantOnly'))) {
throw new InvalidRequestException("The 'paymentType' parameter can be only 'Any' or 'InstantOnly'");
}
$this->type = $recurring ? $this->types['recurring'] : $this->types['single'];
$this->description = $description;
$this->customAnnotation = $customAnnotation;
$this->paymentType = $paymentType;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* @return bool
*/
public function hasPaymentType()
{
return !is_null($this->paymentType);
}
/**
* @return string
*/
public function getPaymentType()
{
return $this->paymentType;
}
/**
* @return bool
*/
public function hasCustomAnnotation()
{
return !is_null($this->customAnnotation);
}
/**
* @return string
*/
public function getCustomAnnotation()
{
return $this->customAnnotation;
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Omnipay\PayPal\Support\InstantUpdateApi;
class ShippingOption
{
/** @var string */
private $name;
/** @var float */
private $amount;
/** @var bool */
private $isDefault;
/** @var string */
private $label;
/**
* @param string $name L_SHIPPINGOPTIONNAME0
* @param float $amount L_SHIPPINGOPTIONAMOUNT0
* @param bool $isDefault L_SHIPPINGOPTIONISDEFAULT0
* @param string $label L_SHIPPINGOPTIONLABEL0
*/
public function __construct($name, $amount, $isDefault = false, $label = null)
{
$this->name = $name;
$this->amount = $amount;
$this->isDefault = $isDefault;
$this->label = $label;
}
/**
* @return bool
*/
public function hasLabel()
{
return !is_null($this->label);
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return float
*/
public function getAmount()
{
return $this->amount;
}
/**
* @return boolean
*/
public function isDefault()
{
return $this->isDefault;
}
/**
* @return string
*/
public function getLabel()
{
return $this->label;
}
}