From 5390288d8af1a3f00102b83f8eb5fb0c13a7d4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Mat=C4=9Bj=C4=8Dek?= Date: Fri, 25 Jan 2019 12:54:47 +0100 Subject: [PATCH] Fio: php7.1+, type hint, nette 3.0 --- .gitattributes | 1 + .gitignore | 5 +- .travis.yml | 13 +- README.md | 50 ++--- changelog.md | 9 + composer.json | 57 +++--- src/Account/AccountCollection.php | 55 +++-- src/Account/AccountCollectionFactory.php | 18 +- src/Account/Bank.php | 124 +++++++----- src/Account/FioAccount.php | 28 +-- src/Exceptions/Fio.php | 8 + src/Exceptions/InvalidArgument.php | 43 ++++ src/Exceptions/InvalidState.php | 8 + src/Exceptions/QueueLimit.php | 8 + src/Exceptions/ResponsePay.php | 8 + src/Exceptions/Runtime.php | 8 + src/Exceptions/ServiceUnavailable.php | 8 + src/Fio.php | 18 +- src/FioPay.php | 119 ++++++----- src/FioRead.php | 70 +++---- src/Request/IQueue.php | 21 +- src/Request/Log.php | 34 ++++ src/Request/Pay/Payment/Euro.php | 191 +++--------------- src/Request/Pay/Payment/Foreign.php | 121 +++++++++++ src/Request/Pay/Payment/International.php | 106 ++++------ src/Request/Pay/Payment/National.php | 96 +++++---- src/Request/Pay/Payment/Property.php | 151 +++++--------- src/Request/Pay/Payment/Symbols.php | 50 +++++ src/Request/Pay/XMLFile.php | 94 +++++---- src/Request/Queue.php | 141 +++++++------ src/Request/Read/Files/Json.php | 38 ++-- src/Request/Read/IReader.php | 31 +-- src/Response/Pay/IResponse.php | 23 ++- src/Response/Pay/XMLResponse.php | 68 ++++--- src/Response/Read/ITransactionListFactory.php | 17 +- src/Response/Read/JsonTransactionFactory.php | 79 ++++---- src/Response/Read/Transaction.php | 3 +- src/Response/Read/TransactionAbstract.php | 53 ++--- src/Response/Read/TransactionList.php | 22 +- src/Utils/FioFactory.php | 71 +++---- src/Utils/Strings.php | 50 ++--- src/exceptions.php | 19 -- tests/bootstrap.php | 7 +- tests/config/phpstan.neon | 3 + tests/data/ClientMock.php | 51 +++++ tests/data/FioFactory.php | 33 +-- tests/data/Queue.php | 16 +- tests/data/Request.php | 113 +++++++++++ tests/data/Response.php | 130 ++++++++++++ tests/data/Stream.php | 109 ++++++++++ .../2015-01-01-2015-04-16-transactions.srlz | Bin 7696 -> 7746 bytes tests/data/tests/2015-2-transactions.srlz | Bin 2824 -> 2839 bytes tests/data/tests/custom.srlz | Bin 3158 -> 3069 bytes tests/data/tests/last-transactions.srlz | Bin 3670 -> 3690 bytes tests/data/tests/payment/euro-minimum.xml | 2 +- .../tests/payment/international-minimum.xml | 2 +- tests/data/tests/payment/multi-pay.xml | 2 +- tests/data/tests/payment/pay-maximum.xml | 2 +- tests/data/tests/payment/pay-minimum.xml | 2 +- tests/data/tests/payment/response-error.xml | 22 ++ .../2015-01-01-2015-04-16-transactions.srlz | Bin 7682 -> 7732 bytes .../tests/php7.1/2015-2-transactions.srlz | Bin 2820 -> 2835 bytes tests/data/tests/php7.1/custom.srlz | Bin 3067 -> 3077 bytes .../data/tests/php7.1/last-transactions.srlz | Bin 3656 -> 3676 bytes tests/origin/FioTest.php | 22 +- tests/origin/account.example.ini | 3 + tests/phpstan | 5 + ...ionTest.phpt => AccountCollectionTest.php} | 52 ++++- tests/src/Account/BankTest.php | 91 +++++++++ tests/src/Account/BankTest.phpt | 58 ------ tests/src/Account/bad-accounts.ini | 3 +- tests/src/Exceptions/InvalidArgumentTest.php | 73 +++++++ tests/src/{FioPayTest.phpt => FioPayTest.php} | 34 ++-- .../src/{FioReadTest.phpt => FioReadTest.php} | 49 +++-- .../Payment/{EuroTest.phpt => EuroTest.php} | 45 +++-- ...ationalTest.phpt => InternationalTest.php} | 40 ++-- .../{NationalTest.phpt => NationalTest.php} | 57 +++--- tests/src/Request/QueueTest.php | 120 +++++++++++ tests/src/Response/Pay/XMLResponseTest.php | 45 +++++ tests/src/Response/Pay/XMLResponseTest.phpt | 27 --- ...Test.phpt => JsonStatementFactoryTest.php} | 45 +++-- ...ptionTest.phpt => ServerExceptionTest.php} | 17 +- 82 files changed, 2154 insertions(+), 1263 deletions(-) create mode 100644 changelog.md create mode 100644 src/Exceptions/Fio.php create mode 100644 src/Exceptions/InvalidArgument.php create mode 100644 src/Exceptions/InvalidState.php create mode 100644 src/Exceptions/QueueLimit.php create mode 100644 src/Exceptions/ResponsePay.php create mode 100644 src/Exceptions/Runtime.php create mode 100644 src/Exceptions/ServiceUnavailable.php create mode 100644 src/Request/Log.php create mode 100644 src/Request/Pay/Payment/Foreign.php create mode 100644 src/Request/Pay/Payment/Symbols.php delete mode 100644 src/exceptions.php create mode 100644 tests/config/phpstan.neon create mode 100644 tests/data/ClientMock.php create mode 100644 tests/data/Request.php create mode 100644 tests/data/Response.php create mode 100644 tests/data/Stream.php create mode 100644 tests/data/tests/payment/response-error.xml create mode 100644 tests/origin/account.example.ini create mode 100755 tests/phpstan rename tests/src/Account/{AccountCollectionTest.phpt => AccountCollectionTest.php} (61%) create mode 100644 tests/src/Account/BankTest.php delete mode 100644 tests/src/Account/BankTest.phpt create mode 100644 tests/src/Exceptions/InvalidArgumentTest.php rename tests/src/{FioPayTest.phpt => FioPayTest.php} (56%) rename tests/src/{FioReadTest.phpt => FioReadTest.php} (87%) rename tests/src/Request/Pay/Payment/{EuroTest.phpt => EuroTest.php} (72%) rename tests/src/Request/Pay/Payment/{InternationalTest.phpt => InternationalTest.php} (73%) rename tests/src/Request/Pay/Payment/{NationalTest.phpt => NationalTest.php} (57%) create mode 100644 tests/src/Request/QueueTest.php create mode 100644 tests/src/Response/Pay/XMLResponseTest.php delete mode 100644 tests/src/Response/Pay/XMLResponseTest.phpt rename tests/src/Response/Read/{JsonTest.phpt => JsonStatementFactoryTest.php} (53%) rename tests/src/Response/Read/{ServerExceptionTest.phpt => ServerExceptionTest.php} (50%) diff --git a/.gitattributes b/.gitattributes index 39d973f..db2655d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ .gitattributes export-ignore .gitignore export-ignore .travis.yml export-ignore +changelog.md export-ignore tests export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore index 683be31..537cd45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ -/.idea/ -/nbproject/ /vendor/ composer.lock *~ /tests/**/output/ -/tests/origin/account.ini \ No newline at end of file +/tests/origin/account.ini +/coverage.html diff --git a/.travis.yml b/.travis.yml index 5378483..50e59a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,21 @@ language: php php: - - 5.5 - - 5.6 - - 7.0 - 7.1 - 7.2 + - 7.3 + - 7.4 + +matrix: + allow_failures: + - php: 7.4 before_script: - composer self-update - - if [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then NTESTER_FLAGS="phpdbg --coverage ./coverage.xml --coverage-src ./src"; else TESTER_FLAGS=""; fi + - if [ "$TRAVIS_PHP_VERSION" == "7.3" ]; then NTESTER_FLAGS="phpdbg --coverage ./coverage.xml --coverage-src ./src"; else TESTER_FLAGS=""; fi after_script: - - if [ "$TRAVIS_PHP_VERSION" == "7.1" ]; then + - if [ "$TRAVIS_PHP_VERSION" == "7.3" ]; then wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar && php coveralls.phar --verbose --config tests/.coveralls.yml || true; diff --git a/README.md b/README.md index 71024a5..75ae2a8 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,37 @@ -Fio -===== +# Fio + [![Build Status](https://travis-ci.org/h4kuna/fio.svg?branch=master)](https://travis-ci.org/h4kuna/fio) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/h4kuna/fio/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/h4kuna/fio/?branch=master) [![Downloads this Month](https://img.shields.io/packagist/dm/h4kuna/fio.svg)](https://packagist.org/packages/h4kuna/fio) [![Latest stable](https://img.shields.io/packagist/v/h4kuna/fio.svg)](https://packagist.org/packages/h4kuna/fio) [![Coverage Status](https://coveralls.io/repos/github/h4kuna/fio/badge.svg?branch=master)](https://coveralls.io/github/h4kuna/fio?branch=master) -Support [Fio API](http://www.fio.sk/docs/cz/API_Bankovnictvi.pdf). Default read via json file. +Support [Fio API](http://www.fio.sk/docs/cz/API_Bankovnictvi.pdf). Read is provided via json file. + +### Versions -Require PHP 5.5+. For older PHP 5.3+ let's use stable [version 1.2.1](https://github.com/h4kuna/fio/releases/tag/v1.2.1). +Here is [changlog](changelog.md) + +- PHP 7.1+ let's use version 2.0+ +- PHP 5.5 - 7.0 let's use stable [version 1.3.5](https://github.com/h4kuna/fio/releases/tag/v1.3.5). +- PHP 5.3 - 5.4 let's use stable [version 1.2.1](https://github.com/h4kuna/fio/releases/tag/v1.2.1). > Note: php 7.1 [has bug](https://bugs.php.net/bug.php?id=72567) with float number and json_encode, therefore all float numbers are retyping to sting. -Nette framework ---------------- +### Nette framework Follow this [extension](//github.com/h4kuna/fio-nette). -Installation to project ------------------------ +### Installation to project + The best way to install h4kuna/fio is using Composer: ```sh $ composer require h4kuna/fio ``` -How to use ---------------- +### How to use Here is [example](tests/origin/FioTest.php) and run via cli. This script require account.ini in same directory, whose looks like. + ```ini [my-account] account = 123456789 @@ -37,8 +42,7 @@ account = 987654321 token = zyxuvtsrfd ``` -### FioFactory -This object help you create instances of FioPay and FioRead. +FioFactory class help you create instances of classes FioPay and FioRead. ```php use h4kuna\Fio; @@ -53,13 +57,13 @@ $fioFactory = new Fio\Utils\FioFactory([ ] ]); -$fioRead = $fioFactory->createFioRead('my-alias'); -$fioPay = $fioFactory->createFioPay('next-alias'); +$fioRead = $fioFactory->createFioRead('my-account'); +$fioPay = $fioFactory->createFioPay('wife-account'); ``` -Reading -======= -### Read range between date. +## Reading + +#### Read range between date. ```php use h4kuna\Fio; @@ -78,7 +82,7 @@ foreach ($list as $transaction) { var_dump($list->getInfo()); ``` -### You can download transaction by id of year. +#### You can download transaction by id of year. ```php use h4kuna\Fio; /* @var $fioRead Fio\FioRead */ @@ -86,7 +90,7 @@ use h4kuna\Fio; $list = $fioRead->movementId(2, 2015); // second transaction of year 2015 ``` -### Very useful method where download last transactions. +#### Very useful method where download last transactions. After download it automaticaly set new break point. ```php use h4kuna\Fio; @@ -97,7 +101,7 @@ $list = $fioRead->lastDownload(); var_dump($list->getInfo()->idLastDownload); ``` -### Change your break point. +#### Change your break point. By date. ```php $fioRead->setLastDate('1986-12-30'); @@ -112,7 +116,7 @@ $list = $fioRead->lastDownload(); var_dump($list->getInfo()->idLastDownload); // 123456789 ``` -### Custom Transaction class +#### Custom Transaction class By default is h4kuna\Fio\Response\Read\Transaction if you want other names for properties. Let's define as second parameter to FioFactory. @@ -140,8 +144,8 @@ $fioFactory = new Utils\FioFactory([/* ... */], 'MyTransaction'); ``` -Payment (writing) -============= +## Payment (writing) + Api has three response languages, default is set **cs**. For change: ```php /* @var $fioPay h4kuna\Fio\FioPay */ diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..58b971d --- /dev/null +++ b/changelog.md @@ -0,0 +1,9 @@ +# Fio + +### v 2.0 +- support only php 7.1+ +- exceptions move and rename from `h4kuna\Fio\Exception` to `h4kuna\Fio\Exceptions\` +- add type hint for methods and parameters +- add to files declare(strict_types=1) +- change interface API `h4kuna\Fio\Response\Pay\IResponse` remove prefix `get` +- add `Log` for request pay xml \ No newline at end of file diff --git a/composer.json b/composer.json index 6f24d96..d4ebb11 100644 --- a/composer.json +++ b/composer.json @@ -1,28 +1,33 @@ { - "name": "h4kuna/fio", - "type": "library", - "description": "Read JSON file from Fio bank and can send request.", - "homepage": "https://github.com/h4kuna/fio", - "license": "MIT", - "authors": [ - { - "name": "Milan Matějček", - "email": "milan.matejcek@gmail.com", - "role": "Developer" - } - ], - "require": { - "guzzlehttp/guzzle": "^6.0", - "nette/safe-stream": "^2.0", - "nette/utils": "^2.2" - }, - "autoload": { - "psr-4": { - "h4kuna\\Fio\\": "src/" - }, - "files": ["src/exceptions.php"] - }, - "require-dev": { - "salamium/testinium": "^0.1" - } + "name": "h4kuna/fio", + "type": "library", + "description": "Read JSON file from Fio bank and can send request.", + "homepage": "https://github.com/h4kuna/fio", + "license": "MIT", + "authors": [ + { + "name": "Milan Matějček", + "email": "milan.matejcek@gmail.com", + "role": "Developer" + } + ], + "require": { + "php-64bit": ">=7.1", + "ext-mbstring": "*", + "ext-xmlwriter": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.0", + "nette/safe-stream": "^2.4", + "nette/utils": "^2.0 || ^3.0" + }, + "autoload": { + "psr-4": { + "h4kuna\\Fio\\": ["src/", "tests/src/"], + "h4kuna\\Fio\\Test\\": ["tests/data/"] + } + }, + "require-dev": { + "salamium/testinium": "^0.1", + "phpstan/phpstan": "^0.11.1" + } } diff --git a/src/Account/AccountCollection.php b/src/Account/AccountCollection.php index 8f9b9f1..e754356 100644 --- a/src/Account/AccountCollection.php +++ b/src/Account/AccountCollection.php @@ -1,12 +1,11 @@ -getDefault(); + } + return $this->get($alias); + } + + + private function get(string $alias): FioAccount { if (isset($this->accounts[$alias])) { return $this->accounts[$alias]; } - throw new AccountException('This account alias does not exists: ' . $alias); + throw new Exceptions\InvalidArgument('This account alias does not exists: ' . $alias); } - /** @return FioAccount|FALSE */ - public function getDefault() + + private function getDefault(): FioAccount { + if ($this->accounts === []) { + throw new Exceptions\InvalidState('Missing account, let\'s fill in configuration.'); + } return reset($this->accounts); } - /** - * @param string $alias - * @param FioAccount $account - * @return self - */ - public function addAccount($alias, FioAccount $account) + + public function addAccount(string $alias, FioAccount $account): AccountCollection { if (isset($this->accounts[$alias])) { - throw new AccountException('This alias already exists: ' . $alias); + throw new Exceptions\InvalidArgument('This alias already exists: ' . $alias); } $this->accounts[$alias] = $account; return $this; } - /** - * Returns items count. - * @return int - */ - public function count() + + public function count(): int { return count($this->accounts); } - /** - * Returns an iterator over all items. - * @return \ArrayIterator - */ - public function getIterator() + + public function getIterator(): \ArrayIterator { return new \ArrayIterator($this->accounts); } diff --git a/src/Account/AccountCollectionFactory.php b/src/Account/AccountCollectionFactory.php index 1d9cd94..7b8a62a 100644 --- a/src/Account/AccountCollectionFactory.php +++ b/src/Account/AccountCollectionFactory.php @@ -1,28 +1,20 @@ - $info) { if (!isset($info['token'])) { - throw new AccountException("Key 'token' is required for $alias."); + throw new Exceptions\InvalidArgument(sprintf('Key "token" is required for alias "%s".', $alias)); } elseif (!isset($info['account'])) { - throw new AccountException("Key 'account' is required for $alias."); + throw new Exceptions\InvalidArgument(sprintf('Key "account" is required for alias "%s".', $alias)); } $accountCollection->addAccount($alias, new FioAccount($info['account'], $info['token'])); } diff --git a/src/Account/Bank.php b/src/Account/Bank.php index 1593334..6bc7fe5 100644 --- a/src/Account/Bank.php +++ b/src/Account/Bank.php @@ -1,84 +1,116 @@ -\d+-)?(?P\d+)(?P/\d+)?$~', $account, $find)) { - throw new AccountException('Account must have format [prefix-]account[/code].'); - } + $this->account = $account; + $this->bankCode = $bankCode; + $this->prefix = $prefix; + } - if (strlen($find['account']) > 16) { - throw new AccountException('Account max length is 16 chars.'); - } - $this->account = $find['account']; + public function getAccount(): string + { + return $this->prefix() . $this->account; + } - if (!empty($find['code'])) { - $this->bankCode = $find['code']; - if (strlen($this->getBankCode()) != 4) { - throw new AccountException('Code must have 4 chars length.'); - } - } - if (!empty($find['prefix'])) { - $this->prefix = $find['prefix']; - } + public function getBankCode(): string + { + return $this->bankCode; } - /** @return string */ - public function getAccount() + + public function getPrefix(): string { - return $this->prefix . $this->account; + return $this->prefix; } - /** @return string */ - public function getBankCode() + + public function getAccountAndCode(): string { - if ($this->bankCode) { - return substr($this->bankCode, 1); + return $this->getAccount() . $this->bankCode(); + } + + + public function __toString() + { + return (string) $this->getAccount(); + } + + + private function bankCode(): string + { + if ($this->bankCode !== '') { + return '/' . $this->bankCode; } - return ''; + return $this->bankCode; } - /** @return string */ - public function getPrefix() + + private function prefix(): string { - if ($this->prefix) { - return substr($this->prefix, 0, -1); + if ($this->prefix !== '') { + return $this->prefix . '-'; } - return ''; + return $this->prefix; } - public function getAccountAndCode() + + public static function createInternational(string $account): self { - return $this->getAccount() . $this->bankCode; + if (!preg_match('~^(?P[a-z0-9]{1,34})(?P/[a-z0-9]{11})?$~i', $account, $find)) { + throw new InvalidArgument('Account must have format account[/code].'); + } + + $bankCode = ''; + if (isset($find['code']) && $find['code'] !== '') { + $bankCode = substr($find['code'], 1); + } + + return new self($find['account'], $bankCode, ''); } - public function __toString() + + public static function createNational(string $account): self { - return (string) $this->getAccount(); + if (!preg_match('~^(?P\d+-)?(?P\d+)(?P/\d+)?$~', $account, $find)) { + throw new InvalidArgument('Account must have format [prefix-]account[/code].'); + } + + if (strlen($find['account']) > 16) { + throw new InvalidArgument('Account max length is 16 chars.'); + } + + $account = $find['account']; + $prefix = $bankCode = ''; + if (isset($find['code']) && $find['code'] !== '') { + $bankCode = substr($find['code'], 1); + if (strlen($bankCode) !== 4) { + throw new InvalidArgument('Code must have 4 chars length.'); + } + } + + if (isset($find['prefix']) && $find['prefix'] !== '') { + $prefix = substr($find['prefix'], 0, -1); + } + return new self($account, $bankCode, $prefix); } } diff --git a/src/Account/FioAccount.php b/src/Account/FioAccount.php index 8c07142..7a4ca3f 100644 --- a/src/Account/FioAccount.php +++ b/src/Account/FioAccount.php @@ -1,10 +1,7 @@ -account = new Bank($account); + $this->account = Bank::createNational($account); $this->token = $token; } - /** @return string */ - public function getAccount() + + public function getAccount(): string { return $this->account->getAccount(); } - /** @return string */ - public function getBankCode() + + public function getBankCode(): string { return $this->account->getBankCode(); } - /** @return string */ - public function getToken() + + public function getToken(): string { return $this->token; } + + public function __toString() + { + return $this->getAccount(); + } + } diff --git a/src/Exceptions/Fio.php b/src/Exceptions/Fio.php new file mode 100644 index 0000000..c0d8f91 --- /dev/null +++ b/src/Exceptions/Fio.php @@ -0,0 +1,8 @@ + $size) { + throw new static(sprintf('Value "%s" is longer then allowed limit (%s).', $text, $size)); + } + return $text; + } + + + public static function checkRange(int $number, int $limit): int + { + if ($number < 0 || $number > $limit) { + throw new static(sprintf('Value is out of range "%s" must contain 1-%s positive digits.', $number, strlen((string) $limit))); + } + return $number; + } + + + public static function checkIsInList($value, array $list) + { + if (!in_array($value, $list, true)) { + throw new InvalidArgument(sprintf('Value "%s" is not contained in list: [%s].', $value, implode(', ', $list))); + } + return $value; + } + + + public static function checkLength(string $text, int $limit): string + { + if (strlen($text) !== $limit) { + throw new static(sprintf('Value has not exact length "%s" this is "%s" with length "%s".', $limit, $text, strlen((string) $text))); + } + return $text; + } + +} diff --git a/src/Exceptions/InvalidState.php b/src/Exceptions/InvalidState.php new file mode 100644 index 0000000..7904f33 --- /dev/null +++ b/src/Exceptions/InvalidState.php @@ -0,0 +1,8 @@ +queue = $queue; $this->account = $account; } - /** @return Account\FioAccount */ - public function getAccount() + + public function getAccount(): Account\FioAccount { return $this->account; } diff --git a/src/FioPay.php b/src/FioPay.php index c6ea1ee..d6a6535 100644 --- a/src/FioPay.php +++ b/src/FioPay.php @@ -1,14 +1,18 @@ -xmlFile = $xmlFile; } - /** @return Pay\Payment\Euro */ - public function createEuro($amount, $accountTo, $name) + + public function enableLog(): Log + { + return $this->log = new Log(); + } + + + public function createEuro(float $amount, string $accountTo, string $name, string $bic = ''): Pay\Payment\Euro { + $account = Bank::createInternational($accountTo); + if ($bic === '') { + $bic = $account->getBankCode(); + } + return (new Pay\Payment\Euro($this->account)) ->setName($name) - ->setAccountTo($accountTo) - ->setAmount($amount); + ->setAccountTo($account->getAccount()) + ->setAmount($amount) + ->setBic($bic); } - /** @return Pay\Payment\National */ - public function createNational($amount, $accountTo, $bankCode = null) + + public function createNational(float $amount, string $accountTo, string $bankCode = ''): Pay\Payment\National { + $account = Bank::createInternational($accountTo); + if ($bankCode === '') { + $bankCode = $account->getBankCode(); + } return (new Pay\Payment\National($this->account)) - ->setAccountTo($accountTo, $bankCode) + ->setAccountTo($account->getAccount()) + ->setBankCode($bankCode) ->setAmount($amount); } - /** @return Pay\Payment\International */ - public function createInternational($amount, $accountTo, $bic, $name, $street, $city, $country, $info) + + public function createInternational(float $amount, string $accountTo, string $name, string $street, string $city, string $country, string $info, string $bic = ''): Pay\Payment\International { + $account = Bank::createInternational($accountTo); + if ($bic === '') { + $bic = $account->getBankCode(); + } + return (new Pay\Payment\International($this->account)) ->setBic($bic) ->setName($name) ->setCountry($country) - ->setAccountTo($accountTo) + ->setAccountTo($account->getAccount()) ->setStreet($street) ->setCity($city) ->setRemittanceInfo1($info) ->setAmount($amount); } - /** @return Pay\IResponse */ - public function getUploadResponse() + + public function getUploadResponse(): IResponse { return $this->response; } + /** - * @param Pay\Payment\Property $property - * @return self + * @return static */ public function addPayment(Pay\Payment\Property $property) { @@ -75,24 +105,26 @@ public function addPayment(Pay\Payment\Property $property) return $this; } + /** * @param string|Pay\Payment\Property $filename - * @return Response\Pay\IResponse - * @throws InvalidArgumentException */ - public function send($filename = null) + public function send($filename = null): IResponse { if ($filename instanceof Pay\Payment\Property) { $this->xmlFile->setData($filename); } if ($this->xmlFile->isReady()) { - $this->setUploadExtenstion('xml'); - $filename = $this->xmlFile->getPathname(); - } elseif (is_file($filename)) { - $this->setUploadExtenstion(pathinfo($filename, PATHINFO_EXTENSION)); + $this->setUploadExtension('xml'); + $filename = $this->xmlFile->getPathname($this->log !== null); + if ($this->log !== null) { + $this->log->setFilename($filename); + } + } elseif (is_string($filename) && is_file($filename)) { + $this->setUploadExtension(pathinfo($filename, PATHINFO_EXTENSION)); } else { - throw new InvalidArgumentException('Is supported only filepath or Property object.'); + throw new InvalidArgument('Is supported only filepath or Property object.'); } $token = $this->getAccount()->getToken(); @@ -102,45 +134,30 @@ public function send($filename = null) 'lng' => $this->language, ]; - return $this->response = $this->queue->upload($this->getUrl(), $token, $post, $filename); + return $this->response = $this->queue->upload(self::getUrl(), $token, $post, $filename); } + /** * Response language. - * @param string $lang - * @return self - * @throws InvalidArgumentException + * @return static */ - public function setLanguage($lang) + public function setLanguage(string $lang) { - $this->language = strtolower($lang); - if (!in_array($this->language, self::$langs)) { - throw new InvalidArgumentException($this->language . ' avaible are ' . implode(', ', self::$langs)); - } + $this->language = InvalidArgument::checkIsInList(strtolower($lang), self::LANGS); return $this; } - /** @return string */ - private function getUrl() + + private static function getUrl(): string { return self::REST_URL . 'import/'; } - /** - * Set upload file extension. - * @param string $extension - * @return self - * @throws InvalidArgumentException - */ - private function setUploadExtenstion($extension) + + private function setUploadExtension(string $extension): void { - $extension = strtolower($extension); - static $extensions = ['xml', 'abo']; - if (!in_array($extension, $extensions)) { - throw new InvalidArgumentException('Unsupported file upload format: ' . $extension . ' avaible are ' . implode(', ', $extensions)); - } - $this->uploadExtension = $extension; - return $this; + $this->uploadExtension = InvalidArgument::checkIsInList(strtolower($extension), self::EXTENSIONS); } } diff --git a/src/FioRead.php b/src/FioRead.php index 85edab9..861e2f0 100644 --- a/src/FioRead.php +++ b/src/FioRead.php @@ -1,12 +1,13 @@ -download('periods/%s/%s/%s/transactions.%s', Utils\Strings::date($from), Utils\Strings::date($to), $this->readerFactory->getExtension()); return $this->readerFactory->create($data); @@ -38,66 +38,68 @@ public function movements($from = '-1 week', $to = 'now') /** * List of movemnts. - * @param int $id - * @param int|string|NULL $year format YYYY, NULL is current - * @return IFile - * @throws ServiceUnavailableException + * @param int $moveId + * @param int $year format YYYY, empty string is current + * @throws ServiceUnavailable */ - public function movementId($id, $year = null) + public function movementId(int $moveId, int $year = 0): TransactionList { - if ($year === null) { - $year = date('Y'); + if ($year === 0) { + $year = (int) date('Y'); } - $data = $this->download('by-id/%s/%s/%s/transactions.%s', $year, $id, $this->readerFactory->getExtension()); + $data = $this->download('by-id/%s/%s/%s/transactions.%s', (string) $year, (string) $moveId, $this->readerFactory->getExtension()); return $this->readerFactory->create($data); } + /** * Last movements from last breakpoint. - * @return IFile - * @throws ServiceUnavailableException + * @throws ServiceUnavailable */ - public function lastDownload() + public function lastDownload(): TransactionList { $data = $this->download('last/%s/transactions.%s', $this->readerFactory->getExtension()); return $this->readerFactory->create($data); } + /** * Set break point to id. - * @param int $moveId - * @return void - * @throws ServiceUnavailableException + * @throws ServiceUnavailable */ - public function setLastId($moveId) + public function setLastId(int $moveId): void { - $this->download('set-last-id/%s/%s/', $moveId); + $this->download('set-last-id/%s/%s/', (string) $moveId); } + /** * Set breakpoint to date. - * @param mixed $date - * @throws ServiceUnavailableException + * @param int|string|\DateTimeInterface $date + * @throws ServiceUnavailable */ public function setLastDate($date) { $this->download('set-last-date/%s/%s/', Utils\Strings::date($date)); } + /** * Last request url for read. This is for tests. - * @return string */ - public function getRequestUrl() + public function getRequestUrl(): string { return $this->requestUrl; } - private function download($apiUrl /* ... params */) + + /** + * @throws ServiceUnavailable + */ + private function download(string $apiUrl, string ...$args): string { - $args = func_get_args(); - $args[0] = $token = $this->account->getToken(); - $this->requestUrl = self::REST_URL . vsprintf($apiUrl, $args); + $token = $this->account->getToken(); + $this->requestUrl = self::REST_URL . sprintf($apiUrl, $token, ...$args); return $this->queue->download($token, $this->requestUrl); } diff --git a/src/Request/IQueue.php b/src/Request/IQueue.php index 1549f48..5cbb1cf 100644 --- a/src/Request/IQueue.php +++ b/src/Request/IQueue.php @@ -1,12 +1,9 @@ -filename = $filename; + } + + + public function getFilename(): string + { + return $this->filename; + } + + + public function getContent(): string + { + $content = @file_get_contents($this->filename); + if ($content === false) { + throw new InvalidState(sprintf('Filname "%s" can not read.', $this->filename)); + } + return $content; + } + +} diff --git a/src/Request/Pay/Payment/Euro.php b/src/Request/Pay/Payment/Euro.php index 31ca00d..0cff5d0 100644 --- a/src/Request/Pay/Payment/Euro.php +++ b/src/Request/Pay/Payment/Euro.php @@ -1,179 +1,40 @@ -setCurrency('EUR'); - } - - /** - * @param string $accountTo ISO 13616 - * @throws Fio\InvalidArgumentException - */ - public function setAccountTo($accountTo) - { - if (strlen($accountTo) > 34) { - throw new Fio\InvalidArgumentException('Account is to long. ISO 13616.'); - } - $this->accountTo = $accountTo; - return $this; - } - - /** - * @param string $bic - * @return self - * @throws Fio\InvalidArgumentException - */ - public function setBic($bic) - { - if (strlen($bic) != 11) { - throw new Fio\InvalidArgumentException('BIC must lenght 11. Is ISO 9362.'); - } - $this->bic = $bic; - return $this; - } - - /** - * @param string $str - * @return self - */ - public function setStreet($str) - { - $this->benefStreet = Utils\Strings::substr($str, 35); - return $this; - } - /** - * @param string $str - * @return self - */ - public function setCity($str) + public function getExpectedProperty(): array { - $this->benefCity = Utils\Strings::substr($str, 35); - return $this; + return [ + 'accountFrom' => true, + 'currency' => true, + 'amount' => true, + 'accountTo' => true, + 'ks' => false, + 'vs' => false, + 'ss' => false, + 'bic' => false, + 'date' => true, + 'comment' => false, + 'benefName' => true, + 'benefStreet' => false, + 'benefCity' => false, + 'benefCountry' => false, + 'remittanceInfo1' => false, + 'remittanceInfo2' => false, + 'remittanceInfo3' => false, + 'paymentReason' => false, + 'paymentType' => false, + ]; } - /** - * @param string $benefCountry - * @return self - */ - public function setCountry($benefCountry) - { - $country = strtoupper($benefCountry); - if (strlen($country) != 2 && $country != 'TCH') { - throw new Fio\InvalidArgumentException('Look at to manual for country code section 6.3.3.'); - } - $this->benefCountry = $country; - return $this; - } - - /** - * @param string $name - * @return self - */ - public function setName($name) - { - $this->benefName = Utils\Strings::substr($name, 35); - return $this; - } - - /** - * @param string $str - * @return self - */ - public function setRemittanceInfo1($str) - { - $this->remittanceInfo1 = Utils\Strings::substr($str, 35); - return $this; - } - - /** - * @param string $str - * @return self - */ - public function setRemittanceInfo2($str) - { - $this->remittanceInfo2 = Utils\Strings::substr($str, 35); - return $this; - } - - /** - * @param string $str - * @return self - */ - public function setRemittanceInfo3($str) - { - $this->remittanceInfo3 = Utils\Strings::substr($str, 35); - return $this; - } - - /** - * @param int $type - * @return self - * @throws Fio\InvalidArgumentException - */ - public function setPaymentType($type) - { - static $types = [self::PAYMENT_STANDARD, self::PAYMENT_PRIORITY]; - if (!in_array($type, $types)) { - throw new Fio\InvalidArgumentException('Unsupported payment type: ' . $type); - } - $this->paymentType = $type; - return $this; - } - - protected function getExpectedProperty() - { - return ['accountFrom', 'currency', 'amount', 'accountTo', 'ks', 'vs', - 'ss', 'bic', 'date', 'comment', 'benefName', 'benefStreet', 'benefCity', - 'benefCountry', 'remittanceInfo1', 'remittanceInfo2', 'remittanceInfo3', - 'paymentReason', 'paymentType']; - } - public function getStartXmlElement() + public function getStartXmlElement(): string { return 'T2Transaction'; } diff --git a/src/Request/Pay/Payment/Foreign.php b/src/Request/Pay/Payment/Foreign.php new file mode 100644 index 0000000..67afc63 --- /dev/null +++ b/src/Request/Pay/Payment/Foreign.php @@ -0,0 +1,121 @@ +setCurrency('EUR'); + } + + + /** + * @param string $accountTo ISO 13616 + */ + public function setAccountTo(string $accountTo) + { + $this->accountTo = InvalidArgument::check($accountTo, 34); + return $this; + } + + + /** + * @param string $bic ISO 9362 + */ + public function setBic(string $bic) + { + $this->bic = InvalidArgument::checkLength($bic, 11); + return $this; + } + + + public function setStreet(string $street) + { + $this->benefStreet = InvalidArgument::check($street, 35); + return $this; + } + + + public function setCity(string $city) + { + $this->benefCity = InvalidArgument::check($city, 35); + return $this; + } + + + public function setCountry(string $benefCountry) + { + $country = strtoupper($benefCountry); + if (strlen($country) !== 2 && $country !== 'TCH') { + throw new InvalidArgument('Look at to manual for country code section 6.3.3.'); + } + $this->benefCountry = $country; + return $this; + } + + + public function setName(string $name) + { + $this->benefName = InvalidArgument::check($name, 35); + return $this; + } + + + public function setRemittanceInfo1(string $info) + { + $this->remittanceInfo1 = InvalidArgument::check($info, 35); + return $this; + } + + + public function setRemittanceInfo2(string $info) + { + $this->remittanceInfo2 = InvalidArgument::check($info, 35); + return $this; + } + + + public function setRemittanceInfo3(string $str) + { + $this->remittanceInfo3 = InvalidArgument::check($str, 35); + return $this; + } + + + public function setPaymentType(int $type) + { + $this->paymentType = InvalidArgument::checkIsInList($type, self::TYPES_PAYMENT); + return $this; + } + +} diff --git a/src/Request/Pay/Payment/International.php b/src/Request/Pay/Payment/International.php index 1960b4c..7d7aa2a 100644 --- a/src/Request/Pay/Payment/International.php +++ b/src/Request/Pay/Payment/International.php @@ -1,38 +1,20 @@ -detailsOfCharges = $type; + $this->detailsOfCharges = Exceptions\InvalidArgument::checkIsInList($type, self::TYPES_CHARGES); return $this; } + /** - * @param string $str - * @return self + * @return static */ - public function setRemittanceInfo4($str) + public function setRemittanceInfo4(string $info) { - $this->remittanceInfo4 = Utils\Strings::substr($str, 35); + $this->remittanceInfo4 = Exceptions\InvalidArgument::check($info, 35); return $this; } - protected function getExpectedProperty() - { - return ['accountFrom', 'currency', 'amount', 'accountTo', 'bic', 'date', - 'comment', 'benefName', 'benefStreet', 'benefCity', 'benefCountry', - 'remittanceInfo1', 'remittanceInfo2', 'remittanceInfo3', 'remittanceInfo4', - 'detailsOfCharges', 'paymentReason']; - } - - public function getStartXmlElement() - { - return 'ForeignTransaction'; - } - /** @internal */ - public function setConstantSymbol($ks) + public function getExpectedProperty(): array { - throw new Fio\InvalidArgumentException('Not available.'); + return [ + 'accountFrom' => true, + 'currency' => true, + 'amount' => true, + 'accountTo' => true, + 'bic' => true, + 'date' => true, + 'comment' => false, + 'benefName' => true, + 'benefStreet' => true, + 'benefCity' => true, + 'benefCountry' => true, + 'remittanceInfo1' => true, + 'remittanceInfo2' => false, + 'remittanceInfo3' => false, + 'remittanceInfo4' => false, + 'detailsOfCharges' => true, + 'paymentReason' => true, + ]; } - /** @internal */ - public function setSpecificSymbol($ss) - { - throw new Fio\InvalidArgumentException('Not available.'); - } - /** @internal */ - public function setVariableSymbol($vs) + public function getStartXmlElement(): string { - throw new Fio\InvalidArgumentException('Not available.'); - } - - /** @internal */ - public function setPaymentType($type) - { - throw new Fio\InvalidArgumentException('Not available.'); + return 'ForeignTransaction'; } } diff --git a/src/Request/Pay/Payment/National.php b/src/Request/Pay/Payment/National.php index cfe0982..a74ff36 100644 --- a/src/Request/Pay/Payment/National.php +++ b/src/Request/Pay/Payment/National.php @@ -1,72 +1,84 @@ -paymentType = $type; + $this->paymentType = Exceptions\InvalidArgument::checkIsInList($type, self::TYPES_PAYMENT);; return $this; } - /** - * @param string $str - * @return self - */ - public function setMessage($str) + + /** @return static */ + public function setMessage(string $message) { - $this->messageForRecipient = Utils\Strings::substr($str, 140); + $this->messageForRecipient = Exceptions\InvalidArgument::check($message, 140); return $this; } - public function setAccountTo($accountTo, $bankCode = null) + + /** @return static */ + public function setAccountTo(string $accountTo) { - $accountObject = Utils\Strings::createAccount($accountTo, $bankCode); - $this->accountTo = $accountObject->getAccount(); - $this->bankCode = $accountObject->getBankCode(); + $this->accountTo = $accountTo; return $this; } - protected function getExpectedProperty() + + /** @return static */ + public function setBankCode(string $bankCode) { - return ['accountFrom', 'currency', 'amount', 'accountTo', 'bankCode', - 'ks', 'vs', 'ss', 'date', 'messageForRecipient', 'comment', - 'paymentReason', 'paymentType']; + $this->bankCode = $bankCode; + return $this; } - public function getStartXmlElement() + + public function getExpectedProperty(): array + { + return [ + // key => mandatory, + 'accountFrom' => true, + 'currency' => true, + 'amount' => true, + 'accountTo' => true, + 'bankCode' => true, + 'ks' => false, + 'vs' => false, + 'ss' => false, + 'date' => true, + 'messageForRecipient' => false, + 'comment' => false, + 'paymentReason' => false, + 'paymentType' => false, + ]; + } + + + public function getStartXmlElement(): string { return 'DomesticTransaction'; } diff --git a/src/Request/Pay/Payment/Property.php b/src/Request/Pay/Payment/Property.php index 7a28b01..3165b1b 100644 --- a/src/Request/Pay/Payment/Property.php +++ b/src/Request/Pay/Payment/Property.php @@ -1,43 +1,28 @@ -accountFrom = $account->getAccount(); + $this->accountFrom = $account; $this->setDate('now'); } - /** @return self */ - public function setAmount($val) + + /** + * @return static + */ + public function setAmount(float $amount) { - $this->amount = floatval($val); - if ($val <= 0) { - throw new Fio\InvalidArgumentException('Amount must by positive number.'); + $this->amount = $amount; + if ($amount <= 0) { + throw new InvalidArgument('Amount must by positive number.'); } return $this; } + /** - * @param string $accountTo - * @return self + * @return static */ - abstract public function setAccountTo($accountTo); + abstract public function setAccountTo(string $accountTo); + /** * Currency code ISO 4217. - * @param string $code case insensitive - * @return self + * @return static */ - public function setCurrency($code) + public function setCurrency(string $code) { if (!preg_match('~[a-z]{3}~i', $code)) { - throw new Fio\InvalidArgumentException('Currency code must match ISO 4217.'); + throw new InvalidArgument('Currency code must match ISO 4217.'); } $this->currency = strtoupper($code); return $this; } - /** - * @param string $ks - * @return self - */ - public function setConstantSymbol($ks) - { - if (!$ks) { - $ks = null; - } elseif (!preg_match('~\d{1,4}~', $ks)) { - throw new Fio\InvalidArgumentException('Constant symbol must contain 1-4 digits.'); - } - $this->ks = $ks; - return $this; - } /** - * @param string $str - * @return self + * @return static */ - public function setMyComment($str) + public function setMyComment(string $comment) { - $this->comment = Utils\Strings::substr($str, 255); + $this->comment = InvalidArgument::check($comment, 255); return $this; } + /** - * @param string|DateTime $str - * @return self + * @param int|string|\DateTimeInterface $date + * @return static */ - public function setDate($str) + public function setDate($date) { - $this->date = DateTime::from($str)->format('Y-m-d'); + $this->date = DateTime::from($date)->format('Y-m-d'); return $this; } - /** @return self */ - public function setPaymentReason($code) - { - if (!$code) { - $code = null; - } elseif (!preg_match('~\d{3}~', $code)) { - throw new Fio\InvalidArgumentException('Payment reason must contain 3 digits.'); - } - $this->paymentReason = $code; - return $this; - } /** - * @param string $ss - * @return self + * @return static */ - public function setSpecificSymbol($ss) + public function setPaymentReason(int $code) { - if (!$ss) { - $ss = null; - } elseif (!preg_match('~\d{1,10}~', $ss)) { - throw new Fio\InvalidArgumentException('Specific symbol must contain 1-10 digits.'); - } - $this->ss = $ss; + $this->paymentReason = InvalidArgument::checkRange($code, 999); return $this; } - /** - * @param string|int $vs - * @return self - */ - public function setVariableSymbol($vs) - { - if (!$vs) { - $vs = null; - } elseif (!preg_match('~\d{1,10}~', $vs)) { - throw new Fio\InvalidArgumentException('Variable symbol must contain 1-10 digits.'); - } - $this->vs = $vs; - return $this; - } /** * Order is important. - * @return string[] + * @return array */ - abstract protected function getExpectedProperty(); + abstract public function getExpectedProperty(): array; + - abstract public function getStartXmlElement(); + abstract public function getStartXmlElement(): string; - private function getProperties() + + private function getProperties(): array { if ($this->key === null) { $this->key = get_called_class(); @@ -188,6 +134,7 @@ private function getProperties() return self::$iterator[$this->key] = $this->getExpectedProperty(); } + /** * ITERATOR INTERFACE ****************************************************** * ************************************************************************* @@ -202,22 +149,26 @@ public function current() return $this->{$property}; } + public function key() { - return current(self::$iterator[$this->key]); + return key(self::$iterator[$this->key]); } + public function next() { next(self::$iterator[$this->key]); } + public function rewind() { $this->getProperties(); reset(self::$iterator[$this->key]); } + public function valid() { return array_key_exists(key(self::$iterator[$this->key]), self::$iterator[$this->key]); diff --git a/src/Request/Pay/Payment/Symbols.php b/src/Request/Pay/Payment/Symbols.php new file mode 100644 index 0000000..14ad5fd --- /dev/null +++ b/src/Request/Pay/Payment/Symbols.php @@ -0,0 +1,50 @@ +ks = InvalidArgument::checkRange($ks, 9999); + return $this; + } + + + /** + * @return static + */ + public function setVariableSymbol(int $vs) + { + $this->vs = InvalidArgument::checkRange($vs, 9999999999); + return $this; + } + + + /** + * @return static + */ + public function setSpecificSymbol(int $ss) + { + $this->ss = InvalidArgument::checkRange($ss, 9999999999); + return $this; + } + +} diff --git a/src/Request/Pay/XMLFile.php b/src/Request/Pay/XMLFile.php index 017d26f..9462d70 100644 --- a/src/Request/Pay/XMLFile.php +++ b/src/Request/Pay/XMLFile.php @@ -1,73 +1,66 @@ -temp = $temp; } - /** - * @param Payment\Property $data - * @return self - */ - public function setData(Payment\Property $data) + + public function setData(Payment\Property $data): self { - if ($this->content) { + if ($this->isReady() === false) { $this->createEmptyXml(); } return $this->setBody($data); } - /** @return string */ - public function getPathname() + + public function getPathname(bool $keepFile = false): string { - $filename = $this->temp . DIRECTORY_SEPARATOR . md5(microtime(true)) . '.xml'; + $filename = $this->temp . DIRECTORY_SEPARATOR . md5((string) microtime(true)) . '.xml'; file_put_contents($filename, $this->getXml()); - register_shutdown_function(function () use ($filename) { - @unlink($filename); - }); + if ($keepFile === false) { + register_shutdown_function(function () use ($filename) { + @unlink($filename); + }); + } return $filename; } - /** @return string XML */ - public function getXml() + + public function getXml(): string { - if ($this->content) { - return $this->content; + if ($this->isReady() === false) { + throw new InvalidState('You can read only onetime.'); } - return $this->content = $this->endDocument(); + return $this->endDocument(); } - /** @return bool */ - public function isReady() + + public function isReady(): bool { - return $this->content === null; + return $this->xml !== null; } - /** - * Prepare XML. - */ - private function createEmptyXml() + + private function createEmptyXml(): void { $this->xml = new XMLWriter; $this->xml->openMemory(); @@ -76,15 +69,22 @@ private function createEmptyXml() $this->xml->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $this->xml->writeAttribute('xsi:noNamespaceSchemaLocation', 'http://www.fio.cz/schema/importIB.xsd'); $this->xml->startElement('Orders'); - $this->content = null; } - private function setBody(Payment\Property $data) + + private function setBody(Payment\Property $data): self { + if ($this->xml === null) { + throw self::exceptionFirstCallSetData(); + } + $elements = $data->getExpectedProperty(); $this->xml->startElement($data->getStartXmlElement()); foreach ($data as $node => $value) { - if ($value === false) { - continue; + if ($value == false) { // intentionally == + if ($elements[$node] === false) { + continue; + } + $value = ''; } $this->xml->startElement($node); @@ -95,10 +95,22 @@ private function setBody(Payment\Property $data) return $this; } - private function endDocument() + + private function endDocument(): string { + if ($this->xml === null) { + throw self::exceptionFirstCallSetData(); + } $this->xml->endDocument(); - return $this->xml->outputMemory(); + $xml = $this->xml->outputMemory(); + $this->xml = null; + return $xml; + } + + + private static function exceptionFirstCallSetData(): InvalidState + { + return new InvalidState('First you must call setData().'); } } diff --git a/src/Request/Queue.php b/src/Request/Queue.php index 58738bd..879a54e 100644 --- a/src/Request/Queue.php +++ b/src/Request/Queue.php @@ -1,11 +1,11 @@ -tempDir = $tempDir; } - /** - * @param int $limitLoop - */ - public function setLimitLoop($limitLoop) + + public function setLimitLoop(int $limitLoop): void { - $this->limitLoop = (int) $limitLoop; + $this->limitLoop = $limitLoop; } - /** - * @param array|\Iterator $downloadOptions - */ - public function setDownloadOptions($downloadOptions) + + public function setDownloadOptions(iterable $downloadOptions): void { foreach ($downloadOptions as $define => $value) { if (is_string($define) && defined($define)) { @@ -52,32 +49,32 @@ public function setDownloadOptions($downloadOptions) } } - public function setSleep($sleep) + + public function setSleep(bool $sleep): void { - $this->sleep = (bool) $sleep; + $this->sleep = $sleep; } + /** - * @param $token - * @param string $url - * @return mixed|string - * @throws Fio\QueueLimitException - * @throws Fio\ServiceUnavailableException + * @throws Exceptions\QueueLimit + * @throws Exceptions\ServiceUnavailable */ - public function download($token, $url) + public function download(string $token, string $url): string { - $response = $this->request($token, function (GuzzleHttp\Client $client) use ($url) { + $response = $this->request($token, function (GuzzleHttp\ClientInterface $client) use ($url) { return $client->request('GET', $url, $this->downloadOptions); }); - self::detectDownloadResponse($response); - return $response->getBody(); + $this->detectDownloadResponse($response); + return (string) $response->getBody(); } + /** - * @return Pay\IResponse - * @throws Fio\QueueLimitException + * @throws Exceptions\QueueLimit + * @throws Exceptions\ServiceUnavailable */ - public function upload($url, $token, array $post, $filename) + public function upload(string $url, string $token, array $post, string $filename): Pay\IResponse { $newPost = []; foreach ($post as $name => $value) { @@ -85,85 +82,85 @@ public function upload($url, $token, array $post, $filename) } $newPost[] = ['name' => 'file', 'contents' => fopen($filename, 'r')]; - $response = $this->request($token, function (GuzzleHttp\Client $client) use ($url, $newPost) { + $response = $this->request($token, function (GuzzleHttp\ClientInterface $client) use ($url, $newPost) { return $client->request('POST', $url, [GuzzleHttp\RequestOptions::MULTIPART => $newPost]); }); - return self::createXmlResponse($response); + return $this->createXmlResponse($response); } + /** - * @param $token - * @param $fallback - * @return ResponseInterface - * @throws Fio\QueueLimitException - * @throws Fio\ServiceUnavailableException + * @throws Exceptions\QueueLimit + * @throws Exceptions\ServiceUnavailable() */ - private function request($token, $fallback) + private function request(string $token, callable $fallback): ResponseInterface { - $request = new GuzzleHttp\Client(['headers' => ['X-Powered-By' => 'h4kuna/fio']]); + $client = $this->createClient(); $tempFile = $this->loadFileName($token); - $file = fopen(self::safeProtocol($tempFile), 'w'); + $file = self::createFileResource($tempFile); $i = 0; do { $next = false; ++$i; try { - $response = $fallback($request); + $response = $fallback($client); + fclose($file); + touch($tempFile); + return $response; } catch (GuzzleHttp\Exception\ClientException $e) { if ($e->getCode() !== self::HEADER_CONFLICT || !$this->sleep) { fclose($file); throw $e; } elseif ($i >= $this->limitLoop) { fclose($file); - throw new Fio\QueueLimitException('You have limit up requests to server ' . $this->limitLoop); + throw new Exceptions\QueueLimit('You have limit up requests to server ' . $this->limitLoop); } self::sleep($tempFile); $next = true; - } catch (GuzzleHttp\Exception\ServerException $e) { - if($e->hasResponse()) { - self::detectDownloadResponse($e->getResponse()); - } - throw self::createServiceUnavailableException(); - } catch (GuzzleHttp\Exception\ConnectException $e) { - throw self::createServiceUnavailableException(); + } catch (GuzzleHttp\Exception\BadResponseException $e) { + throw new Exceptions\ServiceUnavailable($e->getMessage(), $e->getCode(), $e); } } while ($next); - fclose($file); - touch($tempFile); + } - return $response; + + private static function createFileResource(string $filePath) + { + $file = fopen(self::safeProtocol($filePath), 'w'); + if ($file === false) { + throw new Exceptions\InvalidState('Open file is failed ' . $filePath); + } + return $file; } + /** - * @param ResponseInterface $response - * @throws Fio\ServiceUnavailableException + * @throws Exceptions\ServiceUnavailable() */ - private static function detectDownloadResponse($response) + private function detectDownloadResponse(ResponseInterface $response): void { /* @var $contentTypeHeaders array */ $contentTypeHeaders = $response->getHeader('Content-Type'); $contentType = array_shift($contentTypeHeaders); if ($contentType === 'text/xml;charset=UTF-8') { - $xmlResponse = self::createXmlResponse($response); - if ($xmlResponse->getErrorCode() !== 0) { - throw new Fio\ServiceUnavailableException($xmlResponse->getError(), $xmlResponse->getErrorCode()); + $xmlResponse = $this->createXmlResponse($response); + if ($xmlResponse->code() !== 0) { + throw new Exceptions\ServiceUnavailable($xmlResponse->status(), $xmlResponse->code()); } } } - private static function sleep($filename) + + private static function sleep(string $filename): void { $criticalTime = time() - filemtime($filename); - if ($criticalTime < self::WAIT_TIME) { - sleep(self::WAIT_TIME - $criticalTime); + if ($criticalTime < static::WAIT_TIME) { + sleep(static::WAIT_TIME - $criticalTime); } } - /** - * @param string $token - * @return string - */ - private function loadFileName($token) + + private function loadFileName(string $token): string { $key = substr($token, 10, -10); if (!isset(self::$tokens[$key])) { @@ -173,24 +170,22 @@ private function loadFileName($token) return self::$tokens[$key]; } - private static function safeProtocol($filename) + + private static function safeProtocol(string $filename): string { return Utils\SafeStream::PROTOCOL . '://' . $filename; } - /** - * @param ResponseInterface|GuzzleHttp\Psr7\Stream $response - * @return Pay\XMLResponse - */ - private static function createXmlResponse($response) + + protected function createXmlResponse(ResponseInterface $response): Pay\IResponse { return new Pay\XMLResponse($response->getBody()->getContents()); } - private static function createServiceUnavailableException() + protected function createClient(): GuzzleHttp\ClientInterface { - return new Fio\ServiceUnavailableException('Fio server does not response.'); + return new GuzzleHttp\Client(['headers' => ['X-Powered-By' => 'h4kuna/fio']]); } } diff --git a/src/Request/Read/Files/Json.php b/src/Request/Read/Files/Json.php index 538192f..7b656e3 100644 --- a/src/Request/Read/Files/Json.php +++ b/src/Request/Read/Files/Json.php @@ -1,49 +1,54 @@ -transactionListFactory = $transactionListFactory; } + /** @return string */ - public function getExtension() + public function getExtension(): string { return self::JSON; } + /** - * @param string $data - * @return Read\TransactionList + * @throws Exceptions\ServiceUnavailable */ - public function create($data) + public function create(string $data): Read\TransactionList { - if (!$data) { + if ($data === '') { $data = '{}'; } if (self::isJsonBug()) { // all float values are transform to string // bug for php7.1 https://bugs.php.net/bug.php?id=72567 - $data = preg_replace('~: ?(-?\d+\.\d+),~', ':"$1",', $data); + $data = (string) preg_replace('~: ?(-?\d+\.\d+),~', ':"$1",', $data); } $dateFormat = 'Y-m-dO'; - $json = Nette\Utils\Json::decode($data); + try { + $json = Utils\Json::decode($data); + } catch (Utils\JsonException $e) { + throw new Exceptions\ServiceUnavailable($e->getMessage(), 0, $e); + } + if (isset($json->accountStatement->info)) { $info = $this->transactionListFactory->createInfo($json->accountStatement->info, $dateFormat); } else { @@ -61,13 +66,14 @@ public function create($data) return $transactionList; } + /** * @internal * @return bool */ - public static function isJsonBug() + public static function isJsonBug(): bool { - return PHP_VERSION_ID >= 70100; + return PHP_VERSION_ID >= 70100 && PHP_VERSION_ID < 70200; } } diff --git a/src/Request/Read/IReader.php b/src/Request/Read/IReader.php index 4590dcc..0464459 100644 --- a/src/Request/Read/IReader.php +++ b/src/Request/Read/IReader.php @@ -1,12 +1,9 @@ -xml = new SimpleXMLElement($xml); } - public function isOk() + + public function isOk(): bool { - return $this->getError() === 'ok' && $this->getErrorCode() === 0; + return $this->status() === 'ok' && $this->code() === 0; } + /** * READ XML **************************************************************** * ************************************************************************* */ - /** @return SimpleXMLElement */ - public function getXml() + public function getXml(): SimpleXMLElement { return $this->xml; } - /** @return int */ - public function getErrorCode() + + public function code(): int { return (int) $this->getValue('result/errorCode'); } + public function getIdInstruction() { return $this->getValue('result/idInstruction'); } - /** @return string */ - public function getError() + + public function status(): string { return $this->getValue('result/status'); } - /** - * @param string $path - * @return string - */ - private function getValue($path) + + public function errorMessages(): array + { + $errorMessages = []; + /** @var SimpleXMLElement[] $messages */ + $messages = $this->getXml()->xpath('ordersDetails/detail/messages'); + foreach ($messages as $message) { + foreach ($message as $item) { + if (isset($item['errorCode'])) { + $errorMessages[(string) $item['errorCode']] = (string) $item; + } else { + $errorMessages[] = (string) $item; + } + } + } + return $errorMessages; + } + + + private function getValue(string $path): string { - $val = $this->xml->xpath($path . '/text()'); + $val = $this->getXml()->xpath($path . '/text()'); return (string) $val[0]; } - /** - * @param string $fileName - */ - public function saveXML($fileName) + + public function saveXML(string $fileName): void + { + $this->getXml()->saveXML($fileName); + } + + + public function __toString() { - $this->xml->saveXML($fileName); + return (string) $this->xml->asXML(); } } diff --git a/src/Response/Read/ITransactionListFactory.php b/src/Response/Read/ITransactionListFactory.php index a65a130..1d479ed 100644 --- a/src/Response/Read/ITransactionListFactory.php +++ b/src/Response/Read/ITransactionListFactory.php @@ -1,19 +1,16 @@ -transactionClass = $transactionClass; } - public function createInfo($data, $dateFormat) + + public function createInfo(\stdClass $data, string $dateFormat): \stdClass { $data->dateStart = Utils\Strings::createFromFormat($data->dateStart, $dateFormat); $data->dateEnd = Utils\Strings::createFromFormat($data->dateEnd, $dateFormat); return $data; } - public function createTransaction($data, $dateFormat) + + public function createTransaction(\stdClass $data, string $dateFormat): TransactionAbstract { $transaction = $this->createTransactionObject($dateFormat); - foreach (self::metaProperty($transaction) as $id => $meta) { + foreach ($this->metaProperty($transaction) as $id => $meta) { $value = isset($data->{'column' . $id}) ? $data->{'column' . $id}->value : null; $transaction->bindProperty($meta['name'], $meta['type'], $value); } return $transaction; } - /** @return TransactionList */ - public function createTransactionList($info) + + public function createTransactionList(\stdClass $info): TransactionList { return new TransactionList($info); } - protected function createTransactionObject($dateFormat) + + protected function createTransactionObject(string $dateFormat): TransactionAbstract { - if ($this->transactionClassCheck === false) { - if (is_string($this->transactionClass)) { - $class = $this->transactionClass; - $this->transactionClass = new $class($dateFormat); - } else { - throw new Fio\InvalidArgumentException('Add you class as string.'); - } + if ($this->transactionObject === null) { + $class = $this->transactionClass; + $this->transactionObject = new $class($dateFormat); - if (!$this->transactionClass instanceof TransactionAbstract) { - throw new Fio\TransactionExtendException('Transaction class must extends TransationAbstract.'); + if (!$this->transactionObject instanceof TransactionAbstract) { + throw new Exceptions\Runtime(sprintf('Transaction class must extends "%s".', TransactionAbstract::class)); } - $this->transactionClassCheck = true; } - return clone $this->transactionClass; + return clone $this->transactionObject; } - private static function metaProperty($class) + + /** + * @param TransactionAbstract $class + * @return string[][] + */ + private function metaProperty(TransactionAbstract $class): array { - if (self::$property !== null) { - return self::$property; + if ($this->property !== null) { + return $this->property; } $reflection = new \ReflectionClass($class); - if (!preg_match_all('/@property-read (?P[\w|]+) \$(?P\w+).*\[(?P\d+)\]/', $reflection->getDocComment(), $find)) { - throw new Fio\TransactionPropertyException('Property not found you have bad syntax.'); + if ($reflection->getDocComment() === false || !preg_match_all('/@property-read (?P[\w|]+) \$(?P\w+).*\[(?P\d+)\]/', $reflection->getDocComment(), $find)) { + throw new Exceptions\Runtime('Property has bad annotation syntax.'); } - self::$property = []; + $this->property = []; foreach ($find['name'] as $key => $property) { - self::$property[$find['id'][$key]] = ['type' => strtolower($find['type'][$key]), 'name' => $property]; + $this->property[$find['id'][$key]] = ['type' => strtolower($find['type'][$key]), 'name' => $property]; } - return self::$property; + return $this->property; } } diff --git a/src/Response/Read/Transaction.php b/src/Response/Read/Transaction.php index 206cb83..999731a 100644 --- a/src/Response/Read/Transaction.php +++ b/src/Response/Read/Transaction.php @@ -1,4 +1,4 @@ -dateFormat = $dateFormat; } - public function __get($name) + + /** + * @return mixed + */ + public function __get(string $name) { if (array_key_exists($name, $this->properties)) { return $this->properties[$name]; } - throw new Fio\TransactionPropertyException('Property does not exists. ' . $name); + throw new Exceptions\Runtime('Property does not exists. ' . $name); } - public function clearTemporaryValues() + + public function clearTemporaryValues(): void { - $this->dateFormat = null; + $this->dateFormat = ''; } - public function bindProperty($name, $type, $value) + + public function bindProperty(string $name, string $type, $value): void { $method = 'set' . ucfirst($name); if (method_exists($this, $method)) { @@ -46,38 +50,47 @@ public function bindProperty($name, $type, $value) $this->properties[$name] = $value; } + public function current() { return current($this->properties); } + public function key() { return key($this->properties); } + public function next() { next($this->properties); } + public function rewind() { reset($this->properties); } + public function valid() { return array_key_exists($this->key(), $this->properties); } - /** @return array */ - public function getProperties() + + public function getProperties(): array { return $this->properties; } - protected function checkValue($value, $type) + + /** + * @return mixed + */ + protected function checkValue($value, string $type) { switch ($type) { case 'datetime': @@ -86,10 +99,7 @@ protected function checkValue($value, $type) return floatval($value); case 'string': return trim($value); - case 'int': // on 32bit platform works inval() bad with variable symbol - if (self::is32bitOS()) { - return trim($value); - } + case 'int': return intval($value); case 'string|null': return trim($value) ?: null; @@ -97,9 +107,4 @@ protected function checkValue($value, $type) return $value; } - private static function is32bitOS() - { - return PHP_INT_SIZE === 4; - } - } diff --git a/src/Response/Read/TransactionList.php b/src/Response/Read/TransactionList.php index cb002f7..cdc640c 100644 --- a/src/Response/Read/TransactionList.php +++ b/src/Response/Read/TransactionList.php @@ -1,12 +1,7 @@ -info = $info; } - public function append(TransactionAbstract $transaction) + + public function append(TransactionAbstract $transaction): void { $this->transactions[] = $transaction; } - public function getInfo() + + public function getInfo(): \stdClass { return $this->info; } + /** @return Transaction */ public function current() { return current($this->transactions); } + public function key() { return key($this->transactions); } + public function next() { next($this->transactions); } + public function rewind() { reset($this->transactions); } + public function valid() { return array_key_exists($this->key(), $this->transactions); } + public function count() { return count($this->transactions); diff --git a/src/Utils/FioFactory.php b/src/Utils/FioFactory.php index 4bb1fc2..02d1ad9 100644 --- a/src/Utils/FioFactory.php +++ b/src/Utils/FioFactory.php @@ -1,13 +1,15 @@ -setTemp($temp); $this->accountCollection = $this->createAccountCollection($accounts); @@ -27,92 +30,90 @@ public function __construct(array $accounts, $transactionClass = null, $temp = n $this->transactionClass = $transactionClass; } - private function setTemp($temp) + + private function setTemp(string $temp): void { - $this->temp = $temp ?: sys_get_temp_dir(); + if ($temp === '') { + $temp = sys_get_temp_dir(); + } + + $this->temp = $temp; } - /** - * @param string $name Configured account name from AccountCollection - * @return Fio\FioRead - */ - public function createFioRead($name = null) + + public function createFioRead(string $name = ''): Fio\FioRead { - return new Fio\FioRead($this->getQueue(), $this->getAccount($name), $this->createReader()); + return new Fio\FioRead($this->queue(), $this->accountCollection()->account($name), $this->createReader()); } + /** * @param string $name Configured account name from AccountCollection * @return Fio\FioPay */ - public function createFioPay($name = null) + public function createFioPay(string $name = ''): Fio\FioPay { return new Fio\FioPay( - $this->getQueue(), $this->getAccount($name), $this->createXmlFile() + $this->queue(), $this->accountCollection()->account($name), $this->createXmlFile() ); } + /** * COMMON ****************************************************************** * ************************************************************************* */ - protected function createQueue() + protected function createQueue(): Fio\Request\IQueue { return new Fio\Request\Queue($this->temp); } - protected function createAccountCollection(array $accounts) + + protected function createAccountCollection(array $accounts): Account\AccountCollection { - return Fio\Account\AccountCollectionFactory::create($accounts); + return Account\AccountCollectionFactory::create($accounts); } - final protected function getAccountCollection() + + final protected function accountCollection(): Account\AccountCollection { return $this->accountCollection; } - /** - * @param string $name Configured account name from AccountCollection - * @return Fio\Account\FioAccount - */ - final protected function getAccount($name) - { - if ($name) { - return $this->getAccountCollection()->get($name); - } - return $this->getAccountCollection()->getDefault(); - } - - final protected function getQueue() + final protected function queue(): Fio\Request\IQueue { return $this->queue; } - final protected function getTransactionClass() + + final protected function transactionClass(): string { return $this->transactionClass; } + /** * READ ******************************************************************** * ************************************************************************* */ - protected function createTransactionListFactory() + protected function createTransactionListFactory(): Fio\Response\Read\JsonTransactionFactory { - return new Fio\Response\Read\JsonTransactionFactory($this->getTransactionClass()); + return new Fio\Response\Read\JsonTransactionFactory($this->transactionClass()); } - protected function createReader() + + protected function createReader(): Fio\Request\Read\Files\Json { return new Fio\Request\Read\Files\Json($this->createTransactionListFactory()); } + /** * PAY ********************************************************************* * ************************************************************************* */ - protected function createXmlFile() + protected function createXmlFile(): Fio\Request\Pay\XMLFile { return new Fio\Request\Pay\XMLFile($this->temp); } diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 8955755..927562a 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -1,64 +1,46 @@ -format($format); } + /** * Convert string to DateTime. - * @param string $value - * @param bool $midnight - * @return DateTime */ - public static function createFromFormat($value, $format, $midnight = true) + public static function createFromFormat(string $value, string $format, bool $midnight = true): \DateTimeInterface { $dt = date_create_from_format($format, $value); + if ($dt === false) { + throw new InvalidArgument('Create DateTime from string faild. Probably you have bad format.'); + } if ($midnight) { $dt->setTime(0, 0, 0); } return $dt; } + + public static function is32bitOS(): bool + { + return PHP_INT_SIZE === 4; + } + } diff --git a/src/exceptions.php b/src/exceptions.php deleted file mode 100644 index e7b66e8..0000000 --- a/src/exceptions.php +++ /dev/null @@ -1,19 +0,0 @@ - [ 'account' => '123456789', - 'token' => 'abcdefgh' + 'token' => 'abcdefgh', ], 'bar' => [ 'account' => '987654321', - 'token' => 'hgfedcba' - ] + 'token' => 'hgfedcba', + ], ]; parent::__construct($accounts, $transactionClass); } - protected function createQueue() - { - return new Queue; - } - public function getXmlFile() + public function getXmlFile(): XMLFile { return $this->createXmlFile(); } - public function getReader() + + public function getReader(): Json { return $this->createReader(); } + + protected function createQueue(): IQueue + { + return new Queue; + } + } diff --git a/tests/data/Queue.php b/tests/data/Queue.php index 5ffd122..3d88d60 100644 --- a/tests/data/Queue.php +++ b/tests/data/Queue.php @@ -1,17 +1,14 @@ -method = $method; + $this->uri = $uri; + $this->options = $options; + } + + + public function getProtocolVersion() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function withProtocolVersion($version) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getHeaders() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function hasHeader($name) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getHeader($name) + { + if ('Content-Type' === $name) { + if ($this->isOk()) { + return ['application/json;charset=UTF-8']; + } + return ['text/xml;charset=UTF-8']; + } + } + + + public function getHeaderLine($name) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function withHeader($name, $value) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function withAddedHeader($name, $value) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function withoutHeader($name) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getBody() + { + return new Stream($this->isOk()); + } + + + public function withBody(StreamInterface $body) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getStatusCode() + { + if (isset($this->options[self::RESPONSE_CODE])) { + $code = $this->options[self::RESPONSE_CODE]; + } elseif (isset($this->options[self::EXCEPTION_CLASS])) { + $code = 500; + } else { + $code = 200; + } + return $code; + } + + + public function withStatus($code, $reasonPhrase = '') + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getReasonPhrase() + { + throw new \RuntimeException('Not implemented.'); + } + + + private function isOk(): bool + { + return $this->getStatusCode() === 200; + } + +} diff --git a/tests/data/Stream.php b/tests/data/Stream.php new file mode 100644 index 0000000..484718e --- /dev/null +++ b/tests/data/Stream.php @@ -0,0 +1,109 @@ +isOk = $failed; + } + + + public function __toString() + { + return $this->getContents(); + } + + + public function close() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function detach() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getSize() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function tell() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function eof() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function isSeekable() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function seek($offset, $whence = SEEK_SET) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function rewind() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function isWritable() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function write($string) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function isReadable() + { + throw new \RuntimeException('Not implemented.'); + } + + + public function read($length) + { + throw new \RuntimeException('Not implemented.'); + } + + + public function getContents() + { + return File::load(sprintf('payment/response%s.xml', $this->isOk ? '' : '-error')); + } + + + public function getMetadata($key = null) + { + throw new \RuntimeException('Not implemented.'); + } + +} diff --git a/tests/data/tests/2015-01-01-2015-04-16-transactions.srlz b/tests/data/tests/2015-01-01-2015-04-16-transactions.srlz index cdc94dc621f7ccd26fd378707a9bf9a94c76ce65..bf478659d44deb535e4b876ee276af7fde3a5bfc 100644 GIT binary patch delta 186 zcmbPWbI4}HHzw|4D+4PfCF|NuE5peLh1P9e#e9{K4I;R?f%OHl0%MSZ$rHGvHO@v#3RJXVvkadMvY^@KgF>8)o81LV;M(>Gbs(#-09*b;Gyqx95-j*fB8ds+ JqIl_zOaSc*I`sem delta 113 zcmX?PGr?xVHzr2E&3~9WnArTRYcs8kCNnax+ic5b3gsJv`P!TZ7=g+@a&>}KH}GDB l%9?>?xdhLHWbX@gfMjz;nVBJGS%PIXC6hqH6QwsY0RTxvBfkIu diff --git a/tests/data/tests/2015-2-transactions.srlz b/tests/data/tests/2015-2-transactions.srlz index 2984267cc5bb837827281baf57d53e0b14e1d5d0..afdd2a6606901c4aa0fbcfc164a7f54bca74ee90 100644 GIT binary patch delta 43 lcmeAWn=ZB?hMBF{%D_rVX>%-dF%yh^k+l=fj^_MhI+=9lg~4I3lv)!SScx4*JfH7TKikU6vQwZp~)H{ z$wp0n$P|U7(-=uEa`I_reDAu;j)gbn~`*x!Noz2HPACdcdR**f*3|a xG-EB0WTPf0aUeU^5=G9JGn@w&1hvIhCX*G}H6~x?yfJwjmpr5C=7(IRi~zGGT`T|q delta 412 zcmew>eobOREt84S#Ci>ukksOm$^Tg+g$(tKEi6&MCnTOfp85`_CFZc^$JaM9u_N4rq&zff0&}fE-6O`c3}J%(r -123456789EUR500AT6119043002345732012015-01-23Milan +123456789EUR500AT611904300234573201LAVBDD33XXX2015-01-23Milan diff --git a/tests/data/tests/payment/international-minimum.xml b/tests/data/tests/payment/international-minimum.xml index 4966e1a..6d895db 100644 --- a/tests/data/tests/payment/international-minimum.xml +++ b/tests/data/tests/payment/international-minimum.xml @@ -1,2 +1,2 @@ -123456789EUR500AT611904300234573201ABAGATWWXXX2015-01-23MilanStreet 44PragueJPInfo 1470502110 +123456789EUR500AT611904300234573201ABAGATWWXXX2015-01-23MilanStreet 44PragueJPInfo 1470502110 diff --git a/tests/data/tests/payment/multi-pay.xml b/tests/data/tests/payment/multi-pay.xml index ab1f1fa..dbd1bea 100644 --- a/tests/data/tests/payment/multi-pay.xml +++ b/tests/data/tests/payment/multi-pay.xml @@ -1,2 +1,2 @@ -123456789CZK1002430155612342016-01-12123456789CZK200986509972016-01-12 +123456789CZK10024301556123412341232016-01-12123456789CZK2009865099709970992016-01-12 diff --git a/tests/data/tests/payment/pay-maximum.xml b/tests/data/tests/payment/pay-maximum.xml index f5b5827..125fddf 100644 --- a/tests/data/tests/payment/pay-maximum.xml +++ b/tests/data/tests/payment/pay-maximum.xml @@ -1,2 +1,2 @@ -123456789EUR100098765498743211234567893782014-01-23Hello Mr. JoeLorem ipsum333431004 +123456789EUR1000987654987498749873211234567893782014-01-23Hello Mr. JoeLorem ipsum333431005 diff --git a/tests/data/tests/payment/pay-minimum.xml b/tests/data/tests/payment/pay-minimum.xml index d45da48..36e79fb 100644 --- a/tests/data/tests/payment/pay-minimum.xml +++ b/tests/data/tests/payment/pay-minimum.xml @@ -1,2 +1,2 @@ -123456789CZK50098765432143212015-01-23 +123456789CZK500987654321432143214322015-01-23 diff --git a/tests/data/tests/payment/response-error.xml b/tests/data/tests/payment/response-error.xml new file mode 100644 index 0000000..0760d2c --- /dev/null +++ b/tests/data/tests/payment/response-error.xml @@ -0,0 +1,22 @@ + + + + 1 + error + + + 0 + 100 + + + + + + + Chybný formát zadaného IBAN. + Adresa majitele účtu není kompletní + foo + + + + diff --git a/tests/data/tests/php7.1/2015-01-01-2015-04-16-transactions.srlz b/tests/data/tests/php7.1/2015-01-01-2015-04-16-transactions.srlz index 8bcb1ef4e34095205cedfdd9916d301775148d1d..b973f2254ddd132a025704831da2d24a5c6a19e6 100644 GIT binary patch delta 186 zcmZp&*h($ diff --git a/tests/data/tests/php7.1/2015-2-transactions.srlz b/tests/data/tests/php7.1/2015-2-transactions.srlz index 40df0757d2c392bcd7ea2bcf8b9019a9ab6cac8c..9c8019a761be60fa14d7e10ca1d7b6b85d1cfaec 100644 GIT binary patch delta 43 lcmZn>n=G~=hMBF{%D_rVX>%-dF%yh^k+l=fj^JYdh&W^UnEHrWXZ_MJuCr8lBTGVIjm7gl4i(~E0842ktHH0o3bN&!va-Ogag^7 bmZ*~dIU;yq0Z?0PWiq*tNn>*xXDJf^ar$2? delta 280 zcmZpb_$@x6mdV6uV!Z}SNNRD(lDXJXMDU)+qp=O$)%dLQzXO1d*v1uGiQ+fwPne0O84A8UO$Q diff --git a/tests/data/tests/php7.1/last-transactions.srlz b/tests/data/tests/php7.1/last-transactions.srlz index 910923d9866258045572bd13982418bedd957502..f1722c775eb623455bddbd7e7c86413681367f78 100644 GIT binary patch delta 64 zcmX>hb4O;wHzu}XD+4PfrOn@&I^gUER%T{yh`4oarj_yJKTPX3n{y_?70lvZ#{>YJ CpcAeD delta 61 zcmca3b3$grHzr2E&3~9WnArTRYcs8kCNnax+ic4g0OcEl_>*Vy`c3}J%(rcreateFioRead(); foreach ($fioRead->movements('-1 month') as $transaction) { @@ -23,8 +28,13 @@ // blocation is per token $fioPay = $fioFactory->createFioPay(); -$national = $fioPay->createNational(100, '2000242017/2010'); +$log = $fioPay->enableLog(); +//$national = $fioPay->createNational(100, '2600267402/2010'); +//$response = $fioPay->send($national); -$response = $fioPay->send($national); -dd($response->isOk(), $response->getError(), $response->getErrorCode()); +$euro = $fioPay->createEuro(100, 'EE957700771001355096/LHVBEE22XXX', 'Coinbase UK, Ltd.'); +$response = $fioPay->send($euro); +dump($log->getFilename()); +echo($log->getContent()); +dumpe($response->isOk(), $response->status(), $response->code(), $response->errorMessages()); diff --git a/tests/origin/account.example.ini b/tests/origin/account.example.ini new file mode 100644 index 0000000..df9c034 --- /dev/null +++ b/tests/origin/account.example.ini @@ -0,0 +1,3 @@ +[my-fio-account] +account = 123456789 +token = abcdefghijklmnopqrstuvwxyz123456790abcdefghijklmnopqrstuvwxyz123456790 \ No newline at end of file diff --git a/tests/phpstan b/tests/phpstan new file mode 100755 index 0000000..4ba7c33 --- /dev/null +++ b/tests/phpstan @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +DIR=`pwd`/`dirname $0`; + +$DIR/../vendor/bin/phpstan analyse -c $DIR/config/phpstan.neon --level max src tests diff --git a/tests/src/Account/AccountCollectionTest.phpt b/tests/src/Account/AccountCollectionTest.php similarity index 61% rename from tests/src/Account/AccountCollectionTest.phpt rename to tests/src/Account/AccountCollectionTest.php index 5dd7354..0b6a17d 100644 --- a/tests/src/Account/AccountCollectionTest.phpt +++ b/tests/src/Account/AccountCollectionTest.php @@ -1,14 +1,14 @@ -getBankCode()); $account2 = new FioAccount('978654', 'bar'); $accounts = new AccountCollection; $accounts->addAccount('foo', $account1); $accounts->addAccount('bar', $account2); - Assert::same($accounts->get('foo'), $account1); - Assert::same($accounts->get('bar'), $account2); + Assert::same($accounts->account('foo'), $account1); + Assert::same($accounts->account('bar'), $account2); } + /** - * @throws \h4kuna\Fio\AccountException + * @throws \h4kuna\Fio\Exceptions\InvalidArgument */ public function testInvalidAlias() { $account1 = new FioAccount('323536', 'foo'); $accounts = new AccountCollection; $accounts->addAccount('foo', $account1); - $accounts->get('bar'); + $accounts->account('bar'); } + public function testCount() { $account1 = new FioAccount('323536', 'foo'); @@ -48,6 +51,7 @@ public function testCount() Assert::same(count($accounts), 2); } + public function testIteration() { $account1 = new FioAccount('323536', 'foo'); @@ -62,14 +66,18 @@ public function testIteration() ]); } + + /** + * @throws \h4kuna\Fio\Exceptions\InvalidState + */ public function testEmpty() { - $accounts = new AccountCollection; - Assert::equal(FALSE, $accounts->getDefault()); + (new AccountCollection)->account(); } + /** - * @throws \h4kuna\Fio\AccountException + * @throws \h4kuna\Fio\Exceptions\InvalidArgument */ public function testDuplicity() { @@ -80,6 +88,30 @@ public function testDuplicity() $accounts->addAccount('foo', $account2); } + + public function testAccounCollectionFactoryThrowAccount() + { + Assert::throws(function () { + AccountCollectionFactory::create([ + 'foo' => [ + 'token' => 'bar', + ], + ]); + }, InvalidArgument::class, 'Key "account" is required for alias "foo".'); + } + + + public function testAccounCollectionFactoryThrowToken() + { + Assert::throws(function () { + AccountCollectionFactory::create([ + 'foo' => [ + 'account' => 'bar', + ], + ]); + }, InvalidArgument::class, 'Key "token" is required for alias "foo".'); + } + } (new AccountCollectionTest())->run(); diff --git a/tests/src/Account/BankTest.php b/tests/src/Account/BankTest.php new file mode 100644 index 0000000..abcb465 --- /dev/null +++ b/tests/src/Account/BankTest.php @@ -0,0 +1,91 @@ +getPrefix()); + Assert::same('0987', $account->getBankCode()); + Assert::same('123-123456789', $account->getAccount()); + Assert::same('123-123456789/0987', $account->getAccountAndCode()); + } + + + public function testCode() + { + $account = Bank::createNational('123456789/0987'); + Assert::same('', $account->getPrefix()); + Assert::same('0987', $account->getBankCode()); + Assert::same('123456789/0987', $account->getAccountAndCode()); + } + + + public function testPrefix() + { + $account = Bank::createNational('123-123456789'); + Assert::same('123', $account->getPrefix()); + Assert::same('', $account->getBankCode()); + Assert::same('123-123456789', $account->getAccount()); + Assert::same('123-123456789', $account->getAccountAndCode()); + } + + + public function testMinimum() + { + $account = Bank::createNational('123456789'); + Assert::same('', $account->getPrefix()); + Assert::same('', $account->getBankCode()); + Assert::same('123456789', $account->getAccount()); + Assert::same('123456789', (string) $account); + Assert::same('123456789', $account->getAccountAndCode()); + } + + + public function testEuroFull() + { + $account = Bank::createInternational('EE123745671789355096/LAVBDD33XXX'); + Assert::same('EE123745671789355096', $account->getAccount()); + Assert::same('LAVBDD33XXX', $account->getBankCode()); + Assert::same('EE123745671789355096/LAVBDD33XXX', $account->getAccountAndCode()); + } + + + public function testEuroMinimum() + { + $account = Bank::createInternational('EE123745671789355096'); + Assert::same('EE123745671789355096', $account->getAccount()); + Assert::same('', $account->getBankCode()); + Assert::same('', $account->getPrefix()); + Assert::same('EE123745671789355096', $account->getAccountAndCode()); + } + + + /** + * @throws \h4kuna\Fio\Exceptions\InvalidArgument + */ + public function testEuroThrowBadAccount() + { + Bank::createInternational('EE1237456717-9355096'); + } + + + /** + * @dataProvider bad-accounts.ini + * @throws \h4kuna\Fio\Exceptions\InvalidArgument + */ + public function testBadAccount($account) + { + Bank::createNational($account); + } + +} + +(new BankTest())->run(); diff --git a/tests/src/Account/BankTest.phpt b/tests/src/Account/BankTest.phpt deleted file mode 100644 index bdeed60..0000000 --- a/tests/src/Account/BankTest.phpt +++ /dev/null @@ -1,58 +0,0 @@ -getPrefix()); - Assert::equal('0987', $account->getBankCode()); - Assert::equal('123-123456789', $account->getAccount()); - Assert::equal('123-123456789/0987', $account->getAccountAndCode()); - } - - public function testCode() - { - $account = new Bank('123456789/0987'); - Assert::equal('', $account->getPrefix()); - Assert::equal('0987', $account->getBankCode()); - Assert::equal('123456789/0987', $account->getAccountAndCode()); - } - - public function testPrefix() - { - $account = new Bank('123-123456789'); - Assert::equal('123', $account->getPrefix()); - Assert::equal('', $account->getBankCode()); - Assert::equal('123-123456789', $account->getAccount()); - Assert::equal('123-123456789', $account->getAccountAndCode()); - } - - public function testMinimum() - { - $account = new Bank('123456789'); - Assert::equal('', $account->getPrefix()); - Assert::equal('', $account->getBankCode()); - Assert::equal('123456789', $account->getAccount()); - Assert::equal('123456789', $account->getAccountAndCode()); - } - - /** - * @dataProvider bad-accounts.ini - * @throws \h4kuna\Fio\AccountException - */ - public function testBadAccount($account) - { - new Bank($account); - } - -} - -(new BankTest())->run(); diff --git a/tests/src/Account/bad-accounts.ini b/tests/src/Account/bad-accounts.ini index 0ac35bd..45365fe 100644 --- a/tests/src/Account/bad-accounts.ini +++ b/tests/src/Account/bad-accounts.ini @@ -1,4 +1,3 @@ - [prefix-string] account = a-123456/0600 @@ -18,4 +17,4 @@ account = 1-123456/600 account = 123456 / 0600 [account-max] -account = 12345678901234567/0600 \ No newline at end of file +account = 12345678901234567/0600 diff --git a/tests/src/Exceptions/InvalidArgumentTest.php b/tests/src/Exceptions/InvalidArgumentTest.php new file mode 100644 index 0000000..23d2fc0 --- /dev/null +++ b/tests/src/Exceptions/InvalidArgumentTest.php @@ -0,0 +1,73 @@ +run(); diff --git a/tests/src/FioPayTest.phpt b/tests/src/FioPayTest.php similarity index 56% rename from tests/src/FioPayTest.phpt rename to tests/src/FioPayTest.php index ffb1e40..2378c11 100644 --- a/tests/src/FioPayTest.phpt +++ b/tests/src/FioPayTest.php @@ -1,17 +1,14 @@ -fioFactory = $fioFactory; } - protected function setUp() - { - $this->fioPay = $this->fioFactory->createFioPay(); - } public function testSend() { - $payment1 = $this->fioPay->createNational(100, '24301556/1234') + $payment1 = $this->fioPay->createNational(100, '24301556/12341234123') ->setDate('2016-01-12'); $this->fioPay->addPayment($payment1); - $payment2 = $this->fioPay->createNational(200, '9865/0997') + $payment2 = $this->fioPay->createNational(200, '9865/09970997099') ->setDate('2016-01-12'); $xml = $this->fioPay->send($payment2); - Assert::same(Testinium\File::load('payment/multi-pay.xml'), $xml); + // Testinium\File::save('payment/multi-pay.xml', $xml); + Assert::same(Testinium\File::load('payment/multi-pay.xml'), (string) $xml); + } + + + protected function setUp() + { + $this->fioPay = $this->fioFactory->createFioPay(); + $this->fioPay->setLanguage('cs'); } } diff --git a/tests/src/FioReadTest.phpt b/tests/src/FioReadTest.php similarity index 87% rename from tests/src/FioReadTest.phpt rename to tests/src/FioReadTest.php index 34d77af..120a990 100644 --- a/tests/src/FioReadTest.phpt +++ b/tests/src/FioReadTest.php @@ -1,13 +1,13 @@ -fioFactory = $fioFactory; - } - - protected function setUp() - { - $this->fioRead = $this->fioFactory->createFioRead(); - $this->token = $this->fioRead->getAccount()->getToken(); - } public function testMovements() { $data = $this->fioRead->movements(1420070400, '2015-04-16'); - $moveId = 7139752765; - foreach ($data as $transaction) { + $moveId = 7139752766; + foreach ($data as $key => $transaction) { + if ($key === 0) { + continue; + } /* @var $transaction Response\Read\Transaction */ Assert::equal($moveId, $transaction->moveId); foreach ($transaction as $property => $value) { @@ -47,6 +40,9 @@ public function testMovements() } } + Assert::type(\stdClass::class, $data->getInfo()); + Assert::same(10, count($data)); + Assert::equal(Fio::REST_URL . 'periods/' . $this->token . '/2015-01-01/2015-04-16/transactions.json', $this->fioRead->getRequestUrl()); if (Request\Read\Files\Json::isJsonBug()) { @@ -56,9 +52,11 @@ public function testMovements() } } + public function testMovementsEmpty() { $data = $this->fioRead->movements('2011-01-01', '2011-01-02'); + if (Request\Read\Files\Json::isJsonBug()) { Assert::equal(unserialize(Testinium\File::load('php7.1/2011-01-01-2011-01-02-transactions.srlz')), $data); } else { @@ -66,6 +64,7 @@ public function testMovementsEmpty() } } + public function testMovementId() { $fioRead = $this->fioFactory->createFioRead('bar'); @@ -82,6 +81,7 @@ public function testMovementId() Assert::equal(Fio::REST_URL . 'by-id/' . $token . '/2015/2/transactions.json', $fioRead->getRequestUrl()); } + public function testLastDownload() { $data = $this->fioRead->lastDownload(); @@ -93,12 +93,14 @@ public function testLastDownload() Assert::equal(Fio::REST_URL . 'last/' . $this->token . '/transactions.json', $this->fioRead->getRequestUrl()); } + public function testSetLastId() { $this->fioRead->setLastId(7155451447); Assert::equal(Fio::REST_URL . 'set-last-id/' . $this->token . "/7155451447/", $this->fioRead->getRequestUrl()); } + public function testSetLastDate() { $dt = new \DateTime('-1 week'); @@ -106,7 +108,14 @@ public function testSetLastDate() Assert::equal(Fio::REST_URL . 'set-last-date/' . $this->token . '/' . $dt->format('Y-m-d') . '/', $this->fioRead->getRequestUrl()); } + + protected function setUp() + { + $this->fioFactory = new Test\FioFactory(); + $this->fioRead = $this->fioFactory->createFioRead(); + $this->token = $this->fioRead->getAccount()->getToken(); + } + } -$fioFactory = new Test\FioFactory(); -(new FioReadTest($fioFactory))->run(); +(new FioReadTest)->run(); diff --git a/tests/src/Request/Pay/Payment/EuroTest.phpt b/tests/src/Request/Pay/Payment/EuroTest.php similarity index 72% rename from tests/src/Request/Pay/Payment/EuroTest.phpt rename to tests/src/Request/Pay/Payment/EuroTest.php index d2cb161..1673453 100644 --- a/tests/src/Request/Pay/Payment/EuroTest.phpt +++ b/tests/src/Request/Pay/Payment/EuroTest.php @@ -1,18 +1,15 @@ -fioFactory = $fioFactory; } - protected function setUp() - { - $this->fioPay = $this->fioFactory->createFioPay(); - $this->xmlFile = $this->fioFactory->getXmlFile(); - } public function testMinimum() { - $pay = $this->fioPay->createEuro(500, 'AT611904300234573201', 'Milan'); + $pay = $this->fioPay->createEuro(500, 'AT611904300234573201', 'Milan', 'LAVBDD33XXX'); $pay->setDate('2015-01-23'); $xml = $this->xmlFile->setData($pay)->getXml(); + Testinium\File::save('payment/euro-minimum.xml', $xml); Tester\Assert::equal(Testinium\File::load('payment/euro-minimum.xml'), $xml); } + public function testMaximum() { - $pay = $this->fioPay->createEuro(500, 'AT611904300234573201', 'Milan') + $pay = $this->fioPay->createEuro(500, 'AT611904300234573201/ABAGATWWXXX', 'Milan') ->setCity('Prague') - ->setBic('ABAGATWWXXX') ->setRemittanceInfo1('info 1') ->setRemittanceInfo2('info 2') ->setRemittanceInfo3('info 3') ->setStreet('Street 44') ->setCountry('jp') - ->setConstantSymbol('321') + ->setConstantSymbol(321) ->setCurrency('Usd') ->setMyComment('Lorem ipsum') ->setDate('2014-01-23') - ->setPaymentReason('110') - ->setSpecificSymbol('378') - ->setVariableSymbol('123456789') + ->setPaymentReason(110) + ->setSpecificSymbol(378) + ->setVariableSymbol(123456789) ->setPaymentType(Euro::PAYMENT_PRIORITY); $xml = $this->xmlFile->setData($pay)->getXml(); Tester\Assert::equal(Testinium\File::load('payment/euro-maximum.xml'), $xml); } + + protected function setUp() + { + $this->fioPay = $this->fioFactory->createFioPay(); + $this->xmlFile = $this->fioFactory->getXmlFile(); + } + } $fioFactory = new Test\FioFactory; diff --git a/tests/src/Request/Pay/Payment/InternationalTest.phpt b/tests/src/Request/Pay/Payment/InternationalTest.php similarity index 73% rename from tests/src/Request/Pay/Payment/InternationalTest.phpt rename to tests/src/Request/Pay/Payment/InternationalTest.php index 2185fb5..4b6dc35 100644 --- a/tests/src/Request/Pay/Payment/InternationalTest.phpt +++ b/tests/src/Request/Pay/Payment/InternationalTest.php @@ -1,52 +1,47 @@ -fioFactory = $fioFactory; } - protected function setUp() - { - $this->fioPay = $this->fioFactory->createFioPay(); - $this->xmlFile = $this->fioFactory->getXmlFile(); - } public function testMinimum() { - $pay = $this->fioPay->createInternational(500, 'AT611904300234573201', 'ABAGATWWXXX', 'Milan', 'Street 44', 'Prague', 'jp', 'Info 1'); + $pay = $this->fioPay->createInternational(500, 'AT611904300234573201/ABAGATWWXXX', 'Milan', 'Street 44', 'Prague', 'jp', 'Info 1'); $pay->setDate('2015-01-23'); $xml = $this->xmlFile->setData($pay)->getXml(); + Testinium\File::save('payment/international-minimum.xml', $xml); Assert::equal(Testinium\File::load('payment/international-minimum.xml'), $xml); } + public function testMaximum() { - $pay = $this->fioPay->createInternational(500, 'AT611904300234573201', 'ABAGATWWXXX', 'Milan', 'Street 44', 'Prague', 'jp', 'Info 1') + $pay = $this->fioPay->createInternational(500, 'AT611904300234573201', 'Milan', 'Street 44', 'Prague', 'jp', 'Info 1', 'ABAGATWWXXX') ->setDetailsOfCharges(International::CHARGES_SHA) ->setRemittanceInfo2('info 2') ->setRemittanceInfo3('info 3') @@ -54,11 +49,18 @@ public function testMaximum() ->setCurrency('Usd') ->setMyComment('Lorem ipsum') ->setDate('2014-01-23') - ->setPaymentReason('311'); + ->setPaymentReason(311); $xml = $this->xmlFile->setData($pay)->getXml(); Assert::equal(Testinium\File::load('payment/international-maximum.xml'), $xml); } + + protected function setUp() + { + $this->fioPay = $this->fioFactory->createFioPay(); + $this->xmlFile = $this->fioFactory->getXmlFile(); + } + } $fioFactory = new Test\FioFactory; diff --git a/tests/src/Request/Pay/Payment/NationalTest.phpt b/tests/src/Request/Pay/Payment/NationalTest.php similarity index 57% rename from tests/src/Request/Pay/Payment/NationalTest.phpt rename to tests/src/Request/Pay/Payment/NationalTest.php index 47faa1c..eeab3dd 100644 --- a/tests/src/Request/Pay/Payment/NationalTest.phpt +++ b/tests/src/Request/Pay/Payment/NationalTest.php @@ -1,75 +1,78 @@ -fioFactory = $fioFactory; } - protected function setUp() - { - $this->fioPay = $this->fioFactory->createFioPay(); - $this->xmlFile = $this->fioFactory->getXmlFile(); - } public function testMinimum() { - $pay = $this->fioPay->createNational(500, '987654321/4321'); + $pay = $this->fioPay->createNational(500, '987654321/43214321432'); $pay->setDate('2015-01-23'); $xml = $this->xmlFile->setData($pay)->getXml(); + // Testinium\File::save('payment/pay-minimum.xml', $xml); Assert::equal(Testinium\File::load('payment/pay-minimum.xml'), $xml); // same Property paymentFactory - $pay->setAccountTo('987654321/4321'); + $pay->setAccountTo('987654321')->setBankCode('43214321432'); $xml = $this->xmlFile->setData($pay)->getXml(); Assert::equal(Testinium\File::load('payment/pay-minimum.xml'), $xml); // cloned paymentFactory Property - $pay = $this->fioPay->createNational(500, '987654321', '4321'); + $pay = $this->fioPay->createNational(500, '987654321', '43214321432'); $xml = $this->xmlFile->setData($pay)->getXml(); $expectedXml = Testinium\File::load('payment/pay-minimum.xml'); - Assert::equal(str_replace('2015-01-23', date('Y-m-d'), $expectedXml), $xml); + Assert::same(str_replace('2015-01-23', date('Y-m-d'), $expectedXml, $count), $xml); + Assert::same(1, $count); } + public function testMaximum() { - $pay = $this->fioPay->createNational(1000, '987654/9874') - ->setConstantSymbol('321') + $pay = $this->fioPay->createNational(1000, '987654/98749874987') + ->setConstantSymbol(321) ->setCurrency('eur') ->setMyComment('Lorem ipsum') ->setDate('2014-01-23') - ->setPaymentReason('333') + ->setPaymentReason(333) ->setMessage('Hello Mr. Joe') - ->setSpecificSymbol('378') - ->setVariableSymbol('123456789') - ->setPaymentType(National::PAYMENT_FAST); + ->setSpecificSymbol(378) + ->setVariableSymbol(123456789) + ->setPaymentType(National::PAYMENT_PRIORITY); $xml = $this->xmlFile->setData($pay)->getXml(); - Assert::equal(Testinium\File::load('payment/pay-maximum.xml'), $xml); + Assert::same(Testinium\File::load('payment/pay-maximum.xml'), $xml); + } + + + protected function setUp() + { + $this->fioPay = $this->fioFactory->createFioPay(); + $this->xmlFile = $this->fioFactory->getXmlFile(); } } diff --git a/tests/src/Request/QueueTest.php b/tests/src/Request/QueueTest.php new file mode 100644 index 0000000..ef099de --- /dev/null +++ b/tests/src/Request/QueueTest.php @@ -0,0 +1,120 @@ +setDownloadOptions([ + Response::RESPONSE_CODE => 500, + ]); + $queue->download(self::TOKEN, 'http://www.example.com/'); + } + + + /** + * @throws GuzzleHttp\Exception\ClientException + */ + public function testDownloadThrowClientException() + { + $queue = self::createQueue(); + $queue->setDownloadOptions([ + Response::EXCEPTION_CLASS => GuzzleHttp\Exception\ClientException::class, + ]); + $queue->download(self::TOKEN, 'http://www.example.com/'); + } + + + /** + * @throws \h4kuna\Fio\Exceptions\ServiceUnavailable + */ + public function testDownloadThrowServerException() + { + $queue = self::createQueue(); + $queue->setDownloadOptions([ + Response::EXCEPTION_CLASS => GuzzleHttp\Exception\ServerException::class, + ]); + $queue->download(self::TOKEN, 'http://www.example.com/'); + } + + + public function testDownloadOk() + { + $queue = self::createQueue(); + $xml = $queue->download(self::TOKEN, 'http://www.example.com/'); + Assert::same(File::load('payment/response.xml'), $xml); + } + + + /** + * @throws \h4kuna\Fio\Exceptions\QueueLimit + */ + public function testDownloadThrowQueueLimit() + { + $queue = self::createQueue(); + $queue->setSleep(true); + $queue->setDownloadOptions([ + Response::RESPONSE_CODE => Queue::HEADER_CONFLICT, + Response::EXCEPTION_CLASS => GuzzleHttp\Exception\ClientException::class, + ]); + $queue->download(self::TOKEN, 'http://www.example.com/'); + } + + + public function testUpload() + { + $queue = self::createQueue(); + $xml = $queue->upload('http://www.example.com/', self::TOKEN, [ + 'type' => 'xml', + ], __DIR__ . '/../../data/tests/payment/euro-minimum.xml'); + + Assert::true($xml->isOk()); + } + + + private static function createQueue(): QueueMock + { + $q = new QueueMock(__DIR__ . '/../../temp'); + $q->setLimitLoop(2); + $q->setSleep(false); + return $q; + } + +} + +class QueueMock extends Queue +{ + + public const WAIT_TIME = 2; + + + protected function createClient(): GuzzleHttp\ClientInterface + { + return new ClientMock(); + } + + + protected static function waitTime(): int + { + return 2; + } +} + +(new QueueTest())->run(); diff --git a/tests/src/Response/Pay/XMLResponseTest.php b/tests/src/Response/Pay/XMLResponseTest.php new file mode 100644 index 0000000..4fa7c2f --- /dev/null +++ b/tests/src/Response/Pay/XMLResponseTest.php @@ -0,0 +1,45 @@ +isOk()); + Assert::equal('1247458', $xmlResponse->getIdInstruction()); + } + + + public function testErrorResponse() + { + $xml = Testinium\File::load('payment/response-error.xml'); + $xmlResponse = new XMLResponse($xml); + Assert::false($xmlResponse->isOk()); + + Assert::equal('error', $xmlResponse->status()); + Assert::equal(1, $xmlResponse->code()); + + Assert::equal([ + 303 => 'Chybný formát zadaného IBAN.', + 323 => 'Adresa majitele účtu není kompletní', + 'foo', + ], $xmlResponse->errorMessages()); + + $xmlFile = __DIR__ . '/../../../temp/out-test-xml'; + $xmlResponse->saveXML($xmlFile); + Assert::same($xml, file_get_contents($xmlFile)); + } + +} + +(new XMLResponseTest())->run(); diff --git a/tests/src/Response/Pay/XMLResponseTest.phpt b/tests/src/Response/Pay/XMLResponseTest.phpt deleted file mode 100644 index 45d0f63..0000000 --- a/tests/src/Response/Pay/XMLResponseTest.phpt +++ /dev/null @@ -1,27 +0,0 @@ -isOk()); - Assert::equal('1247458', $xmlResponse->getIdInstruction()); - } - -} - -(new XMLResponseTest())->run(); diff --git a/tests/src/Response/Read/JsonTest.phpt b/tests/src/Response/Read/JsonStatementFactoryTest.php similarity index 53% rename from tests/src/Response/Read/JsonTest.phpt rename to tests/src/Response/Read/JsonStatementFactoryTest.php index 7915445..943f459 100644 --- a/tests/src/Response/Read/JsonTest.phpt +++ b/tests/src/Response/Read/JsonStatementFactoryTest.php @@ -1,36 +1,45 @@ -fioFactory = $fioFactory; - } - public function testCustonTransactionClass() { - $json = $this->fioFactory->getReader(); + $fioFactory = new Test\FioFactory(MyTransaction::class); + $json = $fioFactory->getReader(); $list = $json->create(Testinium\File::load('2015-01-01-2015-04-16-transactions.json')); if (Files\Json::isJsonBug()) { Assert::same(Testinium\File::load('php7.1/custom.srlz'), serialize($list)); } else { + // Testinium\File::save('custom.srlz', serialize($list)); Assert::same(Testinium\File::load('custom.srlz'), serialize($list)); } } + + /** + * @throws \h4kuna\Fio\Exceptions\Runtime + */ + public function testThrow() + { + $factory = new JsonTransactionFactory(WrongTransaction::class); + $factory->createTransaction(new \stdClass(), 'Y'); + } + +} + +class WrongTransaction extends \stdClass +{ + } /** @@ -38,15 +47,16 @@ public function testCustonTransactionClass() * @property-read string $to_account [2] * @property-read string $bank_code [3] */ -class MyTransactionTest extends TransactionAbstract +class MyTransaction extends TransactionAbstract { /** custom method */ public function setBank_code($value) { - return str_pad($value, 4, '0', STR_PAD_LEFT); + return str_pad((string) $value, 4, '0', STR_PAD_LEFT); } + public function setTo_account($value) { if (!$value) { @@ -57,5 +67,4 @@ public function setTo_account($value) } -$fioFactory = new Test\FioFactory('h4kuna\Fio\Response\Read\MyTransactionTest'); -(new JsonStatementFactoryTest($fioFactory))->run(); +(new JsonStatementFactoryTest())->run(); diff --git a/tests/src/Response/Read/ServerExceptionTest.phpt b/tests/src/Response/Read/ServerExceptionTest.php similarity index 50% rename from tests/src/Response/Read/ServerExceptionTest.phpt rename to tests/src/Response/Read/ServerExceptionTest.php index 0f8c69e..2a02734 100644 --- a/tests/src/Response/Read/ServerExceptionTest.phpt +++ b/tests/src/Response/Read/ServerExceptionTest.php @@ -1,11 +1,13 @@ -isOk()); } + } (new ServerExceptionTest())->run();