diff --git a/README.md b/README.md index 8cfc743..83c4df2 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Also, this SDK integrated with [Payum](https://github.com/Payum/Payum) library a Features: * payment (method `pay`) +* recurrent (method `recurrent`) * cancel (method `unblock`) * receive results * callback (method for verify incoming signature) @@ -42,7 +43,6 @@ TODO: * translate to English comments and system (error) messages * validation * implement method `card` -* implement method `recurrent` * implement method `confirm` ## Install @@ -99,6 +99,31 @@ $uniteller->payment([ ])->go(); ``` +### Recurrent payment + +```php +setOrderIdp(mt_rand(10000, 99999)) + ->setSubtotalP(15) + ->setParentOrderIdp(00000) // order id of any past payment + ->setParentShopIdp($uniteller->getShopId()); // optional + +$results = $uniteller->recurrent($builder); +``` + +or use plain array + +```php +recurrent([ + 'Order_IDP' => mt_rand(10000, 99999), + // ... other parameters +]); +``` + ### Cancel payment ```php @@ -148,7 +173,7 @@ Receive incoming parameters from gateway and verifying signature. ```php getSignature()->verify('signature_from_post_params', ['all_parameters_from_post'])) { +if (! $uniteller->getSignaturePayment()->verify('signature_from_post_params', ['all_parameters_from_post'])) { return 'invalid_signature'; } ``` diff --git a/README_RU.md b/README_RU.md index 75fd172..fbc8d38 100644 --- a/README_RU.md +++ b/README_RU.md @@ -31,6 +31,7 @@ PHP (5.6+) SDK для интеграции с интернет-эквайрин Реализовано: * оплата (метод `pay`) +* рекуррентные платежи (метод `recurrent`) * отмена (метод `unblock`) * получение результатов * callback (проверка сигнатуры) @@ -41,7 +42,6 @@ PHP (5.6+) SDK для интеграции с интернет-эквайрин * прикрутить валидацию, используя декораторы * добавить билдер для метода `results` * метод `card` -* метод `recurrent` * метод `confirm` ## Установка @@ -100,6 +100,31 @@ $uniteller->payment([ ])->go(); ``` +### Рекуррентный платеж + +```php +setOrderIdp(mt_rand(10000, 99999)) + ->setSubtotalP(15) + ->setParentOrderIdp(00000) // id заказа магазина из ранее оплаченных в uniteller + ->setParentShopIdp($uniteller->getShopId()); // не обязательно задавать, если родительский платеж из того же магазина + +$results = $uniteller->recurrent($builder); +``` + +или + +```php +recurrent([ + 'Order_IDP' => mt_rand(10000, 99999), + // ... +]); +``` + ### Отмена платежа ```php @@ -151,7 +176,7 @@ var_dump($results); ```php getSignature()->verify('signature_from_post_params', ['all_parameters_from_post'])) { +if (! $uniteller->getSignaturePayment()->verify('signature_from_post_params', ['all_parameters_from_post'])) { return 'invalid_signature'; } ``` diff --git a/composer.json b/composer.json index 67a23b1..b57c184 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "require": { "php": ">=5.6", "php-http/httplug": "^1.1", - "php-http/guzzle6-adapter": "^1.1" + "php-http/guzzle6-adapter": "^1.1", + "guzzlehttp/guzzle": "^6.3" }, "require-dev": { "symfony/var-dumper": "^3.2", diff --git a/composer.lock b/composer.lock index 6a8f348..369b3c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "63b3849a3d64b9b08c4c818ab0b2fb07", + "content-hash": "f02e27e2bd4b579761e266c4bdd929bf", "packages": [ { "name": "guzzlehttp/guzzle", - "version": "6.2.3", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", - "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -27,13 +27,16 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -66,7 +69,7 @@ "rest", "web service" ], - "time": "2017-02-28T22:50:30+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -121,16 +124,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/0d6c7ca039329247e4f0f8f8f6506810e8248855", - "reference": "0d6c7ca039329247e4f0f8f8f6506810e8248855", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -182,7 +185,7 @@ "uri", "url" ], - "time": "2017-02-27T10:51:17+00:00" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "php-http/guzzle6-adapter", @@ -404,32 +407,32 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -454,41 +457,47 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22T11:58:36+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.6.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", - "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" - } + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ "clone", "copy", @@ -496,20 +505,20 @@ "object", "object graph" ], - "time": "2017-01-26T22:05:40+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { @@ -550,33 +559,39 @@ "reflection", "static analysis" ], - "time": "2015-12-27T11:43:31+00:00" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -595,24 +610,24 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30T07:12:33+00:00" + "time": "2017-11-30T07:14:17+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2.1", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { - "php": ">=5.5", + "php": "^5.5 || ^7.0", "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { @@ -642,37 +657,37 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25T06:54:22+00:00" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1|^2.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -705,20 +720,20 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.7", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", - "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", "shasum": "" }, "require": { @@ -768,20 +783,20 @@ "testing", "xunit" ], - "time": "2017-03-01T09:12:17+00:00" + "time": "2017-04-02T07:44:40+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -815,7 +830,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -909,29 +924,29 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -954,20 +969,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.15", + "version": "5.7.27", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5" + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b99112aecc01f62acf3d81a3f59646700a1849e5", - "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", + "reference": "b7803aeca3ccb99ad0a506fa80b64cd6a56bbc0c", "shasum": "" }, "require": { @@ -985,14 +1000,14 @@ "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", "sebastian/comparator": "^1.2.4", - "sebastian/diff": "~1.2", + "sebastian/diff": "^1.4.3", "sebastian/environment": "^1.3.4 || ^2.0", "sebastian/exporter": "~2.0", "sebastian/global-state": "^1.1", "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0.3|~2.0", - "symfony/yaml": "~2.1|~3.0" + "sebastian/version": "^1.0.6|^2.0.1", + "symfony/yaml": "~2.1|~3.0|~4.0" }, "conflict": { "phpdocumentor/reflection-docblock": "3.0.2" @@ -1036,20 +1051,20 @@ "testing", "xunit" ], - "time": "2017-03-02T15:22:43+00:00" + "time": "2018-02-01T05:50:59+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", + "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", "shasum": "" }, "require": { @@ -1095,7 +1110,7 @@ "mock", "xunit" ], - "time": "2016-12-08T20:27:08+00:00" + "time": "2017-06-30T09:13:00+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1208,23 +1223,23 @@ }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { @@ -1256,7 +1271,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08T07:14:41+00:00" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -1610,18 +1625,73 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" + }, { "name": "symfony/polyfill-mbstring", - "version": "v1.3.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -1633,7 +1703,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -1667,39 +1737,42 @@ "portable", "shim" ], - "time": "2016-11-14T01:06:16+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.2.6", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "4100f347aff890bc16b0b4b42843b599db257b2d" + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/4100f347aff890bc16b0b4b42843b599db257b2d", - "reference": "4100f347aff890bc16b0b4b42843b599db257b2d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e173954a28a44a32c690815fbe4d0f2eac43accb", + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb", "shasum": "" }, "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, "require-dev": { - "twig/twig": "~1.20|~2.0" + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" }, "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", "ext-symfony_debug": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -1733,27 +1806,31 @@ "debug", "dump" ], - "time": "2017-02-20T13:45:48+00:00" + "time": "2018-06-15T07:47:49+00:00" }, { "name": "symfony/yaml", - "version": "v3.2.6", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" + "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", - "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/80e4bfa9685fc4a09acc4a857ec16974a9cd944e", + "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" }, "require-dev": { - "symfony/console": "~2.8|~3.0" + "symfony/console": "~3.4|~4.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" @@ -1761,7 +1838,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -1788,20 +1865,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-03-07T16:47:02+00:00" + "time": "2018-05-30T07:26:09+00:00" }, { "name": "webmozart/assert", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", "shasum": "" }, "require": { @@ -1838,7 +1915,7 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2018-01-29T19:49:41+00:00" } ], "aliases": [], diff --git a/example/credentials.example.php b/example/credentials.example.php index cf5cc8d..ae32ed0 100644 --- a/example/credentials.example.php +++ b/example/credentials.example.php @@ -5,6 +5,10 @@ * GitHub: Roquie */ +//для дебага +error_reporting(E_ALL); +ini_set('display_errors', 1); + require __DIR__ . '/../vendor/autoload.php'; $uniteller = new \Tmconsulting\Uniteller\Client(); diff --git a/example/index.php b/example/index.php index ac10e00..dc63235 100644 --- a/example/index.php +++ b/example/index.php @@ -9,6 +9,7 @@ $builder = new PaymentBuilder(); $builder + ->useRecurrentPayment() ->setOrderIdp(mt_rand(10000, 99999)) ->setSubtotalP(10) ->setCustomerIdp(mt_rand(10000, 99999)) @@ -22,7 +23,7 @@

Client Payment Sample


Оплатить

- {$uri} + {$uri}

Отмена

/cancel.php diff --git a/example/recurrent.php b/example/recurrent.php new file mode 100644 index 0000000..55da129 --- /dev/null +++ b/example/recurrent.php @@ -0,0 +1,17 @@ +setOrderIdp(mt_rand(10000, 99999)) + ->setSubtotalP(15) + ->setParentOrderIdp(00000) // order id of any past payment + ->setParentShopIdp($uniteller->getShopId()); // optional + +$results = $uniteller->recurrent($builder); + +var_dump($results); diff --git a/src/Client.php b/src/Client.php index 4fef378..209ab6e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -14,10 +14,12 @@ use Tmconsulting\Uniteller\Order\Order; use Tmconsulting\Uniteller\Payment\Payment; use Tmconsulting\Uniteller\Payment\PaymentInterface; +use Tmconsulting\Uniteller\Recurrent\RecurrentRequest; use Tmconsulting\Uniteller\Request\RequestInterface; use Tmconsulting\Uniteller\Results\ResultsRequest; -use Tmconsulting\Uniteller\Signature\Signature; use Tmconsulting\Uniteller\Signature\SignatureInterface; +use Tmconsulting\Uniteller\Signature\SignaturePayment; +use Tmconsulting\Uniteller\Signature\SignatureRecurrent; use GuzzleHttp\Client as GuzzleClient; use Http\Adapter\Guzzle6\Client as GuzzleAdapter; @@ -41,7 +43,12 @@ class Client implements ClientInterface /** * @var SignatureInterface */ - protected $signature; + protected $signaturePayment; + + /** + * @var SignatureInterface + */ + protected $signatureRecurrent; /** * @var RequestInterface @@ -53,6 +60,11 @@ class Client implements ClientInterface */ protected $resultsRequest; + /** + * @var RequestInterface + */ + protected $recurrentRequest; + /** * @var HttpManagerInterface */ @@ -66,7 +78,9 @@ public function __construct() $this->registerPayment(new Payment()); $this->registerCancelRequest(new CancelRequest()); $this->registerResultsRequest(new ResultsRequest()); - $this->registerSignature(new Signature()); + $this->registerRecurrentRequest(new RecurrentRequest()); + $this->registerSignaturePayment(new SignaturePayment()); + $this->registerSignatureRecurrent(new SignatureRecurrent()); } /** @@ -168,13 +182,35 @@ public function registerResultsRequest(RequestInterface $request) return $this; } + /** + * @param RequestInterface $request + * @return $this + */ + public function registerRecurrentRequest(RequestInterface $request) + { + $this->recurrentRequest = $request; + + return $this; + } + + /** + * @param \Tmconsulting\Uniteller\Signature\SignatureInterface $signature + * @return $this + */ + public function registerSignaturePayment(SignatureInterface $signature) + { + $this->signaturePayment = $signature; + + return $this; + } + /** * @param \Tmconsulting\Uniteller\Signature\SignatureInterface $signature * @return $this */ - public function registerSignature(SignatureInterface $signature) + public function registerSignatureRecurrent(SignatureInterface $signature) { - $this->signature = $signature; + $this->signatureRecurrent = $signature; return $this; } @@ -257,12 +293,28 @@ public function getResultsRequest() return $this->resultsRequest; } + /** + * @return \Tmconsulting\Uniteller\Request\RequestInterface + */ + public function getRecurrentRequest() + { + return $this->recurrentRequest; + } + /** * @return \Tmconsulting\Uniteller\Signature\SignatureInterface */ - public function getSignature() + public function getSignaturePayment() { - return $this->signature; + return $this->signaturePayment; + } + + /** + * @return \Tmconsulting\Uniteller\Signature\SignatureInterface + */ + public function getSignatureRecurrent() + { + return $this->signatureRecurrent; } /** @@ -282,22 +334,20 @@ public function getHttpManager() public function payment($parameters) { $array = $this->getParameters($parameters); - $array['Shop_IDP'] = $this->getShopId(); - $array['Password'] = $this->getPassword(); - - $array['Signature'] = $this->signature->create([ - 'Shop_IDP' => array_get($array, 'Shop_IDP'), - 'Order_IDP' => array_get($array, 'Order_IDP'), - 'Subtotal_P' => array_get($array, 'Subtotal_P'), - 'MeanType' => array_get($array, 'MeanType'), - 'EMoneyType' => array_get($array, 'EMoneyType'), - 'Lifetime' => array_get($array, 'Lifetime'), - 'Customer_IDP' => array_get($array, 'Customer_IDP'), - 'Card_IDP' => array_get($array, 'Card_IDP'), - 'IData' => array_get($array, 'IData'), - 'PT_Code' => array_get($array, 'PT_Code'), - 'Password' => array_get($array, 'Password'), - ]); + $array['Shop_IDP'] = $this->getShopId(); + $array['Signature'] = $this->signaturePayment + ->setShopIdp(array_get($array, 'Shop_IDP')) + ->setOrderIdp(array_get($array, 'Order_IDP')) + ->setSubtotalP(array_get($array, 'Subtotal_P')) + ->setMeanType(array_get($array, 'MeanType')) + ->setEMoneyType(array_get($array, 'EMoneyType')) + ->setLifeTime(array_get($array, 'Lifetime')) + ->setCustomerIdp(array_get($array, 'Customer_IDP')) + ->setCardIdp(array_get($array, 'Card_IDP')) + ->setIData(array_get($array, 'IData')) + ->setPtCode(array_get($array, 'PT_Code')) + ->setPassword($this->getPassword()) + ->create(); return $this->getPayment()->execute($array, $this->getOptions()); } @@ -324,15 +374,28 @@ public function results($parameters) } /** - * @param array $parameters + * @param \Tmconsulting\Uniteller\Recurrent\RecurrentBuilder|array $parameters * @return mixed * @throws \Tmconsulting\Uniteller\Exception\NotImplementedException */ - public function reccurent($parameters) + public function recurrent($parameters) { - throw new NotImplementedException(sprintf( - 'In current moment, feature [%s] not implemented.', __METHOD__ - )); + $array = $this->getParameters($parameters); + $array['Shop_IDP'] = $this->getShopId(); + + $this->signatureRecurrent + ->setShopIdp(array_get($array, 'Shop_IDP')) + ->setOrderIdp(array_get($array, 'Order_IDP')) + ->setSubtotalP(array_get($array, 'Subtotal_P')) + ->setParentOrderIdp(array_get($array, 'Parent_Order_IDP')) + ->setPassword($this->getPassword()); + if (array_get($array, 'Parent_Shop_IDP')) { + $this->signatureRecurrent->setParentShopIdp(array_get($array, 'Parent_Shop_IDP')); + } + + $array['Signature'] = $this->signatureRecurrent->create(); + + return $this->callRequestFor('recurrent', $array); } /** diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 487424f..a7f66df 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -39,7 +39,7 @@ public function results($parameters); * @param array $parameters * @return mixed */ - public function reccurent($parameters); + public function recurrent($parameters); /** * @param array $parameters diff --git a/src/Error/Error.php b/src/Error/Error.php index 6ef99f4..7835146 100644 --- a/src/Error/Error.php +++ b/src/Error/Error.php @@ -62,7 +62,7 @@ class Error * Recurrent payment not allowed * Магазин не поддерживает рекуррентные платежи */ - const RECCURENT_PAY_NOT_ALLOWED = 22; + const RECURENT_PAY_NOT_ALLOWED = 22; /** * Incorrect Parent_Order_IDP diff --git a/src/Http/HttpManager.php b/src/Http/HttpManager.php index 31ee540..e14137c 100644 --- a/src/Http/HttpManager.php +++ b/src/Http/HttpManager.php @@ -14,6 +14,7 @@ use Psr\Http\Message\ResponseInterface; use Tmconsulting\Uniteller\Exception\ExceptionFactory; use Tmconsulting\Uniteller\Exception\UnitellerException; +use function Tmconsulting\Uniteller\csv_to_array; /** * Class HttpManager @@ -44,38 +45,60 @@ public function __construct(HttpClient $httpClient, array $options = []) $this->options = $options; } + /** + * @param string $format + * @return array + */ + protected function getDefaultHeaders($format) + { + $headers = [ + 'Content-Type' => 'application/x-www-form-urlencoded', + ]; + + switch ($format) { + case 'xml': + $headers['Accept'] = 'application/xml'; + break; + case 'csv': + $headers['Accept'] = 'text/csv'; + break; + case 'json': + $headers['Accept'] = 'application/json'; + break; + } + + return $headers; + } + /** * @param $uri * @param string $method * @param null $data * @param array $headers + * @param string $format * @return \Psr\Http\Message\ResponseInterface */ - public function request($uri, $method = 'POST', $data = null, array $headers = []) + public function request($uri, $method = 'POST', $data = null, array $headers = [], $format='xml') { $uri = sprintf('%s/%s?%s', $this->options['base_uri'], $uri, http_build_query([ 'Shop_ID' => $this->options['shop_id'], 'Login' => $this->options['login'], 'Password' => $this->options['password'], - 'Format' => Format::resolveXml($uri), + 'Format' => Format::{"resolve$format"}($uri), ])); - $defaultHeaders = [ - 'Accept' => 'application/xml', - 'Content-Type' => 'application/x-www-form-urlencoded', - ]; - - $request = new Request($method, $uri, array_merge($defaultHeaders, $headers), $data); + $request = new Request($method, $uri, array_merge($this->getDefaultHeaders($format), $headers), $data); try { $response = $this->httpClient->sendRequest($request); - } catch (RequestException $e) { + } + catch (RequestException $e) { throw UnitellerException::create($request, $e->getResponse()); } $this->basicError($request, $response); $body = $response->getBody()->getContents(); - $this->providerError($body, $request, $response); + $this->providerError($body, $request, $response, $format); return $body; } @@ -86,24 +109,38 @@ public function request($uri, $method = 'POST', $data = null, array $headers = [ * @param $response * @throws \ErrorException */ - protected function providerError($body, RequestInterface $request, ResponseInterface $response) + protected function providerError($body, RequestInterface $request, ResponseInterface $response, $format='xml') { - if (substr($body, 0, 6) === 'ERROR:') { - throw ExceptionFactory::createFromMessage( - substr($body, 7), $request, $response - ); - } + if ($format === 'csv') { + $data = csv_to_array($body, true); + + if (isset($data['ErrorMessage'])) { + throw ExceptionFactory::createFromMessage( + $data['ErrorMessage'], $request, $response + ); + } - $xml = new \SimpleXMLElement((string) $body); - if (($firstCode = (string) $xml->attributes()['firstcode']) == 0) { - return; } + elseif ($format === 'xml') { - $secondCode = (string) $xml->attributes()['secondcode']; + if (substr($body, 0, 6) === 'ERROR:') { + throw ExceptionFactory::createFromMessage( + substr($body, 7), $request, $response + ); + } - throw ExceptionFactory::create( - $firstCode, $secondCode, $request, $response - ); + $xml = new \SimpleXMLElement((string)$body); + if (($firstCode = (string)$xml->attributes()['firstcode']) == 0) { + return; + } + + $secondCode = (string)$xml->attributes()['secondcode']; + + throw ExceptionFactory::create( + $firstCode, $secondCode, $request, $response + ); + + } } /** diff --git a/src/Order/Order.php b/src/Order/Order.php index 0bfe83a..64e7f76 100644 --- a/src/Order/Order.php +++ b/src/Order/Order.php @@ -291,6 +291,11 @@ class Order implements ArraybleInterface */ protected $packetDate; + /** + * @var string + */ + protected $signature; + /** * @param string $address @@ -466,6 +471,8 @@ public function setDate($date) } // Ёбаный насрать, а даты зачем разного формата отдавать? + // Полностью разделяю и поддерживаю данное негодование, значит ебашим костыли)) + $date = str_replace('.', '-', $date); $this->date = DateTime::createFromFormat('U', strtotime($date)); return $this; @@ -1046,6 +1053,8 @@ public function setPacketDate($packetDate) } // 10.03.2017 15:42:42 - o_O + // 2018.07.16 10:54:05 - O_o + $packetDate = str_replace('.', '-', $packetDate); $this->packetDate = DateTime::createFromFormat('U', strtotime($packetDate)); return $this; @@ -1059,6 +1068,25 @@ public function getPacketDate() return $this->packetDate; } + /** + * @return string + */ + public function getSignature() + { + return $this->signature; + } + + /** + * @param string $signature + * @return Order + */ + public function setSignature($signature) + { + $this->signature = $signature; + + return $this; + } + /** * @return array */ @@ -1104,6 +1132,7 @@ public function toArray() 'Response_Message' => $this->getResponseMessage(), 'Status' => $this->getStatus(), 'Total' => $this->getTotal(), + 'Signature' => $this->getSignature(), ]; } } \ No newline at end of file diff --git a/src/Recurrent/RecurrentBuilder.php b/src/Recurrent/RecurrentBuilder.php new file mode 100644 index 0000000..fa0f6ad --- /dev/null +++ b/src/Recurrent/RecurrentBuilder.php @@ -0,0 +1,174 @@ +shopIdp = $shopIdp; + + return $this; + } + + /** + * @param string $orderIdp + * @return RecurrentBuilder + */ + public function setOrderIdp($orderIdp) + { + $this->orderIdp = $orderIdp; + + return $this; + } + + /** + * @param float|string $subtotalP + * @return RecurrentBuilder + */ + public function setSubtotalP($subtotalP) + { + $this->subtotalP = $subtotalP; + + return $this; + } + + /** + * @param string $parentOrderIdp + * @return RecurrentBuilder + */ + public function setParentOrderIdp($parentOrderIdp) + { + $this->parentOrderIdp = $parentOrderIdp; + + return $this; + } + + /** + * @param string $parentShopIdp + * @return RecurrentBuilder + */ + public function setParentShopIdp($parentShopIdp) + { + $this->parentShopIdp = $parentShopIdp; + + return $this; + } + + /** + * @return string + */ + public function getShopIdp() + { + return $this->shopIdp; + } + + /** + * @return string + */ + public function getOrderIdp() + { + return $this->orderIdp; + } + + /** + * @return float|string + */ + public function getSubtotalP() + { + return $this->subtotalP; + } + + /** + * @return string + */ + public function getParentOrderIdp() + { + return $this->parentOrderIdp; + } + + /** + * @return string + */ + public function getParentShopIdp() + { + return $this->parentShopIdp; + } + + /** + * @return array + */ + public function toArray() + { + return [ + 'Shop_IDP' => $this->getShopIdp(), + 'Parent_Shop_IDP' => $this->getParentShopIdp(), + 'Order_IDP' => $this->getOrderIdp(), + 'Parent_Order_IDP' => $this->getParentOrderIdp(), + 'Subtotal_P' => $this->getSubtotalP(), + ]; + } +} \ No newline at end of file diff --git a/src/Recurrent/RecurrentRequest.php b/src/Recurrent/RecurrentRequest.php new file mode 100644 index 0000000..ecc73f7 --- /dev/null +++ b/src/Recurrent/RecurrentRequest.php @@ -0,0 +1,79 @@ +request('recurrent', 'POST', http_build_query($parameters), [], 'csv'); + $csv = Uniteller\csv_to_array($response); + $array = []; + foreach ($csv as $item) { + $array[] = (new Order()) + ->setAddress(Uniteller\array_get($item, 'Address')) + ->setApprovalCode(Uniteller\array_get($item, 'ApprovalCode')) + ->setBankName(Uniteller\array_get($item, 'BankName')) + ->setBillNumber(Uniteller\array_get($item, 'BillNumber')) + //->setBookingcomId(Uniteller\array_get($item, 'bookingcom_id')) + //->setBookingcomPincode(Uniteller\array_get($item, 'bookingcom_pincode')) + //->setCardIdp(Uniteller\array_get($item, 'card_idp')) + ->setCardHolder(Uniteller\array_get($item, 'CardHolder')) + ->setCardNumber(Uniteller\array_get($item, 'CardNumber')) + ->setCardType(Uniteller\array_get($item, 'CardType')) + ->setComment(Uniteller\array_get($item, 'Comment')) + ->setCurrency(Uniteller\array_get($item, 'Currency')) + ->setCvc2((bool)Uniteller\array_get($item, 'CVC2', false)) + ->setDate(Uniteller\array_get($item, 'Date')) + ->setEmail(Uniteller\array_get($item, 'Email')) + //->setEMoneyType(Uniteller\array_get($item, 'emoneytype')) + //->setEOrderData(Uniteller\array_get($item, 'eorderdata')) + ->setErrorCode(Uniteller\array_get($item, 'Error_Code')) + ->setErrorComment(Uniteller\array_get($item, 'Error_Comment')) + ->setFirstName(Uniteller\array_get($item, 'FirstName')) + //->setGdsPaymentPurposeId(Uniteller\array_get($item, 'gds_payment_purpose_id')) + //->setIData(Uniteller\array_get($item, 'idata')) + ->setIp(Uniteller\array_get($item, 'IPAddress')) + ->setLastName(Uniteller\array_get($item, 'LastName')) + //->setLoanId(Uniteller\array_get($item, 'loan_id')) + ->setMessage(Uniteller\array_get($item, 'Message')) + ->setMiddleName(Uniteller\array_get($item, 'MiddleName')) + //->setNeedConfirm((bool)Uniteller\array_get($item, 'need_confirm')) + ->setOrderNumber(Uniteller\array_get($item, 'OrderNumber')) + //->setParentOrderNumber(Uniteller\array_get($item, 'parent_order_number')) + ->setPaymentType(Uniteller\array_get($item, 'PaymentType')) + ->setPhone(Uniteller\array_get($item, 'Phone')) + //->setPtCode(Uniteller\array_get($item, 'pt_code')) + ->setRecommendation(Uniteller\array_get($item, 'Recommendation')) + ->setResponseCode(Uniteller\array_get($item, 'Response_Code')) + ->setStatus(Uniteller\array_get($item, 'Status')) + ->setTotal(Uniteller\array_get($item, 'Total')) + ->setPacketDate(Uniteller\array_get($item, 'PacketDate')) + ->setSignature(Uniteller\array_get($item, 'Signature')); + } + + return $array; + } +} \ No newline at end of file diff --git a/src/Signature/Signature.php b/src/Signature/AbstractSignature.php similarity index 55% rename from src/Signature/Signature.php rename to src/Signature/AbstractSignature.php index 3c8e7df..43f5cec 100644 --- a/src/Signature/Signature.php +++ b/src/Signature/AbstractSignature.php @@ -7,38 +7,27 @@ namespace Tmconsulting\Uniteller\Signature; + +use Tmconsulting\Uniteller\ArraybleInterface; + /** * Class Signature * * @package Tmconsulting\Client */ -final class Signature implements SignatureInterface +abstract class AbstractSignature implements SignatureInterface, ArraybleInterface { + /** * Create signature for send payment request. * - * @param array $params * @return string */ - public function create(array $params) + public function create() { - $defaults = [ - 'Shop_IDP' => '', - 'Order_IDP' => '', - 'Subtotal_P' => '', - 'MeanType' => '', - 'EMoneyType' => '', - 'Lifetime' => '', - 'Customer_IDP' => '', - 'Card_IDP' => '', - 'IData' => '', - 'PT_Code' => '', - 'Password' => '', - ]; - $string = join('&', array_map(function ($item) { return md5($item); - }, array_merge($defaults, $params))); + }, $this->toArray())); return strtoupper(md5($string)); } diff --git a/src/Signature/SignatureInterface.php b/src/Signature/SignatureInterface.php index 5f46c37..ed949b0 100644 --- a/src/Signature/SignatureInterface.php +++ b/src/Signature/SignatureInterface.php @@ -17,10 +17,9 @@ interface SignatureInterface /** * Create signature for send payment request. * - * @param array $params * @return string */ - public function create(array $params); + public function create(); /** * Verify signature when Client will be send callback request. diff --git a/src/Signature/SignaturePayment.php b/src/Signature/SignaturePayment.php new file mode 100644 index 0000000..f7fd6fe --- /dev/null +++ b/src/Signature/SignaturePayment.php @@ -0,0 +1,302 @@ +shopIdp = $shopIdp; + + return $this; + } + + /** + * @param string $orderIdp + * @return SignaturePayment + */ + public function setOrderIdp($orderIdp) + { + $this->orderIdp = $orderIdp; + + return $this; + } + + /** + * @param string $subtotalP + * @return SignaturePayment + */ + public function setSubtotalP($subtotalP) + { + $this->subtotalP = $subtotalP; + + return $this; + } + + /** + * @param string $meanType + * @return SignaturePayment + */ + public function setMeanType($meanType) + { + $this->meanType = $meanType; + + return $this; + } + + /** + * @param string $eMoneyType + * @return SignaturePayment + */ + public function setEMoneyType($eMoneyType) + { + $this->eMoneyType = $eMoneyType; + + return $this; + } + + /** + * @param string $lifeTime + * @return SignaturePayment + */ + public function setLifeTime($lifeTime) + { + $this->lifeTime = $lifeTime; + + return $this; + } + + /** + * @param string $customerIdp + * @return SignaturePayment + */ + public function setCustomerIdp($customerIdp) + { + $this->customerIdp = $customerIdp; + + return $this; + } + + /** + * @param string $cardIdp + * @return SignaturePayment + */ + public function setCardIdp($cardIdp) + { + $this->cardIdp = $cardIdp; + + return $this; + } + + /** + * @param string $iData + * @return SignaturePayment + */ + public function setIData($iData) + { + $this->iData = $iData; + + return $this; + } + + /** + * @param string $ptCode + * @return SignaturePayment + */ + public function setPtCode($ptCode) + { + $this->ptCode = $ptCode; + + return $this; + } + + /** + * @param string $password + * @return SignaturePayment + */ + public function setPassword($password) + { + $this->password = $password; + + return $this; + } + + /** + * @return string + */ + public function getShopIdp() + { + return $this->shopIdp; + } + + /** + * @return string + */ + public function getOrderIdp() + { + return $this->orderIdp; + } + + /** + * @return string + */ + public function getSubtotalP() + { + return $this->subtotalP; + } + + /** + * @return string + */ + public function getMeanType() + { + return $this->meanType; + } + + /** + * @return string + */ + public function getEMoneyType() + { + return $this->eMoneyType; + } + + /** + * @return string + */ + public function getLifeTime() + { + return $this->lifeTime; + } + + /** + * @return string + */ + public function getCustomerIdp() + { + return $this->customerIdp; + } + + /** + * @return string + */ + public function getCardIdp() + { + return $this->cardIdp; + } + + /** + * @return string + */ + public function getIData() + { + return $this->iData; + } + + /** + * @return string + */ + public function getPtCode() + { + return $this->ptCode; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @return array + */ + public function toArray() + { + $array = []; + $array['Shop_IDP'] = $this->getShopIdp(); + $array['Order_IDP'] = $this->getOrderIdp(); + $array['Subtotal_P'] = $this->getSubtotalP(); + $array['MeanType'] = $this->getMeanType(); + $array['EMoneyType'] = $this->getEMoneyType(); + $array['Lifetime'] = $this->getLifeTime(); + $array['Customer_IDP'] = $this->getCustomerIdp(); + $array['Card_IDP'] = $this->getCardIdp(); + $array['IData'] = $this->getIData(); + $array['PT_Code'] = $this->getPtCode(); + $array['Password'] = $this->getPassword(); + + return $array; + } +} \ No newline at end of file diff --git a/src/Signature/SignatureRecurrent.php b/src/Signature/SignatureRecurrent.php new file mode 100644 index 0000000..adb9a1d --- /dev/null +++ b/src/Signature/SignatureRecurrent.php @@ -0,0 +1,179 @@ +shopIdp = $shopIdp; + + return $this; + } + + /** + * @param string $parentShopIdp + * @return SignatureRecurrent + */ + public function setParentShopIdp($parentShopIdp) + { + $this->parentShopIdp = $parentShopIdp; + + return $this; + } + + /** + * @param string $orderIdp + * @return SignatureRecurrent + */ + public function setOrderIdp($orderIdp) + { + $this->orderIdp = $orderIdp; + + return $this; + } + + /** + * @param string $subtotalP + * @return SignatureRecurrent + */ + public function setSubtotalP($subtotalP) + { + $this->subtotalP = $subtotalP; + + return $this; + } + + /** + * @param string $parentOrderIdp + * @return SignatureRecurrent + */ + public function setParentOrderIdp($parentOrderIdp) + { + $this->parentOrderIdp = $parentOrderIdp; + + return $this; + } + + /** + * @param string $password + * @return SignatureRecurrent + */ + public function setPassword($password) + { + $this->password = $password; + + return $this; + } + + /** + * @return string + */ + public function getShopIdp() + { + return $this->shopIdp; + } + + /** + * @return string + */ + public function getParentShopIdp() + { + return $this->parentShopIdp; + } + + /** + * @return string + */ + public function getOrderIdp() + { + return $this->orderIdp; + } + + /** + * @return string + */ + public function getSubtotalP() + { + return $this->subtotalP; + } + + /** + * @return string + */ + public function getParentOrderIdp() + { + return $this->parentOrderIdp; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @return array + */ + public function toArray() + { + $array = []; + $array['Shop_IDP'] = $this->getShopIdp(); + if($this->getParentShopIdp() !== null) + $array['Parent_Shop_IDP'] = $this->getParentShopIdp(); + $array['Order_IDP'] = $this->getOrderIdp(); + $array['Subtotal_P'] = $this->getSubtotalP(); + $array['Parent_Order_IDP'] = $this->getParentOrderIdp(); + $array['Password'] = $this->getPassword(); + + return $array; + } +} \ No newline at end of file diff --git a/src/helpers.php b/src/helpers.php index 2f9dd0a..ad2a671 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -39,4 +39,29 @@ function xml_get($object, $key, $default = null) } return (string) $object->{$key}; +} + +/** + * @param string $string + * @param bool $isFlat + * @return array|mixed + */ +function csv_to_array($string, $isFlat = false) +{ + $lines = explode("\n", trim($string)); + $headers = str_getcsv(array_shift($lines), ';'); + $data = []; + foreach ($lines as $line) { + $row = []; + foreach (str_getcsv($line, ';') as $key => $field) { + $row[$headers[$key]] = $field; + } + $data[] = array_filter($row); + } + + if ($isFlat && !empty($data)) { + $data = $data[0]; + } + + return $data; } \ No newline at end of file diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 054d027..844d5b9 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -47,7 +47,8 @@ public function testDefaultObjectsIsRegistered() { $uniteller = new Client(); $this->assertInstanceOf(PaymentInterface::class, $uniteller->getPayment()); - $this->assertInstanceOf(SignatureInterface::class, $uniteller->getSignature()); + $this->assertInstanceOf(SignatureInterface::class, $uniteller->getSignaturePayment()); + $this->assertInstanceOf(SignatureInterface::class, $uniteller->getSignatureRecurrent()); } public function testSetOptionsUseArrayNotation() @@ -123,9 +124,11 @@ public function testCanRequestMethodsMayReturnCorrectResult() $client = new Client(); $client->registerCancelRequest($this->createMock(RequestInterface::class)); $client->registerResultsRequest($this->createMock(RequestInterface::class)); + $client->registerRecurrentRequest($this->createMock(RequestInterface::class)); $this->assertInstanceOf(RequestInterface::class, $client->getCancelRequest()); $this->assertInstanceOf(RequestInterface::class, $client->getResultsRequest()); + $this->assertInstanceOf(RequestInterface::class, $client->getRecurrentRequest()); } public function testShouldBePaymentMethodBuildCorrectArray() @@ -136,7 +139,6 @@ public function testShouldBePaymentMethodBuildCorrectArray() ->method('execute') ->willReturnCallback(function ($array) { $this->assertArrayHasKey('Shop_IDP', $array); - $this->assertArrayHasKey('Password', $array); $this->assertArrayHasKey('Signature', $array); }); @@ -160,6 +162,7 @@ public function testCanCancelMethodGiveControlToTheRequestClass() $client = new Client(); $client->registerCancelRequest($request); $client->registerResultsRequest($request); + $client->registerRecurrentRequest($request); $client->cancel([]); $client->results([]); @@ -189,7 +192,6 @@ public function testCanUseCustomHttpManager() public function provideUnsupportedRequestMethods() { return [ - ['reccurent'], ['confirm'], ['card'], ]; @@ -228,6 +230,7 @@ public function testShouldBeActionsAcceptClassesWhichImplementArraybleInterface( $client = new Client(); $client->registerResultsRequest($request); $client->registerCancelRequest($request); + $client->registerRecurrentRequest($request); $client->registerPayment($this->createMock(PaymentInterface::class)); $arrayble = $this->createMock(ArraybleInterface::class); diff --git a/tests/Recurrent/RecurrentBuilderTest.php b/tests/Recurrent/RecurrentBuilderTest.php new file mode 100644 index 0000000..794d8a5 --- /dev/null +++ b/tests/Recurrent/RecurrentBuilderTest.php @@ -0,0 +1,34 @@ +setShopIdp('FOO'); + $builder->setParentShopIdp('BAR'); + $builder->setOrderIdp('BAZ'); + $builder->setParentOrderIdp('old'); + $builder->setSubtotalP(10); + + $expected = [ + 'Shop_IDP' => 'FOO', + 'Parent_Shop_IDP' => 'BAR', + 'Order_IDP' => 'BAZ', + 'Parent_Order_IDP' => 'old', + 'Subtotal_P' => 10, + ]; + + $this->assertEquals($expected, $builder->toArray()); + } +} \ No newline at end of file diff --git a/tests/Recurrent/RecurrentRequestTest.php b/tests/Recurrent/RecurrentRequestTest.php new file mode 100644 index 0000000..59e8daa --- /dev/null +++ b/tests/Recurrent/RecurrentRequestTest.php @@ -0,0 +1,70 @@ +createMock(HttpManagerInterface::class); + $manager + ->expects($this->once()) + ->method('request') + ->willReturn($this->getStubContents('recurrent', 'csv')); + + $request = new RecurrentRequest(); + /** @var \Tmconsulting\Uniteller\Order\Order $order */ + foreach ($request->execute($manager) as $order) { + $this->assertInstanceOf(Order::class, $order); + $this->assertEquals('Value of address', $order->getAddress()); + $this->assertEquals('Value of approvalCode', $order->getApprovalCode()); + $this->assertEquals('Value of bankName', $order->getBankName()); + $this->assertEquals('Value of billNumber', $order->getBillNumber()); + $this->assertEquals(null, $order->getBookingcomId()); + $this->assertEquals(null, $order->getBookingcomPincode()); + $this->assertEquals(null, $order->getCardIdp()); + $this->assertEquals('Value of cardHolder', $order->getCardHolder()); + $this->assertEquals('Value of cardNumber', $order->getCardNumber()); + $this->assertEquals('Value of cardType', $order->getCardType()); + $this->assertEquals('Value of comment', $order->getComment()); + $this->assertEquals('Value of currency', $order->getCurrency()); + $this->assertEquals(true, $order->isCvc2()); + $this->assertInstanceOf(\DateTime::class, $order->getDate()); + $this->assertEquals('Value of email', $order->getEmail()); + $this->assertEquals(null, $order->getEMoneyType()); + $this->assertEquals(null, $order->getEOrderData()); + $this->assertEquals('Value of error_code', $order->getErrorCode()); + $this->assertEquals('Value of error_comment', $order->getErrorComment()); + $this->assertEquals('Value of firstName', $order->getFirstName()); + $this->assertEquals(null, $order->getGdsPaymentPurposeId()); + $this->assertEquals(null, $order->getIData()); + $this->assertEquals('Value of ipAddress', $order->getIp()); + $this->assertEquals('Value of lastName', $order->getLastName()); + $this->assertEquals(null, $order->getLoanId()); + $this->assertEquals('Value of message', $order->getMessage()); + $this->assertEquals('Value of middleName', $order->getMiddleName()); + $this->assertEquals(false, $order->isNeedConfirm()); + $this->assertEquals('Value of orderNumber', $order->getOrderNumber()); + $this->assertEquals(null, $order->getParentOrderNumber()); + $this->assertEquals('Value of paymentType', $order->getPaymentType()); + $this->assertEquals('Value of phone', $order->getPhone()); + $this->assertEquals(null, $order->getPtCode()); + $this->assertEquals('Value of recommendation', $order->getRecommendation()); + $this->assertEquals('Value of response_code', $order->getResponseCode()); + $this->assertEquals(Status::AUTHORIZED, $order->getStatus()); + $this->assertEquals('Value of total', $order->getTotal()); + $this->assertInstanceOf(\DateTime::class, $order->getPacketDate()); + } + } +} \ No newline at end of file diff --git a/tests/Signature/SignatureTest.php b/tests/Signature/SignatureTest.php index c1a8ba7..8e550e4 100644 --- a/tests/Signature/SignatureTest.php +++ b/tests/Signature/SignatureTest.php @@ -7,30 +7,43 @@ namespace Tmconsulting\Uniteller\Tests\Signature; -use Tmconsulting\Uniteller\Signature\Signature; +use Tmconsulting\Uniteller\Signature\SignaturePayment; +use Tmconsulting\Uniteller\Signature\SignatureRecurrent; use Tmconsulting\Uniteller\Tests\TestCase; class SignatureTest extends TestCase { - public function testSignatureCreation() + public function testPaymentSignatureCreation() { - $sig = new Signature; - - $created = $sig->create([ - 'Shop_IDP' => 'ACME', - 'Order_IDP' => 'FOO', - 'Subtotal_P' => '100', - 'Lifetime' => 300, - 'Customer_IDP' => 'short_shop_string', - 'Password' => 'LONG-PWD', - ]); + $sig = (new SignaturePayment) + ->setShopIdp('ACME') + ->setOrderIdp('FOO') + ->setSubtotalP(100) + ->setLifeTime(300) + ->setCustomerIdp('short_shop_string') + ->setPassword('LONG-PWD') + ->create(); + + $this->assertSame('3D1D6F830384886A81AD672F66392B03', $sig); + } - $this->assertSame('3D1D6F830384886A81AD672F66392B03', $created); + + public function testRecurrentSignatureCreation() + { + $sig = (new SignatureRecurrent()) + ->setShopIdp('ACME') + ->setOrderIdp('FOO') + ->setSubtotalP(100) + ->setParentOrderIdp('BAR') + ->setPassword('LONG-PWD') + ->create(); + + $this->assertSame('A5FE1C95A2819EBACFC2145EE83742F6', $sig); } public function testSignatureVerifying() { - $sig = new Signature; + $sig = new SignaturePayment; $results = $sig->verify('3F728AA479E50F5B10EE6C20258BFF88', [ 'Order_ID' => 'FOO', diff --git a/tests/TestCase.php b/tests/TestCase.php index f0b63ee..50ea4de 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -8,10 +8,11 @@ class TestCase extends PHPUnit_Framework_TestCase { /** * @param $filename + * @param string $type * @return bool|string */ - protected function getStubContents($filename) + protected function getStubContents($filename, $type='xml') { - return file_get_contents(__DIR__ . "/stub/$filename.xml"); + return file_get_contents(__DIR__ . "/stub/$filename.$type"); } } \ No newline at end of file diff --git a/tests/stub/recurrent.csv b/tests/stub/recurrent.csv new file mode 100644 index 0000000..a2fa330 --- /dev/null +++ b/tests/stub/recurrent.csv @@ -0,0 +1,2 @@ +OrderNumber;Response_Code;Recommendation;Message;Comment;Date;Total;Currency;CardType;CardNumber;LastName;FirstName;MiddleName;Address;Email;ApprovalCode;CVC2;CardHolder;IPAddress;BillNumber;BankName;Status;Error_Code;Error_Comment;PacketDate;PaymentType;Phone;Signature +Value of orderNumber;Value of response_code;Value of recommendation;Value of message;Value of comment;2018.07.16 10:54:05;Value of total;Value of currency;Value of cardType;Value of cardNumber;Value of lastName;Value of firstName;Value of middleName;Value of address;Value of email;Value of approvalCode;true;Value of cardHolder;Value of ipAddress;Value of billNumber;Value of bankName;authorized;Value of error_code;Value of error_comment;2018.07.16 10:54:05;Value of paymentType;Value of phone;Value of signature \ No newline at end of file