├── .gitignore ├── docs ├── index.md ├── response.md └── request.md ├── .editorconfig ├── .travis.yml ├── src └── whatwedo │ └── PostFinanceEPayment │ ├── Order │ ├── Order.php │ ├── OrderInterface.php │ └── AbstractOrder.php │ ├── Client │ ├── Client.php │ ├── ClientInterface.php │ └── AbstractClient.php │ ├── Environment │ ├── TestEnvironment.php │ ├── ProductionEnvironment.php │ ├── EnvironmentInterface.php │ └── Environment.php │ ├── Exception │ ├── InvalidArgumentException.php │ ├── NotValidSignatureException.php │ ├── InvalidCountryException.php │ └── InvalidCurrencyException.php │ ├── Model │ ├── PaymentMethod.php │ ├── Brand.php │ ├── PaymentStatus.php │ ├── Parameter.php │ └── ErrorCode.php │ ├── PostFinanceEPayment.php │ ├── Form │ └── Form.php │ ├── Bag │ └── ParameterBag.php │ ├── Payment │ └── Payment.php │ └── Response │ └── Response.php ├── Makefile ├── tests ├── bootstrap.php └── whatwedo │ └── PostFinanceEPayment │ └── Tests │ └── PostFinanceEPaymentTest.php ├── phpunit.xml.dist ├── README.md ├── composer.json ├── LICENSE ├── CHANGELOG.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # PHP specific stuff 2 | vendor/ 3 | phpunit.xml 4 | docs/api 5 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | * [create a payment request](request.md) 4 | * [transaction feedback](response.md) 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 4 13 | trim_trailing_whitespace = true 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | matrix: 4 | fast_finish: true 5 | include: 6 | - php: 5.6 7 | - php: 7.0 8 | - php: 7.1 9 | - php: 7.2 10 | - php: 7.3 11 | - php: 7.4 12 | - php: nightly 13 | allow_failures: 14 | - php: nightly 15 | 16 | before_script: 17 | - composer self-update 18 | - composer install --dev 19 | 20 | script: 21 | - cp phpunit.xml.dist phpunit.xml 22 | - vendor/bin/phpunit -c phpunit.xml --coverage-clover clover 23 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Order/Order.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class Order extends AbstractOrder 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Client/Client.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class Client extends AbstractClient 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | doc: 2 | phpdoc --template responsive-twig -d src -t docs/api 3 | 4 | install: 5 | composer install --dev 6 | 7 | test_docker: 8 | if [ ! -a phpunit.xml ]; then cp phpunit.xml.dist phpunit.xml; fi; 9 | docker run -i -v $(PWD):/app composer/composer install 10 | docker run -i -v $(PWD):/app -w /app php:5.6 vendor/bin/phpunit -c phpunit.xml 11 | docker run -i -v $(PWD):/app -w /app php:7.0 vendor/bin/phpunit -c phpunit.xml 12 | docker run -i -v $(PWD):/app -w /app php:7.1 vendor/bin/phpunit -c phpunit.xml 13 | docker run -i -v $(PWD):/app -w /app hhvm/hhvm vendor/bin/phpunit -c phpunit.xml 14 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('JMS\Serializer\Tests', __DIR__); 18 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Environment/TestEnvironment.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class TestEnvironment extends Environment 18 | { 19 | const BASE_URL = 'https://e-payment.postfinance.ch/ncol/test'; 20 | } 21 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Environment/ProductionEnvironment.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class ProductionEnvironment extends Environment 18 | { 19 | const BASE_URL = 'https://e-payment.postfinance.ch/ncol/prod'; 20 | } 21 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | 15 | 16 | ./tests 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostFinance E-Payment [![Build Status](https://travis-ci.org/whatwedo/PostFinanceEPayment.svg)](https://travis-ci.org/whatwedo/PostFinanceEPayment) 2 | 3 | PHP 5 library for handling PostFinance E-Payments 4 | 5 | ## Requirements 6 | 7 | This library has the following requirements: 8 | 9 | - PHP 5.6+ 10 | 11 | ## Installation 12 | 13 | install the library via composer: 14 | 15 | ``` 16 | composer require whatwedo/postfinance-e-payment 17 | ``` 18 | 19 | ## Documentation 20 | 21 | * see [/docs](docs/index.md)-folder for usage. 22 | * see [docs.whatwedo.ch/PostFinanceEPayment/api](http://docs.whatwedo.ch/PostFinanceEPayment/api/) for API docs 23 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class InvalidArgumentException extends BaseInvalidArgumentException 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Model/PaymentMethod.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class PaymentMethod 20 | { 21 | const CREDITCARD = 'CreditCard'; 22 | const POSTFINANCE_EFINANCE = 'PostFinance e-finance'; 23 | const POSTFINANCE_CARD = 'PostFinance Card'; 24 | const UNKNOWN = 'Unknown'; 25 | } 26 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Environment/EnvironmentInterface.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | interface EnvironmentInterface 18 | { 19 | /** 20 | * @return string 21 | */ 22 | public static function getGatewayUrl(); 23 | 24 | /** 25 | * @return string 26 | */ 27 | public static function getDirectLinkMaintenanceUrl(); 28 | } 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "whatwedo/postfinance-e-payment", 3 | "type": "library", 4 | "description": "PHP library for handling PostFinance E-Payments", 5 | "license": "MIT", 6 | "keywords": ["postfinance", "e-payment"], 7 | "homepage": "https://github.com/whatwedo/postfinance-e-payment", 8 | "authors": [ 9 | { 10 | "name": "Ueli Banholzer", 11 | "email": "ueli@whatwedo.ch", 12 | "homepage": "https://whatwedo.ch" 13 | } 14 | ], 15 | "autoload": { 16 | "psr-0": { 17 | "whatwedo\\PostFinanceEPayment": "src/" 18 | } 19 | }, 20 | "require": { 21 | "php": ">=5.6.0" 22 | }, 23 | "require-dev": { 24 | "fzaninotto/faker": "^1.9", 25 | "phpunit/phpunit": "^5.7" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Model/Brand.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class Brand 20 | { 21 | // credit cards 22 | const VISA = 'Visa'; 23 | const MASTERCARD = 'MasterCard'; 24 | 25 | // post finance 26 | const POSTFINANCE_EFINANCE = 'PostFinance e-finance'; 27 | const POSTFINANCE_CARD = 'PostFinance Card'; 28 | 29 | // others (or not yet implemented) 30 | const UNKNOWN = 'Unknown'; 31 | } 32 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Exception/NotValidSignatureException.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class NotValidSignatureException extends Exception 20 | { 21 | public function __construct($message = '', $code = 0, Exception $previous = null) 22 | { 23 | if (empty($message)) { 24 | $message = 'PostFinance signature does not match'; 25 | } 26 | parent::__construct($message, $code, $previous); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Exception/InvalidCountryException.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class InvalidCountryException extends InvalidArgumentException 18 | { 19 | /** 20 | * {@inheritdoc} 21 | */ 22 | public function __construct($inputCountry, $allowedCountries = null) 23 | { 24 | parent::__construct(sprintf( 25 | 'Invalid country given (%s), must be an ISO-3166 Alpha 2 acronym', 26 | $inputCountry 27 | )); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Order/OrderInterface.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | interface OrderInterface 20 | { 21 | /** 22 | * @return string 23 | */ 24 | public function getId(); 25 | 26 | /** 27 | * @return float 28 | */ 29 | public function getAmount(); 30 | 31 | /** 32 | * @return int amount multiplied by 100 (to avoid problems with decimal point) 33 | */ 34 | public function getIntegerAmount(); 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getCurrency(); 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getOrderText(); 45 | } 46 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Exception/InvalidCurrencyException.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class InvalidCurrencyException extends InvalidArgumentException 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function __construct($inputCurrency, $allowedCurrencies = null) 25 | { 26 | if (null === $allowedCurrencies) { 27 | $allowedCurrencies = Environment::$ALLOWED_CURRENCIES; 28 | } 29 | 30 | parent::__construct(sprintf( 31 | 'Invalid currency given (%s), allowed: %s', 32 | $inputCurrency, 33 | implode(', ', $allowedCurrencies) 34 | )); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 whatwedo GmbH (https://whatwedo.ch) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Client/ClientInterface.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | interface ClientInterface 20 | { 21 | /** 22 | * @return string 23 | */ 24 | public function getId(); 25 | 26 | /** 27 | * @return string 28 | */ 29 | public function getName(); 30 | 31 | /** 32 | * @return string 33 | */ 34 | public function getEmail(); 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getAddress(); 40 | 41 | /** 42 | * @return string 43 | */ 44 | public function getZip(); 45 | 46 | /** 47 | * @return string 48 | */ 49 | public function getTown(); 50 | 51 | /** 52 | * @return string 53 | */ 54 | public function getTel(); 55 | 56 | /** 57 | * @return string 58 | */ 59 | public function getCountry(); 60 | 61 | /** 62 | * @return string 63 | */ 64 | public function getLocale(); 65 | } 66 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [v1.1.1] - 2019-01-17 6 | ### Fixed 7 | - Removed the undefined `$parameters` variable from the code (by @finalgamer) 8 | 9 | ### Changed 10 | - updated dependencies 11 | 12 | ### Added 13 | - adding support for PHP 7.2, PHP 7.3 and PHP 7.4 14 | - added a description on how to use `getResponse()` with custom parameters. (by @finalgamer) 15 | 16 | ## [v1.1.0] - 2018-05-01 17 | ### Feature 18 | - added custom zip code parameter with OWNERZIP (by @wanze) 19 | 20 | ## [v1.0.0] - 2017-05-31 21 | ### Fixed 22 | - if getForm() is called twice the signature has been added twice 23 | 24 | ### Changed 25 | - dropping support for PHP 5.3, PHP 5.4, PHP 5.5 and HHVM 26 | - adding support for PHP 7.0, PHP 7.1 27 | 28 | ## [v0.1.0-ALPHA2] - 2015-10-17 29 | ### Added 30 | - all Parameters for alias-usage 31 | - allowing to pass an array of additional parameters to the `PostFinanceEPayment->createPayment` method 32 | - added gateway URL for UTF-8 data (by [Ymox](https://github.com/Ymox) - thanks!) 33 | 34 | ## [v0.1.0-ALPHA1] - 2014-04-22 35 | ### Added 36 | - handle payment request 37 | - parse PostFinance response 38 | 39 | [unreleased]: https://github.com/whatwedo/PostFinanceEPayment/compare/master...develop 40 | [v1.1.1]: https://github.com/whatwedo/PostFinanceEPayment/compare/v1.1.0...v1.1.1 41 | [v1.1.0]: https://github.com/whatwedo/PostFinanceEPayment/compare/v1.0.0...v1.1.0 42 | [v1.0.0]: https://github.com/whatwedo/PostFinanceEPayment/compare/v0.1.0-ALPHA2...v1.0.0 43 | [v0.1.0-ALPHA2]: https://github.com/whatwedo/PostFinanceEPayment/compare/v0.1.0-ALPHA1...v0.1.0-ALPHA2 44 | [v0.1.0-ALPHA1]: https://github.com/whatwedo/PostFinanceEPayment/tree/v0.1.0-ALPHA1 45 | -------------------------------------------------------------------------------- /docs/response.md: -------------------------------------------------------------------------------- 1 | # Transaction Feedback 2 | 3 | You can either get a transaction feedback with GET variables when user is redirecting back to your page or you can 4 | choose a server-side method. For both, you can use this code snippet to get the result of the transaction: 5 | 6 | ```php 7 | setHashAlgorithm(TestEnvironment::HASH_SHA512); // if you want to use another algorithm than sha-1 22 | $env->setCharset(TestEnvironment::CHARSET_UTF_8); // if your application uses UTF-8 rather than ISO 8859-1 23 | 24 | $ePayment = new PostFinanceEPayment($env); 25 | 26 | $response = $ePayment->getResponse(); // takes $_GET array to look for PostFinance variables 27 | // $response = $ePayment->getResponse($_POST); // takes $_POST array to look for PostFinance variables 28 | // $response = $ePayment->getResponse($parameters); // you may pass your own parameters to this function 29 | 30 | try { 31 | $response = $ePayment->getResponse(); 32 | } 33 | catch(NotValidSignatureException $e) { 34 | die("PostFinance signature does not match, maybe fraud access?"); 35 | } 36 | 37 | if ($response->hasError()) { 38 | switch($response->getStatus()) { 39 | case PaymentStatus::INCOMPLETE: 40 | echo "Payment incomplete. "; 41 | break; 42 | case PaymentStatus::DECLINED: 43 | echo "Payment declined. "; 44 | break; 45 | default: 46 | printf("Error: %s.", $response->getError()); 47 | break; 48 | } 49 | if ($response->isRetryError()) { 50 | echo "You should try again."; 51 | } 52 | } else { 53 | echo "success"; 54 | } 55 | ``` 56 | 57 | * [create a payment request](request.md) 58 | * [back to index](index.md) 59 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/PostFinanceEPayment.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class PostFinanceEPayment 27 | { 28 | const POSTFINANCE_VERSION = 04.101; 29 | 30 | /** 31 | * @var Environment 32 | */ 33 | protected $environment = null; 34 | 35 | /** 36 | * @param Environment $environment 37 | */ 38 | public function __construct(Environment &$environment) 39 | { 40 | $this->environment = $environment; 41 | } 42 | 43 | /** 44 | * create a new payment request. 45 | * 46 | * @param ClientInterface $client 47 | * @param OrderInterface $order 48 | * @param array $additionalParameters 49 | * 50 | * @return Payment 51 | */ 52 | public function createPayment(ClientInterface $client, OrderInterface $order, $additionalParameters = array()) 53 | { 54 | $parameterBag = new ParameterBag($additionalParameters); 55 | 56 | return new Payment($client, $order, $parameterBag, $this->environment); 57 | } 58 | 59 | /** 60 | * parses PostFinance response. 61 | * 62 | * @param array|null $parameters 63 | * @param bool $skipSignature skip signature check? 64 | * 65 | * @return Response 66 | */ 67 | public function getResponse($parameters = null, $skipSignature = false) 68 | { 69 | if (null === $parameters) { 70 | $parameters = $_GET; 71 | } 72 | 73 | return Response::create($parameters, $this->environment, $skipSignature); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /docs/request.md: -------------------------------------------------------------------------------- 1 | # Create A Payment Request 2 | 3 | ```php 4 | setHashAlgorithm(TestEnvironment::HASH_SHA512); // if you want to use another algorithm than sha-1 19 | $env->setCharset(TestEnvironment::CHARSET_UTF_8); // if your application uses UTF-8 rather than ISO 8859-1 20 | 21 | // if you want, you can set this in the backoffice 22 | $env->setAcceptUrl("https://www.example.com/checkout/postfinance/accept"); 23 | $env->setCancelUrl("https://www.example.com/checkout/postfinance/cancel"); 24 | $env->setCatalogUrl("https://www.example.com/shop"); 25 | $env->setDeclineUrl("https://www.example.com/checkout/postfinance/decline"); 26 | $env->setExceptionUrl("https://www.example.com/checkout/postfinance/exception"); 27 | $env->setHomeUrl("https://www.example.com/"); 28 | 29 | $ePayment = new PostFinanceEPayment($env); 30 | 31 | /* 32 | * you can implement ClientInterface and OrderInterface 33 | * to use it with your existing classes or create a custom class 34 | * by extending AbstractClient oder AbstractOrder 35 | */ 36 | $client = new Client(); 37 | $client->setId(5) 38 | ->setName("John McClane") 39 | ->setAddress("Willisstrasse 3") 40 | ->setZip(3000) 41 | ->setTown("Bern") 42 | ->setCountry("CH") 43 | ->setTel("+41 99 999 99 99") 44 | ->setEmail("yippee-ki-yay-motherf_cker@nypd.us") 45 | ->setLocale("de_CH"); 46 | 47 | $order = new Order(); 48 | $order->setId(10) 49 | ->setAmount(30.35) 50 | ->setCurrency("CHF") 51 | ->setOrderText("example order"); 52 | 53 | // creates a Payment-object with all form information. 54 | $payment = $ePayment->createPayment($client, $order); 55 | 56 | // or directly print the form 57 | echo $payment->getForm()->getHtml("my form fields...", ""); 58 | ``` 59 | 60 | ## Passing own parameters 61 | 62 | optionally, you can pass more payment parameters to the `createPayment` method. 63 | 64 | ```php 65 | $payment = $ePayment->createPayment($client, $order, [ 66 | // Adding ALIAS Parameter for recurring payments 67 | Parameter::ALIAS => sprintf('RECURRING_%s_CLIENT_%s', $order->getId(), $client->getId()), 68 | Parameter::ALIASUSAGE => 'Recurring Invoice for Domain example.com' 69 | ]); 70 | ``` 71 | 72 | * [back to index](index.md) 73 | * [transaction feedback](response.md) 74 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Form/Form.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | final class Form 18 | { 19 | const METHOD_POST = 'post'; 20 | const METHOD_GET = 'get'; 21 | 22 | /** 23 | * @var string 24 | */ 25 | protected $method; 26 | 27 | /** 28 | * @var string 29 | */ 30 | protected $action; 31 | 32 | /** 33 | * @var array 34 | */ 35 | protected $hiddenFields = array(); 36 | 37 | /** 38 | * @param string $method 39 | * 40 | * @return Form 41 | */ 42 | public function setMethod($method) 43 | { 44 | $this->method = $method; 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getMethod() 53 | { 54 | return $this->method; 55 | } 56 | 57 | /** 58 | * @param string $action 59 | * 60 | * @return Form 61 | */ 62 | public function setAction($action) 63 | { 64 | $this->action = $action; 65 | 66 | return $this; 67 | } 68 | 69 | /** 70 | * @return string 71 | */ 72 | public function getAction() 73 | { 74 | return $this->action; 75 | } 76 | 77 | /** 78 | * @param array $hiddenFields 79 | * 80 | * @return Form 81 | */ 82 | public function setHiddenFields($hiddenFields) 83 | { 84 | $this->hiddenFields = $hiddenFields; 85 | 86 | return $this; 87 | } 88 | 89 | /** 90 | * @return array 91 | */ 92 | public function getHiddenFields() 93 | { 94 | return $this->hiddenFields; 95 | } 96 | 97 | /** 98 | * @return string 99 | */ 100 | public function getHtml($inner = '', $submit = null) 101 | { 102 | $result = array( 103 | sprintf('
', $this->getAction(), $this->getMethod()), 104 | $inner, 105 | $submit === null ? '' : $submit, 106 | ); 107 | 108 | foreach ($this->getHiddenFields() as $key => $value) { 109 | $result[] = sprintf('', $key, $value); 110 | } 111 | $result[] = '
'; 112 | 113 | return implode(PHP_EOL, $result); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Bag/ParameterBag.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class ParameterBag implements \Countable, \IteratorAggregate 20 | { 21 | /** 22 | * @var array 23 | */ 24 | protected $parameters; 25 | 26 | /** 27 | * @param array $parameters 28 | */ 29 | public function __construct(array $parameters = array()) 30 | { 31 | $this->parameters = $parameters; 32 | } 33 | 34 | /** 35 | * @param string|int|float $key 36 | * 37 | * @return bool 38 | */ 39 | public function has($key) 40 | { 41 | return array_key_exists($key, $this->parameters); 42 | } 43 | 44 | /** 45 | * @param string|int|float $key 46 | * @param mixed $value 47 | * @param bool $addEmpty add empty value parameters? 48 | * 49 | * @return $this 50 | */ 51 | public function add($key, $value, $addEmpty = false) 52 | { 53 | if (!$addEmpty 54 | && empty($value)) { 55 | return $this; 56 | } 57 | 58 | $this->parameters[$key] = $value; 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * @param string|int|float $key 65 | * 66 | * @return mixed|null 67 | */ 68 | public function get($key) 69 | { 70 | if ($this->has($key)) { 71 | return $this->parameters[$key]; 72 | } 73 | 74 | return; 75 | } 76 | 77 | /** 78 | * @return array 79 | */ 80 | public function getAll() 81 | { 82 | return $this->parameters; 83 | } 84 | 85 | /** 86 | * @param string|int|float $key 87 | * 88 | * @return $this 89 | */ 90 | public function remove($key) 91 | { 92 | if ($this->has($key)) { 93 | unset($this->parameters[$key]); 94 | } 95 | 96 | return $this; 97 | } 98 | 99 | /** 100 | * @param mixed $value 101 | * 102 | * @return mixed 103 | */ 104 | public function contains($value) 105 | { 106 | return array_search($value, $this->parameters); 107 | } 108 | 109 | /** 110 | * {@inheritdoc} 111 | */ 112 | public function getIterator() 113 | { 114 | return new \ArrayIterator($this->parameters); 115 | } 116 | 117 | /** 118 | * {@inheritdoc} 119 | */ 120 | public function count() 121 | { 122 | return count($this->parameters); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Order/AbstractOrder.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | abstract class AbstractOrder implements OrderInterface 23 | { 24 | /** 25 | * @var string unique order id 26 | */ 27 | protected $id; 28 | 29 | /** 30 | * @var float amount 31 | */ 32 | protected $amount = 0; 33 | 34 | /** 35 | * @var string currency 36 | */ 37 | protected $currency = 'CHF'; 38 | 39 | /** 40 | * @var string short order description (f.ex «three telephone numbers») 41 | */ 42 | protected $orderText = null; 43 | 44 | /** 45 | * @param string $id 46 | * 47 | * @return AbstractOrder 48 | */ 49 | public function setId($id) 50 | { 51 | $this->id = $id; 52 | 53 | return $this; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function getId() 60 | { 61 | return $this->id; 62 | } 63 | 64 | /** 65 | * @param float $amount 66 | * 67 | * @return AbstractOrder 68 | */ 69 | public function setAmount($amount) 70 | { 71 | $this->amount = $amount; 72 | 73 | return $this; 74 | } 75 | 76 | /** 77 | * {@inheritdoc} 78 | */ 79 | public function getAmount() 80 | { 81 | return $this->amount; 82 | } 83 | 84 | /** 85 | * {@inheritdoc} 86 | */ 87 | public function getIntegerAmount() 88 | { 89 | return $this->amount * 100; 90 | } 91 | 92 | /** 93 | * @param string $currency 94 | * 95 | * @throws InvalidCurrencyException 96 | * 97 | * @return AbstractOrder 98 | */ 99 | public function setCurrency($currency) 100 | { 101 | $currency = strtoupper($currency); 102 | 103 | if (!in_array($currency, Environment::$ALLOWED_CURRENCIES)) { 104 | throw new InvalidCurrencyException($currency); 105 | } 106 | 107 | $this->currency = $currency; 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * {@inheritdoc} 114 | */ 115 | public function getCurrency() 116 | { 117 | return $this->currency; 118 | } 119 | 120 | /** 121 | * @param string $orderText 122 | * 123 | * @return AbstractOrder 124 | */ 125 | public function setOrderText($orderText) 126 | { 127 | $this->orderText = $orderText; 128 | 129 | return $this; 130 | } 131 | 132 | /** 133 | * {@inheritdoc} 134 | */ 135 | public function getOrderText() 136 | { 137 | return $this->orderText; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Model/PaymentStatus.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | final class PaymentStatus 20 | { 21 | const INCOMPLETE = 1; 22 | const DECLINED = 2; 23 | const SUCCESS = 5; 24 | 25 | /** 26 | * @var array 27 | */ 28 | public static $codes = array( 29 | 0 => 'Invalid or incomplete', 30 | 1 => 'Cancelled by customer', 31 | 2 => 'Authorisation declined', 32 | 33 | 4 => 'Order stored', 34 | 40 => 'Stored waiting external result', 35 | 41 => 'Waiting for client payment', 36 | 37 | 5 => 'Authorised', 38 | 50 => 'Authorized waiting external result', 39 | 51 => 'Authorisation waiting', 40 | 52 => 'Authorisation not known', 41 | 55 => 'Standby', 42 | 56 => 'OK with scheduled payments', 43 | 57 => 'Not OK with scheduled payments', 44 | 59 => 'Authorisation to be requested manually', 45 | 46 | 6 => 'Authorised and cancelled', 47 | 61 => 'Authorisation deletion waiting', 48 | 62 => 'Authorisation deletion uncertain', 49 | 63 => 'Authorisation deletion refused', 50 | 64 => 'Authorised and cancelled', 51 | 52 | 7 => 'Payment deleted', 53 | 71 => 'Payment deletion pending', 54 | 72 => 'Payment deletion uncertain', 55 | 73 => 'Payment deletion refused', 56 | 74 => 'Payment deleted', 57 | 75 => 'Deletion handled by merchant', 58 | 59 | 8 => 'Refund', 60 | 81 => 'Refund pending', 61 | 82 => 'Refund uncertain', 62 | 83 => 'Refund refused', 63 | 84 => 'Refund', 64 | 85 => 'Refund handled by merchant', 65 | 66 | 9 => 'Payment requested', 67 | 91 => 'Payment processing', 68 | 92 => 'Payment uncertain', 69 | 93 => 'Payment refused', 70 | 94 => 'Refund declined by the acquirer', 71 | 95 => 'Payment handled by merchant', 72 | 96 => 'Refund reversed', 73 | 99 => 'Being processed', 74 | ); 75 | 76 | public static function isSuccess($code) 77 | { 78 | if ($code == 5 79 | || $code == 9) { 80 | return true; 81 | } 82 | 83 | return false; 84 | } 85 | 86 | public static function isPartiallySuccess($code) 87 | { 88 | if (( 89 | $code >= 50 90 | && $code <= 59 91 | ) || ( 92 | $code == 99 93 | || $code == 91 94 | || $code == 92 95 | || $code == 4 96 | || $code == 40 97 | )) { 98 | return true; 99 | } 100 | 101 | return false; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Model/Parameter.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | final class Parameter 20 | { 21 | // PostFinance configuration 22 | const PSPID = 'PSPID'; 23 | const SIGNATURE = 'SHASIGN'; 24 | const SIGNATURE_DATE = 'SIGNDATE'; 25 | const MANDATE_ID = 'MANDATEID'; 26 | 27 | // Money 28 | const AMOUNT = 'AMOUNT'; 29 | const CURRENCY = 'CURRENCY'; 30 | 31 | // Order 32 | const ORDER_ID = 'ORDERID'; 33 | const ORDER_TEXT = 'COM'; 34 | const COMPLUS = 'COMPLUS'; 35 | const PARAMPLUS = 'PARAMPLUS'; 36 | 37 | // Client 38 | const LANGUAGE = 'LANGUAGE'; 39 | const CLIENT_ID = 'USERID'; 40 | const CLIENT_NAME = 'CN'; 41 | const CLIENT_EMAIL = 'EMAIL'; 42 | const CLIENT_ADDRESS = 'OWNERADDRESS'; 43 | const CLIENT_ZIP = 'OWNERZIP'; 44 | const CLIENT_TOWN = 'OWNERTOWN'; 45 | const CLIENT_COUNTRY = 'OWNERCTY'; 46 | const CLIENT_TEL = 'OWNERTELNO'; 47 | const IP_COUNTRY = 'IPCTY'; 48 | const IP = 'IP'; 49 | 50 | // URL's 51 | const HOME_URL = 'HOMEURL'; 52 | const CATALOG_URL = 'CATALOGURL'; 53 | const ACCEPT_URL = 'ACCEPTURL'; 54 | const DECLINE_URL = 'DECLINEURL'; 55 | const EXCEPTION_URL = 'EXCEPTIONURL'; 56 | const CANCEL_URL = 'CANCELURL'; 57 | 58 | // Design 59 | const TEMPLATE_URL = 'TP'; 60 | 61 | // Adress 62 | const AAV_CHECK = 'AAVCHECK'; 63 | const AAV_ADDRESS = 'AAVADDRESS'; 64 | const AAV_NAME = 'AAVNAME'; 65 | const AAV_ZIP = 'AAVZIP'; 66 | const AAV_MAIL = 'AAVMAIL'; 67 | const AAV_PHONE = 'AAVPHONE'; 68 | 69 | // Status 70 | const ACCEPTANCE = 'ACCEPTANCE'; 71 | const NC_ERROR = 'NCERROR'; 72 | const NC_ERROR_PLUS = 'NCERRORPLUS'; 73 | const NC_STATUS = 'NCSTATUS'; 74 | const STATUS = 'STATUS'; 75 | const ECI = 'ECI'; 76 | 77 | // Alias 78 | const ALIAS = 'ALIAS'; 79 | const ALIASOPERATION = 'ALIASOPERATION'; 80 | const ALIASPERSISTEDAFTERUSE = 'ALIASPERSISTEDAFTERUSE'; 81 | const ALIASUSAGE = 'ALIASUSAGE'; 82 | 83 | // Bank / Card 84 | const BIC = 'BIC'; 85 | const CARD_BIN = 'BIN'; 86 | const CARD_BRAND = 'BRAND'; 87 | const CARD_BRAND_SUB = 'BRANDSUB'; 88 | const CARD_COUNTRY = 'CCCTY'; 89 | const CARD_HOLDER = 'CN'; 90 | const CARD_NUMBER = 'CARDNO'; 91 | const CARD_VIRTUAL = 'VC'; 92 | const CVC_CHECK = 'CVCCHECK'; 93 | const DIGEST_CARD_NUMBER = 'DIGESTCARDNO'; 94 | const EXPIRATION_DATE = 'ED'; 95 | 96 | // eDCC 97 | const DCC_COMMPERCENTAGE = 'DCC_COMMPERCENTAGE'; 98 | const DCC_CONVAMOUNT = 'DCC_CONVAMOUNT'; 99 | const DCC_CONVCCY = 'DCC_CONVCCY'; 100 | const DCC_EXCHRATE = 'DCC_EXCHRATE'; 101 | const DCC_EXCHRATESOURCE = 'DCC_EXCHRATESOURCE'; 102 | const DCC_EXCHRATETS = 'DCC_EXCHRATETS'; 103 | const DCC_INDICATOR = 'DCC_INDICATOR'; 104 | const DCC_MARGINPERCENTAGE = 'DCC_MARGINPERCENTAGE'; 105 | const DCC_VALIDHOURS = 'DCC_VALIDHOURS'; 106 | const HTML_ANSWER = 'HTML_ANSWER'; 107 | 108 | // Direct Debit NL 109 | const SEQUENCE_TYPE = 'SEQUENCETYPE'; 110 | 111 | // Payment 112 | const PAYMENT_ID = 'PAYID'; 113 | const PAYMENT_ID_SUB = 'PAYIDSUB'; 114 | const PAYMENT_METHOD = 'PM'; 115 | const SCORING = 'SCORING'; 116 | const SCORING_CATEGORY = 'SCO_CATERY'; 117 | const TRANSACTION_DATE = 'TRXDATE'; 118 | 119 | // Subscription 120 | const SUBSCRIPTION_ID = 'SUBSCRIPTION_ID'; 121 | 122 | /** 123 | * @var array Post-Sale parameters used to create Signature 124 | */ 125 | public static $postSaleParameters = array( 126 | self::AAV_ADDRESS, 127 | self::AAV_CHECK, 128 | self::AAV_MAIL, 129 | self::AAV_NAME, 130 | self::AAV_PHONE, 131 | self::AAV_ZIP, 132 | self::ACCEPTANCE, 133 | self::ALIAS, 134 | self::ALIASOPERATION, 135 | self::ALIASPERSISTEDAFTERUSE, 136 | self::ALIASUSAGE, 137 | self::AMOUNT, 138 | self::BIC, 139 | self::CARD_BIN, 140 | self::CARD_BRAND, 141 | self::CARD_NUMBER, 142 | self::CARD_COUNTRY, 143 | self::CARD_HOLDER, 144 | self::COMPLUS, 145 | self::CURRENCY, 146 | self::CVC_CHECK, 147 | self::DCC_COMMPERCENTAGE, 148 | self::DCC_CONVAMOUNT, 149 | self::DCC_CONVCCY, 150 | self::DCC_EXCHRATE, 151 | self::DCC_EXCHRATESOURCE, 152 | self::DCC_EXCHRATETS, 153 | self::DCC_INDICATOR, 154 | self::DCC_MARGINPERCENTAGE, 155 | self::DCC_VALIDHOURS, 156 | self::DIGEST_CARD_NUMBER, 157 | self::ECI, 158 | self::EXPIRATION_DATE, 159 | self::IP, 160 | self::IP_COUNTRY, 161 | self::NC_ERROR, 162 | self::NC_ERROR_PLUS, 163 | self::ORDER_ID, 164 | self::PAYMENT_ID, 165 | self::PAYMENT_ID_SUB, 166 | self::PAYMENT_METHOD, 167 | self::SCORING_CATEGORY, 168 | self::SCORING, 169 | self::STATUS, 170 | self::CARD_BRAND_SUB, 171 | self::SUBSCRIPTION_ID, 172 | self::TRANSACTION_DATE, 173 | self::CARD_VIRTUAL, 174 | ); 175 | 176 | /** 177 | * @var array required Post-Sale parameters to create our Response-object 178 | */ 179 | public static $requiredPostSaleParameters = array( 180 | self::ORDER_ID, 181 | self::AMOUNT, 182 | self::CURRENCY, 183 | self::PAYMENT_METHOD, 184 | self::ACCEPTANCE, 185 | self::STATUS, 186 | self::CARD_NUMBER, 187 | self::PAYMENT_ID, 188 | self::NC_ERROR, 189 | self::CARD_BRAND, 190 | self::TRANSACTION_DATE, 191 | self::CARD_HOLDER, 192 | self::SIGNATURE, 193 | self::IP, 194 | ); 195 | } 196 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Client/AbstractClient.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | abstract class AbstractClient implements ClientInterface 23 | { 24 | const REGEXP_LANGUAGE = '/^([a-z]{2})_([A-Z]{2})$/'; 25 | 26 | /** 27 | * @var string unique id of the client 28 | */ 29 | protected $id = null; 30 | 31 | /** 32 | * @var string name of the client 33 | */ 34 | protected $name = null; 35 | 36 | /** 37 | * @var string email address of the client 38 | */ 39 | protected $email = null; 40 | 41 | /** 42 | * @var string address of the client 43 | */ 44 | protected $address = null; 45 | 46 | /** 47 | * @var string zip code of the client 48 | */ 49 | protected $zip = null; 50 | 51 | /** 52 | * @var string city of the client 53 | */ 54 | protected $town = null; 55 | 56 | /** 57 | * @var string phone number of the client 58 | */ 59 | protected $tel = null; 60 | 61 | /** 62 | * @var string ISO 3166 Alpha-2 acronym of the country 63 | */ 64 | protected $country = null; 65 | 66 | /** 67 | * @var string Locale of the user: ISO 639-1 (lowercase) underscore ISO 3166-1 (uppercase), ex. de_CH 68 | */ 69 | protected $locale = 'en_US'; 70 | 71 | /** 72 | * @param string $id 73 | * 74 | * @return AbstractClient 75 | */ 76 | public function setId($id) 77 | { 78 | $this->id = $id; 79 | 80 | return $this; 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | public function getId() 87 | { 88 | return $this->id; 89 | } 90 | 91 | /** 92 | * @param string $name 93 | * 94 | * @return AbstractClient 95 | */ 96 | public function setName($name) 97 | { 98 | $this->name = $name; 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * {@inheritdoc} 105 | */ 106 | public function getName() 107 | { 108 | return $this->name; 109 | } 110 | 111 | /** 112 | * @param $email 113 | * 114 | * @return $this 115 | * 116 | * @throws InvalidArgumentException 117 | */ 118 | public function setEmail($email) 119 | { 120 | if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) { 121 | throw new InvalidArgumentException('Invalid e-mail address specified'); 122 | } 123 | 124 | $this->email = strtolower($email); 125 | 126 | return $this; 127 | } 128 | 129 | /** 130 | * {@inheritdoc} 131 | */ 132 | public function getEmail() 133 | { 134 | return $this->email; 135 | } 136 | 137 | /** 138 | * @param string $address 139 | * 140 | * @return AbstractClient 141 | */ 142 | public function setAddress($address) 143 | { 144 | $this->address = $address; 145 | 146 | return $this; 147 | } 148 | 149 | /** 150 | * {@inheritdoc} 151 | */ 152 | public function getAddress() 153 | { 154 | return $this->address; 155 | } 156 | 157 | /** 158 | * @param string $zip 159 | * 160 | * @return AbstractClient 161 | */ 162 | public function setZip($zip) 163 | { 164 | $this->zip = $zip; 165 | 166 | return $this; 167 | } 168 | 169 | /** 170 | * {@inheritdoc} 171 | */ 172 | public function getZip() 173 | { 174 | return $this->zip; 175 | } 176 | 177 | /** 178 | * @param string $town 179 | * 180 | * @return AbstractClient 181 | */ 182 | public function setTown($town) 183 | { 184 | $this->town = $town; 185 | 186 | return $this; 187 | } 188 | 189 | /** 190 | * {@inheritdoc} 191 | */ 192 | public function getTown() 193 | { 194 | return $this->town; 195 | } 196 | 197 | /** 198 | * @param string $tel 199 | * 200 | * @return AbstractClient 201 | */ 202 | public function setTel($tel) 203 | { 204 | $this->tel = $tel; 205 | 206 | return $this; 207 | } 208 | 209 | /** 210 | * {@inheritdoc} 211 | */ 212 | public function getTel() 213 | { 214 | return $this->tel; 215 | } 216 | 217 | /** 218 | * @param $country 219 | * 220 | * @return $this 221 | * 222 | * @throws InvalidCountryException 223 | */ 224 | public function setCountry($country) 225 | { 226 | if (strlen($country) !== 2) { 227 | throw new InvalidCountryException($country); 228 | } 229 | 230 | $this->country = strtoupper($country); 231 | 232 | return $this; 233 | } 234 | 235 | /** 236 | * {@inheritdoc} 237 | */ 238 | public function getCountry() 239 | { 240 | return $this->country; 241 | } 242 | 243 | /** 244 | * @param $locale 245 | * 246 | * @return $this 247 | * 248 | * @throws \whatwedo\PostFinanceEPayment\Exception\InvalidArgumentException 249 | */ 250 | public function setLocale($locale) 251 | { 252 | if (!preg_match(self::REGEXP_LANGUAGE, $locale)) { 253 | throw new InvalidArgumentException(sprintf( 254 | 'Invalid language given (%s) - language code must match %s', 255 | $locale, 256 | self::REGEXP_LANGUAGE 257 | )); 258 | } 259 | 260 | $this->locale = $locale; 261 | 262 | return $this; 263 | } 264 | 265 | /** 266 | * {@inheritdoc} 267 | */ 268 | public function getLocale() 269 | { 270 | return $this->locale; 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Payment/Payment.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | class Payment 27 | { 28 | /** 29 | * @var ParameterBag Payment parameters 30 | */ 31 | protected $parameters; 32 | 33 | /** 34 | * @var ClientInterface|null 35 | */ 36 | protected $client = null; 37 | 38 | /** 39 | * @var OrderInterface|null 40 | */ 41 | protected $order = null; 42 | 43 | /** 44 | * @var Environment 45 | */ 46 | protected $environment; 47 | 48 | /** 49 | * @param ClientInterface $client 50 | * @param OrderInterface $order 51 | * @param ParameterBag $parameterBag 52 | * @param Environment $environment 53 | */ 54 | public function __construct( 55 | ClientInterface &$client, 56 | OrderInterface &$order, 57 | ParameterBag $parameterBag, 58 | Environment &$environment 59 | ) { 60 | $this->parameters = $parameterBag; 61 | $this->client = $client; 62 | $this->order = $order; 63 | $this->environment = $environment; 64 | 65 | $this->buildParameters(); 66 | } 67 | 68 | protected function buildParameters() 69 | { 70 | // PostFinance configuration 71 | $this->parameters->add(Parameter::PSPID, $this->environment->getPSPID()); 72 | 73 | // payment 74 | $this->parameters->add(Parameter::AMOUNT, $this->order->getIntegerAmount()); 75 | $this->parameters->add(Parameter::CURRENCY, $this->order->getCurrency()); 76 | 77 | // order 78 | $this->parameters->add(Parameter::ORDER_ID, $this->order->getId()); 79 | $this->parameters->add(Parameter::ORDER_TEXT, $this->order->getOrderText()); 80 | 81 | // client information for fraud prevention and appearance 82 | $this->parameters->add(Parameter::LANGUAGE, $this->client->getLocale()); 83 | $this->parameters->add(Parameter::CLIENT_NAME, $this->client->getName()); 84 | $this->parameters->add(Parameter::CLIENT_ADDRESS, $this->client->getAddress()); 85 | $this->parameters->add(Parameter::CLIENT_ZIP, $this->client->getZip()); 86 | $this->parameters->add(Parameter::CLIENT_TOWN, $this->client->getTown()); 87 | $this->parameters->add(Parameter::CLIENT_TEL, $this->client->getTel()); 88 | $this->parameters->add(Parameter::CLIENT_COUNTRY, $this->client->getCountry()); 89 | $this->parameters->add(Parameter::CLIENT_NAME, $this->client->getName()); 90 | $this->parameters->add(Parameter::CLIENT_EMAIL, $this->client->getEmail()); 91 | 92 | // URL's 93 | $this->parameters->add(Parameter::HOME_URL, $this->environment->getHomeUrl()); 94 | $this->parameters->add(Parameter::CATALOG_URL, $this->environment->getCatalogUrl()); 95 | $this->parameters->add(Parameter::ACCEPT_URL, $this->environment->getAcceptUrl()); 96 | $this->parameters->add(Parameter::DECLINE_URL, $this->environment->getDeclineUrl()); 97 | $this->parameters->add(Parameter::EXCEPTION_URL, $this->environment->getExceptionUrl()); 98 | $this->parameters->add(Parameter::CANCEL_URL, $this->environment->getCancelUrl()); 99 | 100 | // Design 101 | $this->parameters->add(Parameter::TEMPLATE_URL, $this->environment->getTemplateUrl()); 102 | } 103 | 104 | /** 105 | * adds sha signature to the parameters. 106 | * 107 | * @return $this 108 | */ 109 | protected function addSignature() 110 | { 111 | $parameters = $this->parameters->getAll(); 112 | ksort($parameters); 113 | $string = ''; 114 | 115 | foreach ($parameters as $key => $value) { 116 | $string .= sprintf('%s=%s%s', $key, $value, $this->environment->getShaIn()); 117 | } 118 | 119 | $this->parameters->add(Parameter::SIGNATURE, strtoupper(hash($this->environment->getHashAlgorithm(), $string))); 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * finalizes the parameters. 126 | * 127 | * @return $this 128 | */ 129 | private function finalizeParameters() 130 | { 131 | if (!$this->parameters->has(Parameter::SIGNATURE)) { 132 | $this->addSignature(); // adds the hashed signature 133 | } 134 | 135 | return $this; 136 | } 137 | 138 | /** 139 | * gets all form data for the checkout process. 140 | * 141 | * @return Form 142 | */ 143 | public function getForm() 144 | { 145 | $this->finalizeParameters(); 146 | 147 | $form = new Form(); 148 | $form->setAction($this->environment->getGatewayUrl()); 149 | $form->setMethod(Form::METHOD_POST); 150 | $form->setHiddenFields($this->parameters->getAll()); 151 | 152 | return $form; 153 | } 154 | 155 | /** 156 | * returns an URL for a GET request to the payment process. 157 | * 158 | * @return string 159 | */ 160 | public function getUrl() 161 | { 162 | $this->finalizeParameters(); 163 | 164 | return sprintf('%s?%s', 165 | $this->environment->getGatewayUrl(), 166 | http_build_query($this->parameters->getAll()) 167 | ); 168 | } 169 | 170 | /** 171 | * @return ParameterBag 172 | */ 173 | public function getParameters() 174 | { 175 | return $this->parameters; 176 | } 177 | 178 | /** 179 | * @return ClientInterface 180 | */ 181 | public function getClient() 182 | { 183 | return $this->client; 184 | } 185 | 186 | /** 187 | * @return OrderInterface 188 | */ 189 | public function getOrder() 190 | { 191 | return $this->order; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /tests/whatwedo/PostFinanceEPayment/Tests/PostFinanceEPaymentTest.php: -------------------------------------------------------------------------------- 1 | 30 | */ 31 | class PostFinanceEPaymentTest extends \PHPUnit\Framework\TestCase 32 | { 33 | /** 34 | * @var Environment 35 | */ 36 | protected $environment; 37 | 38 | /** 39 | * @var Generator 40 | */ 41 | protected $faker; 42 | 43 | protected function setUp() 44 | { 45 | $this->environment = new TestEnvironment( 46 | 'phpunitTEST', 47 | 'ABCD*_/1234', 48 | 'ABCD*_/1234' 49 | ); 50 | 51 | $this->faker = Factory::create(); 52 | } 53 | 54 | public function testFormBuilder() 55 | { 56 | $payment = $this->getRandomPayment(); 57 | $order = $payment->getOrder(); 58 | $client = $payment->getClient(); 59 | 60 | $form = $payment->getForm(); 61 | 62 | $this->assertEquals($this->environment->getGatewayUrl(), $form->getAction()); 63 | $this->assertEquals('post', $form->getMethod()); 64 | 65 | $fields = $form->getHiddenFields(); 66 | 67 | $this->assertEquals($fields[Parameter::PSPID], $this->environment->getPSPID()); 68 | 69 | $this->assertEquals($fields[Parameter::ORDER_ID], $order->getId()); 70 | $this->assertEquals($fields[Parameter::AMOUNT], $order->getIntegerAmount()); 71 | $this->assertEquals($fields[Parameter::CURRENCY], $order->getCurrency()); 72 | $this->assertEquals($fields[Parameter::ORDER_TEXT], $order->getOrderText()); 73 | 74 | $this->assertEquals($fields[Parameter::LANGUAGE], $client->getLocale()); 75 | $this->assertEquals($fields[Parameter::CARD_HOLDER], $client->getName()); 76 | $this->assertEquals($fields[Parameter::CLIENT_ADDRESS], $client->getAddress()); 77 | $this->assertEquals($fields[Parameter::CLIENT_ZIP], $client->getZip()); 78 | $this->assertEquals($fields[Parameter::CLIENT_TOWN], $client->getTown()); 79 | $this->assertEquals($fields[Parameter::CLIENT_TEL], $client->getTel()); 80 | $this->assertEquals($fields[Parameter::CLIENT_COUNTRY], $client->getCountry()); 81 | $this->assertEquals($fields[Parameter::CLIENT_EMAIL], $client->getEmail()); 82 | } 83 | 84 | public function testSignature() 85 | { 86 | foreach (Environment::$ALLOWED_HASHES as $hash) { 87 | $this->environment->setHashAlgorithm($hash); 88 | 89 | $payment = $this->getRandomPayment(); 90 | $parameters = $payment->getParameters()->getAll(); 91 | 92 | $fields = $payment->getForm()->getHiddenFields(); 93 | 94 | $hash = $this->createHash( 95 | $parameters, 96 | $this->environment->getShaIn(), 97 | $this->environment->getHashAlgorithm() 98 | ); 99 | 100 | $this->assertEquals($fields[Parameter::SIGNATURE], $hash); 101 | 102 | // if getForm() is triggered twice, the signature should be the same 103 | // @see https://github.com/whatwedo/PostFinanceEPayment/pull/6 104 | $fields = $payment->getForm()->getHiddenFields(); 105 | $this->assertEquals($fields[Parameter::SIGNATURE], $hash); 106 | } 107 | } 108 | 109 | public function testResponse() 110 | { 111 | foreach (array(PaymentStatus::SUCCESS, PaymentStatus::DECLINED, PaymentStatus::INCOMPLETE) as $status) { 112 | $response = array( 113 | 'orderID' => $this->faker->randomNumber(4), 114 | 'currency' => 'CHF', 115 | 'amount' => $this->faker->randomFloat(2, 1, 100), 116 | 'PM' => $this->faker->randomElement(array( 117 | PaymentMethod::POSTFINANCE_EFINANCE, 118 | PaymentMethod::CREDITCARD, 119 | PaymentMethod::POSTFINANCE_CARD, 120 | )), 121 | 'ACCEPTANCE' => 'test123', 122 | 'STATUS' => $status, 123 | 'CARDNO' => 'XXXXXXXXXXXX'.$this->faker->randomNumber(4), 124 | 'ED' => $this->faker->numberBetween(10, 12).$this->faker->numberBetween(10, 99), 125 | 'CN' => $this->faker->name, 126 | 'TRXDATE' => $this->faker->date('m/d/Y'), 127 | 'PAYID' => $this->faker->randomNumber(8), 128 | 'IPCTY' => $this->faker->countryCode, 129 | 'CCCTY' => $this->faker->countryCode, 130 | 'ECI' => '5', 131 | 'CVCCheck' => 'NO', 132 | 'AAVCheck' => 'NO', 133 | 'VC' => 'NO', 134 | 'IP' => $this->faker->ipv4, 135 | 'NCERROR' => '0', 136 | ); 137 | 138 | if ($response['PM'] === PaymentMethod::CREDITCARD) { 139 | $response['BRAND'] = $this->faker->randomElement(array( 140 | Brand::MASTERCARD, 141 | Brand::VISA, 142 | )); 143 | } elseif ($response['PM'] === PaymentMethod::POSTFINANCE_CARD) { 144 | $response['BRAND'] = PaymentMethod::POSTFINANCE_CARD; 145 | } elseif ($response['PM'] === PaymentMethod::POSTFINANCE_EFINANCE) { 146 | $response['BRAND'] = PaymentMethod::POSTFINANCE_EFINANCE; 147 | } 148 | 149 | $response['SHASIGN'] = $this->createHash( 150 | $response, 151 | $this->environment->getShaOut(), 152 | $this->environment->getHashAlgorithm() 153 | ); 154 | 155 | $ePayment = new PostFinanceEPayment($this->environment); 156 | $response = $ePayment->getResponse($response); 157 | 158 | $this->assertTrue($response instanceof Response); 159 | 160 | if ($status === PaymentStatus::SUCCESS) { 161 | $this->assertFalse($response->hasError()); 162 | } else { 163 | $this->assertTrue($response->hasError()); 164 | } 165 | } 166 | } 167 | 168 | /** 169 | * @param $parameters 170 | * @param $secret 171 | * @param $algorithm 172 | * 173 | * @return string 174 | */ 175 | protected function createHash($parameters, $secret, $algorithm) 176 | { 177 | $parameters = array_change_key_case($parameters, CASE_UPPER); 178 | ksort($parameters); 179 | $string = ''; 180 | 181 | foreach ($parameters as $key => $value) { 182 | $string .= sprintf('%s=%s%s', $key, $value, $secret); 183 | } 184 | 185 | //echo $string; 186 | 187 | return strtoupper(hash($algorithm, $string)); 188 | } 189 | 190 | /** 191 | * @return Payment 192 | */ 193 | public function getRandomPayment() 194 | { 195 | $ePayment = new PostFinanceEPayment($this->environment); 196 | 197 | $client = $this->getRandomClient(); 198 | $order = $this->getRandomOrder(); 199 | 200 | return $ePayment->createPayment($client, $order); 201 | } 202 | 203 | /** 204 | * @return Client 205 | */ 206 | protected function getRandomClient() 207 | { 208 | $client = new Client(); 209 | $client->setId($this->faker->numerify('####')) 210 | ->setName($this->faker->name) 211 | ->setAddress(sprintf('%s %s', $this->faker->streetName, $this->faker->numerify('##'))) 212 | ->setZip($this->faker->postcode) 213 | ->setTown($this->faker->city) 214 | ->setCountry('CH') 215 | ->setTel($this->faker->phoneNumber) 216 | ->setEmail($this->faker->email) 217 | ->setLocale($this->faker->randomElement(array( 218 | 'de_DE', 219 | 'de_CH', 220 | 'fr_FR', 221 | 'it_IT', 222 | ))); 223 | 224 | return $client; 225 | } 226 | 227 | /** 228 | * @return Order 229 | */ 230 | protected function getRandomOrder() 231 | { 232 | $order = new Order(); 233 | $order->setId($this->faker->numerify('####')) 234 | ->setAmount($this->faker->randomFloat(2, 1, 100)) 235 | ->setCurrency('CHF') 236 | ->setOrderText($this->faker->sentence(4)); 237 | 238 | return $order; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Environment/Environment.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | abstract class Environment implements EnvironmentInterface 22 | { 23 | const HASH_SHA1 = 'sha1'; 24 | const HASH_SHA256 = 'sha256'; 25 | const HASH_SHA512 = 'sha512'; 26 | 27 | const CHARSET_ISO_8859_1 = 'iso_8859-1'; 28 | const CHARSET_UTF_8 = 'utf-8'; 29 | 30 | /** 31 | * @var string|null 32 | */ 33 | protected $pspid = null; 34 | 35 | /** 36 | * @var string hashing method 37 | */ 38 | protected $hashAlgorithm = self::HASH_SHA1; 39 | 40 | /** 41 | * @var string|null 42 | */ 43 | protected $shaIn = null; 44 | 45 | /** 46 | * @var string|null 47 | */ 48 | protected $shaOut = null; 49 | 50 | /** 51 | * @var string client charset 52 | */ 53 | protected static $CHARSET = self::CHARSET_ISO_8859_1; 54 | 55 | /** 56 | * @var string|null 57 | */ 58 | protected $homeUrl = null; 59 | 60 | /** 61 | * @var string|null 62 | */ 63 | protected $catalogUrl = null; 64 | 65 | /** 66 | * @var string|null 67 | */ 68 | protected $acceptUrl = null; 69 | 70 | /** 71 | * @var string|null 72 | */ 73 | protected $declineUrl = null; 74 | 75 | /** 76 | * @var string|null 77 | */ 78 | protected $exceptionUrl = null; 79 | 80 | /** 81 | * @var string|null 82 | */ 83 | protected $cancelUrl = null; 84 | 85 | /** 86 | * @var string|null 87 | */ 88 | protected $templateUrl = null; 89 | 90 | /** 91 | * @var array allowed currencies based on PostFinance E-Payment 92 | */ 93 | public static $ALLOWED_CURRENCIES = array( 94 | 'AED', 95 | 'ANG', 96 | 'ARS', 97 | 'AUD', 98 | 'AWG', 99 | 'BGN', 100 | 'BRL', 101 | 'BYR', 102 | 'CAD', 103 | 'CHF', 104 | 'CNY', 105 | 'CZK', 106 | 'DKK', 107 | 'EEK', 108 | 'EGP', 109 | 'EUR', 110 | 'GBP', 111 | 'GEL', 112 | 'HKD', 113 | 'HRK', 114 | 'HUF', 115 | 'ILS', 116 | 'ISK', 117 | 'JPY', 118 | 'KRW', 119 | 'LTL', 120 | 'LVL', 121 | 'MAD', 122 | 'MXN', 123 | 'NOK', 124 | 'NZD', 125 | 'PLN', 126 | 'RON', 127 | 'RUB', 128 | 'SEK', 129 | 'SGD', 130 | 'SKK', 131 | 'THB', 132 | 'TRY', 133 | 'UAH', 134 | 'USD', 135 | 'XAF', 136 | 'XOF', 137 | 'XPF', 138 | 'ZAR', 139 | ); 140 | 141 | /** 142 | * @var array allowed hashs for sha-in and sha-out 143 | */ 144 | public static $ALLOWED_HASHES = array( 145 | self::HASH_SHA1, 146 | self::HASH_SHA256, 147 | self::HASH_SHA512, 148 | ); 149 | 150 | /** 151 | * @var array allowed charsets 152 | */ 153 | public static $ALLOWED_CHARSETS = array( 154 | self::CHARSET_ISO_8859_1, 155 | self::CHARSET_UTF_8, 156 | ); 157 | 158 | public function __construct($pspid, $shaIn, $shaOut) 159 | { 160 | $this->setPSPID($pspid); 161 | $this->setShaIn($shaIn); 162 | $this->setShaOut($shaOut); 163 | } 164 | 165 | /** 166 | * {@inheritdoc} 167 | */ 168 | public static function getGatewayUrl() 169 | { 170 | switch (static::$CHARSET) { 171 | case static::CHARSET_UTF_8: 172 | return static::BASE_URL.'/orderstandard_utf8.asp'; 173 | 174 | default: 175 | return static::BASE_URL.'/orderstandard.asp'; 176 | } 177 | } 178 | 179 | /** 180 | * {@inheritdoc} 181 | */ 182 | public static function getDirectLinkMaintenanceUrl() 183 | { 184 | return static::BASE_URL.'/maintenancedirect.asp'; 185 | } 186 | 187 | /** 188 | * @param string $pspid 189 | * 190 | * @return Environment 191 | */ 192 | public function setPSPID($pspid) 193 | { 194 | $this->pspid = $pspid; 195 | 196 | return $this; 197 | } 198 | 199 | /** 200 | * @return mixed 201 | */ 202 | public function getPSPID() 203 | { 204 | return $this->pspid; 205 | } 206 | 207 | /** 208 | * @param null $shaIn 209 | * 210 | * @return Environment 211 | */ 212 | public function setShaIn($shaIn) 213 | { 214 | $this->shaIn = $shaIn; 215 | 216 | return $this; 217 | } 218 | 219 | /** 220 | * @return null|string 221 | */ 222 | public function getShaIn() 223 | { 224 | return $this->shaIn; 225 | } 226 | 227 | /** 228 | * @param null $shaOut 229 | * 230 | * @return Environment 231 | */ 232 | public function setShaOut($shaOut) 233 | { 234 | $this->shaOut = $shaOut; 235 | 236 | return $this; 237 | } 238 | 239 | /** 240 | * @return null|string 241 | */ 242 | public function getShaOut() 243 | { 244 | return $this->shaOut; 245 | } 246 | 247 | /** 248 | * Set charset. 249 | * 250 | * @param string $charset 251 | */ 252 | public function setCharset($charset) 253 | { 254 | if (!in_array($charset, self::$ALLOWED_CHARSETS)) { 255 | throw new InvalidArgumentException(sprintf( 256 | 'Invalid charset specified (%s), allowed: %s', 257 | $charset, 258 | implode(', ', self::ALLOWED_CHARSETS) 259 | )); 260 | } 261 | self::$CHARSET = $charset; 262 | 263 | return $this; 264 | } 265 | 266 | /** 267 | * Get charset. 268 | * 269 | * @return string 270 | */ 271 | public function getCharset() 272 | { 273 | return self::$CHARSET; 274 | } 275 | 276 | /** 277 | * @param null|string $homeUrl 278 | * 279 | * @return Environment 280 | */ 281 | public function setHomeUrl($homeUrl) 282 | { 283 | $this->homeUrl = $homeUrl; 284 | 285 | return $this; 286 | } 287 | 288 | /** 289 | * @return null|string 290 | */ 291 | public function getHomeUrl() 292 | { 293 | return $this->homeUrl; 294 | } 295 | 296 | /** 297 | * @param null|string $acceptUrl 298 | * 299 | * @return Environment 300 | */ 301 | public function setAcceptUrl($acceptUrl) 302 | { 303 | $this->acceptUrl = $acceptUrl; 304 | 305 | return $this; 306 | } 307 | 308 | /** 309 | * @return null|string 310 | */ 311 | public function getAcceptUrl() 312 | { 313 | return $this->acceptUrl; 314 | } 315 | 316 | /** 317 | * @param null|string $cancelUrl 318 | * 319 | * @return Environment 320 | */ 321 | public function setCancelUrl($cancelUrl) 322 | { 323 | $this->cancelUrl = $cancelUrl; 324 | 325 | return $this; 326 | } 327 | 328 | /** 329 | * @return null|string 330 | */ 331 | public function getCancelUrl() 332 | { 333 | return $this->cancelUrl; 334 | } 335 | 336 | /** 337 | * @param null|string $catalogUrl 338 | * 339 | * @return Environment 340 | */ 341 | public function setCatalogUrl($catalogUrl) 342 | { 343 | $this->catalogUrl = $catalogUrl; 344 | 345 | return $this; 346 | } 347 | 348 | /** 349 | * @return null|string 350 | */ 351 | public function getCatalogUrl() 352 | { 353 | return $this->catalogUrl; 354 | } 355 | 356 | /** 357 | * @param null|string $declineUrl 358 | * 359 | * @return Environment 360 | */ 361 | public function setDeclineUrl($declineUrl) 362 | { 363 | $this->declineUrl = $declineUrl; 364 | 365 | return $this; 366 | } 367 | 368 | /** 369 | * @return null|string 370 | */ 371 | public function getDeclineUrl() 372 | { 373 | return $this->declineUrl; 374 | } 375 | 376 | /** 377 | * @param null|string $exceptionUrl 378 | * 379 | * @return Environment 380 | */ 381 | public function setExceptionUrl($exceptionUrl) 382 | { 383 | $this->exceptionUrl = $exceptionUrl; 384 | 385 | return $this; 386 | } 387 | 388 | /** 389 | * @return null|string 390 | */ 391 | public function getExceptionUrl() 392 | { 393 | return $this->exceptionUrl; 394 | } 395 | 396 | /** 397 | * @param null|string $templateUrl 398 | * 399 | * @return Environment 400 | */ 401 | public function setTemplateUrl($templateUrl) 402 | { 403 | $this->templateUrl = $templateUrl; 404 | 405 | return $this; 406 | } 407 | 408 | /** 409 | * @return null|string 410 | */ 411 | public function getTemplateUrl() 412 | { 413 | return $this->templateUrl; 414 | } 415 | 416 | /** 417 | * @param $hash 418 | * 419 | * @return $this 420 | * 421 | * @throws InvalidArgumentException 422 | */ 423 | public function setHashAlgorithm($hash) 424 | { 425 | if (!in_array($hash, self::$ALLOWED_HASHES)) { 426 | throw new InvalidArgumentException(sprintf( 427 | 'Invalid hash method specified (%s), allowed: %s', 428 | $hash, 429 | implode(', ', self::$ALLOWED_HASHES) 430 | )); 431 | } 432 | 433 | $this->hashAlgorithm = $hash; 434 | 435 | return $this; 436 | } 437 | 438 | /** 439 | * @return string 440 | */ 441 | public function getHashAlgorithm() 442 | { 443 | return $this->hashAlgorithm; 444 | } 445 | } 446 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Response/Response.php: -------------------------------------------------------------------------------- 1 | 28 | */ 29 | class Response 30 | { 31 | /** 32 | * @var string 33 | */ 34 | protected $orderId; 35 | 36 | /** 37 | * @var float 38 | */ 39 | protected $amount; 40 | 41 | /** 42 | * @var string 43 | */ 44 | protected $currency; 45 | 46 | /** 47 | * @var string 48 | */ 49 | protected $paymentMethod; 50 | 51 | /** 52 | * @var string 53 | */ 54 | protected $acceptance; 55 | 56 | /** 57 | * @var int 58 | */ 59 | protected $status; 60 | 61 | /** 62 | * @var string 63 | */ 64 | protected $cardNumber; 65 | 66 | /** 67 | * @var string 68 | */ 69 | protected $paymentId; 70 | 71 | /** 72 | * @var string 73 | */ 74 | protected $error; 75 | 76 | /** 77 | * @var string 78 | */ 79 | protected $ip; 80 | 81 | /** 82 | * @var string 83 | */ 84 | protected $brand; 85 | 86 | /** 87 | * @var string 88 | */ 89 | protected $cardExpirationDate; 90 | 91 | /** 92 | * @var DateTime 93 | */ 94 | protected $transactionDate; 95 | 96 | /** 97 | * @var string 98 | */ 99 | protected $cardHolderName; 100 | 101 | /** 102 | * @var string 103 | */ 104 | protected $alias; 105 | 106 | /** 107 | * @param $parameters 108 | * @param Environment $environment 109 | * @param bool $skipSignature skip signature check true / false 110 | * 111 | * @return Response 112 | * 113 | * @throws InvalidArgumentException 114 | * @throws NotValidSignatureException 115 | */ 116 | public static function create($parameters, Environment $environment, $skipSignature = false) 117 | { 118 | $response = new self(); 119 | 120 | $parameters = array_change_key_case($parameters, CASE_UPPER); 121 | 122 | $missing = array_diff(Parameter::$requiredPostSaleParameters, array_keys($parameters)); 123 | 124 | if (count($missing) > 0) { 125 | throw new InvalidArgumentException(sprintf( 126 | 'Missing parameter(s) %s of PostFinance post-sale response', 127 | implode(', ', $missing) 128 | )); 129 | } 130 | 131 | if (!$skipSignature) { 132 | $string = ''; 133 | $p = Parameter::$postSaleParameters; 134 | sort($p); 135 | foreach ($p as $key) { 136 | if ($key === Parameter::SIGNATURE 137 | || !isset($parameters[$key]) 138 | || $parameters[$key] === '') { 139 | continue; 140 | } 141 | 142 | $string .= sprintf('%s=%s%s', $key, $parameters[$key], $environment->getShaOut()); 143 | } 144 | 145 | if (strtoupper(hash($environment->getHashAlgorithm(), $string)) !== $parameters[Parameter::SIGNATURE]) { 146 | throw new NotValidSignatureException(); 147 | } 148 | } 149 | 150 | $response->setOrderId($parameters[Parameter::ORDER_ID]) 151 | ->setAmount($parameters[Parameter::AMOUNT]) 152 | ->setCurrency($parameters[Parameter::CURRENCY]) 153 | ->setAcceptance($parameters[Parameter::ACCEPTANCE]) 154 | ->setStatus($parameters[Parameter::STATUS]) 155 | ->setCardNumber($parameters[Parameter::CARD_NUMBER]) 156 | ->setPaymentId($parameters[Parameter::PAYMENT_ID]) 157 | ->setError($parameters[Parameter::NC_ERROR]) 158 | ->setCardExpirationDate($parameters[Parameter::EXPIRATION_DATE]) 159 | ->setTransactionDate(\DateTime::createFromFormat('m/d/Y', $parameters[Parameter::TRANSACTION_DATE])) 160 | ->setCardHolderName($parameters[Parameter::CARD_HOLDER]) 161 | ->setIp($parameters[Parameter::IP]); 162 | 163 | if (isset($parameters[Parameter::ALIAS]) 164 | && !empty($parameters[Parameter::ALIAS])) { 165 | $response->setAlias($parameters[Parameter::ALIAS]); 166 | } 167 | 168 | switch ($parameters['PM']) { 169 | case 'CreditCard': 170 | $response->setPaymentMethod(PaymentMethod::CREDITCARD); 171 | switch ($parameters['BRAND']) { 172 | case 'MasterCard': 173 | $response->setBrand(Brand::MASTERCARD); 174 | break; 175 | case 'Visa': 176 | $response->setBrand(Brand::VISA); 177 | break; 178 | } 179 | break; 180 | case 'PostFinance e-finance': 181 | $response->setPaymentMethod(PaymentMethod::POSTFINANCE_EFINANCE); 182 | $response->setBrand(Brand::POSTFINANCE_EFINANCE); 183 | break; 184 | case 'PostFinance Card': 185 | $response->setPaymentMethod(PaymentMethod::POSTFINANCE_CARD); 186 | $response->setBrand(Brand::POSTFINANCE_CARD); 187 | break; 188 | } 189 | ; 190 | 191 | return $response; 192 | } 193 | 194 | /** 195 | * @param string $orderId 196 | * 197 | * @return Response 198 | */ 199 | public function setOrderId($orderId) 200 | { 201 | $this->orderId = $orderId; 202 | 203 | return $this; 204 | } 205 | 206 | /** 207 | * @return string 208 | */ 209 | public function getOrderId() 210 | { 211 | return $this->orderId; 212 | } 213 | 214 | /** 215 | * @param float $amount 216 | * 217 | * @return Response 218 | */ 219 | public function setAmount($amount) 220 | { 221 | $this->amount = $amount; 222 | 223 | return $this; 224 | } 225 | 226 | /** 227 | * @return float 228 | */ 229 | public function getAmount() 230 | { 231 | return $this->amount; 232 | } 233 | 234 | /** 235 | * @param string $currency 236 | * 237 | * @return Response 238 | */ 239 | public function setCurrency($currency) 240 | { 241 | $this->currency = $currency; 242 | 243 | return $this; 244 | } 245 | 246 | /** 247 | * @return string 248 | */ 249 | public function getCurrency() 250 | { 251 | return $this->currency; 252 | } 253 | 254 | /** 255 | * @param string $paymentMethod 256 | * 257 | * @return Response 258 | */ 259 | public function setPaymentMethod($paymentMethod) 260 | { 261 | $this->paymentMethod = $paymentMethod; 262 | 263 | return $this; 264 | } 265 | 266 | /** 267 | * @return string 268 | */ 269 | public function getPaymentMethod() 270 | { 271 | return $this->paymentMethod; 272 | } 273 | 274 | /** 275 | * @param string $acceptance 276 | * 277 | * @return Response 278 | */ 279 | public function setAcceptance($acceptance) 280 | { 281 | $this->acceptance = $acceptance; 282 | 283 | return $this; 284 | } 285 | 286 | /** 287 | * @return string 288 | */ 289 | public function getAcceptance() 290 | { 291 | return $this->acceptance; 292 | } 293 | 294 | /** 295 | * @param int $status 296 | * 297 | * @return Response 298 | */ 299 | public function setStatus($status) 300 | { 301 | $this->status = (int) $status; 302 | 303 | return $this; 304 | } 305 | 306 | /** 307 | * @return int 308 | */ 309 | public function getStatus() 310 | { 311 | return $this->status; 312 | } 313 | 314 | /** 315 | * @param string $cardNumber 316 | * 317 | * @return Response 318 | */ 319 | public function setCardNumber($cardNumber) 320 | { 321 | $this->cardNumber = $cardNumber; 322 | 323 | return $this; 324 | } 325 | 326 | /** 327 | * @return string 328 | */ 329 | public function getCardNumber() 330 | { 331 | return $this->cardNumber; 332 | } 333 | 334 | /** 335 | * @param string $cardExpirationDate 336 | * 337 | * @return Response 338 | */ 339 | public function setCardExpirationDate($cardExpirationDate) 340 | { 341 | $this->cardExpirationDate = $cardExpirationDate; 342 | 343 | return $this; 344 | } 345 | 346 | /** 347 | * @return string 348 | */ 349 | public function getCardExpirationDate() 350 | { 351 | return $this->cardExpirationDate; 352 | } 353 | 354 | /** 355 | * @param string $paymentId 356 | * 357 | * @return Response 358 | */ 359 | public function setPaymentId($paymentId) 360 | { 361 | $this->paymentId = $paymentId; 362 | 363 | return $this; 364 | } 365 | 366 | /** 367 | * @return string 368 | */ 369 | public function getPaymentId() 370 | { 371 | return $this->paymentId; 372 | } 373 | 374 | /** 375 | * @param string $error 376 | * 377 | * @return Response 378 | */ 379 | public function setError($error) 380 | { 381 | $this->error = $error; 382 | 383 | return $this; 384 | } 385 | 386 | /** 387 | * @return string|null 388 | */ 389 | public function getError() 390 | { 391 | if (!empty($this->error)) { 392 | if (isset(ErrorCode::$codes[$this->error])) { 393 | return sprintf('%s (%s)', ErrorCode::$codes[$this->error], $this->error); 394 | } else { 395 | return $this->error; 396 | } 397 | } elseif (!empty($this->status)) { 398 | if (isset(PaymentStatus::$codes[$this->status])) { 399 | return sprintf('%s (%s)', PaymentStatus::$codes[$this->status], $this->status); 400 | } else { 401 | return $this->status; 402 | } 403 | } 404 | 405 | return; 406 | } 407 | 408 | /** 409 | * @return bool 410 | */ 411 | public function isRetryError() 412 | { 413 | return ErrorCode::isRetryCode($this->error); 414 | } 415 | 416 | /** 417 | * @return bool 418 | */ 419 | public function hasError() 420 | { 421 | if (PaymentStatus::isSuccess($this->getStatus())) { 422 | return false; 423 | } 424 | 425 | return true; 426 | } 427 | 428 | /** 429 | * @param string $ip 430 | * 431 | * @return Response 432 | */ 433 | public function setIp($ip) 434 | { 435 | $this->ip = $ip; 436 | 437 | return $this; 438 | } 439 | 440 | /** 441 | * @return string 442 | */ 443 | public function getIp() 444 | { 445 | return $this->ip; 446 | } 447 | 448 | /** 449 | * @param string $brand 450 | * 451 | * @return Response 452 | */ 453 | public function setBrand($brand) 454 | { 455 | $this->brand = $brand; 456 | 457 | return $this; 458 | } 459 | 460 | /** 461 | * @return string 462 | */ 463 | public function getBrand() 464 | { 465 | return $this->brand; 466 | } 467 | 468 | /** 469 | * @param DateTime $transactionDate 470 | * 471 | * @return Response 472 | */ 473 | public function setTransactionDate($transactionDate) 474 | { 475 | $this->transactionDate = $transactionDate; 476 | 477 | return $this; 478 | } 479 | 480 | /** 481 | * @return DateTime 482 | */ 483 | public function getTransactionDate() 484 | { 485 | return $this->transactionDate; 486 | } 487 | 488 | /** 489 | * @param string $cardHolderName 490 | * 491 | * @return Response 492 | */ 493 | public function setCardHolderName($cardHolderName) 494 | { 495 | $this->cardHolderName = $cardHolderName; 496 | 497 | return $this; 498 | } 499 | 500 | /** 501 | * @return string 502 | */ 503 | public function getCardHolderName() 504 | { 505 | return $this->cardHolderName; 506 | } 507 | 508 | /** 509 | * @return string 510 | */ 511 | public function getAlias() 512 | { 513 | return $this->alias; 514 | } 515 | 516 | /** 517 | * @param string $alias 518 | * 519 | * @return Response 520 | */ 521 | public function setAlias($alias) 522 | { 523 | $this->alias = $alias; 524 | 525 | return $this; 526 | } 527 | } 528 | -------------------------------------------------------------------------------- /src/whatwedo/PostFinanceEPayment/Model/ErrorCode.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | final class ErrorCode 20 | { 21 | /** 22 | * @var array error codes and english translation 23 | */ 24 | public static $codes = array( 25 | '0020001001' => 'Authorisation failed. Please retry.', 26 | '0020001002' => 'Authorisation failed. Please retry.', 27 | '0020001003' => 'Authorisation failed. Please retry.', 28 | '0020001004' => 'Authorisation failed. Please retry.', 29 | '0020001005' => 'Authorisation failed. Please retry.', 30 | '0020001006' => 'Authorisation failed. Please retry.', 31 | '0020001007' => 'Authorisation failed. Please retry.', 32 | '0020001008' => 'Authorisation failed. Please retry.', 33 | '0020001009' => 'Authorisation failed. Please retry.', 34 | '0020001010' => 'Authorisation failed. Please retry.', 35 | '0030001999' => 'Our payment system is currently under maintenance, please try later.', 36 | '0050001005' => 'Expiry date error', 37 | '0050001007' => 'Requested operation code not permitted', 38 | '0050001008' => 'Invalid time limit value', 39 | '0050001010' => 'Invalid input date format', 40 | '0050001013' => 'Unable to parse socket input stream', 41 | '0050001014' => 'Error in parsing stream content', 42 | '0050001015' => 'Currency error', 43 | '0050001016' => 'Transaction still posted at end of wait', 44 | '0050001017' => 'Sync value not compatible with delay value', 45 | '0050001019' => 'Duplicate of a pre-existing transaction', 46 | '0050001020' => 'Acceptance code required for transaction', 47 | '0050001024' => 'Maintenance acquirer differs from original transaction acquirer', 48 | '0050001025' => 'Maintenance merchant differs from original transaction merchant', 49 | '0050001028' => 'Maintenance operation not appropriate for original transaction', 50 | '0050001031' => 'Host application unknown for the transaction', 51 | '0050001032' => 'Unable to perform requested operation with requested currency', 52 | '0050001033' => 'Maintenance card number differs from original transaction card number', 53 | '0050001034' => 'Operation code not permitted', 54 | '0050001035' => 'Exception occurred in socket input stream processing', 55 | '0050001036' => 'Card length does not correspond to an acceptable value for the brand', 56 | '0050001068' => 'A technical problem has occurred. Please contact the helpdesk.', 57 | '0050001069' => 'Invalid check for CardID and Brand', 58 | '0050001070' => 'A technical problem has occurred. Please contact the helpdesk.', 59 | '0050001116' => 'Unknown origin IP', 60 | '0050001117' => 'No origin IP detected', 61 | '0050001118' => 'Merchant configuration problem. Please contact support.', 62 | 10001001 => 'Communication failure', 63 | 10001002 => 'Communication failure', 64 | 10001003 => 'Communication failure', 65 | 10001004 => 'Communication failure', 66 | 10001005 => 'Communication failure', 67 | 10001016 => 'Waiting for acquirer feedback', 68 | 10001018 => '3XCB pending transaction awaiting for Final status', 69 | 10001101 => 'You must connect in secure mode (https)', 70 | 20001001 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 71 | 20001002 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the status of the transaction within one working day. Please check the status later.', 72 | 20001003 => 'We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction. Please check the status later.', 73 | 20001004 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 74 | 20001005 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 75 | 20001006 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 76 | 20001007 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 77 | 20001008 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 78 | 20001009 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 79 | 20001010 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 80 | 20001101 => 'A technical problem has occurred. Please contact the helpdesk.', 81 | 20001104 => 'We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction. Please check the status later.', 82 | 20001105 => 'We have received an unknown status for the transaction. We shall contact your acquirer and update the transaction status within one working day. Please check the status later.', 83 | 20001111 => 'A technical problem has occurred. Please contact the helpdesk.', 84 | 20001998 => 'We received an unknown status for the transaction. We will contact your acquirer and update the status of the transaction. Please check the status later.', 85 | 20002001 => 'Bank response origin cannot be checked', 86 | 20002002 => 'Beneficiary account number has been modified during processing', 87 | 20002003 => 'Amount has been modified during processing', 88 | 20002004 => 'Currency has been modified during processing', 89 | 20002005 => 'No feedback detected from the bank server', 90 | 30001001 => 'Payment refused by the financial institution', 91 | 30001002 => 'Duplicate request', 92 | 30001010 => 'A technical problem has occurred. Please contact the helpdesk.', 93 | 30001011 => 'A technical problem has occurred. Please contact the helpdesk.', 94 | 30001012 => 'Card blacklisted - Contact acquirer', 95 | 30001015 => 'There has been a connection error to the receiving bank. Please try later or choose another payment method.', 96 | 30001016 => 'Transmission failure and/or Database error. The transaction could not be properly initialised in the send process (db access failures, etc.)', 97 | 30001051 => 'A technical problem has occurred. Please contact the helpdesk.', 98 | 30001054 => 'A technical problem has occurred. Please contact the helpdesk.', 99 | 30001056 => "Your merchant's acquirer is temporarily unavailable, please try later or choose another payment method.", 100 | 30001057 => 'There has been a connection error to the receiving bank. Please try later or choose another payment method.', 101 | 30001058 => 'There has been a connection error to the receiving bank. Please try later or choose another payment method.', 102 | 30001060 => 'Acquirer has indicated a failure during payment processing', 103 | 30001070 => 'RATEPAY Invalid Response Type (Failure)', 104 | 30001071 => 'RATEPAY Missing Mandatory status code field (failure)', 105 | 30001072 => 'RATEPAY Missing Mandatory Result code field (failure)', 106 | 30001073 => 'RATEPAY Response parsing Failed', 107 | 30001090 => 'CVC check required by front end and returned invalid by acquirer', 108 | 30001091 => 'Postcode check required by front end and returned invalid by acquirer', 109 | 30001092 => 'Address check required by frontend and returned as invalid by acquirer.', 110 | 30001095 => 'CVC check failed after transaction processed', 111 | 30001096 => 'AAV check failed after transaction processed', 112 | 30001100 => 'Unauthorised customer country', 113 | 30001101 => 'IP country differs from card country', 114 | 30001102 => 'Number of different countries too high', 115 | 30001103 => 'unauthorised card country', 116 | 30001104 => 'unauthorised IP address country', 117 | 30001105 => 'Anonymous proxy', 118 | 30001110 => "If the problem persists, please contact Support or go to paysafecard's card balance page (https://customer.cc.at.paysafecard.com/psccustomer/GetWelcomePanelServlet?language=en), to see when the amount reserved on your card will be available again.", 119 | 30001120 => "IP address on merchant's blacklist", 120 | 30001130 => "BIN on merchant's blacklist", 121 | 30001131 => 'Wrong BIN for 3xCB', 122 | 30001140 => "Card on merchant's blacklist", 123 | 30001141 => 'E-mail blacklisted', 124 | 30001142 => 'Passenger name blacklisted', 125 | 30001143 => 'Cardholder name blacklisted', 126 | 30001144 => 'Passenger name different from owner name', 127 | 30001145 => 'Time to departure too short', 128 | 30001149 => 'Card Configured in Card Supplier Limit for another relation (CSL)', 129 | 30001150 => 'Card not configured in the system for this customer (CSL)', 130 | 30001151 => 'REF1 not allowed for this relationship (Contract number)', 131 | 30001152 => 'Card/Supplier Amount limit reached (CSL)', 132 | 30001153 => 'Card not permitted for this supplier (Date out of contractual limits)', 133 | 30001154 => 'You have reached the permitted usage limit.', 134 | 30001155 => 'You have reached the permitted usage limit.', 135 | 30001156 => 'You have reached the permitted usage limit', 136 | 30001157 => 'Unauthorised IP country for itinerary', 137 | 30001158 => 'e-mail usage limit reached', 138 | 30001159 => 'Unauthorised card country/IP country combination', 139 | 30001160 => 'Postcode in high-risk group', 140 | 30001161 => 'generic blacklist match', 141 | 30001162 => 'Invoicing Address is a PO Box', 142 | 30001163 => 'Airport in high-risk group', 143 | 30001164 => 'Shipping Method in high-risk group', 144 | 30001165 => 'Shipping Method Details in high-risk group', 145 | 30001166 => 'Product Category in high-risk group', 146 | 30001167 => 'Subbrand in high-risk group', 147 | 30001168 => 'Issuer Number in high-risk group', 148 | 30001169 => 'Time to delivery too short', 149 | 30001180 => 'maximum scoring reached', 150 | 30001201 => '0} does not exist.', 151 | 30001202 => 'No data found.', 152 | 30001203 => '0} is not updated.', 153 | 30001204 => 'Some of the data entered is incorrect. Please retry.', 154 | 30001205 => 'Your account has been terminated. Please contact us.', 155 | 30001206 => 'The maximum permitted number of users has been reached. Please contact us in order to upgrade your account.', 156 | 30001207 => 'This user id already exists. Please choose another.', 157 | 30001997 => 'Authorisation cancelled by simulator', 158 | 30001998 => 'A technical problem has occurred. Please try again.', 159 | 30001999 => 'There has been a connection error with the receiving bank. Please try later or choose another payment method.', 160 | 30002001 => 'Payment refused by the financial institution', 161 | 30021001 => 'Please call the acquirer support call number.', 162 | 30022001 => 'Payment must be approved by the acquirer prior to execution.', 163 | 30031001 => 'Invalid merchant number', 164 | 30041001 => 'Retain card.', 165 | 30051001 => 'Authorisation declined', 166 | 30051002 => 'Voor vragen over uw afwijzing kunt u contact opnemen met de Klantenservice van AfterPay.', 167 | 30051009 => 'It is possible that you may not have completed all the required information (correctly) during the order process.', 168 | 30051010 => 'because your age is under 18. For more information please visit website of AfterPay.', 169 | 30051011 => 'because your address could not be validated. For more information please visit website of AfterPay.', 170 | 30051012 => 'because your emailadres is invalid. For more information please visit website van AfterPay.', 171 | 30051013 => 'because the order amount extends the limit for first time AfterPay users. For more information please visit website of AfterPay.', 172 | 30051014 => 'because there are currently too many outstanding payments at AfterPay. For more information please visit website of AfterPay.', 173 | 30051015 => 'because your chamber of commerce number could not be validated. For more information please visit website of AfterPay.', 174 | 30051016 => 'because the order amount is too low. For more information please visit website of AfterPay.', 175 | 30051017 => 'For more information please visit website of AfterPay.', 176 | 30071001 => 'Retain card - special conditions.', 177 | 30121001 => 'Invalid transaction', 178 | 30131001 => 'Invalid amount', 179 | 30131002 => 'You have reached the permitted limit', 180 | 30141001 => 'Invalid card number', 181 | 30151001 => 'Unknown acquiring institution', 182 | 30171001 => 'Payment method cancelled by the customer.', 183 | 30171002 => 'The maximum time allowed has elapsed.', 184 | 30191001 => 'Please try again later.', 185 | 30201001 => 'A technical problem has occurred. Please contact the helpdesk.', 186 | 30301001 => 'Invalid format', 187 | 30311001 => 'Unknown acquirer ID.', 188 | 30331001 => 'Card expired', 189 | 30341001 => 'Suspicion of fraud.', 190 | 30341002 => 'Suspicion of fraud (3rdMan)', 191 | 30341003 => 'Suspicion of fraud (Perseuss)', 192 | 30341004 => 'Suspicion of fraud (ETHOCA)', 193 | 30341005 => 'Suspicion of fraud (Expert)', 194 | 30381001 => 'A technical problem has occurred. Please contact the helpdesk.', 195 | 30401001 => 'Invalid function', 196 | 30411001 => 'Lost card', 197 | 30431001 => 'Stolen card. Pick up.', 198 | 30511001 => 'Insufficient funds', 199 | 30521001 => 'No Authorisation. Please contact your card issuer.', 200 | 30541001 => 'Card expired', 201 | 30551001 => 'Invalid PIN', 202 | 30561001 => "Card not in authoriser's database.", 203 | 30571001 => 'Transaction not permitted on card', 204 | 30581001 => 'Transaction not permitted on this terminal', 205 | 30591001 => 'Suspicion of fraud', 206 | 30601001 => 'The merchant should contact the acquirer.', 207 | 30611001 => 'Amount exceeds card limit', 208 | 30621001 => 'Restricted card', 209 | 30631001 => 'Security policy not respected', 210 | 30641001 => 'Amount changed from ref. transaction.', 211 | 30681001 => 'The maximum allowed time has elapsed.', 212 | 30751001 => 'Incorrect PIN entered too many times', 213 | 30761001 => 'Already disputed by cardholder.', 214 | 30771001 => 'PIN entry required', 215 | 30811001 => 'Message flow error', 216 | 30821001 => 'Authorisation centre unavailable', 217 | 30831001 => 'Authorisation centre unavailable', 218 | 30901001 => 'Temporary system shutdown', 219 | 30911001 => 'Acquirer unavailable', 220 | 30921001 => 'Invalid card type for acquirer', 221 | 30941001 => 'Duplicate transaction', 222 | 30961001 => 'Processing temporarily not possible', 223 | 30971001 => 'A technical problem has occurred. Please contact the helpdesk.', 224 | 30981001 => 'A technical problem has occurred. Please contact the helpdesk.', 225 | 31011001 => 'Unknown acceptance code', 226 | 31021001 => 'Invalid currency', 227 | 31031001 => 'Acceptance code missing', 228 | 31041001 => 'Inactive card', 229 | 31051001 => 'Merchant not active', 230 | 31061001 => 'Invalid expiry date', 231 | 31071001 => 'Interrupted host communication', 232 | 31081001 => 'Card refused', 233 | 31091001 => 'Invalid password', 234 | 31101001 => 'Plafond transaction (majoré du bonus) dépassé', 235 | 31111001 => 'Plafond mensuel (majoré du bonus) dépassé', 236 | 31121001 => 'Plafond centre de facturation dépassé', 237 | 31131001 => 'Plafond entreprise dépassé', 238 | 31141001 => 'Code MCC du fournisseur non autorisé pour la carte', 239 | 31151001 => 'Numéro SIRET du fournisseur non autorisé pour la carte', 240 | 31161001 => 'This is not a valid online bank account', 241 | 32001004 => 'A technical problem has occurred. Please try again.', 242 | 32001105 => 'A technical problem has occurred. Please contact the helpdesk.', 243 | 34011001 => 'Bezahlung mit RatePAY nicht möglich.', 244 | 39991001 => "A technical problem has occurred. Please contact your acquirer's helpdesk.", 245 | 40001001 => 'A technical problem has occurred. Please try again.', 246 | 40001002 => 'A technical problem has occurred. Please try again.', 247 | 40001003 => 'A technical problem has occurred. Please try again.', 248 | 40001004 => 'A technical problem has occurred. Please try again.', 249 | 40001005 => 'A technical problem has occurred. Please try again.', 250 | 40001006 => 'A technical problem has occurred. Please try again.', 251 | 40001007 => 'A technical problem has occurred. Please try again.', 252 | 40001008 => 'A technical problem has occurred. Please try again.', 253 | 40001009 => 'A technical problem has occurred. Please try again.', 254 | 40001010 => 'A technical problem has occurred. Please try again.', 255 | 40001011 => 'A technical problem has occurred. Please contact the helpdesk.', 256 | 40001012 => 'There has been a connection error with the receiving bank. Please try later or choose another payment method.', 257 | 40001013 => 'A technical problem has occurred. Please contact the helpdesk.', 258 | 40001016 => 'A technical problem has occurred. Please contact the helpdesk.', 259 | 40001018 => 'A technical problem has occurred. Please try again.', 260 | 40001019 => "Sorry, an error has occurred during processing. Please retry the transaction (using the Back button of the browser). If the problem persists, contact your merchant's helpdesk.", 261 | 40001020 => "Sorry, an error occurred during processing. Please retry the operation (using the Back button of the browser). If the problem persists, please contact your merchant's helpdesk.", 262 | 40001050 => 'A technical problem has occurred. Please contact the helpdesk.', 263 | 40001133 => "Authentication failed. Incorrect signature for your bank's access control server.", 264 | 40001134 => 'Authentication failed. Please retry or cancel.', 265 | 40001135 => 'Authentication temporarily unavailable. Please retry or cancel.', 266 | 40001136 => 'Technical problem with your browser. Please retry or cancel.', 267 | 40001137 => 'Your bank is temporarily unavailable. Please try again later or choose another payment method.', 268 | 40001202 => 'This action is not authorized for your profile.', 269 | 40001203 => 'Current user is not authenticated', 270 | 40001204 => '40001205 No ', 271 | 40001210 => 'Your password must contain at least one letter (a-z) and at least one number (0-9) or symbol (&,@,#,!, etc.).', 272 | 40001211 => '40001212 No ', 273 | 40001213 => '40001998 No Temporary technical problem. Please retry later.', 274 | 50001001 => 'Unknown card type', 275 | 50001002 => 'Card number format check failed for given card number.', 276 | 50001003 => 'Merchant data error', 277 | 50001004 => 'Merchant identification missing', 278 | 50001005 => 'Expiry date error', 279 | 50001006 => 'Amount is not a number', 280 | 50001007 => 'A technical has problem occurred. Please contact the helpdesk.', 281 | 50001008 => 'A technical has problem occurred. Please contact the helpdesk.', 282 | 50001009 => 'A technical has problem occurred. Please contact the helpdesk.', 283 | 50001010 => 'A technical has problem occurred. Please contact the helpdesk.', 284 | 50001011 => 'Brand not supported for that merchant', 285 | 50001012 => 'A technical has problem occurred. Please contact the helpdesk.', 286 | 50001013 => 'A technical has problem occurred. Please contact the helpdesk.', 287 | 50001014 => 'A technical has problem occurred. Please contact the helpdesk.', 288 | 50001015 => 'Invalid currency code', 289 | 50001016 => 'A technical has problem occurred. Please contact the helpdesk.', 290 | 50001017 => 'A technical has problem occurred. Please contact the helpdesk.', 291 | 50001018 => 'A technical has problem occurred. Please contact the helpdesk.', 292 | 50001019 => 'A technical has problem occurred. Please contact the helpdesk.', 293 | 50001020 => 'A technical has problem occurred. Please contact the helpdesk.', 294 | 50001021 => 'A technical has problem occurred. Please contact the helpdesk.', 295 | 50001022 => 'A technical has problem occurred. Please contact the helpdesk.', 296 | 50001023 => 'A technical has problem occurred. Please contact the helpdesk.', 297 | 50001024 => 'A technical has problem occurred. Please contact the helpdesk.', 298 | 50001025 => 'A technical has problem occurred. Please contact the helpdesk.', 299 | 50001026 => 'A technical has problem occurred. Please contact the helpdesk.', 300 | 50001027 => 'A technical has problem occurred. Please contact the helpdesk.', 301 | 50001028 => 'A technical has problem occurred. Please contact the helpdesk.', 302 | 50001029 => 'A technical has problem occurred. Please contact the helpdesk.', 303 | 50001030 => 'A technical has problem occurred. Please contact the helpdesk.', 304 | 50001031 => 'A technical has problem occurred. Please contact the helpdesk.', 305 | 50001032 => 'A technical has problem occurred. Please contact the helpdesk.', 306 | 50001033 => 'A technical has problem occurred. Please contact the helpdesk.', 307 | 50001034 => 'A technical has problem occurred. Please contact the helpdesk.', 308 | 50001035 => 'A technical problem has occurred. Please contact the helpdesk.', 309 | 50001036 => 'Incorrect card length for the brand', 310 | 50001037 => 'Purchasing card number for a standard merchant', 311 | 50001038 => 'You should use a purchasing card for this transaction.', 312 | 50001039 => 'Details sent for a non-purchasing card merchant. Please contact the helpdesk.', 313 | 50001040 => 'Details not sent for a purchasing card transaction. Please contact the helpdesk.', 314 | 50001041 => 'Payment detail validation failed', 315 | 50001042 => 'Sum of given transaction amounts (tax, discount, delivery, net, etc.) does not match total.', 316 | 50001043 => 'A technical problem has occurred. Please contact the helpdesk.', 317 | 50001044 => 'No acquirer configured for this operation', 318 | 50001045 => 'No UID configured for this operation', 319 | 50001046 => 'Operation not permitted for the merchant', 320 | 50001047 => 'A technical problem has occurred. Please contact the helpdesk.', 321 | 50001048 => 'A technical problem has occurred. Please contact the helpdesk.', 322 | 50001049 => 'A technical problem has occurred. Please contact the helpdesk.', 323 | 50001050 => 'A technical problem has occurred. Please contact the helpdesk.', 324 | 50001051 => 'A technical problem has occurred. Please contact the helpdesk.', 325 | 50001052 => 'A technical problem has occurred. Please contact the helpdesk.', 326 | 50001053 => 'A technical problem has occurred. Please contact the helpdesk.', 327 | 50001054 => 'Card number incorrect or incompatible', 328 | 50001055 => 'A technical problem has occurred. Please contact the helpdesk.', 329 | 50001056 => 'A technical problem has occurred. Please contact the helpdesk.', 330 | 50001057 => 'A technical problem has occurred. Please contact the helpdesk.', 331 | 50001058 => 'A technical problem has occurred. Please contact the helpdesk.', 332 | 50001059 => 'A technical problem has occurred. Please contact the helpdesk.', 333 | 50001060 => 'A technical problem has occurred. Please contact the helpdesk.', 334 | 50001061 => 'A technical problem has occurred. Please contact the helpdesk.', 335 | 50001062 => 'A technical problem has occurred. Please contact the helpdesk.', 336 | 50001063 => 'Card Issue Number does not correspond to range or is not present', 337 | 50001064 => 'Start Date invalid or not present', 338 | 50001066 => 'Invalid CVC code format', 339 | 50001067 => 'The merchant is not registered for 3D-Secure', 340 | 50001068 => 'Invalid card number or account number (PAN)', 341 | 50001069 => 'Invalid CardID and Brand match', 342 | 50001070 => 'The ECI value is either not supported or conflicts with other transaction data', 343 | 50001071 => 'Incomplete TRN demat', 344 | 50001072 => 'Incomplete PAY demat', 345 | 50001073 => 'No demat APP', 346 | 50001074 => 'Authorisation period expired', 347 | 50001075 => 'VERRes was an error message', 348 | 50001076 => 'DCP amount greater than authorisation amount', 349 | 50001077 => 'Details negative amount', 350 | 50001078 => 'Details negative quantity', 351 | 50001079 => 'Could not decode/decompress received PARes (3-D Secure)', 352 | 50001080 => 'Received PARes was an error message from ACS (3-D Secure)', 353 | 50001081 => 'Received PARes format was invalid according to the 3-D Secure specifications (3-D Secure)', 354 | 50001082 => 'PAReq/PARes reconciliation failure (3-D Secure)', 355 | 50001084 => 'Maximum amount reached', 356 | 50001087 => 'This transaction requires authentication. Please check with your bank.', 357 | 50001090 => 'CVC missing at input, but CVC check requested', 358 | 50001091 => 'Postcode missing at input, but postcode check requested', 359 | 50001092 => 'Address missing at input, but Address check requested', 360 | 50001093 => 'Partial capture not allowed', 361 | 50001095 => 'Invalid date of birth', 362 | 50001096 => 'Invalid commodity code', 363 | 50001097 => 'The requested currency and brand are incompatible.', 364 | 50001111 => 'Data validation error', 365 | 50001113 => 'This order has already been processed.', 366 | 50001114 => 'Error in accessing the pre-payment check page', 367 | 50001115 => 'Request not received in secure mode', 368 | 50001116 => 'Unknown IP address origin', 369 | 50001117 => 'No IP address origin', 370 | 50001118 => 'PSPID not found or incorrect', 371 | 50001119 => 'Password incorrect or disabled due to number of errors', 372 | 50001120 => 'Invalid currency', 373 | 50001121 => 'Invalid number of decimals for the currency', 374 | 50001122 => 'Currency not accepted by the merchant', 375 | 50001123 => 'Card type not active', 376 | 50001124 => "Number of lines doesn't match the number of payments", 377 | 50001125 => 'Format validation error', 378 | 50001126 => 'Overflow in data capture requests for the original order', 379 | 50001127 => 'Incorrect original order status', 380 | 50001128 => 'missing authorisation code for unauthorised order', 381 | 50001129 => 'Overflow in refunds requests', 382 | 50001130 => 'Original order access error', 383 | 50001131 => 'Original history item access error', 384 | 50001132 => 'The selected Catalogue is empty', 385 | 50001133 => 'Duplicate request', 386 | 50001134 => 'Authentication failed. Please retry or cancel.', 387 | 50001135 => 'Authentication temporarily unavailable. Please retry or cancel.', 388 | 50001136 => 'Technical problem with your browser. Please retry or cancel.', 389 | 50001137 => 'Your bank is temporarily unavailable. Please try again later or choose another payment method.', 390 | 50001150 => 'Fraud Detection: technical error (invalid IP)', 391 | 50001151 => 'Fraud detection: technical error (IPCTY unknown or error)', 392 | 50001152 => 'Fraud detection: technical error (CCCTY unknown or error)', 393 | 50001153 => 'Overflow in redo-authorisation requests', 394 | 50001170 => 'Dynamic BIN check failed', 395 | 50001171 => 'Dynamic country check failed', 396 | 50001172 => 'Amadeus signature error', 397 | 50001174 => 'Cardholder Name is too long', 398 | 50001175 => 'Name contains invalid characters', 399 | 50001176 => 'Card number is too long', 400 | 50001177 => 'Card number contains non-numeric info', 401 | 50001178 => 'Card Number Empty', 402 | 50001179 => 'CVC too long', 403 | 50001180 => 'CVC contains non-numeric info', 404 | 50001181 => 'Expiry date contains non-numeric info', 405 | 50001182 => 'Invalid expiry month', 406 | 50001183 => 'Expiry date must be in the future', 407 | 50001184 => 'SHA Mismatch', 408 | 50001185 => 'Incorrect BIC code length', 409 | 50001186 => 'Operation not permitted', 410 | 50001187 => 'Operation not permitted', 411 | 50001191 => '0} length cannot be more than {1} characters.', 412 | 50001192 => 'Only alphanumeric characters are allowed.', 413 | 50001193 => 'Only {0} characters and special characters {1} are allowed.', 414 | 50001194 => '0} is invalid.', 415 | 50001205 => 'Missing mandatory fields in invoicing address', 416 | 50001206 => 'Missing mandatory date of birth field.', 417 | 50001207 => 'Missing required shopping basket details', 418 | 50001208 => 'Missing social security number', 419 | 50001209 => 'Invalid country code', 420 | 50001210 => 'Missing annual salary', 421 | 50001211 => 'Missing gender', 422 | 50001212 => 'Missing e-mail', 423 | 50001213 => 'Missing IP address', 424 | 50001214 => 'Missing part-payment campaign ID', 425 | 50001215 => 'Missing invoice number', 426 | 50001216 => 'The alias must be different to the card number.', 427 | 50001217 => 'Invalid details for shopping basket calculation', 428 | 50001218 => 'No Refunds allowed', 429 | 50001220 => 'Invalid format of phone number', 430 | 50001221 => 'Invalid ZIP format', 431 | 50001222 => 'Firstname or/and lastname missing', 432 | 50001223 => 'Firstname and/or lastname format invalid', 433 | 50001224 => 'The phone number is missing.', 434 | 50001225 => 'Invalid email format', 435 | 50001300 => 'Wrong brand/payment method', 436 | 50001301 => 'Wrong account number format', 437 | 50001302 => 'RFP operation code is only permitted with scheduled payments.', 438 | 50001303 => 'RFP operation code not permitted for a Disputed payment', 439 | 50001304 => 'RFP operation code not permitted - Unpaid amounts', 440 | 50001501 => '0} is required.', 441 | 55555555 => 'An error occurred.', 442 | 60000001 => 'account number unknown', 443 | 60000003 => 'not credited dd-mm-yy', 444 | 60000005 => 'name/number do not match', 445 | 60000007 => 'account number blocked', 446 | 60000008 => 'specific direct debit block', 447 | 60000009 => 'account number WKA', 448 | 60000010 => 'administrative reason', 449 | 60000011 => 'account number expired', 450 | 60000012 => 'no direct debit authorisation', 451 | 60000013 => 'debit not approved', 452 | 60000014 => 'double payment', 453 | 60000018 => 'name/address/city not entered', 454 | 60001001 => 'no original direct debit for revocation', 455 | 60001002 => 'payer’s account number format error', 456 | 60001004 => 'payer’s account at different bank', 457 | 60001005 => 'payee’s account at different bank', 458 | 60001006 => 'payee’s account number format error', 459 | 60001007 => 'payer’s account number blocked', 460 | 60001008 => 'payer’s account number expired', 461 | 60001009 => 'payee’s account number expired', 462 | 60001010 => 'direct debit not possible', 463 | 60001011 => 'creditor payment not possible', 464 | 60001012 => 'payer’s account number unknown WKA-number', 465 | 60001013 => 'payee’s account number unknown WKA-number', 466 | 60001014 => 'WKA transaction not permitted', 467 | 60001015 => 'revocation period expired', 468 | 60001017 => 'incorrect revocation reason', 469 | 60001018 => 'original run number not numeric', 470 | 60001019 => 'payment ID incorrect', 471 | 60001020 => 'amount not numeric', 472 | 60001021 => 'zero amount not permitted', 473 | 60001022 => 'negative amount not permitted', 474 | 60001023 => 'payer and payee giro account number', 475 | 60001025 => 'processing code (verwerkingscode) incorrect', 476 | 60001028 => 'revocation not permitted', 477 | 60001029 => 'guaranteed direct debit on giro account number', 478 | 60001030 => 'NBC transaction type incorrect', 479 | 60001031 => 'description too long', 480 | 60001032 => 'book account number not issued', 481 | 60001034 => 'book account number incorrect', 482 | 60001035 => 'payer’s account number not numeric', 483 | 60001036 => 'payer’s account number not eleven-proof', 484 | 60001037 => 'payer’s account number not issued', 485 | 60001039 => 'payer’s account number of DNB/BGC/BLA', 486 | 60001040 => 'payee’s account number not numeric', 487 | 60001041 => 'payee’s account number not eleven-proof', 488 | 60001042 => 'payee’s account number not issued', 489 | 60001044 => 'payee’s account number unknown', 490 | 60001050 => 'payee’s name missing', 491 | 60001051 => 'indicate payee’s bank account number instead of 3102', 492 | 60001052 => 'no direct debit contract', 493 | 60001053 => 'amount beyond limits', 494 | 60001054 => 'selective direct debit block', 495 | 60001055 => 'original run number unknown', 496 | 60001057 => 'payer’s name missing', 497 | 60001058 => 'payee’s account number missing', 498 | 60001059 => 'restore not permitted', 499 | 60001060 => 'bank’s reference (navraaggegeven) missing', 500 | 60001061 => 'BEC/GBK number incorrect', 501 | 60001062 => 'BEC/GBK code incorrect', 502 | 60001087 => 'book account number not numeric', 503 | 60001090 => 'cancelled on request', 504 | 60001091 => 'cancellation order executed', 505 | 60001092 => 'cancelled instead of ended', 506 | 60001093 => 'book account number is a shortened account number', 507 | 60001094 => 'instructing party and payer account numbers do not match', 508 | 60001095 => 'payee unknown GBK acceptor', 509 | 60001097 => 'instructing party and payee account numbers do not match', 510 | 60001099 => 'clearing not permitted', 511 | 60001101 => 'payer’s account number has no spaces', 512 | 60001102 => 'PAN length not numeric', 513 | 60001103 => 'PAN length outside limits', 514 | 60001104 => 'track number not numeric', 515 | 60001105 => 'track number not valid', 516 | 60001106 => 'PAN sequence number not numeric', 517 | 60001107 => 'domestic PAN not numeric', 518 | 60001108 => 'domestic PAN not eleven-proof', 519 | 60001109 => 'domestic PAN not issued', 520 | 60001110 => 'foreign PAN not numeric', 521 | 60001111 => 'card validity date not numeric', 522 | 60001112 => 'book period number (boekperiodenr) not numeric', 523 | 60001113 => 'transaction number not numeric', 524 | 60001114 => 'transaction time not numeric', 525 | 60001115 => 'invalid transaction time', 526 | 60001116 => 'transaction date not numeric', 527 | 60001117 => 'invalid transaction date', 528 | 60001118 => 'STAN not numeric', 529 | 60001119 => 'instructing party’s name missing', 530 | 60001120 => 'foreign amount (bedrag-vv) not numeric', 531 | 60001122 => 'rate (verrekenkoers) not numeric', 532 | 60001125 => 'number of decimals (aantaldecimalen) incorrect', 533 | 60001126 => 'tariff (tarifering) not B/O/S', 534 | 60001127 => 'domestic costs (kostenbinnenland) not numeric', 535 | 60001128 => 'domestic costs (kostenbinnenland) not higher than zero', 536 | 60001129 => 'foreign costs (kostenbuitenland) not numeric', 537 | 60001130 => 'foreign costs (kostenbuitenland) not higher than zero', 538 | 60001131 => 'domestic costs (kostenbinnenland) not zero', 539 | 60001132 => 'foreign costs (kostenbuitenland) not zero', 540 | 60001134 => 'Euro record not completed', 541 | 60001135 => 'Customer currency incorrect', 542 | 60001136 => 'NLG amount not numeric', 543 | 60001137 => 'NLG amount not higher than zero', 544 | 60001138 => 'NLG amount not equal to Amount', 545 | 60001139 => 'NLG amount incorrectly converted', 546 | 60001140 => 'EUR amount not numeric', 547 | 60001141 => 'EUR amount not greater than zero', 548 | 60001142 => 'EUR amount not equal to Amount', 549 | 60001143 => 'EUR amount incorrectly converted', 550 | 60001144 => 'Customer currency not NLG', 551 | 60001145 => 'rate euro-vv (Koerseuro-vv) not numeric', 552 | 60001146 => 'comma rate euro-vv (Kommakoerseuro-vv) incorrect', 553 | 60001147 => 'invalid acceptgiro distributor', 554 | 60001148 => 'Original run number and/or BRN missing', 555 | 60001149 => 'Amount/Account number/ BRN different', 556 | 60001150 => 'Direct debit already revoked/restored', 557 | 60001151 => 'Direct debit already reversed/revoked/restored', 558 | 60001153 => 'Payer’s account number not known', 559 | ); 560 | 561 | /** 562 | * @var array return codes in which case a retry makes sense 563 | */ 564 | protected static $retryCodes = array( 565 | '0020001001', 566 | '0020001002', 567 | '0020001003', 568 | '0020001004', 569 | '0020001005', 570 | '0020001006', 571 | '0020001007', 572 | '0020001008', 573 | '0020001009', 574 | '0020001010', 575 | 30001010, 576 | 30001011, 577 | 30001015, 578 | 30001057, 579 | 30001058, 580 | 30001998, 581 | 30001999, 582 | 30611001, 583 | 30961001, 584 | 40001001, 585 | 40001002, 586 | 40001003, 587 | 40001004, 588 | 40001005, 589 | 40001006, 590 | 40001007, 591 | 40001008, 592 | 40001009, 593 | 40001010, 594 | 40001012, 595 | 40001018, 596 | 40001019, 597 | 40001020, 598 | 40001134, 599 | 40001135, 600 | 40001136, 601 | 40001137, 602 | 50001174, 603 | ); 604 | 605 | /** 606 | * is it recommended to retry? 607 | * 608 | * @param $code 609 | * 610 | * @return bool 611 | */ 612 | public static function isRetryCode($code) 613 | { 614 | return in_array($code, self::$retryCodes); 615 | } 616 | } 617 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "9c3af7429acbaf05d9d06f35828a248c", 8 | "content-hash": "6b6da06f3cd6a33079afdf94cb1066cf", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "1.0.5", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 22 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "~2.0" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2015-06-14 21:17:01" 64 | }, 65 | { 66 | "name": "fzaninotto/faker", 67 | "version": "v1.9.1", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/fzaninotto/Faker.git", 71 | "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/fc10d778e4b84d5bd315dad194661e091d307c6f", 76 | "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": "^5.3.3 || ^7.0" 81 | }, 82 | "require-dev": { 83 | "ext-intl": "*", 84 | "phpunit/phpunit": "^4.8.35 || ^5.7", 85 | "squizlabs/php_codesniffer": "^2.9.2" 86 | }, 87 | "type": "library", 88 | "extra": { 89 | "branch-alias": { 90 | "dev-master": "1.9-dev" 91 | } 92 | }, 93 | "autoload": { 94 | "psr-4": { 95 | "Faker\\": "src/Faker/" 96 | } 97 | }, 98 | "notification-url": "https://packagist.org/downloads/", 99 | "license": [ 100 | "MIT" 101 | ], 102 | "authors": [ 103 | { 104 | "name": "François Zaninotto" 105 | } 106 | ], 107 | "description": "Faker is a PHP library that generates fake data for you.", 108 | "keywords": [ 109 | "data", 110 | "faker", 111 | "fixtures" 112 | ], 113 | "time": "2019-12-12 13:22:17" 114 | }, 115 | { 116 | "name": "myclabs/deep-copy", 117 | "version": "1.7.0", 118 | "source": { 119 | "type": "git", 120 | "url": "https://github.com/myclabs/DeepCopy.git", 121 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" 122 | }, 123 | "dist": { 124 | "type": "zip", 125 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 126 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 127 | "shasum": "" 128 | }, 129 | "require": { 130 | "php": "^5.6 || ^7.0" 131 | }, 132 | "require-dev": { 133 | "doctrine/collections": "^1.0", 134 | "doctrine/common": "^2.6", 135 | "phpunit/phpunit": "^4.1" 136 | }, 137 | "type": "library", 138 | "autoload": { 139 | "psr-4": { 140 | "DeepCopy\\": "src/DeepCopy/" 141 | }, 142 | "files": [ 143 | "src/DeepCopy/deep_copy.php" 144 | ] 145 | }, 146 | "notification-url": "https://packagist.org/downloads/", 147 | "license": [ 148 | "MIT" 149 | ], 150 | "description": "Create deep copies (clones) of your objects", 151 | "keywords": [ 152 | "clone", 153 | "copy", 154 | "duplicate", 155 | "object", 156 | "object graph" 157 | ], 158 | "time": "2017-10-19 19:58:43" 159 | }, 160 | { 161 | "name": "phpdocumentor/reflection-common", 162 | "version": "1.0.1", 163 | "source": { 164 | "type": "git", 165 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 166 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 167 | }, 168 | "dist": { 169 | "type": "zip", 170 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 171 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 172 | "shasum": "" 173 | }, 174 | "require": { 175 | "php": ">=5.5" 176 | }, 177 | "require-dev": { 178 | "phpunit/phpunit": "^4.6" 179 | }, 180 | "type": "library", 181 | "extra": { 182 | "branch-alias": { 183 | "dev-master": "1.0.x-dev" 184 | } 185 | }, 186 | "autoload": { 187 | "psr-4": { 188 | "phpDocumentor\\Reflection\\": [ 189 | "src" 190 | ] 191 | } 192 | }, 193 | "notification-url": "https://packagist.org/downloads/", 194 | "license": [ 195 | "MIT" 196 | ], 197 | "authors": [ 198 | { 199 | "name": "Jaap van Otterdijk", 200 | "email": "opensource@ijaap.nl" 201 | } 202 | ], 203 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 204 | "homepage": "http://www.phpdoc.org", 205 | "keywords": [ 206 | "FQSEN", 207 | "phpDocumentor", 208 | "phpdoc", 209 | "reflection", 210 | "static analysis" 211 | ], 212 | "time": "2017-09-11 18:02:19" 213 | }, 214 | { 215 | "name": "phpdocumentor/reflection-docblock", 216 | "version": "3.3.2", 217 | "source": { 218 | "type": "git", 219 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 220 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" 221 | }, 222 | "dist": { 223 | "type": "zip", 224 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", 225 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", 226 | "shasum": "" 227 | }, 228 | "require": { 229 | "php": "^5.6 || ^7.0", 230 | "phpdocumentor/reflection-common": "^1.0.0", 231 | "phpdocumentor/type-resolver": "^0.4.0", 232 | "webmozart/assert": "^1.0" 233 | }, 234 | "require-dev": { 235 | "mockery/mockery": "^0.9.4", 236 | "phpunit/phpunit": "^4.4" 237 | }, 238 | "type": "library", 239 | "autoload": { 240 | "psr-4": { 241 | "phpDocumentor\\Reflection\\": [ 242 | "src/" 243 | ] 244 | } 245 | }, 246 | "notification-url": "https://packagist.org/downloads/", 247 | "license": [ 248 | "MIT" 249 | ], 250 | "authors": [ 251 | { 252 | "name": "Mike van Riel", 253 | "email": "me@mikevanriel.com" 254 | } 255 | ], 256 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 257 | "time": "2017-11-10 14:09:06" 258 | }, 259 | { 260 | "name": "phpdocumentor/type-resolver", 261 | "version": "0.4.0", 262 | "source": { 263 | "type": "git", 264 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 265 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 266 | }, 267 | "dist": { 268 | "type": "zip", 269 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 270 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 271 | "shasum": "" 272 | }, 273 | "require": { 274 | "php": "^5.5 || ^7.0", 275 | "phpdocumentor/reflection-common": "^1.0" 276 | }, 277 | "require-dev": { 278 | "mockery/mockery": "^0.9.4", 279 | "phpunit/phpunit": "^5.2||^4.8.24" 280 | }, 281 | "type": "library", 282 | "extra": { 283 | "branch-alias": { 284 | "dev-master": "1.0.x-dev" 285 | } 286 | }, 287 | "autoload": { 288 | "psr-4": { 289 | "phpDocumentor\\Reflection\\": [ 290 | "src/" 291 | ] 292 | } 293 | }, 294 | "notification-url": "https://packagist.org/downloads/", 295 | "license": [ 296 | "MIT" 297 | ], 298 | "authors": [ 299 | { 300 | "name": "Mike van Riel", 301 | "email": "me@mikevanriel.com" 302 | } 303 | ], 304 | "time": "2017-07-14 14:27:02" 305 | }, 306 | { 307 | "name": "phpspec/prophecy", 308 | "version": "1.10.1", 309 | "source": { 310 | "type": "git", 311 | "url": "https://github.com/phpspec/prophecy.git", 312 | "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc" 313 | }, 314 | "dist": { 315 | "type": "zip", 316 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/cbe1df668b3fe136bcc909126a0f529a78d4cbbc", 317 | "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc", 318 | "shasum": "" 319 | }, 320 | "require": { 321 | "doctrine/instantiator": "^1.0.2", 322 | "php": "^5.3|^7.0", 323 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 324 | "sebastian/comparator": "^1.2.3|^2.0|^3.0", 325 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 326 | }, 327 | "require-dev": { 328 | "phpspec/phpspec": "^2.5 || ^3.2", 329 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 330 | }, 331 | "type": "library", 332 | "extra": { 333 | "branch-alias": { 334 | "dev-master": "1.10.x-dev" 335 | } 336 | }, 337 | "autoload": { 338 | "psr-4": { 339 | "Prophecy\\": "src/Prophecy" 340 | } 341 | }, 342 | "notification-url": "https://packagist.org/downloads/", 343 | "license": [ 344 | "MIT" 345 | ], 346 | "authors": [ 347 | { 348 | "name": "Konstantin Kudryashov", 349 | "email": "ever.zet@gmail.com", 350 | "homepage": "http://everzet.com" 351 | }, 352 | { 353 | "name": "Marcello Duarte", 354 | "email": "marcello.duarte@gmail.com" 355 | } 356 | ], 357 | "description": "Highly opinionated mocking framework for PHP 5.3+", 358 | "homepage": "https://github.com/phpspec/prophecy", 359 | "keywords": [ 360 | "Double", 361 | "Dummy", 362 | "fake", 363 | "mock", 364 | "spy", 365 | "stub" 366 | ], 367 | "time": "2019-12-22 21:05:45" 368 | }, 369 | { 370 | "name": "phpunit/php-code-coverage", 371 | "version": "4.0.8", 372 | "source": { 373 | "type": "git", 374 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 375 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" 376 | }, 377 | "dist": { 378 | "type": "zip", 379 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 380 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 381 | "shasum": "" 382 | }, 383 | "require": { 384 | "ext-dom": "*", 385 | "ext-xmlwriter": "*", 386 | "php": "^5.6 || ^7.0", 387 | "phpunit/php-file-iterator": "^1.3", 388 | "phpunit/php-text-template": "^1.2", 389 | "phpunit/php-token-stream": "^1.4.2 || ^2.0", 390 | "sebastian/code-unit-reverse-lookup": "^1.0", 391 | "sebastian/environment": "^1.3.2 || ^2.0", 392 | "sebastian/version": "^1.0 || ^2.0" 393 | }, 394 | "require-dev": { 395 | "ext-xdebug": "^2.1.4", 396 | "phpunit/phpunit": "^5.7" 397 | }, 398 | "suggest": { 399 | "ext-xdebug": "^2.5.1" 400 | }, 401 | "type": "library", 402 | "extra": { 403 | "branch-alias": { 404 | "dev-master": "4.0.x-dev" 405 | } 406 | }, 407 | "autoload": { 408 | "classmap": [ 409 | "src/" 410 | ] 411 | }, 412 | "notification-url": "https://packagist.org/downloads/", 413 | "license": [ 414 | "BSD-3-Clause" 415 | ], 416 | "authors": [ 417 | { 418 | "name": "Sebastian Bergmann", 419 | "email": "sb@sebastian-bergmann.de", 420 | "role": "lead" 421 | } 422 | ], 423 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 424 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 425 | "keywords": [ 426 | "coverage", 427 | "testing", 428 | "xunit" 429 | ], 430 | "time": "2017-04-02 07:44:40" 431 | }, 432 | { 433 | "name": "phpunit/php-file-iterator", 434 | "version": "1.4.5", 435 | "source": { 436 | "type": "git", 437 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 438 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 439 | }, 440 | "dist": { 441 | "type": "zip", 442 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 443 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 444 | "shasum": "" 445 | }, 446 | "require": { 447 | "php": ">=5.3.3" 448 | }, 449 | "type": "library", 450 | "extra": { 451 | "branch-alias": { 452 | "dev-master": "1.4.x-dev" 453 | } 454 | }, 455 | "autoload": { 456 | "classmap": [ 457 | "src/" 458 | ] 459 | }, 460 | "notification-url": "https://packagist.org/downloads/", 461 | "license": [ 462 | "BSD-3-Clause" 463 | ], 464 | "authors": [ 465 | { 466 | "name": "Sebastian Bergmann", 467 | "email": "sb@sebastian-bergmann.de", 468 | "role": "lead" 469 | } 470 | ], 471 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 472 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 473 | "keywords": [ 474 | "filesystem", 475 | "iterator" 476 | ], 477 | "time": "2017-11-27 13:52:08" 478 | }, 479 | { 480 | "name": "phpunit/php-text-template", 481 | "version": "1.2.1", 482 | "source": { 483 | "type": "git", 484 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 485 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 486 | }, 487 | "dist": { 488 | "type": "zip", 489 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 490 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 491 | "shasum": "" 492 | }, 493 | "require": { 494 | "php": ">=5.3.3" 495 | }, 496 | "type": "library", 497 | "autoload": { 498 | "classmap": [ 499 | "src/" 500 | ] 501 | }, 502 | "notification-url": "https://packagist.org/downloads/", 503 | "license": [ 504 | "BSD-3-Clause" 505 | ], 506 | "authors": [ 507 | { 508 | "name": "Sebastian Bergmann", 509 | "email": "sebastian@phpunit.de", 510 | "role": "lead" 511 | } 512 | ], 513 | "description": "Simple template engine.", 514 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 515 | "keywords": [ 516 | "template" 517 | ], 518 | "time": "2015-06-21 13:50:34" 519 | }, 520 | { 521 | "name": "phpunit/php-timer", 522 | "version": "1.0.9", 523 | "source": { 524 | "type": "git", 525 | "url": "https://github.com/sebastianbergmann/php-timer.git", 526 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 527 | }, 528 | "dist": { 529 | "type": "zip", 530 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 531 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 532 | "shasum": "" 533 | }, 534 | "require": { 535 | "php": "^5.3.3 || ^7.0" 536 | }, 537 | "require-dev": { 538 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 539 | }, 540 | "type": "library", 541 | "extra": { 542 | "branch-alias": { 543 | "dev-master": "1.0-dev" 544 | } 545 | }, 546 | "autoload": { 547 | "classmap": [ 548 | "src/" 549 | ] 550 | }, 551 | "notification-url": "https://packagist.org/downloads/", 552 | "license": [ 553 | "BSD-3-Clause" 554 | ], 555 | "authors": [ 556 | { 557 | "name": "Sebastian Bergmann", 558 | "email": "sb@sebastian-bergmann.de", 559 | "role": "lead" 560 | } 561 | ], 562 | "description": "Utility class for timing", 563 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 564 | "keywords": [ 565 | "timer" 566 | ], 567 | "time": "2017-02-26 11:10:40" 568 | }, 569 | { 570 | "name": "phpunit/php-token-stream", 571 | "version": "1.4.12", 572 | "source": { 573 | "type": "git", 574 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 575 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 576 | }, 577 | "dist": { 578 | "type": "zip", 579 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 580 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 581 | "shasum": "" 582 | }, 583 | "require": { 584 | "ext-tokenizer": "*", 585 | "php": ">=5.3.3" 586 | }, 587 | "require-dev": { 588 | "phpunit/phpunit": "~4.2" 589 | }, 590 | "type": "library", 591 | "extra": { 592 | "branch-alias": { 593 | "dev-master": "1.4-dev" 594 | } 595 | }, 596 | "autoload": { 597 | "classmap": [ 598 | "src/" 599 | ] 600 | }, 601 | "notification-url": "https://packagist.org/downloads/", 602 | "license": [ 603 | "BSD-3-Clause" 604 | ], 605 | "authors": [ 606 | { 607 | "name": "Sebastian Bergmann", 608 | "email": "sebastian@phpunit.de" 609 | } 610 | ], 611 | "description": "Wrapper around PHP's tokenizer extension.", 612 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 613 | "keywords": [ 614 | "tokenizer" 615 | ], 616 | "time": "2017-12-04 08:55:13" 617 | }, 618 | { 619 | "name": "phpunit/phpunit", 620 | "version": "5.7.27", 621 | "source": { 622 | "type": "git", 623 | "url": "https://github.com/sebastianbergmann/phpunit.git", 624 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" 625 | }, 626 | "dist": { 627 | "type": "zip", 628 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", 629 | "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", 630 | "shasum": "" 631 | }, 632 | "require": { 633 | "ext-dom": "*", 634 | "ext-json": "*", 635 | "ext-libxml": "*", 636 | "ext-mbstring": "*", 637 | "ext-xml": "*", 638 | "myclabs/deep-copy": "~1.3", 639 | "php": "^5.6 || ^7.0", 640 | "phpspec/prophecy": "^1.6.2", 641 | "phpunit/php-code-coverage": "^4.0.4", 642 | "phpunit/php-file-iterator": "~1.4", 643 | "phpunit/php-text-template": "~1.2", 644 | "phpunit/php-timer": "^1.0.6", 645 | "phpunit/phpunit-mock-objects": "^3.2", 646 | "sebastian/comparator": "^1.2.4", 647 | "sebastian/diff": "^1.4.3", 648 | "sebastian/environment": "^1.3.4 || ^2.0", 649 | "sebastian/exporter": "~2.0", 650 | "sebastian/global-state": "^1.1", 651 | "sebastian/object-enumerator": "~2.0", 652 | "sebastian/resource-operations": "~1.0", 653 | "sebastian/version": "^1.0.6|^2.0.1", 654 | "symfony/yaml": "~2.1|~3.0|~4.0" 655 | }, 656 | "conflict": { 657 | "phpdocumentor/reflection-docblock": "3.0.2" 658 | }, 659 | "require-dev": { 660 | "ext-pdo": "*" 661 | }, 662 | "suggest": { 663 | "ext-xdebug": "*", 664 | "phpunit/php-invoker": "~1.1" 665 | }, 666 | "bin": [ 667 | "phpunit" 668 | ], 669 | "type": "library", 670 | "extra": { 671 | "branch-alias": { 672 | "dev-master": "5.7.x-dev" 673 | } 674 | }, 675 | "autoload": { 676 | "classmap": [ 677 | "src/" 678 | ] 679 | }, 680 | "notification-url": "https://packagist.org/downloads/", 681 | "license": [ 682 | "BSD-3-Clause" 683 | ], 684 | "authors": [ 685 | { 686 | "name": "Sebastian Bergmann", 687 | "email": "sebastian@phpunit.de", 688 | "role": "lead" 689 | } 690 | ], 691 | "description": "The PHP Unit Testing framework.", 692 | "homepage": "https://phpunit.de/", 693 | "keywords": [ 694 | "phpunit", 695 | "testing", 696 | "xunit" 697 | ], 698 | "time": "2018-02-01 05:50:59" 699 | }, 700 | { 701 | "name": "phpunit/phpunit-mock-objects", 702 | "version": "3.4.4", 703 | "source": { 704 | "type": "git", 705 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 706 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" 707 | }, 708 | "dist": { 709 | "type": "zip", 710 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", 711 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", 712 | "shasum": "" 713 | }, 714 | "require": { 715 | "doctrine/instantiator": "^1.0.2", 716 | "php": "^5.6 || ^7.0", 717 | "phpunit/php-text-template": "^1.2", 718 | "sebastian/exporter": "^1.2 || ^2.0" 719 | }, 720 | "conflict": { 721 | "phpunit/phpunit": "<5.4.0" 722 | }, 723 | "require-dev": { 724 | "phpunit/phpunit": "^5.4" 725 | }, 726 | "suggest": { 727 | "ext-soap": "*" 728 | }, 729 | "type": "library", 730 | "extra": { 731 | "branch-alias": { 732 | "dev-master": "3.2.x-dev" 733 | } 734 | }, 735 | "autoload": { 736 | "classmap": [ 737 | "src/" 738 | ] 739 | }, 740 | "notification-url": "https://packagist.org/downloads/", 741 | "license": [ 742 | "BSD-3-Clause" 743 | ], 744 | "authors": [ 745 | { 746 | "name": "Sebastian Bergmann", 747 | "email": "sb@sebastian-bergmann.de", 748 | "role": "lead" 749 | } 750 | ], 751 | "description": "Mock Object library for PHPUnit", 752 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 753 | "keywords": [ 754 | "mock", 755 | "xunit" 756 | ], 757 | "abandoned": true, 758 | "time": "2017-06-30 09:13:00" 759 | }, 760 | { 761 | "name": "sebastian/code-unit-reverse-lookup", 762 | "version": "1.0.1", 763 | "source": { 764 | "type": "git", 765 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 766 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 767 | }, 768 | "dist": { 769 | "type": "zip", 770 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 771 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 772 | "shasum": "" 773 | }, 774 | "require": { 775 | "php": "^5.6 || ^7.0" 776 | }, 777 | "require-dev": { 778 | "phpunit/phpunit": "^5.7 || ^6.0" 779 | }, 780 | "type": "library", 781 | "extra": { 782 | "branch-alias": { 783 | "dev-master": "1.0.x-dev" 784 | } 785 | }, 786 | "autoload": { 787 | "classmap": [ 788 | "src/" 789 | ] 790 | }, 791 | "notification-url": "https://packagist.org/downloads/", 792 | "license": [ 793 | "BSD-3-Clause" 794 | ], 795 | "authors": [ 796 | { 797 | "name": "Sebastian Bergmann", 798 | "email": "sebastian@phpunit.de" 799 | } 800 | ], 801 | "description": "Looks up which function or method a line of code belongs to", 802 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 803 | "time": "2017-03-04 06:30:41" 804 | }, 805 | { 806 | "name": "sebastian/comparator", 807 | "version": "1.2.4", 808 | "source": { 809 | "type": "git", 810 | "url": "https://github.com/sebastianbergmann/comparator.git", 811 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 812 | }, 813 | "dist": { 814 | "type": "zip", 815 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 816 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 817 | "shasum": "" 818 | }, 819 | "require": { 820 | "php": ">=5.3.3", 821 | "sebastian/diff": "~1.2", 822 | "sebastian/exporter": "~1.2 || ~2.0" 823 | }, 824 | "require-dev": { 825 | "phpunit/phpunit": "~4.4" 826 | }, 827 | "type": "library", 828 | "extra": { 829 | "branch-alias": { 830 | "dev-master": "1.2.x-dev" 831 | } 832 | }, 833 | "autoload": { 834 | "classmap": [ 835 | "src/" 836 | ] 837 | }, 838 | "notification-url": "https://packagist.org/downloads/", 839 | "license": [ 840 | "BSD-3-Clause" 841 | ], 842 | "authors": [ 843 | { 844 | "name": "Jeff Welch", 845 | "email": "whatthejeff@gmail.com" 846 | }, 847 | { 848 | "name": "Volker Dusch", 849 | "email": "github@wallbash.com" 850 | }, 851 | { 852 | "name": "Bernhard Schussek", 853 | "email": "bschussek@2bepublished.at" 854 | }, 855 | { 856 | "name": "Sebastian Bergmann", 857 | "email": "sebastian@phpunit.de" 858 | } 859 | ], 860 | "description": "Provides the functionality to compare PHP values for equality", 861 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 862 | "keywords": [ 863 | "comparator", 864 | "compare", 865 | "equality" 866 | ], 867 | "time": "2017-01-29 09:50:25" 868 | }, 869 | { 870 | "name": "sebastian/diff", 871 | "version": "1.4.3", 872 | "source": { 873 | "type": "git", 874 | "url": "https://github.com/sebastianbergmann/diff.git", 875 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 876 | }, 877 | "dist": { 878 | "type": "zip", 879 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 880 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 881 | "shasum": "" 882 | }, 883 | "require": { 884 | "php": "^5.3.3 || ^7.0" 885 | }, 886 | "require-dev": { 887 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 888 | }, 889 | "type": "library", 890 | "extra": { 891 | "branch-alias": { 892 | "dev-master": "1.4-dev" 893 | } 894 | }, 895 | "autoload": { 896 | "classmap": [ 897 | "src/" 898 | ] 899 | }, 900 | "notification-url": "https://packagist.org/downloads/", 901 | "license": [ 902 | "BSD-3-Clause" 903 | ], 904 | "authors": [ 905 | { 906 | "name": "Kore Nordmann", 907 | "email": "mail@kore-nordmann.de" 908 | }, 909 | { 910 | "name": "Sebastian Bergmann", 911 | "email": "sebastian@phpunit.de" 912 | } 913 | ], 914 | "description": "Diff implementation", 915 | "homepage": "https://github.com/sebastianbergmann/diff", 916 | "keywords": [ 917 | "diff" 918 | ], 919 | "time": "2017-05-22 07:24:03" 920 | }, 921 | { 922 | "name": "sebastian/environment", 923 | "version": "2.0.0", 924 | "source": { 925 | "type": "git", 926 | "url": "https://github.com/sebastianbergmann/environment.git", 927 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 928 | }, 929 | "dist": { 930 | "type": "zip", 931 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 932 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 933 | "shasum": "" 934 | }, 935 | "require": { 936 | "php": "^5.6 || ^7.0" 937 | }, 938 | "require-dev": { 939 | "phpunit/phpunit": "^5.0" 940 | }, 941 | "type": "library", 942 | "extra": { 943 | "branch-alias": { 944 | "dev-master": "2.0.x-dev" 945 | } 946 | }, 947 | "autoload": { 948 | "classmap": [ 949 | "src/" 950 | ] 951 | }, 952 | "notification-url": "https://packagist.org/downloads/", 953 | "license": [ 954 | "BSD-3-Clause" 955 | ], 956 | "authors": [ 957 | { 958 | "name": "Sebastian Bergmann", 959 | "email": "sebastian@phpunit.de" 960 | } 961 | ], 962 | "description": "Provides functionality to handle HHVM/PHP environments", 963 | "homepage": "http://www.github.com/sebastianbergmann/environment", 964 | "keywords": [ 965 | "Xdebug", 966 | "environment", 967 | "hhvm" 968 | ], 969 | "time": "2016-11-26 07:53:53" 970 | }, 971 | { 972 | "name": "sebastian/exporter", 973 | "version": "2.0.0", 974 | "source": { 975 | "type": "git", 976 | "url": "https://github.com/sebastianbergmann/exporter.git", 977 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" 978 | }, 979 | "dist": { 980 | "type": "zip", 981 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 982 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 983 | "shasum": "" 984 | }, 985 | "require": { 986 | "php": ">=5.3.3", 987 | "sebastian/recursion-context": "~2.0" 988 | }, 989 | "require-dev": { 990 | "ext-mbstring": "*", 991 | "phpunit/phpunit": "~4.4" 992 | }, 993 | "type": "library", 994 | "extra": { 995 | "branch-alias": { 996 | "dev-master": "2.0.x-dev" 997 | } 998 | }, 999 | "autoload": { 1000 | "classmap": [ 1001 | "src/" 1002 | ] 1003 | }, 1004 | "notification-url": "https://packagist.org/downloads/", 1005 | "license": [ 1006 | "BSD-3-Clause" 1007 | ], 1008 | "authors": [ 1009 | { 1010 | "name": "Jeff Welch", 1011 | "email": "whatthejeff@gmail.com" 1012 | }, 1013 | { 1014 | "name": "Volker Dusch", 1015 | "email": "github@wallbash.com" 1016 | }, 1017 | { 1018 | "name": "Bernhard Schussek", 1019 | "email": "bschussek@2bepublished.at" 1020 | }, 1021 | { 1022 | "name": "Sebastian Bergmann", 1023 | "email": "sebastian@phpunit.de" 1024 | }, 1025 | { 1026 | "name": "Adam Harvey", 1027 | "email": "aharvey@php.net" 1028 | } 1029 | ], 1030 | "description": "Provides the functionality to export PHP variables for visualization", 1031 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1032 | "keywords": [ 1033 | "export", 1034 | "exporter" 1035 | ], 1036 | "time": "2016-11-19 08:54:04" 1037 | }, 1038 | { 1039 | "name": "sebastian/global-state", 1040 | "version": "1.1.1", 1041 | "source": { 1042 | "type": "git", 1043 | "url": "https://github.com/sebastianbergmann/global-state.git", 1044 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1045 | }, 1046 | "dist": { 1047 | "type": "zip", 1048 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1049 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1050 | "shasum": "" 1051 | }, 1052 | "require": { 1053 | "php": ">=5.3.3" 1054 | }, 1055 | "require-dev": { 1056 | "phpunit/phpunit": "~4.2" 1057 | }, 1058 | "suggest": { 1059 | "ext-uopz": "*" 1060 | }, 1061 | "type": "library", 1062 | "extra": { 1063 | "branch-alias": { 1064 | "dev-master": "1.0-dev" 1065 | } 1066 | }, 1067 | "autoload": { 1068 | "classmap": [ 1069 | "src/" 1070 | ] 1071 | }, 1072 | "notification-url": "https://packagist.org/downloads/", 1073 | "license": [ 1074 | "BSD-3-Clause" 1075 | ], 1076 | "authors": [ 1077 | { 1078 | "name": "Sebastian Bergmann", 1079 | "email": "sebastian@phpunit.de" 1080 | } 1081 | ], 1082 | "description": "Snapshotting of global state", 1083 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1084 | "keywords": [ 1085 | "global state" 1086 | ], 1087 | "time": "2015-10-12 03:26:01" 1088 | }, 1089 | { 1090 | "name": "sebastian/object-enumerator", 1091 | "version": "2.0.1", 1092 | "source": { 1093 | "type": "git", 1094 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1095 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" 1096 | }, 1097 | "dist": { 1098 | "type": "zip", 1099 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", 1100 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", 1101 | "shasum": "" 1102 | }, 1103 | "require": { 1104 | "php": ">=5.6", 1105 | "sebastian/recursion-context": "~2.0" 1106 | }, 1107 | "require-dev": { 1108 | "phpunit/phpunit": "~5" 1109 | }, 1110 | "type": "library", 1111 | "extra": { 1112 | "branch-alias": { 1113 | "dev-master": "2.0.x-dev" 1114 | } 1115 | }, 1116 | "autoload": { 1117 | "classmap": [ 1118 | "src/" 1119 | ] 1120 | }, 1121 | "notification-url": "https://packagist.org/downloads/", 1122 | "license": [ 1123 | "BSD-3-Clause" 1124 | ], 1125 | "authors": [ 1126 | { 1127 | "name": "Sebastian Bergmann", 1128 | "email": "sebastian@phpunit.de" 1129 | } 1130 | ], 1131 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1132 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1133 | "time": "2017-02-18 15:18:39" 1134 | }, 1135 | { 1136 | "name": "sebastian/recursion-context", 1137 | "version": "2.0.0", 1138 | "source": { 1139 | "type": "git", 1140 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1141 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" 1142 | }, 1143 | "dist": { 1144 | "type": "zip", 1145 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1146 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1147 | "shasum": "" 1148 | }, 1149 | "require": { 1150 | "php": ">=5.3.3" 1151 | }, 1152 | "require-dev": { 1153 | "phpunit/phpunit": "~4.4" 1154 | }, 1155 | "type": "library", 1156 | "extra": { 1157 | "branch-alias": { 1158 | "dev-master": "2.0.x-dev" 1159 | } 1160 | }, 1161 | "autoload": { 1162 | "classmap": [ 1163 | "src/" 1164 | ] 1165 | }, 1166 | "notification-url": "https://packagist.org/downloads/", 1167 | "license": [ 1168 | "BSD-3-Clause" 1169 | ], 1170 | "authors": [ 1171 | { 1172 | "name": "Jeff Welch", 1173 | "email": "whatthejeff@gmail.com" 1174 | }, 1175 | { 1176 | "name": "Sebastian Bergmann", 1177 | "email": "sebastian@phpunit.de" 1178 | }, 1179 | { 1180 | "name": "Adam Harvey", 1181 | "email": "aharvey@php.net" 1182 | } 1183 | ], 1184 | "description": "Provides functionality to recursively process PHP variables", 1185 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1186 | "time": "2016-11-19 07:33:16" 1187 | }, 1188 | { 1189 | "name": "sebastian/resource-operations", 1190 | "version": "1.0.0", 1191 | "source": { 1192 | "type": "git", 1193 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1194 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1195 | }, 1196 | "dist": { 1197 | "type": "zip", 1198 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1199 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1200 | "shasum": "" 1201 | }, 1202 | "require": { 1203 | "php": ">=5.6.0" 1204 | }, 1205 | "type": "library", 1206 | "extra": { 1207 | "branch-alias": { 1208 | "dev-master": "1.0.x-dev" 1209 | } 1210 | }, 1211 | "autoload": { 1212 | "classmap": [ 1213 | "src/" 1214 | ] 1215 | }, 1216 | "notification-url": "https://packagist.org/downloads/", 1217 | "license": [ 1218 | "BSD-3-Clause" 1219 | ], 1220 | "authors": [ 1221 | { 1222 | "name": "Sebastian Bergmann", 1223 | "email": "sebastian@phpunit.de" 1224 | } 1225 | ], 1226 | "description": "Provides a list of PHP built-in functions that operate on resources", 1227 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1228 | "time": "2015-07-28 20:34:47" 1229 | }, 1230 | { 1231 | "name": "sebastian/version", 1232 | "version": "2.0.1", 1233 | "source": { 1234 | "type": "git", 1235 | "url": "https://github.com/sebastianbergmann/version.git", 1236 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1237 | }, 1238 | "dist": { 1239 | "type": "zip", 1240 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1241 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1242 | "shasum": "" 1243 | }, 1244 | "require": { 1245 | "php": ">=5.6" 1246 | }, 1247 | "type": "library", 1248 | "extra": { 1249 | "branch-alias": { 1250 | "dev-master": "2.0.x-dev" 1251 | } 1252 | }, 1253 | "autoload": { 1254 | "classmap": [ 1255 | "src/" 1256 | ] 1257 | }, 1258 | "notification-url": "https://packagist.org/downloads/", 1259 | "license": [ 1260 | "BSD-3-Clause" 1261 | ], 1262 | "authors": [ 1263 | { 1264 | "name": "Sebastian Bergmann", 1265 | "email": "sebastian@phpunit.de", 1266 | "role": "lead" 1267 | } 1268 | ], 1269 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1270 | "homepage": "https://github.com/sebastianbergmann/version", 1271 | "time": "2016-10-03 07:35:21" 1272 | }, 1273 | { 1274 | "name": "symfony/polyfill-ctype", 1275 | "version": "v1.13.1", 1276 | "source": { 1277 | "type": "git", 1278 | "url": "https://github.com/symfony/polyfill-ctype.git", 1279 | "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" 1280 | }, 1281 | "dist": { 1282 | "type": "zip", 1283 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", 1284 | "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", 1285 | "shasum": "" 1286 | }, 1287 | "require": { 1288 | "php": ">=5.3.3" 1289 | }, 1290 | "suggest": { 1291 | "ext-ctype": "For best performance" 1292 | }, 1293 | "type": "library", 1294 | "extra": { 1295 | "branch-alias": { 1296 | "dev-master": "1.13-dev" 1297 | } 1298 | }, 1299 | "autoload": { 1300 | "psr-4": { 1301 | "Symfony\\Polyfill\\Ctype\\": "" 1302 | }, 1303 | "files": [ 1304 | "bootstrap.php" 1305 | ] 1306 | }, 1307 | "notification-url": "https://packagist.org/downloads/", 1308 | "license": [ 1309 | "MIT" 1310 | ], 1311 | "authors": [ 1312 | { 1313 | "name": "Gert de Pagter", 1314 | "email": "BackEndTea@gmail.com" 1315 | }, 1316 | { 1317 | "name": "Symfony Community", 1318 | "homepage": "https://symfony.com/contributors" 1319 | } 1320 | ], 1321 | "description": "Symfony polyfill for ctype functions", 1322 | "homepage": "https://symfony.com", 1323 | "keywords": [ 1324 | "compatibility", 1325 | "ctype", 1326 | "polyfill", 1327 | "portable" 1328 | ], 1329 | "time": "2019-11-27 13:56:44" 1330 | }, 1331 | { 1332 | "name": "symfony/yaml", 1333 | "version": "v3.4.36", 1334 | "source": { 1335 | "type": "git", 1336 | "url": "https://github.com/symfony/yaml.git", 1337 | "reference": "dab657db15207879217fc81df4f875947bf68804" 1338 | }, 1339 | "dist": { 1340 | "type": "zip", 1341 | "url": "https://api.github.com/repos/symfony/yaml/zipball/dab657db15207879217fc81df4f875947bf68804", 1342 | "reference": "dab657db15207879217fc81df4f875947bf68804", 1343 | "shasum": "" 1344 | }, 1345 | "require": { 1346 | "php": "^5.5.9|>=7.0.8", 1347 | "symfony/polyfill-ctype": "~1.8" 1348 | }, 1349 | "conflict": { 1350 | "symfony/console": "<3.4" 1351 | }, 1352 | "require-dev": { 1353 | "symfony/console": "~3.4|~4.0" 1354 | }, 1355 | "suggest": { 1356 | "symfony/console": "For validating YAML files using the lint command" 1357 | }, 1358 | "type": "library", 1359 | "extra": { 1360 | "branch-alias": { 1361 | "dev-master": "3.4-dev" 1362 | } 1363 | }, 1364 | "autoload": { 1365 | "psr-4": { 1366 | "Symfony\\Component\\Yaml\\": "" 1367 | }, 1368 | "exclude-from-classmap": [ 1369 | "/Tests/" 1370 | ] 1371 | }, 1372 | "notification-url": "https://packagist.org/downloads/", 1373 | "license": [ 1374 | "MIT" 1375 | ], 1376 | "authors": [ 1377 | { 1378 | "name": "Fabien Potencier", 1379 | "email": "fabien@symfony.com" 1380 | }, 1381 | { 1382 | "name": "Symfony Community", 1383 | "homepage": "https://symfony.com/contributors" 1384 | } 1385 | ], 1386 | "description": "Symfony Yaml Component", 1387 | "homepage": "https://symfony.com", 1388 | "time": "2019-10-24 15:33:53" 1389 | }, 1390 | { 1391 | "name": "webmozart/assert", 1392 | "version": "1.6.0", 1393 | "source": { 1394 | "type": "git", 1395 | "url": "https://github.com/webmozart/assert.git", 1396 | "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" 1397 | }, 1398 | "dist": { 1399 | "type": "zip", 1400 | "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", 1401 | "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", 1402 | "shasum": "" 1403 | }, 1404 | "require": { 1405 | "php": "^5.3.3 || ^7.0", 1406 | "symfony/polyfill-ctype": "^1.8" 1407 | }, 1408 | "conflict": { 1409 | "vimeo/psalm": "<3.6.0" 1410 | }, 1411 | "require-dev": { 1412 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 1413 | }, 1414 | "type": "library", 1415 | "autoload": { 1416 | "psr-4": { 1417 | "Webmozart\\Assert\\": "src/" 1418 | } 1419 | }, 1420 | "notification-url": "https://packagist.org/downloads/", 1421 | "license": [ 1422 | "MIT" 1423 | ], 1424 | "authors": [ 1425 | { 1426 | "name": "Bernhard Schussek", 1427 | "email": "bschussek@gmail.com" 1428 | } 1429 | ], 1430 | "description": "Assertions to validate method input/output with nice error messages.", 1431 | "keywords": [ 1432 | "assert", 1433 | "check", 1434 | "validate" 1435 | ], 1436 | "time": "2019-11-24 13:36:37" 1437 | } 1438 | ], 1439 | "aliases": [], 1440 | "minimum-stability": "stable", 1441 | "stability-flags": [], 1442 | "prefer-stable": false, 1443 | "prefer-lowest": false, 1444 | "platform": { 1445 | "php": ">=5.6.0" 1446 | }, 1447 | "platform-dev": [] 1448 | } 1449 | --------------------------------------------------------------------------------