├── tests
├── bootstrap.php
├── stub
│ ├── error.xml
│ ├── recurrent.csv
│ ├── cancel.xml
│ └── results.xml
├── TestCase.php
├── Cancel
│ ├── RVRReasonTest.php
│ ├── CancelBuilderTest.php
│ └── CancelRequestTest.php
├── Payment
│ └── PaymentTest.php
├── Recurrent
│ ├── RecurrentBuilderTest.php
│ └── RecurrentRequestTest.php
├── Error
│ └── ResponseCodeTest.php
├── Order
│ └── StatusTest.php
├── Http
│ ├── FormatTest.php
│ └── HttpManagerTest.php
├── Exception
│ └── ExceptionFactoryTest.php
├── Signature
│ └── SignatureTest.php
├── Results
│ └── ResultsRequestTest.php
└── ClientTest.php
├── .gitignore
├── src
├── Exception
│ ├── FormatNotSupportedException.php
│ ├── RequestNotSupportedException.php
│ ├── NotImplementedException.php
│ ├── ErrorException.php
│ ├── AuthenticationException.php
│ ├── BadFieldFormatException.php
│ ├── OperationFailedException.php
│ ├── MandatoryParameterException.php
│ ├── NotSupportedSFieldException.php
│ ├── AuthConfirmIsNotAllowedException.php
│ ├── BillNotFoundException.php
│ ├── UnitellerException.php
│ └── ExceptionFactory.php
├── ArraybleInterface.php
├── Payment
│ ├── UriInterface.php
│ ├── PaymentInterface.php
│ ├── Type.php
│ ├── MeanType.php
│ ├── Currency.php
│ ├── EMoneyType.php
│ ├── Payment.php
│ ├── Uri.php
│ └── PaymentBuilder.php
├── Http
│ ├── HttpManagerInterface.php
│ ├── Format.php
│ └── HttpManager.php
├── Cancel
│ ├── RVRReason.php
│ ├── CancelBuilder.php
│ └── CancelRequest.php
├── Signature
│ ├── SignatureInterface.php
│ ├── AbstractSignature.php
│ ├── SignatureCallback.php
│ ├── SignatureRecurrent.php
│ └── SignaturePayment.php
├── Request
│ └── RequestInterface.php
├── ClientInterface.php
├── helpers.php
├── Error
│ ├── ResponseCode.php
│ └── Error.php
├── Order
│ ├── Status.php
│ └── Order.php
├── Results
│ └── ResultsRequest.php
├── Recurrent
│ ├── RecurrentRequest.php
│ └── RecurrentBuilder.php
└── Client.php
├── example
├── results.php
├── README_RU.md
├── callback.php
├── README.md
├── credentials.example.php
├── recurrent.php
├── cancel.php
└── index.php
├── .travis.yml
├── phpunit.xml
├── composer.json
├── LICENSE
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── .github
└── workflows
│ └── run-tests.yml
├── README.md
└── README_RU.md
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/Exception/FormatNotSupportedException.php:
--------------------------------------------------------------------------------
1 | results([
13 | 'ShopOrderNumber' => 'number'
14 | ]);
15 |
16 |
17 | var_dump($results);
18 |
--------------------------------------------------------------------------------
/src/Exception/NotImplementedException.php:
--------------------------------------------------------------------------------
1 | getSignature()->verify('signature_from_post_params', ['all_parameters_from_post'])) {
13 | return 'invalid_signature';
14 | }
15 |
16 | // ok!
17 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # SDK Payment Sample
2 |
3 | Simple example of usage Client PHP SDK.
4 |
5 | ## Install
6 |
7 | * `git clone git@github.com:tmconsulting/uniteller-php-sdk.git`
8 | * `composer install`
9 | * `cd ./examples`
10 | * `mv ./credentials.example.php ./credentials.php`
11 |
12 | First, your should be fill `./credentials.php` file with your credentials.
13 | Second, run server: `php -S localhost:8080`
14 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | setShopId('your_shop_id');
16 | $uniteller->setLogin(1234);
17 | $uniteller->setPassword('your_password');
18 | $uniteller->setBaseUri('https://wpay.uniteller.ru');
19 |
--------------------------------------------------------------------------------
/src/Payment/MeanType.php:
--------------------------------------------------------------------------------
1 | setOrderIdp(mt_rand(10000, 99999))
11 | ->setSubtotalP(15)
12 | ->setParentOrderIdp(00000) // order id of any past payment
13 | ->setParentShopIdp($uniteller->getShopId()); // optional
14 |
15 | $results = $uniteller->recurrent($builder);
16 |
17 | var_dump($results);
18 |
--------------------------------------------------------------------------------
/src/Exception/ErrorException.php:
--------------------------------------------------------------------------------
1 | errorCode;
28 | }
29 | }
--------------------------------------------------------------------------------
/example/cancel.php:
--------------------------------------------------------------------------------
1 | setBillNumber('RRN Number, (12 digits)');
15 | $results = $uniteller->cancel($builder);
16 |
17 | // or ...
18 | /*
19 | $results = $uniteller->cancel([
20 | 'Billnumber' => 'RRN Number, (12 digits)',
21 | // ...
22 | ]);
23 | */
24 |
25 | var_dump($results);
26 |
--------------------------------------------------------------------------------
/tests/Cancel/RVRReasonTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(RVRReason::SHOP, 1);
19 | $this->assertEquals(RVRReason::CARDHOLDER, 2);
20 | $this->assertEquals(RVRReason::FRAUD, 3);
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Cancel/RVRReason.php:
--------------------------------------------------------------------------------
1 | execute(['q' => 'banana'], ['base_uri' => 'https://google.com']);
21 |
22 | $this->assertInstanceOf(UriInterface::class, $results);
23 | $this->assertEquals('https://google.com/pay?q=banana', $results->getUri());
24 | }
25 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.6
5 | - 7.0
6 | - 7.1
7 | - 7.2
8 | - nightly
9 |
10 | # This triggers builds to run on the new TravisCI infrastructure.
11 | # See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
12 | sudo: false
13 |
14 | ## Cache composer
15 | cache:
16 | directories:
17 | - $HOME/.composer/cache
18 |
19 | matrix:
20 | fast_finish: true
21 | include:
22 | - php: 5.6
23 | env: 'COMPOSER_FLAGS="--prefer-stable --prefer-dist --optimize-autoloader"'
24 | allow_failures:
25 | - php: nightly
26 |
27 | before_script:
28 | - travis_retry composer self-update
29 | - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction
30 | - composer config --list --global
31 |
32 | script:
33 | - vendor/bin/phpunit
34 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 | tests
13 |
14 |
15 |
16 |
17 |
18 | integration
19 |
20 |
21 |
22 |
23 |
24 | ./src/
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Payment/EMoneyType.php:
--------------------------------------------------------------------------------
1 | uri = $uri;
30 | }
31 |
32 | /**
33 | * @return string
34 | */
35 | public function getUri()
36 | {
37 | return $this->uri;
38 | }
39 |
40 | /**
41 | * @return void
42 | */
43 | public function go()
44 | {
45 | header(sprintf('Location: %s', $this->uri));
46 | }
47 | }
--------------------------------------------------------------------------------
/src/Exception/AuthenticationException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::AUTHENTICATION;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/Exception/BadFieldFormatException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::BAD_FIELD_FORMAT;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/Exception/OperationFailedException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::OPERATION_FAILED;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/Exception/MandatoryParameterException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::MANDATORY_PARAMETER;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/Exception/NotSupportedSFieldException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::NOT_SUPPORTED_SFIELD;
31 | }
32 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tmconsulting/uniteller-php-sdk",
3 | "description": "PHP Library for integration with Uniteller payment processing.",
4 | "type": "library",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "roquie",
9 | "email": "roquie0@gmail.com"
10 | }
11 | ],
12 | "require": {
13 | "php": "^7.2 || ^8.0",
14 | "ext-simplexml": "*",
15 | "php-http/httplug": "^2",
16 | "php-http/guzzle7-adapter": "^1",
17 | "guzzlehttp/guzzle": "^7.4"
18 | },
19 | "require-dev": {
20 | "symfony/var-dumper": "^3.2",
21 | "phpunit/phpunit": "^8"
22 | },
23 | "autoload": {
24 | "psr-4": {
25 | "Tmconsulting\\Uniteller\\": "src"
26 | },
27 | "files": [
28 | "src/helpers.php"
29 | ]
30 | },
31 | "autoload-dev": {
32 | "psr-4": {
33 | "Tmconsulting\\Uniteller\\Tests\\": "tests"
34 | }
35 | },
36 | "scripts": {
37 | "test": "phpunit --coverage-text"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Exception/AuthConfirmIsNotAllowedException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::AUTH_CONFIRM_IS_NOT_ALLOWED;
31 | }
32 | }
--------------------------------------------------------------------------------
/tests/Recurrent/RecurrentBuilderTest.php:
--------------------------------------------------------------------------------
1 | setShopIdp('FOO');
19 | $builder->setParentShopIdp('BAR');
20 | $builder->setOrderIdp('BAZ');
21 | $builder->setParentOrderIdp('old');
22 | $builder->setSubtotalP(10);
23 |
24 | $expected = [
25 | 'Shop_IDP' => 'FOO',
26 | 'Parent_Shop_IDP' => 'BAR',
27 | 'Order_IDP' => 'BAZ',
28 | 'Parent_Order_IDP' => 'old',
29 | 'Subtotal_P' => 10,
30 | ];
31 |
32 | $this->assertEquals($expected, $builder->toArray());
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Signature/AbstractSignature.php:
--------------------------------------------------------------------------------
1 | toArray()));
31 |
32 | return strtoupper(md5($string));
33 | }
34 |
35 | /**
36 | * Verify signature
37 | *
38 | * @param string $signature
39 | * @return bool
40 | */
41 | public function verify($signature)
42 | {
43 | return $this->create() === $signature;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Exception/BillNotFoundException.php:
--------------------------------------------------------------------------------
1 | errorCode = Error::BILL_NOT_FOUND;
36 | }
37 | }
--------------------------------------------------------------------------------
/tests/Cancel/CancelBuilderTest.php:
--------------------------------------------------------------------------------
1 | setBillNumber(1);
21 | $builder->setCurrency('RUB');
22 | $builder->setRvrReason(RVRReason::SHOP);
23 | $builder->setSelectFields([]);
24 | $builder->setSubtotalP(10);
25 |
26 | $expected = [
27 | 'Billnumber' => 1,
28 | 'Subtotal_P' => 10,
29 | 'Currency' => 'RUB',
30 | 'RVRReason' => RVRReason::SHOP,
31 | 'S_FIELDS' => []
32 | ];
33 |
34 | $this->assertEquals($expected, $builder->toArray());
35 | }
36 | }
--------------------------------------------------------------------------------
/example/index.php:
--------------------------------------------------------------------------------
1 | useRecurrentPayment()
13 | ->setOrderIdp(mt_rand(10000, 99999))
14 | ->setSubtotalP(10)
15 | ->setCustomerIdp(mt_rand(10000, 99999))
16 | ->setUrlReturnOk('http://google.ru/?q=success')
17 | ->setUrlReturnNo('http://google.ru/?q=failure');
18 |
19 |
20 | $uri = $uniteller->payment($builder)->getUri();
21 |
22 | echo <<< HTML
23 |
Client Payment Sample
24 |
25 | Оплатить
26 | {$uri}
27 |
28 | Отмена
29 | /cancel.php
30 |
31 |
32 | Результаты платежа
33 | /results.php
34 |
35 | HTML;
36 |
37 | // or...
38 |
39 | /*
40 |
41 | $uniteller->payment([
42 | 'Shop_IDP' => '',
43 | // ...
44 | ]);
45 |
46 | */
47 |
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 SpaceTab.io
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tests/Error/ResponseCodeTest.php:
--------------------------------------------------------------------------------
1 | {$method}(ResponseCode::message($code));
42 | }
43 | }
--------------------------------------------------------------------------------
/src/Exception/UnitellerException.php:
--------------------------------------------------------------------------------
1 | getRequestTarget(),
30 | $request->getMethod(),
31 | $response->getStatusCode(),
32 | $response->getReasonPhrase()
33 | );
34 |
35 | return new static($message, $request, $response, $previous);
36 | }
37 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | * Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
4 | * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
5 | * Any contribution must provide tests for additional introduced conditions
6 | * Any un-confirmed issue needs a failing test case before being accepted
7 | * Pull requests must be sent from a new hotfix/feature branch, not from `master`.
8 |
9 | ## Installation
10 |
11 | To install the project and run the tests, you need to clone it first:
12 |
13 | ```sh
14 | git@github.com:tmconsulting/uniteller-php-sdk.git
15 | ```
16 |
17 | You will then need to run a composer installation:
18 |
19 | ```sh
20 | cd uniteller-php-sdk
21 | curl -s https://getcomposer.org/installer | php
22 | php composer.phar install
23 | ```
24 |
25 | ## Testing
26 |
27 | The PHPUnit version to be used is the one installed as a dev- dependency via composer:
28 |
29 | ```sh
30 | ./vendor/bin/phpunit
31 | ```
32 |
33 | Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement
34 | won't be merged.
35 |
--------------------------------------------------------------------------------
/tests/Order/StatusTest.php:
--------------------------------------------------------------------------------
1 | assertEquals($expected, Status::resolve($name));
41 | }
42 | }
--------------------------------------------------------------------------------
/src/Request/RequestInterface.php:
--------------------------------------------------------------------------------
1 | expectException(RequestNotSupportedException::class);
23 | $this->expectExceptionMessage('Request [unknown] not supported here.');
24 |
25 | Format::resolveXml('unknown');
26 | }
27 |
28 | public function testCanNotResolveUnsupportedFormat()
29 | {
30 | $this->expectException(FormatNotSupportedException::class);
31 | $this->expectExceptionMessage('Format [xml] not supported for request [recurrent].');
32 |
33 | Format::resolveXml(RequestInterface::REQUEST_RECURRENT);
34 | }
35 |
36 | public function testCanCallBadMagicStaticMethod()
37 | {
38 | $this->expectException(BadMethodCallException::class);
39 | $this->expectExceptionMessage('Method [resolvingJson] not found.');
40 |
41 | Format::resolvingJson('unknown');
42 | }
43 |
44 | public function testCanResolveSupportedFormat()
45 | {
46 | $value = Format::resolveXml(RequestInterface::REQUEST_CONFIRM);
47 | $this->assertEquals(3, $value);
48 | }
49 | }
--------------------------------------------------------------------------------
/src/helpers.php:
--------------------------------------------------------------------------------
1 | {$key})) {
34 | return $default;
35 | }
36 |
37 | if (trim((string) $object->{$key}) === '*НЕ ЗАДАВАЛСЯ*') {
38 | return $default;
39 | }
40 |
41 | return (string) $object->{$key};
42 | }
43 |
44 | /**
45 | * @param string $string
46 | * @param bool $isFlat
47 | * @return array|mixed
48 | */
49 | function csv_to_array($string, $isFlat = false)
50 | {
51 | $lines = explode("\n", trim($string));
52 | $headers = str_getcsv(array_shift($lines), ';');
53 | $data = [];
54 | foreach ($lines as $line) {
55 | $row = [];
56 | foreach (str_getcsv($line, ';') as $key => $field) {
57 | $row[$headers[$key]] = $field;
58 | }
59 | $data[] = array_filter($row);
60 | }
61 |
62 | if ($isFlat && !empty($data)) {
63 | $data = $data[0];
64 | }
65 |
66 | return $data;
67 | }
68 |
69 | /**
70 | * @param $array
71 | * @param array $excludeKeys
72 | * @return mixed
73 | */
74 | function array_except($array, array $excludeKeys)
75 | {
76 | foreach ($excludeKeys as $key) {
77 | unset($array[$key]);
78 | }
79 |
80 | return $array;
81 | }
--------------------------------------------------------------------------------
/src/Error/ResponseCode.php:
--------------------------------------------------------------------------------
1 | 'АВТОРИЗАЦИЯ УСПЕШНО ЗАВЕРШЕНА',
28 | 'AS100' => 'ОТКАЗ В АВТОРИЗАЦИИ',
29 | 'AS101' => 'ОТКАЗ В АВТОРИЗАЦИИ. Ошибочный номер карты.',
30 | 'AS102' => 'ОТКАЗ В АВТОРИЗАЦИИ. Недостаточно средств.',
31 | 'AS104' => 'ОТКАЗ В АВТОРИЗАЦИИ. Неверный срок действия карты.',
32 | 'AS105' => 'ОТКАЗ В АВТОРИЗАЦИИ. Превышен лимит.',
33 | 'AS107' => 'ОТКАЗ В АВТОРИЗАЦИИ. Ошибка приёма данных.',
34 | 'AS108' => 'ОТКАЗ В АВТОРИЗАЦИИ. Подозрение на мошенничество.',
35 | 'AS109' => 'ОТКАЗ В АВТОРИЗАЦИИ. Превышен лимит операций Client.',
36 | 'AS200' => 'ПОВТОРИТЕ АВТОРИЗАЦИЮ',
37 | 'AS998' => 'ОШИБКА СИСТЕМЫ. Свяжитесь с Client.',
38 | ];
39 |
40 | /**
41 | * Преобразование кода ошибки в сообщение.
42 | *
43 | * @param $code
44 | * @return string|null
45 | */
46 | public static function message($code)
47 | {
48 | if (array_key_exists($code, self::$messages)) {
49 | return self::$messages[$code];
50 | }
51 |
52 | return null;
53 | }
54 | }
--------------------------------------------------------------------------------
/tests/Exception/ExceptionFactoryTest.php:
--------------------------------------------------------------------------------
1 | expectException($e);
52 |
53 | throw ExceptionFactory::createFromMessage(
54 | $message,
55 | $this->createMock(RequestInterface::class),
56 | $this->createMock(ResponseInterface::class)
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/stub/cancel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Value of ordernumber
6 | Value of response_code
7 | Value of recommendation
8 | Value of message
9 | Value of comment
10 | 10.03.2017 15:42:42
11 | Value of total
12 | Value of currency
13 | Value of cardtype
14 | Value of emoneytype
15 | Value of cardnumber
16 | foo=bar, baz=bue
17 | Value of lastname
18 | Value of firstname
19 | Value of middlename
20 | Value of bookingcom_id
21 | Value of bookingcom_pincode
22 | Value of gds_payment_purpose_id
23 | Value of idata
24 | 1
25 | Value of loan_id
26 | Value of card_idp
27 | Value of parent_order_number
28 | Value of address
29 | Value of email
30 | paid
31 | Value of pt_code
32 | Value of approvalcode
33 | Value of cvc2
34 | Value of cardholder
35 | Value of ipaddress
36 | Value of billnumber
37 | Value of bankname
38 | Value of status
39 | Value of error_code
40 | Value of error_comment
41 | 10.03.2017 15:42:42
42 | Value of paymenttype
43 | Value of phone
44 |
45 |
46 |
--------------------------------------------------------------------------------
/tests/stub/results.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Value of ordernumber
6 | Value of response_code
7 | Value of recommendation
8 | Value of message
9 | Value of comment
10 | 10.03.2017 15:42:42
11 | Value of total
12 | Value of currency
13 | Value of cardtype
14 | Value of emoneytype
15 | Value of cardnumber
16 | foo=bar, baz=bue
17 | Value of lastname
18 | Value of firstname
19 | Value of middlename
20 | Value of bookingcom_id
21 | Value of bookingcom_pincode
22 | Value of gds_payment_purpose_id
23 | Value of idata
24 | 1
25 | Value of loan_id
26 | Value of card_idp
27 | Value of parent_order_number
28 | Value of address
29 | Value of email
30 | paid
31 | Value of pt_code
32 | Value of approvalcode
33 | Value of cvc2
34 | Value of cardholder
35 | Value of ipaddress
36 | Value of billnumber
37 | Value of bankname
38 | Value of status
39 | Value of error_code
40 | Value of error_comment
41 | 10.03.2017 15:42:42
42 | Value of paymenttype
43 | Value of phone
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/Order/Status.php:
--------------------------------------------------------------------------------
1 | orderId = $orderId;
45 |
46 | return $this;
47 | }
48 |
49 | /**
50 | * @param $status
51 | * @return SignatureCallback
52 | */
53 | public function setStatus($status)
54 | {
55 | $this->status = $status;
56 |
57 | return $this;
58 | }
59 |
60 | /**
61 | * @param array $fields
62 | * @return SignatureCallback
63 | */
64 | public function setFields($fields)
65 | {
66 | $this->fields = $fields;
67 |
68 | return $this;
69 | }
70 |
71 | /**
72 | * @param string $password
73 | * @return SignatureCallback
74 | */
75 | public function setPassword($password)
76 | {
77 | $this->password = $password;
78 |
79 | return $this;
80 | }
81 |
82 | /**
83 | * @return string
84 | */
85 | public function getOrderId()
86 | {
87 | return $this->orderId;
88 | }
89 |
90 | /**
91 | * @return string
92 | */
93 | public function getStatus()
94 | {
95 | return $this->status;
96 | }
97 |
98 | /**
99 | * @return array
100 | */
101 | public function getFields()
102 | {
103 | return $this->fields;
104 | }
105 |
106 | /**
107 | * @return string
108 | */
109 | public function getPassword()
110 | {
111 | return $this->password;
112 | }
113 |
114 | /**
115 | * @return array
116 | */
117 | public function toArray()
118 | {
119 | $array = [];
120 | $array['Order_ID'] = $this->getOrderId();
121 | $array['Status'] = $this->getStatus();
122 | $array = array_merge($array, $this->getFields());
123 | $array['Password'] = $this->getPassword();
124 |
125 | return $array;
126 | }
127 |
128 | /**
129 | * Create signature
130 | *
131 | * @return string
132 | */
133 | public function create()
134 | {
135 | return strtoupper(md5(join('', $this->toArray())));
136 | }
137 | }
--------------------------------------------------------------------------------
/src/Http/Format.php:
--------------------------------------------------------------------------------
1 | ['csv' => 1, 'wddx' => 2, 'xml' => 3],
34 | RequestInterface::REQUEST_CONFIRM => ['csv' => 1, 'wddx' => 2, 'xml' => 3],
35 | RequestInterface::REQUEST_RECURRENT => ['csv' => 1],
36 | RequestInterface::REQUEST_CANCEL => ['csv' => 1, 'wddx' => 2, 'xml' => 3, 'soap' => 4],
37 | RequestInterface::REQUEST_RESULTS => ['csv' => 1, 'wddx' => 2, 'brackets' => 3, 'xml' => 4, 'soap' => 5]
38 | ];
39 |
40 | /**
41 | * Преобразование от имени запроса к одному формату.
42 | *
43 | * @param $format
44 | * @param $requestName
45 | * @return int
46 | * @throws \Tmconsulting\Uniteller\Exception\FormatNotSupportedException
47 | * @throws \Tmconsulting\Uniteller\Exception\RequestNotSupportedException
48 | */
49 | public static function resolve($format, $requestName)
50 | {
51 | if (! array_key_exists($requestName, self::$variants)) {
52 | throw new RequestNotSupportedException(sprintf(
53 | 'Request [%s] not supported here.', $requestName
54 | ));
55 | }
56 |
57 | if (! array_key_exists($format, self::$variants[$requestName])) {
58 | throw new FormatNotSupportedException(sprintf(
59 | 'Format [%s] not supported for request [%s].', $format, $requestName
60 | ));
61 | }
62 |
63 | return self::$variants[$requestName][$format];
64 | }
65 |
66 | /**
67 | * Вариант Format::resolveXml(...), для ленивых, как я.
68 | *
69 | * @param $name
70 | * @param array $arguments
71 | * @return int
72 | */
73 | public static function __callStatic($name, array $arguments)
74 | {
75 | if (false === strpos($name, 'resolve')) {
76 | throw new BadMethodCallException(sprintf(
77 | 'Method [%s] not found.', $name
78 | ));
79 | }
80 |
81 | return self::resolve(
82 | strtolower(substr($name, 7)),
83 | Uniteller\array_get($arguments, 0)
84 | );
85 | }
86 | }
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at roquie0@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/src/Exception/ExceptionFactory.php:
--------------------------------------------------------------------------------
1 | 'Authorization(\s)+confirm(\s)+is(\s)+not(\s)+allowed',
28 | Error::AUTHENTICATION => 'Authentication(\s)+error',
29 | Error::BAD_FIELD_FORMAT => 'Field(.*)has(\s)+bad(\s)+format',
30 | Error::MANDATORY_PARAMETER => 'Mandatory(\s)+parameter(\s)+\\\'(.*)\\\'(.*)',
31 | Error::NOT_SUPPORTED_SFIELD => 'S_FIELDS(\s)+contains(\s)+field(\s)+\\\'(.*)\\\'(.*)',
32 | Error::OPERATION_FAILED => 'The(\s)+operation(\s)+failed',
33 | ];
34 |
35 | /**
36 | * В /results запросе кода ошибки нет, есть только его сообщение.
37 | * С помощью регулярок (а как еще!?) вызовем нужный эксепшен на помощь разработчикам.
38 | */
39 | public static function createFromMessage(
40 | string $message,
41 | RequestInterface $request,
42 | ResponseInterface $response
43 | ): ErrorException {
44 | foreach (self::$messageToErrorCode as $code => $regex) {
45 | preg_match('/' . $regex . '/', $message, $matches);
46 |
47 | if (count($matches) > 0) {
48 | return self::create($code, $message, $request, $response);
49 | }
50 | }
51 |
52 | return self::create(Error::UNKNOWN, $message, $request, $response);
53 | }
54 |
55 | /**
56 | * Конвертируем код ошибки в эксепшен.
57 | */
58 | public static function create(
59 | int $code,
60 | string $message,
61 | RequestInterface $request,
62 | ResponseInterface $response
63 | ): ErrorException {
64 | switch ($code) {
65 | case Error::AUTH_CONFIRM_IS_NOT_ALLOWED:
66 | return new AuthConfirmIsNotAllowedException(
67 | $message, $request, $response
68 | );
69 | case Error::AUTHENTICATION:
70 | return new AuthenticationException(
71 | $message, $request, $response
72 | );
73 | case Error::BAD_FIELD_FORMAT:
74 | return new BadFieldFormatException(
75 | $message, $request, $response
76 | );
77 | case Error::MANDATORY_PARAMETER:
78 | return new MandatoryParameterException(
79 | $message, $request, $response
80 | );
81 | case Error::NOT_SUPPORTED_SFIELD:
82 | return new NotSupportedSFieldException(
83 | $message, $request, $response
84 | );
85 | case Error::OPERATION_FAILED:
86 | return new OperationFailedException(
87 | $message, $request, $response
88 | );
89 | }
90 |
91 | return new ErrorException($message, $request, $response);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/tests/Http/HttpManagerTest.php:
--------------------------------------------------------------------------------
1 | http([
30 | new Response(200, [], $this->getStubContents('cancel')),
31 | ]);
32 |
33 | $this->assertEquals(
34 | $this->getStubContents('cancel'),
35 | $manager->request(RequestInterface::REQUEST_CANCEL)
36 | );
37 | }
38 |
39 | public function testBehaviorIfServerReturnError()
40 | {
41 | $this->expectException(UnitellerException::class);
42 |
43 | $manager = $this->http([
44 | new RequestException(
45 | 'Error Communicating with Server',
46 | new Request('GET', 'test'),
47 | new Response(500)
48 | )
49 | ]);
50 |
51 | $manager->request(RequestInterface::REQUEST_CANCEL);
52 | }
53 |
54 | public function testCreatingExceptionsFromPayloadErrorText()
55 | {
56 | $this->expectException(AuthConfirmIsNotAllowedException::class);
57 |
58 | $manager = $this->http([
59 | new Response(200, [], 'ERROR: Authorization confirm is not allowed')
60 | ]);
61 |
62 | $manager->request(RequestInterface::REQUEST_CANCEL);
63 | }
64 |
65 | public function testCreatingExceptionsFromXmlResponse()
66 | {
67 | $this->expectException(AuthenticationException::class);
68 |
69 | $manager = $this->http([
70 | new Response(200, [], $this->getStubContents('error'))
71 | ]);
72 |
73 | $manager->request(RequestInterface::REQUEST_CANCEL);
74 | }
75 |
76 | public function testThrownBasicExceptionIfStatusNotIncludedInTheRange()
77 | {
78 | $this->expectException(UnitellerException::class);
79 |
80 | $manager = $this->http([new Response(302, [])]);
81 |
82 | $manager->request(RequestInterface::REQUEST_CANCEL);
83 | }
84 |
85 | /**
86 | * @param $queue
87 | * @return \Tmconsulting\Uniteller\Http\HttpManager
88 | */
89 | protected function http($queue)
90 | {
91 | $mock = new MockHandler($queue);
92 |
93 | $httpClient = new GuzzleAdapter(new GuzzleClient([
94 | 'handler' => HandlerStack::create($mock)
95 | ]));
96 |
97 | return new HttpManager($httpClient, [
98 | 'base_uri' => '',
99 | 'shop_id' => '',
100 | 'login' => '',
101 | 'password' => '',
102 | ]);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/Error/Error.php:
--------------------------------------------------------------------------------
1 | billNumber = $billNumber;
66 |
67 | return $this;
68 | }
69 |
70 | /**
71 | * @param string $currency
72 | * @return $this
73 | */
74 | public function setCurrency($currency)
75 | {
76 | $this->currency = $currency;
77 |
78 | return $this;
79 | }
80 |
81 | /**
82 | * @param int $rvrReason
83 | * @return $this
84 | */
85 | public function setRvrReason($rvrReason)
86 | {
87 | $this->rvrReason = $rvrReason;
88 |
89 | return $this;
90 | }
91 |
92 | /**
93 | * @param float $subtotalP
94 | * @return $this
95 | */
96 | public function setSubtotalP($subtotalP)
97 | {
98 | $this->subtotalP = $subtotalP;
99 |
100 | return $this;
101 | }
102 |
103 | /**
104 | * @param array $selectFields
105 | * @return $this
106 | */
107 | public function setSelectFields(array $selectFields)
108 | {
109 | $this->selectFields = $selectFields;
110 |
111 | return $this;
112 | }
113 |
114 | /**
115 | * @return int
116 | */
117 | public function getBillNumber()
118 | {
119 | return $this->billNumber;
120 | }
121 |
122 | /**
123 | * @return string
124 | */
125 | public function getCurrency()
126 | {
127 | return $this->currency;
128 | }
129 |
130 | /**
131 | * @return int
132 | */
133 | public function getRvrReason()
134 | {
135 | return $this->rvrReason;
136 | }
137 |
138 | /**
139 | * @return float
140 | */
141 | public function getSubtotalP()
142 | {
143 | return $this->subtotalP;
144 | }
145 |
146 | /**
147 | * @return array
148 | */
149 | public function getSelectFields()
150 | {
151 | return $this->selectFields;
152 | }
153 |
154 | public function toArray()
155 | {
156 | return [
157 | 'Billnumber' => $this->getBillNumber(),
158 | 'Subtotal_P' => $this->getSubtotalP(),
159 | 'Currency' => $this->getCurrency(),
160 | 'RVRReason' => $this->getRvrReason(),
161 | 'S_FIELDS' => $this->getSelectFields()
162 | ];
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tests/Recurrent/RecurrentRequestTest.php:
--------------------------------------------------------------------------------
1 | createMock(HttpManagerInterface::class);
21 | $manager
22 | ->expects($this->once())
23 | ->method('request')
24 | ->willReturn($this->getStubContents('recurrent', 'csv'));
25 |
26 | $request = new RecurrentRequest();
27 | /** @var \Tmconsulting\Uniteller\Order\Order $order */
28 | foreach ($request->execute($manager) as $order) {
29 | $this->assertInstanceOf(Order::class, $order);
30 | $this->assertEquals('Value of address', $order->getAddress());
31 | $this->assertEquals('Value of approvalCode', $order->getApprovalCode());
32 | $this->assertEquals('Value of bankName', $order->getBankName());
33 | $this->assertEquals('Value of billNumber', $order->getBillNumber());
34 | $this->assertEquals(null, $order->getBookingcomId());
35 | $this->assertEquals(null, $order->getBookingcomPincode());
36 | $this->assertEquals(null, $order->getCardIdp());
37 | $this->assertEquals('Value of cardHolder', $order->getCardHolder());
38 | $this->assertEquals('Value of cardNumber', $order->getCardNumber());
39 | $this->assertEquals('Value of cardType', $order->getCardType());
40 | $this->assertEquals('Value of comment', $order->getComment());
41 | $this->assertEquals('Value of currency', $order->getCurrency());
42 | $this->assertEquals(true, $order->isCvc2());
43 | $this->assertInstanceOf(\DateTime::class, $order->getDate());
44 | $this->assertEquals('Value of email', $order->getEmail());
45 | $this->assertEquals(null, $order->getEMoneyType());
46 | $this->assertEquals(null, $order->getEOrderData());
47 | $this->assertEquals('Value of error_code', $order->getErrorCode());
48 | $this->assertEquals('Value of error_comment', $order->getErrorComment());
49 | $this->assertEquals('Value of firstName', $order->getFirstName());
50 | $this->assertEquals(null, $order->getGdsPaymentPurposeId());
51 | $this->assertEquals(null, $order->getIData());
52 | $this->assertEquals('Value of ipAddress', $order->getIp());
53 | $this->assertEquals('Value of lastName', $order->getLastName());
54 | $this->assertEquals(null, $order->getLoanId());
55 | $this->assertEquals('Value of message', $order->getMessage());
56 | $this->assertEquals('Value of middleName', $order->getMiddleName());
57 | $this->assertEquals(false, $order->isNeedConfirm());
58 | $this->assertEquals('Value of orderNumber', $order->getOrderNumber());
59 | $this->assertEquals(null, $order->getParentOrderNumber());
60 | $this->assertEquals('Value of paymentType', $order->getPaymentType());
61 | $this->assertEquals('Value of phone', $order->getPhone());
62 | $this->assertEquals(null, $order->getPtCode());
63 | $this->assertEquals('Value of recommendation', $order->getRecommendation());
64 | $this->assertEquals('Value of response_code', $order->getResponseCode());
65 | $this->assertEquals(Status::AUTHORIZED, $order->getStatus());
66 | $this->assertEquals('Value of total', $order->getTotal());
67 | $this->assertInstanceOf(\DateTime::class, $order->getPacketDate());
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/src/Cancel/CancelRequest.php:
--------------------------------------------------------------------------------
1 | request('unblock', 'POST', http_build_query($parameters));
32 | $xml = new \SimpleXMLElement($response);
33 |
34 | $array = [];
35 | foreach ($xml->orders->order as $item) {
36 | $array[] = (new Order())
37 | ->setAddress(Uniteller\xml_get($item, 'address'))
38 | ->setApprovalCode(Uniteller\xml_get($item, 'approvalcode'))
39 | ->setBankName(Uniteller\xml_get($item, 'bankname'))
40 | ->setBillNumber(Uniteller\xml_get($item, 'billnumber'))
41 | ->setBookingcomId(Uniteller\xml_get($item, 'bookingcom_id'))
42 | ->setBookingcomPincode(Uniteller\xml_get($item, 'bookingcom_pincode'))
43 | ->setCardIdp(Uniteller\xml_get($item, 'card_idp'))
44 | ->setCardHolder(Uniteller\xml_get($item, 'cardholder'))
45 | ->setCardNumber(Uniteller\xml_get($item, 'cardnumber'))
46 | ->setCardType(Uniteller\xml_get($item, 'cardtype'))
47 | ->setComment(Uniteller\xml_get($item, 'comment'))
48 | ->setCurrency(Uniteller\xml_get($item, 'currency'))
49 | ->setCvc2((bool)Uniteller\xml_get($item, 'cvc2'))
50 | ->setDate(Uniteller\xml_get($item, 'date'))
51 | ->setEmail(Uniteller\xml_get($item, 'email'))
52 | ->setEMoneyType(Uniteller\xml_get($item, 'emoneytype'))
53 | ->setEOrderData(Uniteller\xml_get($item, 'eorderdata'))
54 | ->setErrorCode(Uniteller\xml_get($item, 'error_code'))
55 | ->setErrorComment(Uniteller\xml_get($item, 'error_comment'))
56 | ->setFirstName(Uniteller\xml_get($item, 'firstname'))
57 | ->setGdsPaymentPurposeId(Uniteller\xml_get($item, 'gds_payment_purpose_id'))
58 | ->setIData(Uniteller\xml_get($item, 'idata'))
59 | ->setIp(Uniteller\xml_get($item, 'ipaddress'))
60 | ->setLastName(Uniteller\xml_get($item, 'lastname'))
61 | ->setLoanId(Uniteller\xml_get($item, 'loan_id'))
62 | ->setMessage(Uniteller\xml_get($item, 'message'))
63 | ->setMiddleName(Uniteller\xml_get($item, 'middlename'))
64 | ->setNeedConfirm((bool) Uniteller\xml_get($item, 'need_confirm'))
65 | ->setOrderNumber(Uniteller\xml_get($item, 'ordernumber'))
66 | ->setParentOrderNumber(Uniteller\xml_get($item, 'parent_order_number'))
67 | ->setPaymentType(Uniteller\xml_get($item, 'paymenttype'))
68 | ->setPhone(Uniteller\xml_get($item, 'phone'))
69 | ->setPtCode(Uniteller\xml_get($item, 'pt_code'))
70 | ->setRecommendation(Uniteller\xml_get($item, 'recommendation'))
71 | ->setResponseCode(Uniteller\xml_get($item, 'response_code'))
72 | ->setStatus(Uniteller\xml_get($item, 'status'))
73 | ->setTotal(Uniteller\xml_get($item, 'total'))
74 | ->setPacketDate(Uniteller\xml_get($item, 'packetdate'))
75 | ;
76 | }
77 |
78 | return $array;
79 | }
80 | }
--------------------------------------------------------------------------------
/src/Results/ResultsRequest.php:
--------------------------------------------------------------------------------
1 | request('results', 'POST', http_build_query($parameters));
32 | $xml = new \SimpleXMLElement($response);
33 |
34 | $array = [];
35 | foreach ($xml->orders->order as $item) {
36 | $array[] = (new Order())
37 | ->setAddress(Uniteller\xml_get($item, 'address'))
38 | ->setApprovalCode(Uniteller\xml_get($item, 'approvalcode'))
39 | ->setBankName(Uniteller\xml_get($item, 'bankname'))
40 | ->setBillNumber(Uniteller\xml_get($item, 'billnumber'))
41 | ->setBookingcomId(Uniteller\xml_get($item, 'bookingcom_id'))
42 | ->setBookingcomPincode(Uniteller\xml_get($item, 'bookingcom_pincode'))
43 | ->setCardIdp(Uniteller\xml_get($item, 'card_idp'))
44 | ->setCardHolder(Uniteller\xml_get($item, 'cardholder'))
45 | ->setCardNumber(Uniteller\xml_get($item, 'cardnumber'))
46 | ->setCardType(Uniteller\xml_get($item, 'cardtype'))
47 | ->setComment(Uniteller\xml_get($item, 'comment'))
48 | ->setCurrency(Uniteller\xml_get($item, 'currency'))
49 | ->setCvc2((bool)Uniteller\xml_get($item, 'cvc2'))
50 | ->setDate(Uniteller\xml_get($item, 'date'))
51 | ->setEmail(Uniteller\xml_get($item, 'email'))
52 | ->setEMoneyType(Uniteller\xml_get($item, 'emoneytype'))
53 | ->setEOrderData(Uniteller\xml_get($item, 'eorderdata'))
54 | ->setErrorCode(Uniteller\xml_get($item, 'error_code'))
55 | ->setErrorComment(Uniteller\xml_get($item, 'error_comment'))
56 | ->setFirstName(Uniteller\xml_get($item, 'firstname'))
57 | ->setGdsPaymentPurposeId(Uniteller\xml_get($item, 'gds_payment_purpose_id'))
58 | ->setIData(Uniteller\xml_get($item, 'idata'))
59 | ->setIp(Uniteller\xml_get($item, 'ipaddress'))
60 | ->setLastName(Uniteller\xml_get($item, 'lastname'))
61 | ->setLoanId(Uniteller\xml_get($item, 'loan_id'))
62 | ->setMessage(Uniteller\xml_get($item, 'message'))
63 | ->setMiddleName(Uniteller\xml_get($item, 'middlename'))
64 | ->setNeedConfirm((bool) Uniteller\xml_get($item, 'need_confirm'))
65 | ->setOrderNumber(Uniteller\xml_get($item, 'ordernumber'))
66 | ->setParentOrderNumber(Uniteller\xml_get($item, 'parent_order_number'))
67 | ->setPaymentType(Uniteller\xml_get($item, 'paymenttype'))
68 | ->setPhone(Uniteller\xml_get($item, 'phone'))
69 | ->setPtCode(Uniteller\xml_get($item, 'pt_code'))
70 | ->setRecommendation(Uniteller\xml_get($item, 'recommendation'))
71 | ->setResponseCode(Uniteller\xml_get($item, 'response_code'))
72 | ->setStatus(Uniteller\xml_get($item, 'status'))
73 | ->setTotal(Uniteller\xml_get($item, 'total'))
74 | ->setPacketDate(Uniteller\xml_get($item, 'packetdate'))
75 | ;
76 | }
77 |
78 | return $array;
79 | }
80 | }
--------------------------------------------------------------------------------
/src/Signature/SignatureRecurrent.php:
--------------------------------------------------------------------------------
1 | shopIdp = $shopIdp;
56 |
57 | return $this;
58 | }
59 |
60 | /**
61 | * @param string $parentShopIdp
62 | * @return SignatureRecurrent
63 | */
64 | public function setParentShopIdp($parentShopIdp)
65 | {
66 | $this->parentShopIdp = $parentShopIdp;
67 |
68 | return $this;
69 | }
70 |
71 | /**
72 | * @param string $orderIdp
73 | * @return SignatureRecurrent
74 | */
75 | public function setOrderIdp($orderIdp)
76 | {
77 | $this->orderIdp = $orderIdp;
78 |
79 | return $this;
80 | }
81 |
82 | /**
83 | * @param string $subtotalP
84 | * @return SignatureRecurrent
85 | */
86 | public function setSubtotalP($subtotalP)
87 | {
88 | $this->subtotalP = $subtotalP;
89 |
90 | return $this;
91 | }
92 |
93 | /**
94 | * @param string $parentOrderIdp
95 | * @return SignatureRecurrent
96 | */
97 | public function setParentOrderIdp($parentOrderIdp)
98 | {
99 | $this->parentOrderIdp = $parentOrderIdp;
100 |
101 | return $this;
102 | }
103 |
104 | /**
105 | * @param string $password
106 | * @return SignatureRecurrent
107 | */
108 | public function setPassword($password)
109 | {
110 | $this->password = $password;
111 |
112 | return $this;
113 | }
114 |
115 | /**
116 | * @return string
117 | */
118 | public function getShopIdp()
119 | {
120 | return $this->shopIdp;
121 | }
122 |
123 | /**
124 | * @return string
125 | */
126 | public function getParentShopIdp()
127 | {
128 | return $this->parentShopIdp;
129 | }
130 |
131 | /**
132 | * @return string
133 | */
134 | public function getOrderIdp()
135 | {
136 | return $this->orderIdp;
137 | }
138 |
139 | /**
140 | * @return string
141 | */
142 | public function getSubtotalP()
143 | {
144 | return $this->subtotalP;
145 | }
146 |
147 | /**
148 | * @return string
149 | */
150 | public function getParentOrderIdp()
151 | {
152 | return $this->parentOrderIdp;
153 | }
154 |
155 | /**
156 | * @return string
157 | */
158 | public function getPassword()
159 | {
160 | return $this->password;
161 | }
162 |
163 | /**
164 | * @return array
165 | */
166 | public function toArray()
167 | {
168 | $array = [];
169 | $array['Shop_IDP'] = $this->getShopIdp();
170 | if($this->getParentShopIdp() !== null)
171 | $array['Parent_Shop_IDP'] = $this->getParentShopIdp();
172 | $array['Order_IDP'] = $this->getOrderIdp();
173 | $array['Subtotal_P'] = $this->getSubtotalP();
174 | $array['Parent_Order_IDP'] = $this->getParentOrderIdp();
175 | $array['Password'] = $this->getPassword();
176 |
177 | return $array;
178 | }
179 | }
--------------------------------------------------------------------------------
/tests/Signature/SignatureTest.php:
--------------------------------------------------------------------------------
1 | setShopIdp('ACME')
21 | ->setOrderIdp('FOO')
22 | ->setSubtotalP(100)
23 | ->setLifeTime(300)
24 | ->setCustomerIdp('short_shop_string')
25 | ->setPassword('LONG-PWD')
26 | ->create();
27 |
28 | $this->assertSame('3D1D6F830384886A81AD672F66392B03', $sig);
29 | }
30 |
31 | public function testRecurrentSignatureCreation()
32 | {
33 | $sig = (new SignatureRecurrent())
34 | ->setShopIdp('ACME')
35 | ->setOrderIdp('FOO')
36 | ->setSubtotalP(100)
37 | ->setParentOrderIdp('BAR')
38 | ->setPassword('LONG-PWD')
39 | ->create();
40 |
41 | $this->assertSame('A5FE1C95A2819EBACFC2145EE83742F6', $sig);
42 | }
43 |
44 | public function testCallbackSignatureCreation()
45 | {
46 | $sig = (new SignatureCallback())
47 | ->setOrderId('FOO')
48 | ->setStatus('paid')
49 | ->setPassword('LONG-PWD')
50 | ->create();
51 |
52 | $this->assertSame('3F728AA479E50F5B10EE6C20258BFF88', $sig);
53 | }
54 |
55 | public function testCallbackSignatureCreationWithFields()
56 | {
57 | $sig = (new SignatureCallback())
58 | ->setOrderId('FOO')
59 | ->setStatus('paid')
60 | ->setFields([
61 | 'AcquirerID' => 'fOO',
62 | 'ApprovalCode' => 'BaR',
63 | 'BillNumber' => 'baz',
64 | ])
65 | ->setPassword('LONG-PWD')
66 | ->create();
67 |
68 | $this->assertSame('1F4E3B63AE408D0BE1E33965E6697236', $sig);
69 | }
70 |
71 | public function testPaymentSignatureVerifying()
72 | {
73 | $sig = (new SignaturePayment())
74 | ->setShopIdp('ACME')
75 | ->setOrderIdp('FOO')
76 | ->setSubtotalP(100)
77 | ->setLifeTime(300)
78 | ->setCustomerIdp('short_shop_string')
79 | ->setPassword('LONG-PWD');
80 |
81 | $this->assertTrue($sig->verify('3D1D6F830384886A81AD672F66392B03'));
82 | }
83 |
84 | public function testRecurrentSignatureVerifying()
85 | {
86 | $sig = (new SignatureRecurrent())
87 | ->setShopIdp('ACME')
88 | ->setOrderIdp('FOO')
89 | ->setSubtotalP(100)
90 | ->setParentOrderIdp('BAR')
91 | ->setPassword('LONG-PWD');
92 |
93 | $this->assertTrue($sig->verify('A5FE1C95A2819EBACFC2145EE83742F6'));
94 | }
95 |
96 | public function testCallbackSignatureVerifying()
97 | {
98 | $sig = (new SignatureCallback())
99 | ->setOrderId('FOO')
100 | ->setStatus('paid')
101 | ->setPassword('LONG-PWD');
102 |
103 | $this->assertTrue($sig->verify('3F728AA479E50F5B10EE6C20258BFF88'));
104 | }
105 |
106 | public function testCallbackSignatureVerifyingWithFields()
107 | {
108 | $sig = (new SignatureCallback())
109 | ->setOrderId('FOO')
110 | ->setStatus('paid')
111 | ->setFields([
112 | 'AcquirerID' => 'fOO',
113 | 'ApprovalCode' => 'BaR',
114 | 'BillNumber' => 'baz',
115 | ])
116 | ->setPassword('LONG-PWD');
117 |
118 | $this->assertTrue($sig->verify('1F4E3B63AE408D0BE1E33965E6697236'));
119 | }
120 | }
--------------------------------------------------------------------------------
/src/Recurrent/RecurrentRequest.php:
--------------------------------------------------------------------------------
1 | request('recurrent', 'POST', http_build_query($parameters), [], 'csv');
32 | $csv = Uniteller\csv_to_array($response);
33 | $array = [];
34 | foreach ($csv as $item) {
35 | $array[] = (new Order())
36 | ->setAddress(Uniteller\array_get($item, 'Address'))
37 | ->setApprovalCode(Uniteller\array_get($item, 'ApprovalCode'))
38 | ->setBankName(Uniteller\array_get($item, 'BankName'))
39 | ->setBillNumber(Uniteller\array_get($item, 'BillNumber'))
40 | //->setBookingcomId(Uniteller\array_get($item, 'bookingcom_id'))
41 | //->setBookingcomPincode(Uniteller\array_get($item, 'bookingcom_pincode'))
42 | //->setCardIdp(Uniteller\array_get($item, 'card_idp'))
43 | ->setCardHolder(Uniteller\array_get($item, 'CardHolder'))
44 | ->setCardNumber(Uniteller\array_get($item, 'CardNumber'))
45 | ->setCardType(Uniteller\array_get($item, 'CardType'))
46 | ->setComment(Uniteller\array_get($item, 'Comment'))
47 | ->setCurrency(Uniteller\array_get($item, 'Currency'))
48 | ->setCvc2((bool)Uniteller\array_get($item, 'CVC2', false))
49 | ->setDate(Uniteller\array_get($item, 'Date'))
50 | ->setEmail(Uniteller\array_get($item, 'Email'))
51 | //->setEMoneyType(Uniteller\array_get($item, 'emoneytype'))
52 | //->setEOrderData(Uniteller\array_get($item, 'eorderdata'))
53 | ->setErrorCode(Uniteller\array_get($item, 'Error_Code'))
54 | ->setErrorComment(Uniteller\array_get($item, 'Error_Comment'))
55 | ->setFirstName(Uniteller\array_get($item, 'FirstName'))
56 | //->setGdsPaymentPurposeId(Uniteller\array_get($item, 'gds_payment_purpose_id'))
57 | //->setIData(Uniteller\array_get($item, 'idata'))
58 | ->setIp(Uniteller\array_get($item, 'IPAddress'))
59 | ->setLastName(Uniteller\array_get($item, 'LastName'))
60 | //->setLoanId(Uniteller\array_get($item, 'loan_id'))
61 | ->setMessage(Uniteller\array_get($item, 'Message'))
62 | ->setMiddleName(Uniteller\array_get($item, 'MiddleName'))
63 | //->setNeedConfirm((bool)Uniteller\array_get($item, 'need_confirm'))
64 | ->setOrderNumber(Uniteller\array_get($item, 'OrderNumber'))
65 | //->setParentOrderNumber(Uniteller\array_get($item, 'parent_order_number'))
66 | ->setPaymentType(Uniteller\array_get($item, 'PaymentType'))
67 | ->setPhone(Uniteller\array_get($item, 'Phone'))
68 | //->setPtCode(Uniteller\array_get($item, 'pt_code'))
69 | ->setRecommendation(Uniteller\array_get($item, 'Recommendation'))
70 | ->setResponseCode(Uniteller\array_get($item, 'Response_Code'))
71 | ->setStatus(Uniteller\array_get($item, 'Status'))
72 | ->setTotal(Uniteller\array_get($item, 'Total'))
73 | ->setPacketDate(Uniteller\array_get($item, 'PacketDate'))
74 | ->setSignature(Uniteller\array_get($item, 'Signature'));
75 | }
76 |
77 | return $array;
78 | }
79 | }
--------------------------------------------------------------------------------
/tests/Cancel/CancelRequestTest.php:
--------------------------------------------------------------------------------
1 | createMock(HttpManagerInterface::class);
22 | $manager
23 | ->expects($this->once())
24 | ->method('request')
25 | ->willReturn($this->getStubContents('cancel'));
26 |
27 | $request = new CancelRequest();
28 | /** @var \Tmconsulting\Uniteller\Order\Order $order */
29 | foreach ($request->execute($manager) as $order) {
30 | $this->assertInstanceOf(Order::class, $order);
31 | $this->assertEquals('Value of address', $order->getAddress());
32 | $this->assertEquals('Value of approvalcode', $order->getApprovalCode());
33 | $this->assertEquals('Value of bankname', $order->getBankName());
34 | $this->assertEquals('Value of billnumber', $order->getBillNumber());
35 | $this->assertEquals('Value of bookingcom_id', $order->getBookingcomId());
36 | $this->assertEquals('Value of bookingcom_pincode', $order->getBookingcomPincode());
37 | $this->assertEquals('Value of card_idp', $order->getCardIdp());
38 | $this->assertEquals('Value of cardholder', $order->getCardHolder());
39 | $this->assertEquals('Value of cardnumber', $order->getCardNumber());
40 | $this->assertEquals('Value of cardtype', $order->getCardType());
41 | $this->assertEquals('Value of comment', $order->getComment());
42 | $this->assertEquals('Value of currency', $order->getCurrency());
43 | $this->assertEquals(true, $order->isCvc2());
44 | $this->assertInstanceOf(\DateTime::class, $order->getDate());
45 | $this->assertEquals('Value of email', $order->getEmail());
46 | $this->assertEquals('Value of emoneytype', $order->getEMoneyType());
47 | $this->assertEquals(['foo' => 'bar', 'baz' => 'bue'], $order->getEOrderData());
48 | $this->assertEquals('Value of error_code', $order->getErrorCode());
49 | $this->assertEquals('Value of error_comment', $order->getErrorComment());
50 | $this->assertEquals('Value of firstname', $order->getFirstName());
51 | $this->assertEquals('Value of gds_payment_purpose_id', $order->getGdsPaymentPurposeId());
52 | $this->assertEquals('Value of idata', $order->getIData());
53 | $this->assertEquals('Value of ipaddress', $order->getIp());
54 | $this->assertEquals('Value of lastname', $order->getLastName());
55 | $this->assertEquals('Value of loan_id', $order->getLoanId());
56 | $this->assertEquals('Value of message', $order->getMessage());
57 | $this->assertEquals('Value of middlename', $order->getMiddleName());
58 | $this->assertEquals(true, $order->isNeedConfirm());
59 | $this->assertEquals('Value of ordernumber', $order->getOrderNumber());
60 | $this->assertEquals('Value of parent_order_number', $order->getParentOrderNumber());
61 | $this->assertEquals('Value of paymenttype', $order->getPaymentType());
62 | $this->assertEquals('Value of phone', $order->getPhone());
63 | $this->assertEquals('Value of pt_code', $order->getPtCode());
64 | $this->assertEquals('Value of recommendation', $order->getRecommendation());
65 | $this->assertEquals('Value of response_code', $order->getResponseCode());
66 | $this->assertEquals(Status::PAID, $order->getStatus());
67 | $this->assertEquals('Value of total', $order->getTotal());
68 | $this->assertInstanceOf(\DateTime::class, $order->getPacketDate());
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/tests/Results/ResultsRequestTest.php:
--------------------------------------------------------------------------------
1 | createMock(HttpManagerInterface::class);
22 | $manager
23 | ->expects($this->once())
24 | ->method('request')
25 | ->willReturn($this->getStubContents('cancel'));
26 |
27 | $request = new ResultsRequest();
28 | /** @var \Tmconsulting\Uniteller\Order\Order $order */
29 | foreach ($request->execute($manager) as $order) {
30 | $this->assertInstanceOf(Order::class, $order);
31 | $this->assertEquals('Value of address', $order->getAddress());
32 | $this->assertEquals('Value of approvalcode', $order->getApprovalCode());
33 | $this->assertEquals('Value of bankname', $order->getBankName());
34 | $this->assertEquals('Value of billnumber', $order->getBillNumber());
35 | $this->assertEquals('Value of bookingcom_id', $order->getBookingcomId());
36 | $this->assertEquals('Value of bookingcom_pincode', $order->getBookingcomPincode());
37 | $this->assertEquals('Value of card_idp', $order->getCardIdp());
38 | $this->assertEquals('Value of cardholder', $order->getCardHolder());
39 | $this->assertEquals('Value of cardnumber', $order->getCardNumber());
40 | $this->assertEquals('Value of cardtype', $order->getCardType());
41 | $this->assertEquals('Value of comment', $order->getComment());
42 | $this->assertEquals('Value of currency', $order->getCurrency());
43 | $this->assertEquals(true, $order->isCvc2());
44 | $this->assertInstanceOf(\DateTime::class, $order->getDate());
45 | $this->assertEquals('Value of email', $order->getEmail());
46 | $this->assertEquals('Value of emoneytype', $order->getEMoneyType());
47 | $this->assertEquals(['foo' => 'bar', 'baz' => 'bue'], $order->getEOrderData());
48 | $this->assertEquals('Value of error_code', $order->getErrorCode());
49 | $this->assertEquals('Value of error_comment', $order->getErrorComment());
50 | $this->assertEquals('Value of firstname', $order->getFirstName());
51 | $this->assertEquals('Value of gds_payment_purpose_id', $order->getGdsPaymentPurposeId());
52 | $this->assertEquals('Value of idata', $order->getIData());
53 | $this->assertEquals('Value of ipaddress', $order->getIp());
54 | $this->assertEquals('Value of lastname', $order->getLastName());
55 | $this->assertEquals('Value of loan_id', $order->getLoanId());
56 | $this->assertEquals('Value of message', $order->getMessage());
57 | $this->assertEquals('Value of middlename', $order->getMiddleName());
58 | $this->assertEquals(true, $order->isNeedConfirm());
59 | $this->assertEquals('Value of ordernumber', $order->getOrderNumber());
60 | $this->assertEquals('Value of parent_order_number', $order->getParentOrderNumber());
61 | $this->assertEquals('Value of paymenttype', $order->getPaymentType());
62 | $this->assertEquals('Value of phone', $order->getPhone());
63 | $this->assertEquals('Value of pt_code', $order->getPtCode());
64 | $this->assertEquals('Value of recommendation', $order->getRecommendation());
65 | $this->assertEquals('Value of response_code', $order->getResponseCode());
66 | $this->assertEquals(Status::PAID, $order->getStatus());
67 | $this->assertEquals('Value of total', $order->getTotal());
68 | $this->assertInstanceOf(\DateTime::class, $order->getPacketDate());
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/.github/workflows/run-tests.yml:
--------------------------------------------------------------------------------
1 | name: Run tests
2 |
3 | on: [push, workflow_dispatch, pull_request]
4 |
5 | jobs:
6 | php7234:
7 | name: Run tests PHP 7.2.34
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout repository
11 | uses: actions/checkout@v4
12 |
13 | - name: Composer install
14 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.2.34-cli-alpine3.12 composer install
15 |
16 | - name: Run tests
17 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.2.34-cli-alpine3.12 vendor/bin/phpunit --do-not-cache-result
18 | php7333:
19 | name: Run tests PHP 7.3.33
20 | runs-on: ubuntu-latest
21 | steps:
22 | - name: Checkout repository
23 | uses: actions/checkout@v4
24 |
25 | - name: Composer install
26 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.3.33-cli-alpine3.15 composer install
27 |
28 | - name: Run tests
29 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.3.33-cli-alpine3.15 vendor/bin/phpunit --do-not-cache-result
30 | php7433:
31 | name: Run tests PHP 7.4.33
32 | runs-on: ubuntu-latest
33 | steps:
34 | - name: Checkout repository
35 | uses: actions/checkout@v4
36 |
37 | - name: Composer install
38 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.4.33-cli-alpine3.16 composer install
39 |
40 | - name: Run tests
41 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-7.4.33-cli-alpine3.16 vendor/bin/phpunit --do-not-cache-result
42 | php8030:
43 | name: Run tests PHP 8.0.30
44 | runs-on: ubuntu-latest
45 | steps:
46 | - name: Checkout repository
47 | uses: actions/checkout@v4
48 |
49 | - name: Composer install
50 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.0.30-cli-alpine3.16 composer install
51 |
52 | - name: Run tests
53 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.0.30-cli-alpine3.16 vendor/bin/phpunit --do-not-cache-result
54 | php8131:
55 | name: Run tests PHP 8.1.31
56 | runs-on: ubuntu-latest
57 | steps:
58 | - name: Checkout repository
59 | uses: actions/checkout@v4
60 |
61 | - name: Composer install
62 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.1.31-cli-alpine3.21 composer install
63 |
64 | - name: Run tests
65 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.1.31-cli-alpine3.21 vendor/bin/phpunit --do-not-cache-result
66 | php8227:
67 | name: Run tests PHP 8.2.27
68 | runs-on: ubuntu-latest
69 | steps:
70 | - name: Checkout repository
71 | uses: actions/checkout@v4
72 |
73 | - name: Composer install
74 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.2.27-cli-alpine3.21 composer install
75 |
76 | - name: Run tests
77 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.2.27-cli-alpine3.21 vendor/bin/phpunit --do-not-cache-result
78 | php8316:
79 | name: Run tests PHP 8.3.16
80 | runs-on: ubuntu-latest
81 | steps:
82 | - name: Checkout repository
83 | uses: actions/checkout@v4
84 |
85 | - name: Composer install
86 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.3.16-cli-alpine3.21 composer install
87 |
88 | - name: Run tests
89 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.3.16-cli-alpine3.21 vendor/bin/phpunit --do-not-cache-result
90 | php8403:
91 | name: Run tests PHP 8.4.3
92 | runs-on: ubuntu-latest
93 | steps:
94 | - name: Checkout repository
95 | uses: actions/checkout@v4
96 |
97 | - name: Composer install
98 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.4.3-cli-alpine3.21 composer install
99 |
100 | - name: Run tests
101 | run: docker run --rm -v $(pwd):/home/www-data/application i3bepb/php-for-test:1.2.6-php-8.4.3-cli-alpine3.21 vendor/bin/phpunit --do-not-cache-result
102 |
--------------------------------------------------------------------------------
/src/Recurrent/RecurrentBuilder.php:
--------------------------------------------------------------------------------
1 | shopIdp = $shopIdp;
73 |
74 | return $this;
75 | }
76 |
77 | /**
78 | * @param string $orderIdp
79 | * @return RecurrentBuilder
80 | */
81 | public function setOrderIdp($orderIdp)
82 | {
83 | $this->orderIdp = $orderIdp;
84 |
85 | return $this;
86 | }
87 |
88 | /**
89 | * @param float|string $subtotalP
90 | * @return RecurrentBuilder
91 | */
92 | public function setSubtotalP($subtotalP)
93 | {
94 | $this->subtotalP = $subtotalP;
95 |
96 | return $this;
97 | }
98 |
99 | /**
100 | * @param string $parentOrderIdp
101 | * @return RecurrentBuilder
102 | */
103 | public function setParentOrderIdp($parentOrderIdp)
104 | {
105 | $this->parentOrderIdp = $parentOrderIdp;
106 |
107 | return $this;
108 | }
109 |
110 | /**
111 | * @param string $parentShopIdp
112 | * @return RecurrentBuilder
113 | */
114 | public function setParentShopIdp($parentShopIdp)
115 | {
116 | $this->parentShopIdp = $parentShopIdp;
117 |
118 | return $this;
119 | }
120 |
121 | /**
122 | * @return string
123 | */
124 | public function getShopIdp()
125 | {
126 | return $this->shopIdp;
127 | }
128 |
129 | /**
130 | * @return string
131 | */
132 | public function getOrderIdp()
133 | {
134 | return $this->orderIdp;
135 | }
136 |
137 | /**
138 | * @return float|string
139 | */
140 | public function getSubtotalP()
141 | {
142 | return $this->subtotalP;
143 | }
144 |
145 | /**
146 | * @return string
147 | */
148 | public function getParentOrderIdp()
149 | {
150 | return $this->parentOrderIdp;
151 | }
152 |
153 | /**
154 | * @return string
155 | */
156 | public function getParentShopIdp()
157 | {
158 | return $this->parentShopIdp;
159 | }
160 |
161 | /**
162 | * @return array
163 | */
164 | public function toArray()
165 | {
166 | return [
167 | 'Shop_IDP' => $this->getShopIdp(),
168 | 'Parent_Shop_IDP' => $this->getParentShopIdp(),
169 | 'Order_IDP' => $this->getOrderIdp(),
170 | 'Parent_Order_IDP' => $this->getParentOrderIdp(),
171 | 'Subtotal_P' => $this->getSubtotalP(),
172 | ];
173 | }
174 | }
--------------------------------------------------------------------------------
/src/Http/HttpManager.php:
--------------------------------------------------------------------------------
1 | httpClient = $httpClient;
50 | $this->options = $options;
51 | }
52 |
53 | protected function getDefaultHeaders(string $format): array
54 | {
55 | $headers = [
56 | 'Content-Type' => 'application/x-www-form-urlencoded',
57 | ];
58 |
59 | switch ($format) {
60 | case 'xml':
61 | $headers['Accept'] = 'application/xml';
62 | break;
63 | case 'csv':
64 | $headers['Accept'] = 'text/csv';
65 | break;
66 | case 'json':
67 | $headers['Accept'] = 'application/json';
68 | break;
69 | }
70 |
71 | return $headers;
72 | }
73 |
74 | /**
75 | * @param $uri
76 | * @param string $method
77 | * @param null $data
78 | * @param array $headers
79 | * @param string $format
80 | * @return string
81 | * @throws ErrorException|ClientExceptionInterface
82 | */
83 | public function request($uri, $method = 'POST', $data = null, array $headers = [], string $format = 'xml'): string
84 | {
85 | $uri = sprintf('%s/%s?%s', $this->options['base_uri'], $uri, http_build_query([
86 | 'Shop_ID' => $this->options['shop_id'],
87 | 'Login' => $this->options['login'],
88 | 'Password' => $this->options['password'],
89 | 'Format' => Format::{"resolve$format"}($uri),
90 | ]));
91 |
92 | $request = new Request($method, $uri, array_merge($this->getDefaultHeaders($format), $headers), $data);
93 |
94 | try {
95 | $response = $this->httpClient->sendRequest($request);
96 | } catch (RequestException $e) {
97 | throw UnitellerException::create($request, $e->getResponse());
98 | }
99 |
100 | if ($response->getStatusCode() < 200 || $response->getStatusCode() > 299) {
101 | throw UnitellerException::create($request, $response);
102 | }
103 |
104 | $body = (string) $response->getBody();
105 |
106 | $this->providerError($body, $request, $response, $format);
107 |
108 | return $body;
109 | }
110 |
111 | /**
112 | * @param $body
113 | * @param RequestInterface $request
114 | * @param ResponseInterface $response
115 | * @param string $format
116 | * @throws ErrorException
117 | */
118 | protected function providerError($body, RequestInterface $request, ResponseInterface $response, string $format = 'xml'): void
119 | {
120 | if ($format === 'csv') {
121 | $data = csv_to_array($body, true);
122 |
123 | if (isset($data['ErrorMessage'])) {
124 | throw ExceptionFactory::createFromMessage(
125 | $data['ErrorMessage'], $request, $response
126 | );
127 | }
128 |
129 | return;
130 | }
131 |
132 | if ($format === 'xml') {
133 | if (substr($body, 0, 6) === 'ERROR:') {
134 | throw ExceptionFactory::createFromMessage(
135 | substr($body, 7), $request, $response
136 | );
137 | }
138 |
139 | try {
140 | $xml = new SimpleXMLElement((string) $body);
141 | } catch (Throwable $e) {
142 | throw new UnitellerException('XML parsing failed', $request, $response, $e);
143 | }
144 |
145 | $firstCode = (int) $xml->attributes()['firstcode'];
146 |
147 | if ($firstCode === 0) {
148 | return;
149 | }
150 |
151 | $secondCode = (string) $xml->attributes()['secondcode'];
152 |
153 | throw ExceptionFactory::create(
154 | $firstCode, $secondCode, $request, $response
155 | );
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Uniteller PHP SDK
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | PHP (7.2+) SDK for integration internet-acquiring of the Uniteller (unofficial).
26 | [This documentation is available in Russian language](README_RU.md).
27 | Also, this SDK integrated with [Payum](https://github.com/Payum/Payum) library and you can use [gateway](https://github.com/tmconsulting/payum-uniteller-gateway).
28 |
29 | Features:
30 | * payment (method `pay`)
31 | * recurrent (method `recurrent`)
32 | * cancel (method `unblock`)
33 | * receive results
34 | * callback (method for verify incoming signature)
35 | * general error handler for any request
36 | * general statuses (In the requests/responses may to meet `canceled` or `cancelled` variants. They will be converted to general status like as `cancelled`.)
37 |
38 | TODO:
39 | * translate to English comments and system (error) messages
40 | * validation
41 | * implement method `card`
42 | * implement method `confirm`
43 |
44 | ## Install
45 |
46 | For install package follow this command:
47 |
48 | `composer require tmconsulting/uniteller-php-sdk`
49 |
50 | ## Usage
51 |
52 | A few usage example the current SDK your can found on the `examples` folder.
53 | Just follow instruction on `README.md` file.
54 |
55 | ### Configure credentials
56 |
57 | ```php
58 | setShopId('you_shop_id');
61 | $uniteller->setLogin('you_login_number');
62 | $uniteller->setPassword('you_password');
63 | $uniteller->setBaseUri('https://wpay.uniteller.ru');
64 | ```
65 |
66 | ### Redirect to page payment
67 |
68 | So, for redirect to page your enough to run `payment` method with parameters like as:
69 |
70 | ```php
71 | setOrderIdp(mt_rand(10000, 99999))
77 | ->setSubtotalP(10)
78 | ->setCustomerIdp(mt_rand(10000, 99999))
79 | ->setUrlReturnOk('http://google.ru/?q=success')
80 | ->setUrlReturnNo('http://google.ru/?q=failure');
81 |
82 | $uniteller->payment($builder)->go();
83 | // if you don't need redirect
84 | // $uniteller->payment($builder)->getUri();
85 |
86 | ```
87 |
88 | or use plain array
89 |
90 | ```php
91 | payment([
93 | 'Order_IDP' => mt_rand(10000, 99999),
94 | // ... other parameters
95 | ])->go();
96 | ```
97 |
98 | ### Recurrent payment
99 |
100 | ```php
101 | setOrderIdp(mt_rand(10000, 99999))
106 | ->setSubtotalP(15)
107 | ->setParentOrderIdp(00000) // order id of any past payment
108 | ->setParentShopIdp($uniteller->getShopId()); // optional
109 |
110 | $results = $uniteller->recurrent($builder);
111 | ```
112 |
113 | or use plain array
114 |
115 | ```php
116 | recurrent([
118 | 'Order_IDP' => mt_rand(10000, 99999),
119 | // ... other parameters
120 | ]);
121 | ```
122 |
123 | ### Cancel payment
124 |
125 | ```php
126 | setBillNumber('RRN Number, (12 digits)');
130 | $results = $uniteller->cancel($builder);
131 | ```
132 |
133 | or
134 |
135 | ```php
136 | cancel([
140 | 'Billnumber' => 'RRN Number, (12 digits)',
141 | // ...
142 | ]);
143 |
144 | foreach ($results as $payment) {
145 | // see Tmconsulting\Uniteller\Order\Order for other methods.
146 | if ($payment->getStatus() === Status::CANCELLED) {
147 | // payment was cancelled
148 | }
149 | }
150 | ```
151 |
152 | ### Receive results
153 |
154 | ```php
155 | results([
158 | 'ShopOrderNumber' => 'Order_IDP number'
159 | ]);
160 |
161 | var_dump($results);
162 |
163 | // $results[0]->getCardNumber();
164 | ```
165 |
166 | ### Callback (gateway notification)
167 |
168 | Receive incoming parameters from gateway and verifying signature.
169 |
170 | ```php
171 | verifyCallbackRequest(['all_parameters_from_post_with_signature'])) {
173 | return 'invalid_signature';
174 | }
175 | ```
176 |
177 | ## Tests
178 |
179 | `vendor/bin/phpunit`
180 |
181 | ## License
182 |
183 | MIT.
184 |
--------------------------------------------------------------------------------
/README_RU.md:
--------------------------------------------------------------------------------
1 | # Uniteller PHP SDK
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | PHP (7.2+) SDK для интеграции с интернет-эквайрингом от Uniteller (не официальная).
27 | Также, SDK интегрирован с библиотекой [Payum](https://github.com/Payum/Payum) и вы можете использовать этот [шлюз]((https://github.com/tmconsulting/payum-uniteller-gateway)) для работы.
28 |
29 | Реализовано:
30 | * оплата (метод `pay`)
31 | * рекуррентные платежи (метод `recurrent`)
32 | * отмена (метод `unblock`)
33 | * получение результатов
34 | * callback (проверка сигнатуры)
35 | * обработчик ошибок, кидает эксепшены даже на строку `ERROR: %s` в теле ответа на запрос
36 | * единство статусов.
37 |
38 | Что осталось:
39 | * прикрутить валидацию, используя декораторы
40 | * добавить билдер для метода `results`
41 | * метод `card`
42 | * метод `confirm`
43 |
44 | ## Установка
45 |
46 | Чтобы установить пакет, достаточно подключить его в проект, как зависимость:
47 |
48 | `composer require tmconsulting/uniteller-php-sdk`
49 |
50 | ## Использование
51 |
52 | Примеры использования SDK лежат в папке `./examples`, а так-же `README.md` файл,
53 | в котором написан способ установки.
54 |
55 | ### Установка учетных данных
56 |
57 | ```php
58 | setShopId('you_shop_id');
61 | $uniteller->setLogin('you_login_number');
62 | $uniteller->setPassword('you_password');
63 | $uniteller->setBaseUri('https://wpay.uniteller.ru');
64 | ```
65 |
66 | ### Переход к оплате
67 |
68 | Чтобы произвести оплату, достаточно вызвать метод `payment`,
69 | он принимает первым аргументом либо построитель запроса, либо обычный массив параметров.
70 |
71 | ```php
72 | setOrderIdp(mt_rand(10000, 99999))
78 | ->setSubtotalP(10)
79 | ->setCustomerIdp(mt_rand(10000, 99999))
80 | ->setUrlReturnOk('http://google.ru/?q=success')
81 | ->setUrlReturnNo('http://google.ru/?q=failure');
82 |
83 | $uniteller->payment($builder)->go();
84 | // Если переходить к оплате сразу нет необходимости,
85 | // можно получить готовую ссылку для оплаты
86 | // $uniteller->payment($builder)->getUri();
87 |
88 | ```
89 |
90 | или
91 |
92 | ```php
93 | payment([
95 | 'Order_IDP' => mt_rand(10000, 99999),
96 | // ... прочие параметры
97 | ])->go();
98 | ```
99 |
100 | ### Рекуррентный платеж
101 |
102 | ```php
103 | setOrderIdp(mt_rand(10000, 99999))
108 | ->setSubtotalP(15)
109 | ->setParentOrderIdp(00000) // id заказа магазина из ранее оплаченных в uniteller
110 | ->setParentShopIdp($uniteller->getShopId()); // не обязательно задавать, если родительский платеж из того же магазина
111 |
112 | $results = $uniteller->recurrent($builder);
113 | ```
114 |
115 | или
116 |
117 | ```php
118 | recurrent([
120 | 'Order_IDP' => mt_rand(10000, 99999),
121 | // ...
122 | ]);
123 | ```
124 |
125 | ### Отмена платежа
126 |
127 | ```php
128 | setBillNumber('RRN Number, (12 digits)');
132 | $results = $uniteller->cancel($builder);
133 | ```
134 |
135 | или
136 |
137 | ```php
138 | cancel([
142 | 'Billnumber' => 'RRN Number, (12 digits)',
143 | // ...
144 | ]);
145 |
146 | var_dump($results);
147 |
148 | foreach ($results as $payment) {
149 | // смотрите в Tmconsulting\Uniteller\Order\Order остальные методы.
150 | if ($payment->getStatus() === Status::CANCELLED) {
151 | // платеж отменён
152 | }
153 | }
154 | ```
155 |
156 | ### Получение результатов
157 |
158 | ```php
159 | results([
162 | 'ShopOrderNumber' => 'Order_IDP number'
163 | ]);
164 |
165 | var_dump($results);
166 |
167 | // $results[0]->getCardNumber();
168 | ```
169 |
170 | ### Callback
171 |
172 | Проверка сигнатуры при приёме данных от шлюза.
173 |
174 | ```php
175 | verifyCallbackRequest(['all_parameters_from_post_with_signature'])) {
177 | return 'invalid_signature';
178 | }
179 | ```
180 |
181 |
182 | ## Тесты
183 |
184 | `vendor/bin/phpunit`
185 |
186 | ## Лицензия
187 |
188 | MIT.
189 |
--------------------------------------------------------------------------------
/src/Signature/SignaturePayment.php:
--------------------------------------------------------------------------------
1 | shopIdp = $shopIdp;
80 |
81 | return $this;
82 | }
83 |
84 | /**
85 | * @param string $orderIdp
86 | * @return SignaturePayment
87 | */
88 | public function setOrderIdp($orderIdp)
89 | {
90 | $this->orderIdp = $orderIdp;
91 |
92 | return $this;
93 | }
94 |
95 | /**
96 | * @param string $subtotalP
97 | * @return SignaturePayment
98 | */
99 | public function setSubtotalP($subtotalP)
100 | {
101 | $this->subtotalP = $subtotalP;
102 |
103 | return $this;
104 | }
105 |
106 | /**
107 | * @param string $meanType
108 | * @return SignaturePayment
109 | */
110 | public function setMeanType($meanType)
111 | {
112 | $this->meanType = $meanType;
113 |
114 | return $this;
115 | }
116 |
117 | /**
118 | * @param string $eMoneyType
119 | * @return SignaturePayment
120 | */
121 | public function setEMoneyType($eMoneyType)
122 | {
123 | $this->eMoneyType = $eMoneyType;
124 |
125 | return $this;
126 | }
127 |
128 | /**
129 | * @param string $lifeTime
130 | * @return SignaturePayment
131 | */
132 | public function setLifeTime($lifeTime)
133 | {
134 | $this->lifeTime = $lifeTime;
135 |
136 | return $this;
137 | }
138 |
139 | /**
140 | * @param string $customerIdp
141 | * @return SignaturePayment
142 | */
143 | public function setCustomerIdp($customerIdp)
144 | {
145 | $this->customerIdp = $customerIdp;
146 |
147 | return $this;
148 | }
149 |
150 | /**
151 | * @param string $cardIdp
152 | * @return SignaturePayment
153 | */
154 | public function setCardIdp($cardIdp)
155 | {
156 | $this->cardIdp = $cardIdp;
157 |
158 | return $this;
159 | }
160 |
161 | /**
162 | * @param string $iData
163 | * @return SignaturePayment
164 | */
165 | public function setIData($iData)
166 | {
167 | $this->iData = $iData;
168 |
169 | return $this;
170 | }
171 |
172 | /**
173 | * @param string $ptCode
174 | * @return SignaturePayment
175 | */
176 | public function setPtCode($ptCode)
177 | {
178 | $this->ptCode = $ptCode;
179 |
180 | return $this;
181 | }
182 |
183 | /**
184 | * @param string $password
185 | * @return SignaturePayment
186 | */
187 | public function setPassword($password)
188 | {
189 | $this->password = $password;
190 |
191 | return $this;
192 | }
193 |
194 | /**
195 | * @return string
196 | */
197 | public function getShopIdp()
198 | {
199 | return $this->shopIdp;
200 | }
201 |
202 | /**
203 | * @return string
204 | */
205 | public function getOrderIdp()
206 | {
207 | return $this->orderIdp;
208 | }
209 |
210 | /**
211 | * @return string
212 | */
213 | public function getSubtotalP()
214 | {
215 | return $this->subtotalP;
216 | }
217 |
218 | /**
219 | * @return string
220 | */
221 | public function getMeanType()
222 | {
223 | return $this->meanType;
224 | }
225 |
226 | /**
227 | * @return string
228 | */
229 | public function getEMoneyType()
230 | {
231 | return $this->eMoneyType;
232 | }
233 |
234 | /**
235 | * @return string
236 | */
237 | public function getLifeTime()
238 | {
239 | return $this->lifeTime;
240 | }
241 |
242 | /**
243 | * @return string
244 | */
245 | public function getCustomerIdp()
246 | {
247 | return $this->customerIdp;
248 | }
249 |
250 | /**
251 | * @return string
252 | */
253 | public function getCardIdp()
254 | {
255 | return $this->cardIdp;
256 | }
257 |
258 | /**
259 | * @return string
260 | */
261 | public function getIData()
262 | {
263 | return $this->iData;
264 | }
265 |
266 | /**
267 | * @return string
268 | */
269 | public function getPtCode()
270 | {
271 | return $this->ptCode;
272 | }
273 |
274 | /**
275 | * @return string
276 | */
277 | public function getPassword()
278 | {
279 | return $this->password;
280 | }
281 |
282 | /**
283 | * @return array
284 | */
285 | public function toArray()
286 | {
287 | $array = [];
288 | $array['Shop_IDP'] = $this->getShopIdp();
289 | $array['Order_IDP'] = $this->getOrderIdp();
290 | $array['Subtotal_P'] = $this->getSubtotalP();
291 | $array['MeanType'] = $this->getMeanType();
292 | $array['EMoneyType'] = $this->getEMoneyType();
293 | $array['Lifetime'] = $this->getLifeTime();
294 | $array['Customer_IDP'] = $this->getCustomerIdp();
295 | $array['Card_IDP'] = $this->getCardIdp();
296 | $array['IData'] = $this->getIData();
297 | $array['PT_Code'] = $this->getPtCode();
298 | $array['Password'] = $this->getPassword();
299 |
300 | return $array;
301 | }
302 | }
--------------------------------------------------------------------------------
/tests/ClientTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf(ClientInterface::class, $client);
27 | }
28 |
29 | public function testOptionsAccessorsAndMutators()
30 | {
31 | $uniteller = new Client();
32 | $uniteller->setShopId('shop_id');
33 | $uniteller->setBaseUri('https://google.com');
34 | $uniteller->setPassword('security-long-password');
35 | $uniteller->setLogin(330011);
36 |
37 | $this->assertSame('shop_id', $uniteller->getShopId());
38 | $this->assertSame('https://google.com', $uniteller->getBaseUri());
39 | $this->assertSame('security-long-password', $uniteller->getPassword());
40 | $this->assertSame(330011, $uniteller->getLogin());
41 | }
42 |
43 | public function testOptionKeyResolver()
44 | {
45 | $uniteller = new Client();
46 | $this->assertSame('default', $uniteller->getOption('shop_id', 'default'));
47 | }
48 |
49 | public function testDefaultObjectsIsRegistered()
50 | {
51 | $uniteller = new Client();
52 | $this->assertInstanceOf(PaymentInterface::class, $uniteller->getPayment());
53 | $this->assertInstanceOf(SignatureInterface::class, $uniteller->getSignaturePayment());
54 | $this->assertInstanceOf(SignatureInterface::class, $uniteller->getSignatureRecurrent());
55 | }
56 |
57 | public function testSetOptionsUseArrayNotation()
58 | {
59 | $uniteller = new Client();
60 | $uniteller->setShopId('111');
61 | $uniteller->setPassword('pwd');
62 |
63 | $uniteller->setOptions([
64 | 'password' => 1234,
65 | 'base_uri' => 'https://google.com'
66 | ]);
67 |
68 | $true = [
69 | 'shop_id' => '111',
70 | 'password' => 1234,
71 | 'base_uri' => 'https://google.com',
72 | ];
73 |
74 | $this->assertSame($true, $uniteller->getOptions());
75 | }
76 |
77 | // public function testGivenArgumentShouldBeImplementHttpManagerInterface()
78 | // {
79 | // $part1 = 'Argument 1 passed to ' . Client::class . '::setHttpManager()';
80 | // $part2 = HttpManagerInterface::class;
81 | //
82 | // $client = new Client();
83 | // try {
84 | // $client->setHttpManager(new \stdClass());
85 | // } catch (\Throwable $e) { // PHP 7
86 | // $this->assertStringStartsWith($part1, $e->getMessage());
87 | // $this->assertContains($part2, $e->getMessage());
88 | // }
89 | //
90 | // $client->setHttpManager($this->createMock(HttpManagerInterface::class));
91 | // $this->assertInstanceOf(HttpManagerInterface::class, $client->getHttpManager());
92 | // }
93 |
94 | /**
95 | * @return array
96 | */
97 | public function provideMethodsWhenHaveAnFirstArgumentIsRequestInterface()
98 | {
99 | return [
100 | ['registerCancelRequest'],
101 | ['registerResultsRequest'],
102 | ];
103 | }
104 |
105 | /**
106 | * @dataProvider provideMethodsWhenHaveAnFirstArgumentIsRequestInterface
107 | * @param $methodName
108 | */
109 | // public function testGivenArgumentShouldBeTypeHintedAsRequestInterface($methodName)
110 | // {
111 | // $reflect = new \ReflectionClass(Client::class);
112 | // $first = $reflect->getMethod($methodName)->getParameters()[0]->getClass()->getName();
113 | //
114 | // $this->assertEquals(RequestInterface::class, $first);
115 | // }
116 |
117 | public function testCanRequestMethodsMayReturnCorrectResult()
118 | {
119 | $client = new Client();
120 | $client->registerCancelRequest($this->createMock(RequestInterface::class));
121 | $client->registerResultsRequest($this->createMock(RequestInterface::class));
122 | $client->registerRecurrentRequest($this->createMock(RequestInterface::class));
123 |
124 | $this->assertInstanceOf(RequestInterface::class, $client->getCancelRequest());
125 | $this->assertInstanceOf(RequestInterface::class, $client->getResultsRequest());
126 | $this->assertInstanceOf(RequestInterface::class, $client->getRecurrentRequest());
127 | }
128 |
129 | public function testShouldBePaymentMethodBuildCorrectArray()
130 | {
131 | $payment = $this->createMock(PaymentInterface::class);
132 | $payment
133 | ->expects($this->once())
134 | ->method('execute')
135 | ->willReturnCallback(function ($array) {
136 | $this->assertArrayHasKey('Shop_IDP', $array);
137 | $this->assertArrayHasKey('Signature', $array);
138 | });
139 |
140 | $client = new Client();
141 | $client->registerPayment($payment);
142 |
143 | $client->payment([]);
144 | }
145 |
146 | public function testCanCancelMethodGiveControlToTheRequestClass()
147 | {
148 | $request = $this->createMock(RequestInterface::class);
149 | $request
150 | ->expects($this->at(1))
151 | ->method('execute')
152 | ->willReturnCallback(function ($manager, $array) {
153 | $this->assertInstanceOf(HttpManagerInterface::class, $manager);
154 | $this->assertTrue(is_array($array));
155 | });
156 |
157 | $client = new Client();
158 | $client->registerCancelRequest($request);
159 | $client->registerResultsRequest($request);
160 | $client->registerRecurrentRequest($request);
161 |
162 | $client->cancel([]);
163 | $client->results([]);
164 |
165 | $this->assertInstanceOf(HttpManagerInterface::class, $client->getHttpManager());
166 | }
167 |
168 | public function testCanUseCustomHttpManager()
169 | {
170 | $cancel = $this->createMock(CancelRequest::class);
171 | $cancel
172 | ->expects($this->once())
173 | ->method('execute');
174 |
175 | $client = new Client();
176 | $client->setHttpManager(new HttpManagerStub());
177 | $client->registerCancelRequest($cancel);
178 |
179 | $client->cancel([]);
180 |
181 | $this->assertInstanceOf(HttpManagerStub::class, $client->getHttpManager());
182 | }
183 |
184 | /**
185 | * @return array
186 | */
187 | public function provideUnsupportedRequestMethods()
188 | {
189 | return [
190 | ['confirm'],
191 | ['card'],
192 | ];
193 | }
194 |
195 | /**
196 | * @dataProvider provideUnsupportedRequestMethods
197 | * @param $methodName
198 | */
199 | public function testShouldBeUnsupportedMethodsThrowException($methodName)
200 | {
201 | $this->expectException(NotImplementedException::class);
202 | $this->expectExceptionMessageMatches('/In current moment, feature \[.*\] not implemented./');
203 |
204 | $client = new Client();
205 | $client->{$methodName}([]);
206 | }
207 |
208 | // public function provideActionsWhichShouldBeAcceptArrayble(): array
209 | // {
210 | // return [
211 | // ['payment'],
212 | // ['cancel'],
213 | // ['results'],
214 | // ];
215 | // }
216 | //
217 | // /**
218 | // * @dataProvider provideActionsWhichShouldBeAcceptArrayble
219 | // */
220 | // public function testShouldBeActionsAcceptClassesWhichImplementArraybleInterface(string $methodName): void
221 | // {
222 | // $request = $this->createMock(RequestInterface::class);
223 | // $request->method('execute');
224 | //
225 | // $client = new Client();
226 | // $client->registerResultsRequest($request);
227 | // $client->registerCancelRequest($request);
228 | // $client->registerRecurrentRequest($request);
229 | // $client->registerPayment($this->createMock(PaymentInterface::class));
230 | //
231 | // $arrayble = $this->createMock(ArraybleInterface::class);
232 | // $arrayble
233 | // ->method('toArray')
234 | // ->willReturn([]);
235 | //
236 | // $client->{$methodName}($arrayble);
237 | // }
238 |
239 | public function testCallbackSignatureVerifying()
240 | {
241 | $params = [
242 | 'Order_ID' => 'FOO',
243 | 'Status' => 'paid',
244 | 'Signature' => '3F728AA479E50F5B10EE6C20258BFF88',
245 | ];
246 | $client = new Client();
247 | $client->setPassword('LONG-PWD');
248 | $this->assertTrue($client->verifyCallbackRequest($params));
249 | }
250 |
251 | public function testCallbackSignatureVerifyingWithFields()
252 | {
253 | $params = [
254 | 'Order_ID' => 'FOO',
255 | 'Status' => 'paid',
256 | 'AcquirerID' => 'fOO',
257 | 'ApprovalCode' => 'BaR',
258 | 'BillNumber' => 'baz',
259 | 'Signature' => '1F4E3B63AE408D0BE1E33965E6697236',
260 | ];
261 | $client = new Client();
262 | $client->setPassword('LONG-PWD');
263 | $this->assertTrue($client->verifyCallbackRequest($params));
264 | }
265 |
266 | }
267 |
268 | class HttpManagerStub implements HttpManagerInterface {
269 |
270 | /**
271 | * @param $uri
272 | * @param string $method
273 | * @param null $data
274 | * @param array $headers
275 | * @return string
276 | */
277 | public function request($uri, $method = 'POST', $data = null, array $headers = [])
278 | {
279 | // TODO: Implement request() method.
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/src/Client.php:
--------------------------------------------------------------------------------
1 | registerPayment(new Payment());
85 | $this->registerCancelRequest(new CancelRequest());
86 | $this->registerResultsRequest(new ResultsRequest());
87 | $this->registerRecurrentRequest(new RecurrentRequest());
88 | $this->registerSignaturePayment(new SignaturePayment());
89 | $this->registerSignatureRecurrent(new SignatureRecurrent());
90 | $this->registerSignatureCallback(new SignatureCallback());
91 | }
92 |
93 | /**
94 | * @param $uri
95 | * @return $this
96 | */
97 | public function setBaseUri($uri)
98 | {
99 | $this->options['base_uri'] = $uri;
100 |
101 | return $this;
102 | }
103 |
104 | /**
105 | * @param $value
106 | * @return $this
107 | */
108 | public function setLogin($value)
109 | {
110 | $this->options['login'] = $value;
111 |
112 | return $this;
113 | }
114 |
115 | /**
116 | * @param $value
117 | * @return $this
118 | */
119 | public function setPassword($value)
120 | {
121 | $this->options['password'] = $value;
122 |
123 | return $this;
124 | }
125 |
126 | /**
127 | * @param $value
128 | * @return $this
129 | */
130 | public function setShopId($value)
131 | {
132 | $this->options['shop_id'] = $value;
133 |
134 | return $this;
135 | }
136 |
137 | /**
138 | * @param array $options
139 | * @return $this
140 | */
141 | public function setOptions(array $options)
142 | {
143 | $this->options = array_merge($this->options, $options);
144 |
145 | return $this;
146 | }
147 |
148 | /**
149 | * @param HttpManagerInterface $httpManager
150 | * @return $this
151 | */
152 | public function setHttpManager(HttpManagerInterface $httpManager)
153 | {
154 | $this->httpManager = $httpManager;
155 |
156 | return $this;
157 | }
158 |
159 | /**
160 | * @param PaymentInterface $payment
161 | * @return $this
162 | */
163 | public function registerPayment(PaymentInterface $payment)
164 | {
165 | $this->payment = $payment;
166 |
167 | return $this;
168 | }
169 |
170 | /**
171 | * @param RequestInterface $cancel
172 | * @return $this
173 | */
174 | public function registerCancelRequest(RequestInterface $cancel)
175 | {
176 | $this->cancelRequest = $cancel;
177 |
178 | return $this;
179 | }
180 |
181 | /**
182 | * @param RequestInterface $request
183 | * @return $this
184 | */
185 | public function registerResultsRequest(RequestInterface $request)
186 | {
187 | $this->resultsRequest = $request;
188 |
189 | return $this;
190 | }
191 |
192 | /**
193 | * @param RequestInterface $request
194 | * @return $this
195 | */
196 | public function registerRecurrentRequest(RequestInterface $request)
197 | {
198 | $this->recurrentRequest = $request;
199 |
200 | return $this;
201 | }
202 |
203 | /**
204 | * @param \Tmconsulting\Uniteller\Signature\SignatureInterface $signature
205 | * @return $this
206 | */
207 | public function registerSignaturePayment(SignatureInterface $signature)
208 | {
209 | $this->signaturePayment = $signature;
210 |
211 | return $this;
212 | }
213 |
214 | /**
215 | * @param \Tmconsulting\Uniteller\Signature\SignatureInterface $signature
216 | * @return $this
217 | */
218 | public function registerSignatureRecurrent(SignatureInterface $signature)
219 | {
220 | $this->signatureRecurrent = $signature;
221 |
222 | return $this;
223 | }
224 |
225 | /**
226 | * @param \Tmconsulting\Uniteller\Signature\SignatureInterface $signature
227 | * @return $this
228 | */
229 | public function registerSignatureCallback(SignatureInterface $signature)
230 | {
231 | $this->signatureCallback = $signature;
232 |
233 | return $this;
234 | }
235 |
236 | /**
237 | * @return array
238 | */
239 | public function getOptions()
240 | {
241 | return $this->options;
242 | }
243 |
244 | /**
245 | * @param $key
246 | * @param null $default
247 | * @return string|mixed
248 | */
249 | public function getOption($key, $default = null)
250 | {
251 | if (array_key_exists($key, $this->options)) {
252 | return $this->options[$key];
253 | }
254 |
255 | return $default;
256 | }
257 |
258 | /**
259 | * @return string
260 | */
261 | public function getBaseUri()
262 | {
263 | return $this->getOption('base_uri');
264 | }
265 |
266 | /**
267 | * @return string
268 | */
269 | public function getLogin()
270 | {
271 | return $this->getOption('login');
272 | }
273 |
274 | /**
275 | * @return string
276 | */
277 | public function getShopId()
278 | {
279 | return $this->getOption('shop_id');
280 | }
281 |
282 | /**
283 | * @return string
284 | */
285 | public function getPassword()
286 | {
287 | return $this->getOption('password');
288 | }
289 |
290 | /**
291 | * @return \Tmconsulting\Uniteller\Payment\PaymentInterface
292 | */
293 | public function getPayment()
294 | {
295 | return $this->payment;
296 | }
297 |
298 | /**
299 | * @return \Tmconsulting\Uniteller\Request\RequestInterface
300 | */
301 | public function getCancelRequest()
302 | {
303 | return $this->cancelRequest;
304 | }
305 |
306 | /**
307 | * @return \Tmconsulting\Uniteller\Request\RequestInterface
308 | */
309 | public function getResultsRequest()
310 | {
311 | return $this->resultsRequest;
312 | }
313 |
314 | /**
315 | * @return \Tmconsulting\Uniteller\Request\RequestInterface
316 | */
317 | public function getRecurrentRequest()
318 | {
319 | return $this->recurrentRequest;
320 | }
321 |
322 | /**
323 | * @return \Tmconsulting\Uniteller\Signature\SignatureInterface
324 | */
325 | public function getSignaturePayment()
326 | {
327 | return $this->signaturePayment;
328 | }
329 |
330 | /**
331 | * @return \Tmconsulting\Uniteller\Signature\SignatureInterface
332 | */
333 | public function getSignatureRecurrent()
334 | {
335 | return $this->signatureRecurrent;
336 | }
337 |
338 | /**
339 | * @return \Tmconsulting\Uniteller\Signature\SignatureInterface
340 | */
341 | public function getSignatureCallback()
342 | {
343 | return $this->signatureCallback;
344 | }
345 |
346 | /**
347 | * @return \Tmconsulting\Uniteller\Http\HttpManagerInterface
348 | */
349 | public function getHttpManager()
350 | {
351 | return $this->httpManager;
352 | }
353 |
354 | /**
355 | * Получение платежной ссылки или сразу переход к оплате.
356 | *
357 | * @param array $parameters|\Tmconsulting\Client\Payment\PaymentBuilder $builder
358 | * @return \Tmconsulting\Uniteller\Payment\UriInterface
359 | */
360 | public function payment($parameters)
361 | {
362 | $array = $this->getParameters($parameters);
363 | $array['Shop_IDP'] = $this->getShopId();
364 | $array['Signature'] = $this->signaturePayment
365 | ->setShopIdp(array_get($array, 'Shop_IDP'))
366 | ->setOrderIdp(array_get($array, 'Order_IDP'))
367 | ->setSubtotalP(array_get($array, 'Subtotal_P'))
368 | ->setMeanType(array_get($array, 'MeanType'))
369 | ->setEMoneyType(array_get($array, 'EMoneyType'))
370 | ->setLifeTime(array_get($array, 'Lifetime'))
371 | ->setCustomerIdp(array_get($array, 'Customer_IDP'))
372 | ->setCardIdp(array_get($array, 'Card_IDP'))
373 | ->setIData(array_get($array, 'IData'))
374 | ->setPtCode(array_get($array, 'PT_Code'))
375 | ->setPassword($this->getPassword())
376 | ->create();
377 |
378 | return $this->getPayment()->execute($array, $this->getOptions());
379 | }
380 |
381 | /**
382 | * Отмена платежа.
383 | *
384 | * @param \Tmconsulting\Uniteller\Cancel\CancelBuilder|array $parameters
385 | * @return mixed
386 | * @internal param $builder
387 | */
388 | public function cancel($parameters)
389 | {
390 | return $this->callRequestFor('cancel', $parameters);
391 | }
392 |
393 | /**
394 | * @param \Tmconsulting\Uniteller\Cancel\CancelBuilder|array $parameters
395 | * @return Order
396 | */
397 | public function results($parameters)
398 | {
399 | return $this->callRequestFor('results', $parameters);
400 | }
401 |
402 | /**
403 | * @param \Tmconsulting\Uniteller\Recurrent\RecurrentBuilder|array $parameters
404 | * @return mixed
405 | * @throws \Tmconsulting\Uniteller\Exception\NotImplementedException
406 | */
407 | public function recurrent($parameters)
408 | {
409 | $array = $this->getParameters($parameters);
410 | $array['Shop_IDP'] = $this->getShopId();
411 |
412 | $this->signatureRecurrent
413 | ->setShopIdp(array_get($array, 'Shop_IDP'))
414 | ->setOrderIdp(array_get($array, 'Order_IDP'))
415 | ->setSubtotalP(array_get($array, 'Subtotal_P'))
416 | ->setParentOrderIdp(array_get($array, 'Parent_Order_IDP'))
417 | ->setPassword($this->getPassword());
418 | if (array_get($array, 'Parent_Shop_IDP')) {
419 | $this->signatureRecurrent->setParentShopIdp(array_get($array, 'Parent_Shop_IDP'));
420 | }
421 |
422 | $array['Signature'] = $this->signatureRecurrent->create();
423 |
424 | return $this->callRequestFor('recurrent', $array);
425 | }
426 |
427 | /**
428 | * @param array $parameters
429 | * @return mixed
430 | * @throws \Tmconsulting\Uniteller\Exception\NotImplementedException
431 | */
432 | public function confirm($parameters)
433 | {
434 | throw new NotImplementedException(sprintf(
435 | 'In current moment, feature [%s] not implemented.', __METHOD__
436 | ));
437 | }
438 |
439 | /**
440 | * @param array $parameters
441 | * @return mixed
442 | * @throws \Tmconsulting\Uniteller\Exception\NotImplementedException
443 | */
444 | public function card($parameters)
445 | {
446 | throw new NotImplementedException(sprintf(
447 | 'In current moment, feature [%s] not implemented.', __METHOD__
448 | ));
449 | }
450 |
451 | /**
452 | * Подгружаем собственный HttpManager с газлом в качестве клиента, если
453 | * не был задан свой, перед выполнением запроса.
454 | *
455 | * @param $name
456 | * @param $parameters
457 | * @return Order|mixed
458 | */
459 | private function callRequestFor($name, $parameters)
460 | {
461 | if (! $this->getHttpManager()) {
462 | $httpClient = new GuzzleAdapter(new GuzzleClient());
463 | $this->setHttpManager(new HttpManager($httpClient, $this->getOptions()));
464 | }
465 |
466 | /** @var RequestInterface $request */
467 | $request = $this->{'get' . ucfirst($name) . 'Request'}();
468 |
469 | return $request->execute(
470 | $this->getHttpManager(),
471 | $this->getParameters($parameters)
472 | );
473 | }
474 |
475 | /**
476 | * @param $parameters
477 | * @return mixed
478 | */
479 | private function getParameters($parameters)
480 | {
481 | if ($parameters instanceof ArraybleInterface) {
482 | return $parameters->toArray();
483 | }
484 |
485 | return $parameters;
486 | }
487 |
488 | /**
489 | * Verify signature when Client will be send callback request.
490 | *
491 | * @param array $params
492 | * @return bool
493 | */
494 | public function verifyCallbackRequest(array $params)
495 | {
496 | return $this->signatureCallback
497 | ->setOrderId(array_get($params, 'Order_ID'))
498 | ->setStatus(array_get($params, 'Status'))
499 | ->setFields(array_except($params, ['Order_ID', 'Status', 'Signature']))
500 | ->setPassword($this->getPassword())
501 | ->verify(array_get($params, 'Signature'));
502 | }
503 | }
504 |
--------------------------------------------------------------------------------
/src/Payment/PaymentBuilder.php:
--------------------------------------------------------------------------------
1 | shopIdp = $shopIdp;
295 |
296 | return $this;
297 | }
298 |
299 | /**
300 | * @param string $orderIdp
301 | * @return $this
302 | */
303 | public function setOrderIdp($orderIdp)
304 | {
305 | $this->orderIdp = $orderIdp;
306 |
307 | return $this;
308 | }
309 |
310 | /**
311 | * @param float|string $subtotalP
312 | * @return $this
313 | */
314 | public function setSubtotalP($subtotalP)
315 | {
316 | $this->subtotalP = $subtotalP;
317 |
318 | return $this;
319 | }
320 |
321 | /**
322 | * @param string $signature
323 | * @return $this
324 | */
325 | public function setSignature($signature)
326 | {
327 | $this->signature = $signature;
328 |
329 | return $this;
330 | }
331 |
332 | /**
333 | * @param string $urlReturnOk
334 | * @return $this
335 | */
336 | public function setUrlReturnOk($urlReturnOk)
337 | {
338 | $this->urlReturnOk = $urlReturnOk;
339 |
340 | return $this;
341 | }
342 |
343 | /**
344 | * @param string $urlReturnNo
345 | * @return $this
346 | */
347 | public function setUrlReturnNo($urlReturnNo)
348 | {
349 | $this->urlReturnNo = $urlReturnNo;
350 |
351 | return $this;
352 | }
353 |
354 | /**
355 | * @param string $currency
356 | * @return $this
357 | */
358 | public function setCurrency($currency)
359 | {
360 | $this->currency = $currency;
361 |
362 | return $this;
363 | }
364 |
365 | /**
366 | * @param string $email
367 | * @return $this
368 | */
369 | public function setEmail($email)
370 | {
371 | $this->email = $email;
372 |
373 | return $this;
374 | }
375 |
376 | /**
377 | * @param int $lifetime
378 | * @return $this
379 | */
380 | public function setLifetime($lifetime)
381 | {
382 | $this->lifetime = $lifetime;
383 |
384 | return $this;
385 | }
386 |
387 | /**
388 | * @param int $orderLifetime
389 | * @return $this
390 | */
391 | public function setOrderLifetime($orderLifetime)
392 | {
393 | $this->orderLifetime = $orderLifetime;
394 |
395 | return $this;
396 | }
397 |
398 | /**
399 | * @param string $customerIdp
400 | * @return $this
401 | */
402 | public function setCustomerIdp($customerIdp)
403 | {
404 | $this->customerIdp = $customerIdp;
405 |
406 | return $this;
407 | }
408 |
409 | /**
410 | * @param mixed $cardIdp
411 | * @return $this
412 | */
413 | public function setCardIdp($cardIdp)
414 | {
415 | $this->cardIdp = $cardIdp;
416 |
417 | return $this;
418 | }
419 |
420 | /**
421 | * @param string $iData
422 | * @return $this
423 | */
424 | public function setIData($iData)
425 | {
426 | $this->iData = $iData;
427 |
428 | return $this;
429 | }
430 |
431 | /**
432 | * @param string $ptCode
433 | * @return $this
434 | */
435 | public function setPtCode($ptCode)
436 | {
437 | $this->ptCode = $ptCode;
438 |
439 | return $this;
440 | }
441 |
442 | /**
443 | * @param int $meanType
444 | * @return $this
445 | */
446 | public function setMeanType($meanType)
447 | {
448 | $this->meanType = $meanType;
449 |
450 | return $this;
451 | }
452 |
453 | /**
454 | * @param int $eMoneyType
455 | * @return $this
456 | */
457 | public function setEMoneyType($eMoneyType)
458 | {
459 | $this->eMoneyType = $eMoneyType;
460 |
461 | return $this;
462 | }
463 |
464 | /**
465 | * @param int $billLifetime
466 | * @return $this
467 | */
468 | public function setBillLifetime($billLifetime)
469 | {
470 | $this->billLifetime = $billLifetime;
471 |
472 | return $this;
473 | }
474 |
475 | /**
476 | *
477 | */
478 | public function usePreAuth()
479 | {
480 | $this->preAuth = true;
481 |
482 | return $this;
483 | }
484 |
485 | /**
486 | * @return bool
487 | */
488 | public function useRecurrentPayment()
489 | {
490 | $this->IsRecurrentStart = true;
491 |
492 | return $this;
493 | }
494 |
495 | /**
496 | * @param array $callbackFields
497 | * @return $this
498 | */
499 | public function setCallbackFields(array $callbackFields)
500 | {
501 | $this->callbackFields = join(' ', $callbackFields);
502 |
503 | return $this;
504 | }
505 |
506 | /**
507 | * @param string $callbackFormat
508 | * @return $this
509 | */
510 | public function setCallbackFormat($callbackFormat)
511 | {
512 | $this->callbackFormat = $callbackFormat;
513 |
514 | return $this;
515 | }
516 |
517 | /**
518 | * @param string $language
519 | * @return $this
520 | */
521 | public function setLanguage($language)
522 | {
523 | $this->language = $language;
524 |
525 | return $this;
526 | }
527 |
528 | /**
529 | * @param string $comment
530 | * @return $this
531 | */
532 | public function setComment($comment)
533 | {
534 | $this->comment = $comment;
535 |
536 | return $this;
537 | }
538 |
539 | /**
540 | * @param string $firstName
541 | * @return $this
542 | */
543 | public function setFirstName($firstName)
544 | {
545 | $this->firstName = $firstName;
546 |
547 | return $this;
548 | }
549 |
550 | /**
551 | * @param mixed $lastName
552 | * @return $this
553 | */
554 | public function setLastName($lastName)
555 | {
556 | $this->lastName = $lastName;
557 |
558 | return $this;
559 | }
560 |
561 | /**
562 | * @param string $middleName
563 | * @return $this
564 | */
565 | public function setMiddleName($middleName)
566 | {
567 | $this->middleName = $middleName;
568 |
569 | return $this;
570 | }
571 |
572 | /**
573 | * @param string $phone
574 | * @return $this
575 | */
576 | public function setPhone($phone)
577 | {
578 | $this->phone = $phone;
579 |
580 | return $this;
581 | }
582 |
583 | /**
584 | * @param string $address
585 | * @return $this
586 | */
587 | public function setAddress($address)
588 | {
589 | $this->address = $address;
590 |
591 | return $this;
592 | }
593 |
594 | /**
595 | * @param string $country
596 | * @return $this
597 | */
598 | public function setCountry($country)
599 | {
600 | $this->country = $country;
601 |
602 | return $this;
603 | }
604 |
605 | /**
606 | * @param string $state
607 | * @return $this
608 | */
609 | public function setState($state)
610 | {
611 | $this->state = $state;
612 |
613 | return $this;
614 | }
615 |
616 | /**
617 | * @param string $city
618 | * @return $this
619 | */
620 | public function setCity($city)
621 | {
622 | $this->city = $city;
623 |
624 | return $this;
625 | }
626 |
627 | /**
628 | * @param mixed $zip
629 | * @return $this
630 | */
631 | public function setZip($zip)
632 | {
633 | $this->zip = $zip;
634 |
635 | return $this;
636 | }
637 |
638 | /* Getters */
639 |
640 | /**
641 | * @return string
642 | */
643 | public function getShopIdp()
644 | {
645 | return $this->shopIdp;
646 |
647 | return $this;
648 | }
649 |
650 | /**
651 | * @return string
652 | */
653 | public function getOrderIdp()
654 | {
655 | return $this->orderIdp;
656 |
657 | return $this;
658 | }
659 |
660 | /**
661 | * @return float|string
662 | */
663 | public function getSubtotalP()
664 | {
665 | return $this->subtotalP;
666 |
667 | return $this;
668 | }
669 |
670 | /**
671 | * @return string
672 | */
673 | public function getSignature()
674 | {
675 | return $this->signature;
676 | }
677 |
678 | /**
679 | * @return string
680 | */
681 | public function getUrlReturnOk()
682 | {
683 | return $this->urlReturnOk;
684 | }
685 |
686 | /**
687 | * @return string
688 | */
689 | public function getUrlReturnNo()
690 | {
691 | return $this->urlReturnNo;
692 | }
693 |
694 | /**
695 | * @return string
696 | */
697 | public function getCurrency()
698 | {
699 | return $this->currency;
700 | }
701 |
702 | /**
703 | * @return string
704 | */
705 | public function getEmail()
706 | {
707 | return $this->email;
708 | }
709 |
710 | /**
711 | * @return int
712 | */
713 | public function getLifetime()
714 | {
715 | return $this->lifetime;
716 | }
717 |
718 | /**
719 | * @return int
720 | */
721 | public function getOrderLifetime()
722 | {
723 | return $this->orderLifetime;
724 | }
725 |
726 |
727 | /**
728 | * @return string
729 | */
730 | public function getCustomerIdp()
731 | {
732 | return $this->customerIdp;
733 | }
734 |
735 | /**
736 | * @return mixed
737 | */
738 | public function getCardIdp()
739 | {
740 | return $this->cardIdp;
741 | }
742 |
743 | /**
744 | * @return string
745 | */
746 | public function getIData()
747 | {
748 | return $this->iData;
749 | }
750 |
751 | /**
752 | * @return string
753 | */
754 | public function getPtCode()
755 | {
756 | return $this->ptCode;
757 | }
758 |
759 | /**
760 | * @return int
761 | */
762 | public function getMeanType()
763 | {
764 | return $this->meanType;
765 | }
766 |
767 | /**
768 | * @return int
769 | */
770 | public function getEMoneyType()
771 | {
772 | return $this->eMoneyType;
773 | }
774 |
775 | /**
776 | * @return int
777 | */
778 | public function getBillLifetime()
779 | {
780 | return $this->billLifetime;
781 | }
782 |
783 | /**
784 | * @return bool
785 | */
786 | public function isPreAuth()
787 | {
788 | return $this->preAuth;
789 | }
790 |
791 | /**
792 | * @return bool
793 | */
794 | public function isIsRecurrentStart()
795 | {
796 | return $this->IsRecurrentStart;
797 | }
798 |
799 | /**
800 | * @return array
801 | */
802 | public function getCallbackFields()
803 | {
804 | return $this->callbackFields;
805 | }
806 |
807 | /**
808 | * @return string
809 | */
810 | public function getCallbackFormat()
811 | {
812 | return $this->callbackFormat;
813 | }
814 |
815 | /**
816 | * @return string
817 | */
818 | public function getLanguage()
819 | {
820 | return $this->language;
821 | }
822 |
823 | /**
824 | * @return string
825 | */
826 | public function getComment()
827 | {
828 | return $this->comment;
829 | }
830 |
831 | /**
832 | * @return string
833 | */
834 | public function getFirstName()
835 | {
836 | return $this->firstName;
837 | }
838 |
839 | /**
840 | * @return mixed
841 | */
842 | public function getLastName()
843 | {
844 | return $this->lastName;
845 | }
846 |
847 | /**
848 | * @return string
849 | */
850 | public function getMiddleName()
851 | {
852 | return $this->middleName;
853 | }
854 |
855 | /**
856 | * @return string
857 | */
858 | public function getPhone()
859 | {
860 | return $this->phone;
861 | }
862 |
863 | /**
864 | * @return string
865 | */
866 | public function getAddress()
867 | {
868 | return $this->address;
869 | }
870 |
871 | /**
872 | * @return string
873 | */
874 | public function getCountry()
875 | {
876 | return $this->country;
877 | }
878 |
879 | /**
880 | * @return string
881 | */
882 | public function getState()
883 | {
884 | return $this->state;
885 | }
886 |
887 | /**
888 | * @return string
889 | */
890 | public function getCity()
891 | {
892 | return $this->city;
893 | }
894 |
895 | /**
896 | * @return mixed
897 | */
898 | public function getZip()
899 | {
900 | return $this->zip;
901 | }
902 |
903 | /**
904 | * @return array
905 | */
906 | public function toArray()
907 | {
908 | return [
909 | 'Shop_IDP' => $this->getShopIdp(),
910 | 'Order_IDP' => $this->getOrderIdp(),
911 | 'Subtotal_P' => $this->getSubtotalP(),
912 | 'Signature' => $this->getSignature(),
913 | 'URL_RETURN_OK' => $this->getUrlReturnOk(),
914 | 'URL_RETURN_NO' => $this->getUrlReturnNo(),
915 | 'Currency' => $this->getCurrency(),
916 | 'Email' => $this->getEmail(),
917 | 'Lifetime' => $this->getLifetime(),
918 | 'OrderLifetime' => $this->getOrderLifetime(),
919 | 'Customer_IDP' => $this->getCustomerIdp(),
920 | 'Card_IDP' => $this->getCardIdp(),
921 | 'IData' => $this->getIData(),
922 | 'PT_Code' => $this->getPtCode(),
923 | 'MeanType' => $this->getMeanType(),
924 | 'EMoneyType' => $this->getEMoneyType(),
925 | 'BillLifetime' => $this->getBillLifetime(),
926 | 'Preauth' => $this->isPreAuth(),
927 | 'IsRecurrentStart' => $this->isIsRecurrentStart(),
928 | 'CallbackFields' => $this->getCallbackFields(),
929 | 'CallbackFormat' => $this->getCallbackFormat(),
930 | 'Language' => $this->getLanguage(),
931 | 'Comment' => $this->getComment(),
932 | 'FirstName' => $this->getFirstName(),
933 | 'LastName' => $this->getLastName(),
934 | 'MiddleName' => $this->getMiddleName(),
935 | 'Phone' => $this->getPhone(),
936 | 'Address' => $this->getAddress(),
937 | 'Country' => $this->getCountry(),
938 | 'State' => $this->getState(),
939 | 'City' => $this->getCity(),
940 | 'Zip' => $this->getZip(),
941 | ];
942 | }
943 | }
--------------------------------------------------------------------------------
/src/Order/Order.php:
--------------------------------------------------------------------------------
1 | address = $address;
307 |
308 | return $this;
309 | }
310 |
311 | /**
312 | * @param string $approvalCode
313 | * @return $this
314 | */
315 | public function setApprovalCode($approvalCode)
316 | {
317 | $this->approvalCode = $approvalCode;
318 |
319 | return $this;
320 | }
321 |
322 | /**
323 | * @param string $bankName
324 | * @return $this
325 | */
326 | public function setBankName($bankName)
327 | {
328 | $this->bankName = $bankName;
329 |
330 | return $this;
331 | }
332 |
333 | /**
334 | * @param int $billNumber
335 | * @return $this
336 | */
337 | public function setBillNumber($billNumber)
338 | {
339 | $this->billNumber = $billNumber;
340 |
341 | return $this;
342 | }
343 |
344 | /**
345 | * @param string $bookingcomId
346 | * @return $this
347 | */
348 | public function setBookingcomId($bookingcomId)
349 | {
350 | $this->bookingcomId = $bookingcomId;
351 |
352 | return $this;
353 | }
354 |
355 | /**
356 | * @param string $bookingcomPincode
357 | * @return $this
358 | */
359 | public function setBookingcomPincode($bookingcomPincode)
360 | {
361 | $this->bookingcomPincode = $bookingcomPincode;
362 |
363 | return $this;
364 | }
365 |
366 | /**
367 | * @param string $cardIdp
368 | * @return $this
369 | */
370 | public function setCardIdp($cardIdp)
371 | {
372 | $this->cardIdp = $cardIdp;
373 |
374 | return $this;
375 | }
376 |
377 | /**
378 | * @param string $cardHolder
379 | * @return $this
380 | */
381 | public function setCardHolder($cardHolder)
382 | {
383 | $this->cardHolder = $cardHolder;
384 |
385 | return $this;
386 | }
387 |
388 | /**
389 | * @param string $cardNumber
390 | * @return $this
391 | */
392 | public function setCardNumber($cardNumber)
393 | {
394 | $this->cardNumber = $cardNumber;
395 |
396 | return $this;
397 | }
398 |
399 | /**
400 | * @param string $cardType
401 | * @return $this
402 | */
403 | public function setCardType($cardType)
404 | {
405 | $this->cardType = $cardType;
406 |
407 | return $this;
408 | }
409 |
410 | /**
411 | * @param string $comment
412 | * @return $this
413 | */
414 | public function setComment($comment)
415 | {
416 | $this->comment = $comment;
417 |
418 | return $this;
419 | }
420 |
421 | /**
422 | * @param string $currency
423 | * @return $this
424 | */
425 | public function setCurrency($currency)
426 | {
427 | $this->currency = $currency;
428 |
429 | return $this;
430 | }
431 |
432 | /**
433 | * @param $value
434 | * @return $this
435 | */
436 | public function setCvc2($value)
437 | {
438 | $this->cvc2 = (bool) $value;
439 |
440 | return $this;
441 | }
442 |
443 | /**
444 | * @return $this
445 | */
446 | public function withCvc2()
447 | {
448 | $this->cvc2 = true;
449 |
450 | return $this;
451 | }
452 |
453 | /**
454 | * @return $this
455 | */
456 | public function withoutCvc2()
457 | {
458 | $this->cvc2 = false;
459 |
460 | return $this;
461 | }
462 |
463 | /**
464 | * @param DateTime $date
465 | * @return $this
466 | */
467 | public function setDate($date)
468 | {
469 | if (empty($date)) {
470 | return $this;
471 | }
472 |
473 | // Ёбаный насрать, а даты зачем разного формата отдавать?
474 | // Полностью разделяю и поддерживаю данное негодование, значит ебашим костыли))
475 | $date = str_replace('.', '-', $date);
476 | $this->date = DateTime::createFromFormat('U', strtotime($date));
477 |
478 | return $this;
479 | }
480 |
481 | /**
482 | * @param string $email
483 | * @return $this
484 | */
485 | public function setEmail($email)
486 | {
487 | $this->email = $email;
488 |
489 | return $this;
490 | }
491 |
492 | /**
493 | * @param string $eMoneyType
494 | * @return $this
495 | */
496 | public function setEMoneyType($eMoneyType)
497 | {
498 | $this->eMoneyType = $eMoneyType;
499 |
500 | return $this;
501 | }
502 |
503 | /**
504 | * @param array $eOrderData
505 | * @return $this
506 | */
507 | public function setEOrderData($eOrderData)
508 | {
509 | if (empty($eOrderData)) {
510 | return $this;
511 | }
512 |
513 | foreach (explode(', ', $eOrderData) as $item) {
514 | list($key, $value) = explode('=', $item);
515 | $this->eOrderData[$key] = $value;
516 | }
517 |
518 | return $this;
519 | }
520 |
521 | /**
522 | * @param int $errorCode
523 | * @return $this
524 | */
525 | public function setErrorCode($errorCode)
526 | {
527 | $this->errorCode = $errorCode;
528 |
529 | return $this;
530 | }
531 |
532 | /**
533 | * @param string $errorComment
534 | * @return $this
535 | */
536 | public function setErrorComment($errorComment)
537 | {
538 | $this->errorComment = $errorComment;
539 |
540 | return $this;
541 | }
542 |
543 | /**
544 | * @param string $firstName
545 | * @return $this
546 | */
547 | public function setFirstName($firstName)
548 | {
549 | $this->firstName = $firstName;
550 |
551 | return $this;
552 | }
553 |
554 | /**
555 | * @param int $gdsPaymentPurposeId
556 | * @return $this
557 | */
558 | public function setGdsPaymentPurposeId($gdsPaymentPurposeId)
559 | {
560 | $this->gdsPaymentPurposeId = $gdsPaymentPurposeId;
561 |
562 | return $this;
563 | }
564 |
565 | /**
566 | * @param string $iData
567 | * @return $this
568 | */
569 | public function setIData($iData)
570 | {
571 | $this->iData = $iData;
572 |
573 | return $this;
574 | }
575 |
576 | /**
577 | * @param string $ip
578 | * @return $this
579 | */
580 | public function setIp($ip)
581 | {
582 | $this->ip = $ip;
583 |
584 | return $this;
585 | }
586 |
587 | /**
588 | * @param string $lastName
589 | * @return $this
590 | */
591 | public function setLastName($lastName)
592 | {
593 | $this->lastName = $lastName;
594 |
595 | return $this;
596 | }
597 |
598 | /**
599 | * @param string $loanId
600 | * @return $this
601 | */
602 | public function setLoanId($loanId)
603 | {
604 | $this->loanId = $loanId;
605 |
606 | return $this;
607 | }
608 |
609 | /**
610 | * @param string $message
611 | * @return $this
612 | */
613 | public function setMessage($message)
614 | {
615 | $this->message = $message;
616 |
617 | return $this;
618 | }
619 |
620 | /**
621 | * @param string $middleName
622 | * @return $this
623 | */
624 | public function setMiddleName($middleName)
625 | {
626 | $this->middleName = $middleName;
627 |
628 | return $this;
629 | }
630 |
631 | /**
632 | * @param bool $needConfirm
633 | * @return $this
634 | */
635 | public function setNeedConfirm($needConfirm)
636 | {
637 | $this->needConfirm = (bool) $needConfirm;
638 |
639 | return $this;
640 | }
641 |
642 | /**
643 | * @param string $orderNumber
644 | * @return $this
645 | */
646 | public function setOrderNumber($orderNumber)
647 | {
648 | $this->orderNumber = $orderNumber;
649 |
650 | return $this;
651 | }
652 |
653 | /**
654 | * @param string $parentOrderNumber
655 | * @return $this
656 | */
657 | public function setParentOrderNumber($parentOrderNumber)
658 | {
659 | $this->parentOrderNumber = $parentOrderNumber;
660 |
661 | return $this;
662 | }
663 |
664 | /**
665 | * @param int $paymentType
666 | * @return $this
667 | */
668 | public function setPaymentType($paymentType)
669 | {
670 | $this->paymentType = $paymentType;
671 |
672 | return $this;
673 | }
674 |
675 | /**
676 | * @param string $phone
677 | * @return $this
678 | */
679 | public function setPhone($phone)
680 | {
681 | $this->phone = $phone;
682 |
683 | return $this;
684 | }
685 |
686 | /**
687 | * @param string $ptCode
688 | * @return $this
689 | */
690 | public function setPtCode($ptCode)
691 | {
692 | $this->ptCode = $ptCode;
693 |
694 | return $this;
695 | }
696 |
697 | /**
698 | * @param string $recommendation
699 | * @return $this
700 | */
701 | public function setRecommendation($recommendation)
702 | {
703 | $this->recommendation = $recommendation;
704 |
705 | return $this;
706 | }
707 |
708 | /**
709 | * @param string $responseCode
710 | * @return $this
711 | */
712 | public function setResponseCode($responseCode)
713 | {
714 | $this->responseCode = $responseCode;
715 |
716 | return $this;
717 | }
718 |
719 | /**
720 | * @param string $status
721 | * @return $this
722 | */
723 | public function setStatus($status)
724 | {
725 | $this->status = Status::resolve($status);
726 |
727 | return $this;
728 | }
729 |
730 | /**
731 | * @param string $total
732 | * @return $this
733 | */
734 | public function setTotal($total)
735 | {
736 | $this->total = $total;
737 |
738 | return $this;
739 | }
740 |
741 | /**
742 | * @return string
743 | */
744 | public function getAddress()
745 | {
746 | return $this->address;
747 | }
748 |
749 | /**
750 | * @return string
751 | */
752 | public function getApprovalCode()
753 | {
754 | return $this->approvalCode;
755 | }
756 |
757 | /**
758 | * @return string
759 | */
760 | public function getBankName()
761 | {
762 | return $this->bankName;
763 | }
764 |
765 | /**
766 | * @return int
767 | */
768 | public function getBillNumber()
769 | {
770 | return $this->billNumber;
771 | }
772 |
773 | /**
774 | * @return string
775 | */
776 | public function getBookingcomId()
777 | {
778 | return $this->bookingcomId;
779 | }
780 |
781 | /**
782 | * @return string
783 | */
784 | public function getBookingcomPincode()
785 | {
786 | return $this->bookingcomPincode;
787 | }
788 |
789 | /**
790 | * @return string
791 | */
792 | public function getCardIdp()
793 | {
794 | return $this->cardIdp;
795 | }
796 |
797 | /**
798 | * @return string
799 | */
800 | public function getCardHolder()
801 | {
802 | return $this->cardHolder;
803 | }
804 |
805 | /**
806 | * @return string
807 | */
808 | public function getCardNumber()
809 | {
810 | return $this->cardNumber;
811 | }
812 |
813 | /**
814 | * @return string
815 | */
816 | public function getCardType()
817 | {
818 | return $this->cardType;
819 | }
820 |
821 | /**
822 | * @return string
823 | */
824 | public function getComment()
825 | {
826 | return $this->comment;
827 | }
828 |
829 | /**
830 | * @return string
831 | */
832 | public function getCurrency()
833 | {
834 | return $this->currency;
835 | }
836 |
837 | /**
838 | * @return int
839 | */
840 | public function isCvc2()
841 | {
842 | return $this->cvc2;
843 | }
844 |
845 | /**
846 | * @return DateTime
847 | */
848 | public function getDate()
849 | {
850 | return $this->date;
851 | }
852 |
853 | /**
854 | * @return string
855 | */
856 | public function getEmail()
857 | {
858 | return $this->email;
859 | }
860 |
861 | /**
862 | * @return string
863 | */
864 | public function getEMoneyType()
865 | {
866 | return $this->eMoneyType;
867 | }
868 |
869 | /**
870 | * @return array
871 | */
872 | public function getEOrderData()
873 | {
874 | return $this->eOrderData;
875 | }
876 |
877 | /**
878 | * @return int
879 | */
880 | public function getErrorCode()
881 | {
882 | return $this->errorCode;
883 | }
884 |
885 | /**
886 | * @return string
887 | */
888 | public function getErrorComment()
889 | {
890 | return $this->errorComment;
891 | }
892 |
893 | /**
894 | * @return string
895 | */
896 | public function getFirstName()
897 | {
898 | return $this->firstName;
899 | }
900 |
901 | /**
902 | * @return int
903 | */
904 | public function getGdsPaymentPurposeId()
905 | {
906 | return $this->gdsPaymentPurposeId;
907 | }
908 |
909 | /**
910 | * @return string
911 | */
912 | public function getIData()
913 | {
914 | return $this->iData;
915 | }
916 |
917 | /**
918 | * @return string
919 | */
920 | public function getIp()
921 | {
922 | return $this->ip;
923 | }
924 |
925 | /**
926 | * @return string
927 | */
928 | public function getLastName()
929 | {
930 | return $this->lastName;
931 | }
932 |
933 | /**
934 | * @return string
935 | */
936 | public function getLoanId()
937 | {
938 | return $this->loanId;
939 | }
940 |
941 | /**
942 | * @return string
943 | */
944 | public function getMessage()
945 | {
946 | return $this->message;
947 | }
948 |
949 | /**
950 | * @return string
951 | */
952 | public function getMiddleName()
953 | {
954 | return $this->middleName;
955 | }
956 |
957 | /**
958 | * @return bool
959 | */
960 | public function isNeedConfirm()
961 | {
962 | return $this->needConfirm;
963 | }
964 |
965 | /**
966 | * @return string
967 | */
968 | public function getOrderNumber()
969 | {
970 | return $this->orderNumber;
971 | }
972 |
973 | /**
974 | * @return string
975 | */
976 | public function getParentOrderNumber()
977 | {
978 | return $this->parentOrderNumber;
979 | }
980 |
981 | /**
982 | * @return int
983 | */
984 | public function getPaymentType()
985 | {
986 | return $this->paymentType;
987 | }
988 |
989 | /**
990 | * @return string
991 | */
992 | public function getPhone()
993 | {
994 | return $this->phone;
995 | }
996 |
997 | /**
998 | * @return string
999 | */
1000 | public function getPtCode()
1001 | {
1002 | return $this->ptCode;
1003 | }
1004 |
1005 | /**
1006 | * @return string
1007 | */
1008 | public function getRecommendation()
1009 | {
1010 | return $this->recommendation;
1011 | }
1012 |
1013 | /**
1014 | * @return string
1015 | */
1016 | public function getResponseCode()
1017 | {
1018 | return $this->responseCode;
1019 | }
1020 |
1021 | /**
1022 | * @return string
1023 | */
1024 | public function getResponseMessage()
1025 | {
1026 | return ResponseCode::message($this->responseCode);
1027 | }
1028 |
1029 | /**
1030 | * @return string
1031 | */
1032 | public function getStatus()
1033 | {
1034 | return $this->status;
1035 | }
1036 |
1037 | /**
1038 | * @return string
1039 | */
1040 | public function getTotal()
1041 | {
1042 | return $this->total;
1043 | }
1044 |
1045 | /**
1046 | * @param DateTime $packetDate
1047 | * @return $this
1048 | */
1049 | public function setPacketDate($packetDate)
1050 | {
1051 | if (empty($packetDate)) {
1052 | return $this;
1053 | }
1054 |
1055 | // 10.03.2017 15:42:42 - o_O
1056 | // 2018.07.16 10:54:05 - O_o
1057 | $packetDate = str_replace('.', '-', $packetDate);
1058 | $this->packetDate = DateTime::createFromFormat('U', strtotime($packetDate));
1059 |
1060 | return $this;
1061 | }
1062 |
1063 | /**
1064 | * @return DateTime
1065 | */
1066 | public function getPacketDate()
1067 | {
1068 | return $this->packetDate;
1069 | }
1070 |
1071 | /**
1072 | * @return string
1073 | */
1074 | public function getSignature()
1075 | {
1076 | return $this->signature;
1077 | }
1078 |
1079 | /**
1080 | * @param string $signature
1081 | * @return Order
1082 | */
1083 | public function setSignature($signature)
1084 | {
1085 | $this->signature = $signature;
1086 |
1087 | return $this;
1088 | }
1089 |
1090 | /**
1091 | * @return array
1092 | */
1093 | public function toArray()
1094 | {
1095 | return [
1096 | 'Address' => $this->getAddress(),
1097 | 'ApprovalCode' => $this->getApprovalCode(),
1098 | 'BankName' => $this->getBankName(),
1099 | 'BillNumber' => $this->getBillNumber(),
1100 | 'bookingcom_id' => $this->getBookingcomId(),
1101 | 'bookingcom_pincode' => $this->getBookingcomPincode(),
1102 | 'Card_IDP' => $this->getCardIdp(),
1103 | 'CardHolder' => $this->getCardHolder(),
1104 | 'CardNumber' => $this->getCardNumber(),
1105 | 'CardType' => $this->getCardType(),
1106 | 'Comment' => $this->getComment(),
1107 | 'Currency' => $this->getCurrency(),
1108 | 'CVC2' => $this->isCvc2(),
1109 | 'Date' => $this->getDate(),
1110 | 'PacketDate' => $this->getPacketDate(),
1111 | 'Email' => $this->getEmail(),
1112 | 'EMoneyType' => $this->getEMoneyType(),
1113 | 'EOrderData' => $this->getEOrderData(),
1114 | 'Error_Code' => $this->getErrorCode(),
1115 | 'Error_Comment' => $this->getErrorComment(),
1116 | 'FirstName' => $this->getFirstName(),
1117 | 'gds_payment_purpose_id' => $this->getGdsPaymentPurposeId(),
1118 | 'IData' => $this->getIData(),
1119 | 'IPAddress' => $this->getIp(),
1120 | 'LastName' => $this->getLastName(),
1121 | 'LoanID' => $this->getLoanId(),
1122 | 'Message' => $this->getMessage(),
1123 | 'MiddleName' => $this->getMiddleName(),
1124 | 'need_confirm' => $this->isNeedConfirm(),
1125 | 'OrderNumber' => $this->getOrderNumber(),
1126 | 'parent_order_number' => $this->getParentOrderNumber(),
1127 | 'PaymentType' => $this->getPaymentType(),
1128 | 'Phone' => $this->getPhone(),
1129 | 'PT_Code' => $this->getPtCode(),
1130 | 'Recommendation' => $this->getRecommendation(),
1131 | 'Response_Code' => $this->getResponseCode(),
1132 | 'Response_Message' => $this->getResponseMessage(),
1133 | 'Status' => $this->getStatus(),
1134 | 'Total' => $this->getTotal(),
1135 | 'Signature' => $this->getSignature(),
1136 | ];
1137 | }
1138 | }
--------------------------------------------------------------------------------