From ab9fb47a848656a4ee91079f1fbc78399b401174 Mon Sep 17 00:00:00 2001 From: Thomas Faurbye Nielsen Date: Thu, 14 Jul 2016 16:45:29 +0200 Subject: [PATCH 1/2] Add a method for using the link facility quickpay provides. http://tech.quickpay.net/payments/link/ --- .gitignore | 3 +- composer.json | 8 +- composer.lock | 1056 +++++++++++++++++ phpunit.xml.dist | 25 + src/Gateway.php | 741 ++++++------ src/Message/CompleteRequest.php | 58 +- src/Message/LinkRequest.php | 105 ++ src/Message/LinkResponse.php | 69 ++ src/Message/Notification.php | 2 +- src/Message/PurchaseRequest.php | 226 ++-- tests/GatewayTest.php | 112 ++ tests/Message/AuthorizeRequestTest.php | 40 + tests/Message/CompleteRequestTest.php | 78 ++ tests/Message/LinkRequestTest.php | 112 ++ tests/Message/NotificationTest.php | 127 ++ .../LinkRequestCreatePaymentLinkFailure.txt | 10 + .../LinkRequestCreatePaymentLinkSuccess.txt | 12 + .../Mock/LinkRequestCreatePaymentSuccess.txt | 13 + 18 files changed, 2299 insertions(+), 498 deletions(-) create mode 100644 composer.lock create mode 100644 phpunit.xml.dist create mode 100644 src/Message/LinkRequest.php create mode 100644 src/Message/LinkResponse.php create mode 100644 tests/GatewayTest.php create mode 100644 tests/Message/AuthorizeRequestTest.php create mode 100644 tests/Message/CompleteRequestTest.php create mode 100644 tests/Message/LinkRequestTest.php create mode 100644 tests/Message/NotificationTest.php create mode 100644 tests/Mock/LinkRequestCreatePaymentLinkFailure.txt create mode 100644 tests/Mock/LinkRequestCreatePaymentLinkSuccess.txt create mode 100644 tests/Mock/LinkRequestCreatePaymentSuccess.txt diff --git a/.gitignore b/.gitignore index 57f1cb2..ce0c956 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/.idea/ \ No newline at end of file +/.idea/ +vendor/ diff --git a/composer.json b/composer.json index 43db41a..41b18cb 100644 --- a/composer.json +++ b/composer.json @@ -21,5 +21,11 @@ "autoload": { "psr-4": { "Omnipay\\Quickpay\\" : "src/" } }, - "minimum-stability": "dev" + "minimum-stability": "dev", + "require": { + "omnipay/common": "~2.0" + }, + "require-dev": { + "omnipay/tests": "~2.0" + } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..26db357 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1056 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "e7d505d8648456964b3528bbc2776fbf", + "content-hash": "b522cc874142165d1584bedc6e799fe4", + "packages": [ + { + "name": "guzzle/guzzle", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle3.git", + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "reference": "b3f5050cb6270c7a728a0b74ac2de50a262b3e02", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.3", + "symfony/event-dispatcher": "~2.1" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-error-response": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/cache": "~1.3", + "monolog/monolog": "~1.0", + "phpunit/phpunit": "3.7.*", + "psr/log": "~1.0", + "symfony/class-loader": "~2.1", + "zendframework/zend-cache": "2.*,<2.3", + "zendframework/zend-log": "2.*,<2.3" + }, + "suggest": { + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.9-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle": "src/", + "Guzzle\\Tests": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "abandoned": "guzzlehttp/guzzle", + "time": "2015-04-29 17:06:53" + }, + { + "name": "omnipay/common", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/omnipay-common.git", + "reference": "731386e54688405a475d6dd43cd6397728cd709e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/omnipay-common/zipball/731386e54688405a475d6dd43cd6397728cd709e", + "reference": "731386e54688405a475d6dd43cd6397728cd709e", + "shasum": "" + }, + "require": { + "guzzle/guzzle": "~3.9", + "php": ">=5.3.2", + "symfony/http-foundation": "~2.1|~3.0" + }, + "require-dev": { + "omnipay/tests": "~2.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + }, + "gateways": [ + "AuthorizeNet_AIM", + "AuthorizeNet_SIM", + "Buckaroo_CreditCard", + "Buckaroo_Ideal", + "Buckaroo_PayPal", + "CardSave", + "Coinbase", + "Dummy", + "Eway_Rapid", + "FirstData_Connect", + "GoCardless", + "Manual", + "Migs_ThreeParty", + "Migs_TwoParty", + "Mollie", + "MultiSafepay", + "Netaxept", + "NetBanx", + "PayFast", + "Payflow_Pro", + "PaymentExpress_PxPay", + "PaymentExpress_PxPost", + "PayPal_Express", + "PayPal_Pro", + "Pin", + "SagePay_Direct", + "SagePay_Server", + "SecurePay_DirectPost", + "Stripe", + "TargetPay_Directebanking", + "TargetPay_Ideal", + "TargetPay_Mrcash", + "WorldPay" + ] + }, + "autoload": { + "psr-0": { + "Omnipay\\Common\\": "src/" + }, + "classmap": [ + "src/Omnipay/Omnipay.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Adrian Macneil", + "email": "adrian@adrianmacneil.com" + }, + { + "name": "Omnipay Contributors", + "homepage": "https://github.com/thephpleague/omnipay-common/contributors" + } + ], + "description": "Common components for Omnipay payment processing library", + "homepage": "https://github.com/thephpleague/omnipay-common", + "keywords": [ + "gateway", + "merchant", + "omnipay", + "pay", + "payment", + "purchase" + ], + "time": "2016-07-07 09:52:09" + }, + { + "name": "symfony/event-dispatcher", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2016-06-29 05:29:29" + }, + { + "name": "symfony/http-foundation", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "1c9b7deebc55aed2d36c05399b22129522ec4ca2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1c9b7deebc55aed2d36c05399b22129522ec4ca2", + "reference": "1c9b7deebc55aed2d36c05399b22129522ec4ca2", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "symfony/expression-language": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2016-07-10 09:37:41" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8a6bdec191138e01c92ae026e5aacb7b3e66267d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8a6bdec191138e01c92ae026e5aacb7b3e66267d", + "reference": "8a6bdec191138e01c92ae026e5aacb7b3e66267d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-06-29 14:58:48" + } + ], + "packages-dev": [ + { + "name": "hamcrest/hamcrest-php", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b72949ccf2f640e7de66ff7dd92d83f577ce782e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b72949ccf2f640e7de66ff7dd92d83f577ce782e", + "reference": "b72949ccf2f640e7de66ff7dd92d83f577ce782e", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ], + "files": [ + "hamcrest/Hamcrest.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "time": "2016-01-19 12:08:55" + }, + { + "name": "mockery/mockery", + "version": "0.9.x-dev", + "source": { + "type": "git", + "url": "https://github.com/padraic/mockery.git", + "reference": "0f3617e31907c2f5a061cb2e652596449ddd54f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/padraic/mockery/zipball/0f3617e31907c2f5a061cb2e652596449ddd54f7", + "reference": "0f3617e31907c2f5a061cb2e652596449ddd54f7", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "~1.1", + "lib-pcre": ">=7.0", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + }, + "autoload": { + "psr-0": { + "Mockery": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "http://davedevelopment.co.uk" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", + "homepage": "http://github.com/padraic/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "time": "2016-07-14 08:27:13" + }, + { + "name": "omnipay/tests", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/omnipay-tests.git", + "reference": "137fdeaa8ef449c88ced15a50e02821732e7a125" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/omnipay-tests/zipball/137fdeaa8ef449c88ced15a50e02821732e7a125", + "reference": "137fdeaa8ef449c88ced15a50e02821732e7a125", + "shasum": "" + }, + "require": { + "guzzle/plugin-mock": "~3.1", + "mockery/mockery": "~0.8", + "phpunit/phpunit": "~3.7.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Omnipay\\Tests\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Adrian Macneil", + "email": "adrian@adrianmacneil.com" + }, + { + "name": "Omnipay Contributors", + "homepage": "https://github.com/thephpleague/omnipay-tests/contributors" + } + ], + "description": "Testing components for Omnipay payment processing library", + "homepage": "https://github.com/thephpleague/omnipay-tests", + "keywords": [ + "gateway", + "merchant", + "omnipay", + "pay", + "payment", + "purchase" + ], + "time": "2016-07-07 09:35:23" + }, + { + "name": "phpunit/php-code-coverage", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.0@stable", + "phpunit/php-text-template": ">=1.2.0@stable", + "phpunit/php-token-stream": ">=1.1.3,<1.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@dev" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2014-09-02 10:13:14" + }, + { + "name": "phpunit/php-file-iterator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2015-06-21 13:08:43" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21 13:50:34" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2016-05-12 18:03:57" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2014-03-03 05:10:30" + }, + { + "name": "phpunit/phpunit", + "version": "3.7.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": "~1.2", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.1", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~1.2", + "symfony/yaml": "~2.0" + }, + "require-dev": { + "pear-pear.php.net/pear": "1.9.4" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "composer/bin/phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2014-10-17 09:04:17" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "c39c4511c3b007539eb170c32cbc2af49a07351a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c39c4511c3b007539eb170c32cbc2af49a07351a", + "reference": "c39c4511c3b007539eb170c32cbc2af49a07351a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@dev" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2014-02-16 12:43:56" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "1.5.x-dev", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "reference": "6f3e42d311b882b25b4d409d23a289f4d3b803d5", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.1.2" + }, + "suggest": { + "phpunit/php-timer": "dev-master" + }, + "bin": [ + "scripts/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-phpcs-fixer": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/CommentParser/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2014-12-04 22:32:15" + }, + { + "name": "symfony/yaml", + "version": "2.8.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "b57a8d1b316b6aaf6dc77852fed4ddb8adac77a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/b57a8d1b316b6aaf6dc77852fed4ddb8adac77a7", + "reference": "b57a8d1b316b6aaf6dc77852fed4ddb8adac77a7", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-07-01 06:55:04" + } + ], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..a35b736 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests/ + + + + + + + + ./src + + + diff --git a/src/Gateway.php b/src/Gateway.php index 6018e53..070e372 100755 --- a/src/Gateway.php +++ b/src/Gateway.php @@ -10,373 +10,380 @@ */ class Gateway extends AbstractGateway { - /** - * @return string - */ - public function getName() - { - return 'Quickpay'; - } - - /** - * @return array - */ - public function getDefaultParameters() - { - parent::getDefaultParameters(); - return array( - 'type' => '', - 'merchant' => '', - 'agreement' => '', - 'apikey' => '', - 'privatekey' => '', - 'language' => '', - 'google_analytics_tracking_id' => '', - 'google_analytics_client_id' => '', - 'description' => '', - 'order_id' => '', - 'payment_methods' => array() - ); - } - - /** - * @return array - */ - public function getPaymentMethods(){ - return $this->getParameter('payment_methods'); - } - - /** - * @param array $value - * @return mixed - */ - public function setPaymentMethods($value = array()){ - return $this->setParameter('payment_methods', $value); - } - - /** - * @return int - */ - public function getMerchant() - { - return $this->getParameter('merchant'); - } - - /** - * @param $value - * @return mixed - */ - public function setMerchant($value) - { - return $this->setParameter('merchant', $value); - } - - /** - * @return int - */ - public function getAgreement() - { - return $this->getParameter('agreement'); - } - - /** - * @param $value - * @return mixed - */ - public function setAgreement($value) - { - return $this->setParameter('agreement', $value); - } - - /** - * @param $value - * @return mixed - */ - public function setApikey($value) - { - return $this->setParameter('apikey', $value); - } - - /** - * @return string - */ - public function getApikey() - { - return $this->getParameter('apikey'); - } - - /** - * @param $value - * @return mixed - */ - public function setPrivatekey($value) - { - return $this->setParameter('privatekey', $value); - } - - /** - * @return string - */ - public function getPrivatekey() - { - return $this->getParameter('privatekey'); - } - - /** - * @return string - */ - public function getLanguage() - { - return $this->getParameter('language'); - } - - /** - * @param $value - * @return mixed - */ - public function setLanguage($value) - { - return $this->setParameter('language', $value); - } - - /** - * @return string - */ - public function getGoogleAnalyticsTrackingID() - { - return $this->getParameter('google_analytics_tracking_id'); - } - - /** - * @param $value - * @return mixed - */ - public function setGoogleAnalyticsTrackingID($value) - { - return $this->setParameter('google_analytics_tracking_id', $value); - } - - /** - * @return string - */ - public function getGoogleAnalyticsClientID() - { - return $this->getParameter('google_analytics_client_id'); - } - - /** - * @param $value - * @return mixed - */ - public function setGoogleAnalyticsClientID($value) - { - return $this->setParameter('google_analytics_client_id', $value); - } - - /** - * @return string - */ - public function getType() - { - return $this->getParameter('type'); - } - - /** - * @param $value - * @return mixed - */ - public function setType($value) - { - return $this->setParameter('type', $value); - } - - /** - * @return string - */ - public function getDescription() - { - return $this->getParameter('description'); - } - - /** - * @param $value - * @return mixed - */ - public function setDescription($value) - { - return $this->setParameter('description', $value); - } - - /** - * @return string - */ - public function getOrderID() - { - return $this->getParameter('order_id'); - } - - /** - * @param $value - * @return mixed - */ - public function setOrderID($value) - { - return $this->setParameter('order_id', $value); - } - - /** - * Start an authorize request - * - * @param array $parameters array of options - * @return \Omnipay\Quickpay\Message\AuthorizeRequest - */ - public function authorize(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\AuthorizeRequest', $parameters); - } - - /** - * Start a purchase request - * - * @param array $parameters array of options - * @return \Omnipay\Quickpay\Message\PurchaseRequest - */ - public function purchase(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\PurchaseRequest', $parameters); - } - - /** - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CaptureRequest - */ - public function capture(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\CaptureRequest', $parameters); - } - - /** - * @param array $parameters - * @return \Omnipay\Quickpay\Message\VoidRequest - */ - public function void(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\VoidRequest', $parameters); - } - - /** - * @param array $parameters - * @return \Omnipay\Quickpay\Message\RefundRequest - */ - public function refund(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\RefundRequest', $parameters); - } - - /** - * @param array $parameters - * @return \Omnipay\Quickpay\Message\RefundRequest - */ - public function recurring(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\RecurringRequest', $parameters); - } - - /** - * Is used for callbacks coming in to the system - * notify will verify these callbacks and eventually return the body of the callback to the app - * @param array $parameters - * @return \Omnipay\Quickpay\Message\NotifyRequest - */ - public function notify(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\NotifyRequest', $parameters); - } - - /** - * Complete a purchase - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completePurchase(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * Complete an authorization - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeAuthorize(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * A complete request - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeRequest(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Quickpay\Message\CompleteRequest', $parameters); - } - - /** - * Complete capture - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeCapture(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * Complete cancel - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeVoid(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * Complete refund - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeRefund(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * Complete recurring - * - * @param array $parameters - * @return \Omnipay\Quickpay\Message\CompleteRequest - */ - public function completeRecurring(array $parameters = array()) - { - return $this->completeRequest($parameters); - } - - /** - * @return Notification - */ - public function acceptNotification() - { - return new Notification($this->httpRequest, $this->getPrivatekey()); - } + /** + * @return string + */ + public function getName() + { + return 'Quickpay'; + } + + /** + * @return array + */ + public function getDefaultParameters() + { + parent::getDefaultParameters(); + return array( + 'type' => '', + 'merchant' => '', + 'agreement' => '', + 'apikey' => '', + 'privatekey' => '', + 'language' => '', + 'google_analytics_tracking_id' => '', + 'google_analytics_client_id' => '', + 'description' => '', + 'order_id' => '', + 'payment_methods' => array() + ); + } + + /** + * @return array + */ + public function getPaymentMethods() + { + return $this->getParameter('payment_methods'); + } + + /** + * @param array $value + * @return mixed + */ + public function setPaymentMethods($value = array()) + { + return $this->setParameter('payment_methods', $value); + } + + /** + * @return int + */ + public function getMerchant() + { + return $this->getParameter('merchant'); + } + + /** + * @param $value + * @return mixed + */ + public function setMerchant($value) + { + return $this->setParameter('merchant', $value); + } + + /** + * @return int + */ + public function getAgreement() + { + return $this->getParameter('agreement'); + } + + /** + * @param $value + * @return mixed + */ + public function setAgreement($value) + { + return $this->setParameter('agreement', $value); + } + + /** + * @param $value + * @return mixed + */ + public function setApikey($value) + { + return $this->setParameter('apikey', $value); + } + + /** + * @return string + */ + public function getApikey() + { + return $this->getParameter('apikey'); + } + + /** + * @param $value + * @return mixed + */ + public function setPrivatekey($value) + { + return $this->setParameter('privatekey', $value); + } + + /** + * @return string + */ + public function getPrivatekey() + { + return $this->getParameter('privatekey'); + } + + /** + * @return string + */ + public function getLanguage() + { + return $this->getParameter('language'); + } + + /** + * @param $value + * @return mixed + */ + public function setLanguage($value) + { + return $this->setParameter('language', $value); + } + + /** + * @return string + */ + public function getGoogleAnalyticsTrackingID() + { + return $this->getParameter('google_analytics_tracking_id'); + } + + /** + * @param $value + * @return mixed + */ + public function setGoogleAnalyticsTrackingID($value) + { + return $this->setParameter('google_analytics_tracking_id', $value); + } + + /** + * @return string + */ + public function getGoogleAnalyticsClientID() + { + return $this->getParameter('google_analytics_client_id'); + } + + /** + * @param $value + * @return mixed + */ + public function setGoogleAnalyticsClientID($value) + { + return $this->setParameter('google_analytics_client_id', $value); + } + + /** + * @return string + */ + public function getType() + { + return $this->getParameter('type'); + } + + /** + * @param $value + * @return mixed + */ + public function setType($value) + { + return $this->setParameter('type', $value); + } + + /** + * @return string + */ + public function getDescription() + { + return $this->getParameter('description'); + } + + /** + * @param $value + * @return mixed + */ + public function setDescription($value) + { + return $this->setParameter('description', $value); + } + + /** + * @return string + */ + public function getOrderID() + { + return $this->getParameter('order_id'); + } + + /** + * @param $value + * @return mixed + */ + public function setOrderID($value) + { + return $this->setParameter('order_id', $value); + } + + /** + * Start an authorize request + * + * @param array $parameters array of options + * @return \Omnipay\Quickpay\Message\AuthorizeRequest + */ + public function authorize(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\AuthorizeRequest', $parameters); + } + + /** + * Start a purchase request + * + * @param array $parameters array of options + * @return \Omnipay\Quickpay\Message\PurchaseRequest + */ + public function purchase(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\PurchaseRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CaptureRequest + */ + public function capture(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\CaptureRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\Quickpay\Message\VoidRequest + */ + public function void(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\VoidRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\Quickpay\Message\RefundRequest + */ + public function refund(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\RefundRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\Quickpay\Message\RefundRequest + */ + public function recurring(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\RecurringRequest', $parameters); + } + + /** + * Is used for callbacks coming in to the system + * notify will verify these callbacks and eventually return the body of the callback to the app + * @param array $parameters + * @return \Omnipay\Quickpay\Message\NotifyRequest + */ + public function notify(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\NotifyRequest', $parameters); + } + + /** + * Complete a purchase + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completePurchase(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * Complete an authorization + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeAuthorize(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * A complete request + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeRequest(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\CompleteRequest', $parameters); + } + + /** + * Complete capture + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeCapture(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * Complete cancel + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeVoid(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * Complete refund + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeRefund(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * Complete recurring + * + * @param array $parameters + * @return \Omnipay\Quickpay\Message\CompleteRequest + */ + public function completeRecurring(array $parameters = array()) + { + return $this->completeRequest($parameters); + } + + /** + * @return Notification + */ + public function acceptNotification() + { + return new Notification($this->httpRequest, $this->getPrivatekey()); + } + + public function link(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Quickpay\Message\LinkRequest', $parameters); + } } diff --git a/src/Message/CompleteRequest.php b/src/Message/CompleteRequest.php index e16d6cb..39da000 100755 --- a/src/Message/CompleteRequest.php +++ b/src/Message/CompleteRequest.php @@ -10,30 +10,38 @@ */ class CompleteRequest extends AbstractRequest { - public function getData() - { - $data = $this->httpRequest->query->all(); - - // if its the notifyUrl (callback) being handled and not returnUrl - if($this->httpRequest->headers->get('Content-Type') == "application/json"){ - $data = $this->httpRequest->getContent(); - - $header_checksum = $this->httpRequest->headers->get('Quickpay-Checksum-Sha256'); - // validate with accounts private key. - $our_checksum = hash_hmac("sha256", $this->httpRequest->getContent(), $this->getPrivateKey()); - if ($our_checksum != $header_checksum) { - throw new InvalidResponseException; - } - } - - return $data; - } - - public function sendData($data) - { - return $this->response = new Response($this, $data); - } - - public function getHttpMethod(){} + public function getData() + { + $data = $this->httpRequest->query->all(); + + // if its the notifyUrl (callback) being handled and not returnUrl + if ($this->httpRequest->headers->get('Content-Type') == "application/json") { + $data = $this->httpRequest->getContent(); + + $header_checksum = $this->httpRequest->headers->get('Quickpay-Checksum-Sha256'); + // validate with accounts private key. + $our_checksum = hash_hmac("sha256", $this->httpRequest->getContent(), $this->getPrivateKey()); + if ($our_checksum != $header_checksum) { + throw new InvalidResponseException; + } + } + + return $data; + } + + /** + * @codeCoverageIgnore + */ + public function sendData($data) + { + return $this->response = new Response($this, $data); + } + + /** + * @codeCoverageIgnore + */ + public function getHttpMethod() + { + } } diff --git a/src/Message/LinkRequest.php b/src/Message/LinkRequest.php new file mode 100644 index 0000000..5dd9c6b --- /dev/null +++ b/src/Message/LinkRequest.php @@ -0,0 +1,105 @@ + 24) { + throw new InvalidRequestException('transactionId has a max length of 24'); + } + return parent::setTransactionId($value); + } + + /** + * @return array + */ + public function getQuickpayParams() + { + $params = array( + 'version' => 'v10', + 'agreement_id' => $this->getAgreement(), + 'order_id' => $this->getTransactionId(), + 'amount' => $this->getAmountInteger(), + 'currency' => $this->getCurrency(), + 'continue_url' => $this->getReturnUrl(), + 'cancel_url' => $this->getCancelUrl(), + 'callback_url' => $this->getNotifyUrl(), + 'language' => $this->getLanguage(), + 'google_analytics_tracking_id' => $this->getGoogleAnalyticsTrackingID(), + 'google_analytics_client_id' => $this->getGoogleAnalyticsClientID(), + 'auto_capture' => false, + 'payment_methods' => $this->getPaymentMethods() + ); + + + return $params; + } + + public function getData() + { + $this->validate('apikey', 'agreement', 'amount', 'transactionId', 'currency'); + + return $this->getQuickpayParams(); + } + + + public function send() + { + $fullData = $this->getData(); + $reference = $this->getTransactionReference(); + + if (!$reference) { + $url = $this->getEndPoint() . '/' . $this->getTypeOfRequest() . '/'; + $data = [ + 'order_id' => $fullData['order_id'], + 'currency' => $fullData['currency'], + ]; + + $httpRequest = $this->httpClient->createRequest('POST', $url, null, $data) + ->setHeader('Authorization', ' Basic ' . base64_encode(":" . $this->getApikey())) + ->setHeader('Accept-Version', ' v10') + ->setHeader('QuickPay-Callback-Url', $this->getNotifyUrl()); + try { + $httpResponse = $httpRequest->send(); + } catch (ClientErrorResponseException $e) { + $httpResponse = $e->getResponse(); + } + $body = $httpResponse->getBody(true); + $response = json_decode($body, true); + if (array_key_exists('id', $response)) { + $reference = $response['id']; + } else { + return new LinkResponse($this, $body); + } + } + unset($fullData['order_id']); + unset($fullData['currency']); + + $url = $this->getEndPoint() . '/' . $this->getTypeOfRequest() . '/' . $reference . '/link'; + + + $httpRequest = $this->httpClient->createRequest('PUT', $url, null, $fullData) + ->setHeader('Authorization', ' Basic ' . base64_encode(":" . $this->getApikey())) + ->setHeader('Accept-Version', ' v10') + ->setHeader('QuickPay-Callback-Url', $this->getNotifyUrl()); + + try { + $httpResponse = $httpRequest->send(); + } catch (ClientErrorResponseException $e) { + $httpResponse = $e->getResponse(); + } + + return new LinkResponse($this, $httpResponse->getBody(true), $reference); + + } + + +} diff --git a/src/Message/LinkResponse.php b/src/Message/LinkResponse.php new file mode 100644 index 0000000..a604c07 --- /dev/null +++ b/src/Message/LinkResponse.php @@ -0,0 +1,69 @@ +reference = $reference; + } + + public function isSuccessful() + { + $body = $this->getResponseBody(); + $body = json_decode($body); + if (isset($body->url)) { + return true; + } + return false; + } + + public function getTransactionReference() + { + return $this->reference; + } + + /** + * @return bool + * @codeCoverageIgnore + */ + public function isRedirect() + { + return true; + } + + public function getRedirectUrl() + { + $data = json_decode($this->getResponseBody()); + return $data->url; + } + + /** + * @return string + * @codeCoverageIgnore + */ + public function getRedirectMethod() + { + return 'GET'; + } + + /** + * @return array + * @codeCoverageIgnore + */ + public function getRedirectData() + { + return []; + } + + +} diff --git a/src/Message/Notification.php b/src/Message/Notification.php index 922481a..4fa8147 100755 --- a/src/Message/Notification.php +++ b/src/Message/Notification.php @@ -105,4 +105,4 @@ public function getMessage() } return ''; } -} \ No newline at end of file +} diff --git a/src/Message/PurchaseRequest.php b/src/Message/PurchaseRequest.php index a9c5f78..9329cb1 100755 --- a/src/Message/PurchaseRequest.php +++ b/src/Message/PurchaseRequest.php @@ -2,6 +2,8 @@ namespace Omnipay\Quickpay\Message; +use Omnipay\Common\Exception\InvalidRequestException; + /** * quickpay Purchase Request @@ -9,108 +11,126 @@ */ class PurchaseRequest extends AbstractRequest { - /** - * @var string - */ - protected $endpoint = 'https://payment.quickpay.net'; - - /** - * @return array - */ - public function getQuickpayParams() - { - $params = array( - "version" => "v10", - "merchant_id" => $this->getMerchant(), - "agreement_id" => $this->getAgreement(), - "order_id" => $this->getTransactionId(), - "amount" => $this->getAmountInteger(), - "currency" => $this->getCurrency(), - "continueurl" => $this->getReturnUrl(), - "cancelurl" => $this->getCancelUrl(), - "callbackurl" => $this->getNotifyUrl(), - "type" => $this->getType(), - "language" => $this->getLanguage(), - "google_analytics_tracking_id" => $this->getGoogleAnalyticsTrackingID(), - "autocapture" => 1, - "payment_methods" => $this->getPaymentMethods() - ); - - // it seems description param is not always allowed, depending on the Type set - if($this->getDescription() != ''){ - $params['description'] = $this->getDescription(); - } - - return $params; - } - - /** - * @return array|mixed - */ - public function getData() - { - // checks if any of these are empty, so we can throw an error without calling the API - $this->validate('merchant', 'agreement', 'amount', 'transactionId'); - - return $this->createChecksum($this->getQuickpayParams()); - } - - /** - * @param $data - * @return mixed - */ - public function createChecksum($data) - { - $data["checksum"] = $this->sign($data, $this->getApikey()); - return $data; - } - - // taken from quickpays PHP example on how to calculate checksum for the payment form - /** - * @param $params - * @param $api_key - * @return string - */ - public function sign($params, $api_key) - { - $flattened_params = $this->flatten_params($params); - ksort($flattened_params); - $base = implode(" ", $flattened_params); - - return hash_hmac("sha256", $base, $api_key); - } - - /** - * @param $obj - * @param array $result - * @param array $path - * @return array - */ - public function flatten_params($obj, $result = array(), $path = array()) - { - if (is_array($obj)) { - foreach ($obj as $k => $v) { - $result = array_merge($result, $this->flatten_params($v, $result, array_merge($path, array($k)))); - } - } else { - $result[implode("", array_map(function($p) { return "[{$p}]"; }, $path))] = $obj; - } - - return $result; - } - - /** - * @param $data - * @return mixed|PurchaseResponse - */ - public function sendData($data) - { - return $this->response = new PurchaseResponse($this, $data); - } - - /** - * @return string|void - */ - public function getHttpMethod(){} + /** + * @var string + */ + protected $endpoint = 'https://payment.quickpay.net'; + + /** + * @return array + */ + public function getQuickpayParams() + { + $params = array( + "version" => "v10", + "merchant_id" => $this->getMerchant(), + "agreement_id" => $this->getAgreement(), + "order_id" => $this->getTransactionId(), + "amount" => $this->getAmountInteger(), + "currency" => $this->getCurrency(), + "continueurl" => $this->getReturnUrl(), + "cancelurl" => $this->getCancelUrl(), + "callbackurl" => $this->getNotifyUrl(), + "language" => $this->getLanguage(), + "google_analytics_tracking_id" => $this->getGoogleAnalyticsTrackingID(), + "autocapture" => 1, + "payment_methods" => $this->getPaymentMethods() + ); + + // it seems description param is not always allowed, depending on the Type set + if ($this->getDescription() != '') { + $params['description'] = $this->getDescription(); + } + + return $params; + } + + public function setTransactionId($value) + { + $value = str_pad($value, 4, '0', STR_PAD_LEFT); + if (strlen($value) > 24) { + throw new InvalidRequestException('transactionId has a max length of 24'); + } + return parent::setTransactionId($value); + } + + /** + * @return array|mixed + */ + public function getData() + { + // checks if any of these are empty, so we can throw an error without calling the API + $this->validate('merchant', 'agreement', 'amount', 'transactionId'); + + return $this->createChecksum($this->getQuickpayParams()); + } + + /** + * @param $data + * @return mixed + */ + public function createChecksum($data) + { + $data["checksum"] = $this->sign($data, $this->getApikey()); + return $data; + } + + // taken from quickpays PHP example on how to calculate checksum for the payment form + /** + * @param $params + * @param $api_key + * @return string + */ + public function sign($params, $api_key) + { + $flattened_params = $this->flatten_params($params); + ksort($flattened_params); + $base = implode(" ", $flattened_params); + + return hash_hmac("sha256", $base, $api_key); + } + + /** + * @param $obj + * @param array $result + * @param array $path + * @return array + */ + public function flatten_params($obj, $result = array(), $path = array()) + { + if (is_array($obj)) { + foreach ($obj as $k => $v) { + $result = array_merge($result, $this->flatten_params($v, $result, array_merge($path, array($k)))); + } + } else { + $result[implode( + "", + array_map( + function ($p) { + return "[{$p}]"; + }, + $path + ) + )] = $obj; + } + + return $result; + } + + /** + * @param $data + * @return mixed|PurchaseResponse + */ + public function sendData($data) + { + return $this->response = new PurchaseResponse($this, $data); + } + + /** + * @return string|void + */ + public function getHttpMethod() + { + } } diff --git a/tests/GatewayTest.php b/tests/GatewayTest.php new file mode 100644 index 0000000..197659d --- /dev/null +++ b/tests/GatewayTest.php @@ -0,0 +1,112 @@ +gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); + } + + public function testAuthorize() + { + $request = $this->gateway->authorize(array('amount' => '10.00')); + $this->assertInstanceOf('Omnipay\Quickpay\Message\AuthorizeRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testCapture() + { + $request = $this->gateway->capture(array('amount' => '10.00')); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CaptureRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + $this->assertTrue(count($request->getData()) > 0); + } + + public function testPurchase() + { + $request = $this->gateway->purchase(array('amount' => '10.00')); + $this->assertInstanceOf('Omnipay\Quickpay\Message\PurchaseRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testRefund() + { + $request = $this->gateway->refund(array('amount' => '10.00')); + $this->assertInstanceOf('Omnipay\Quickpay\Message\RefundRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testVoid() + { + $request = $this->gateway->void(); + $this->assertInstanceOf('Omnipay\Quickpay\Message\VoidRequest', $request); + } + + public function testLink() + { + $request = $this->gateway->link(['amount' => '10.00']); + $this->assertInstanceOf('Omnipay\Quickpay\Message\LinkRequest', $request); + } + + public function testRecurring() + { + $request = $this->gateway->recurring(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\RecurringRequest', $request); + } + + public function testNotify() + { + $request = $this->gateway->notify(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\NotifyRequest', $request); + } + + public function testCompletePurchase() + { + $request = $this->gateway->completePurchase(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testCompleteVoid() + { + $request = $this->gateway->completeVoid(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testCompleteAuthorize() + { + $request = $this->gateway->completeAuthorize(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testCompleteCapture() + { + $request = $this->gateway->completeCapture(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testCompleteRefund() + { + $request = $this->gateway->completeRefund(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testCompleteRecurring() + { + $request = $this->gateway->completeRecurring(['amount' => 10.00]); + $this->assertInstanceOf('Omnipay\Quickpay\Message\CompleteRequest', $request); + } + + public function testAcceptNotification() + { + $notification = $this->gateway->acceptNotification(); + $this->assertInstanceOf('Omnipay\Quickpay\Message\Notification', $notification); + } + +} diff --git a/tests/Message/AuthorizeRequestTest.php b/tests/Message/AuthorizeRequestTest.php new file mode 100644 index 0000000..928f480 --- /dev/null +++ b/tests/Message/AuthorizeRequestTest.php @@ -0,0 +1,40 @@ +request = new AuthorizeRequest($this->getHttpClient(), $this->getHttpRequest()); + } + + public function testGetData() + { + $this->request->initialize( + ['apikey' => 1, 'transactionId' => '10', 'agreement' => 2, 'amount' => 10.00, 'currency' => 'DKK'] + ); + $data = $this->request->getData(); + $fields = [ + 'version' => 'v10', + 'order_id' => '0010', + 'agreement_id' => 2, + 'amount' => '1000', + 'currency' => 'DKK', + 'autocapture' => 0, + + ]; + foreach ($fields as $key => $value) { + $this->assertEquals($value, $data[$key], 'Key: ' . $key . ' not found in the data'); + } + $this->assertTrue(strlen($data['order_id']) === 4); + } + +} diff --git a/tests/Message/CompleteRequestTest.php b/tests/Message/CompleteRequestTest.php new file mode 100644 index 0000000..d003d0d --- /dev/null +++ b/tests/Message/CompleteRequestTest.php @@ -0,0 +1,78 @@ +mockRequest = $this->getHttpRequest(); + $this->request = new CompleteRequest($this->getHttpClient(), $this->mockRequest); + } + + public function testGetData() + { + $this->request->initialize( + ['privateKey' => 1] + ); + $data = $this->request->getData(); + $this->assertTrue(is_array($data)); + $this->assertTrue(count($data) === 0); + } + + public function testGetDataWithContentTypeJson() + { + $this->mockRequest->initialize( + ['test' => 1], + [], + [], + [], + [], + [ + 'HTTP_CONTENT_TYPE' => 'application/json', + 'HTTP_QUICKPAY_CHECKSUM_SHA256' => '83ce13bda6523334daa14f33d1fc2adc98ff8b57c4df5be5d2f58b1c2c78fa1e' + ], + '[]' + ); + + $data = $this->request->getData(); + + $this->assertEquals('[]', $data); + } + + public function testGetDataWithContentTypeJsonWithInvalidSha() + { + $this->mockRequest->initialize( + ['test' => 1], + [], + [], + [], + [], + [ + 'HTTP_CONTENT_TYPE' => 'application/json', + 'HTTP_QUICKPAY_CHECKSUM_SHA256' => '83ce13dffa6523334daa14f33d1fc2adc98ff8b57c4df5be5d2f58b1c2c78fa1e' + ], + '[]' + ); + + try { + $this->request->getData(); + $this->fail('Expected an exception'); + } catch (InvalidResponseException $e) { + $this->assertEquals('Invalid response from payment gateway', $e->getMessage()); + } + + } + +} diff --git a/tests/Message/LinkRequestTest.php b/tests/Message/LinkRequestTest.php new file mode 100644 index 0000000..63f70ce --- /dev/null +++ b/tests/Message/LinkRequestTest.php @@ -0,0 +1,112 @@ +request = new LinkRequest($this->getHttpClient(), $this->getHttpRequest()); + } + + public function testGetData() + { + $this->request->initialize( + ['apikey' => 1, 'transactionId' => '10', 'agreement' => 2, 'amount' => 10.00, 'currency' => 'DKK'] + ); + $data = $this->request->getData(); + $fields = [ + 'version' => 'v10', + 'order_id' => '0010', + 'agreement_id' => 2, + 'amount' => '1000', + 'currency' => 'DKK' + ]; + foreach ($fields as $key => $value) { + $this->assertEquals($value, $data[$key], 'Key: ' . $key . ' not found in the data'); + } + $this->assertTrue(strlen($data['order_id']) === 4); + } + + public function testTransactionId() + { + try { + $this->request->initialize(['transactionId' => str_repeat('0', 25)]); + $this->fail('Expecting an exception'); + } catch (InvalidRequestException $e) { + $this->assertEquals('transactionId has a max length of 24', $e->getMessage()); + } + } + + public function testSendingALinkRequest() + { + $this->setMockHttpResponse(['LinkRequestCreatePaymentSuccess.txt', 'LinkRequestCreatePaymentLinkSuccess.txt']); + $this->request->initialize( + ['apikey' => 1, 'transactionId' => '10', 'agreement' => 2, 'amount' => 10.00, 'currency' => 'DKK'] + ); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertEquals('http://test.link', $response->getRedirectUrl()); + $this->assertEquals('GET', $response->getRedirectMethod()); + $this->assertEquals('123123123', $response->getTransactionReference()); + } + + public function testSendingALinkRequestWithAnAlreadyExistingTransactionReference() + { + $this->setMockHttpResponse(['LinkRequestCreatePaymentLinkSuccess.txt']); + $this->request->initialize( + [ + 'apikey' => 1, + 'transactionId' => '10', + 'agreement' => 2, + 'amount' => 10.00, + 'currency' => 'DKK', + 'transactionReference' => 123123123 + ] + ); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertEquals('http://test.link', $response->getRedirectUrl()); + $this->assertEquals('GET', $response->getRedirectMethod()); + $this->assertEquals('123123123', $response->getTransactionReference()); + } + + public function testSendingALinkRequestWithAnError() + { + $this->setMockHttpResponse(['LinkRequestCreatePaymentLinkFailure.txt']); + $this->request->initialize( + [ + 'apikey' => 1, + 'transactionId' => '10', + 'agreement' => 2, + 'amount' => 10.00, + 'currency' => 'DKK', + ] + ); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + } + public function testSendingALinkRequestWithAnErrorOnTransaction() + { + $this->setMockHttpResponse(['LinkRequestCreatePaymentLinkFailure.txt']); + $this->request->initialize( + [ + 'apikey' => 1, + 'transactionId' => '10', + 'agreement' => 2, + 'amount' => 10.00, + 'currency' => 'DKK', + 'transactionReference' => 123123123 + ] + ); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + } +} diff --git a/tests/Message/NotificationTest.php b/tests/Message/NotificationTest.php new file mode 100644 index 0000000..479b36a --- /dev/null +++ b/tests/Message/NotificationTest.php @@ -0,0 +1,127 @@ +request = $this->getHttpRequest(); + $this->notification = new Notification($this->request, '123'); + } + + public function testGetPrivateKey() + { + $this->assertEquals('123', $this->notification->getPrivateKey()); + $this->assertEquals('1234', $this->notification->setPrivateKey('1234')->getPrivateKey()); + } + + public function testGetDataWithContentTypeJson() + { + $this->generateContent( + [ + 'id' => 1, + 'order_id' => '0010', + 'operations' => [['qp_status_msg' => 'test', 'pending' => false, 'qp_status_code' => 20000]] + ] + ); + + $data = $this->notification->getMessage(); + $this->assertEquals('test', $data); + $this->assertEquals(1, $this->notification->getTransactionReference()); + $this->assertEquals(NotificationInterface::STATUS_COMPLETED, $this->notification->getTransactionStatus()); + } + + public function testGetDataWithContentTypeJsonStatusPending() + { + $this->generateContent( + [ + 'id' => 1, + 'order_id' => '0010', + 'operations' => [['qp_status_msg' => 'test', 'pending' => true]] + ] + ); + + $data = $this->notification->getMessage(); + $this->assertEquals('test', $data); + $this->assertEquals(1, $this->notification->getTransactionReference()); + $this->assertEquals(NotificationInterface::STATUS_PENDING, $this->notification->getTransactionStatus()); + } + + public function testGetDataWithContentTypeJsonStatusFailed() + { + $this->generateContent( + [ + 'id' => 1, + 'order_id' => '0010', + 'operations' => [['qp_status_msg' => 'test', 'pending' => false, 'qp_status_code' => -1]] + ] + ); + + $data = $this->notification->getMessage(); + $this->assertEquals('test', $data); + $this->assertEquals(1, $this->notification->getTransactionReference()); + $this->assertEquals(NotificationInterface::STATUS_FAILED, $this->notification->getTransactionStatus()); + } + + public function testGetDataWithContentTypeJsonWithInvalidSha() + { + $this->request->initialize( + ['test' => 1], + [], + [], + [], + [], + [ + 'HTTP_CONTENT_TYPE' => 'application/json', + 'HTTP_QUICKPAY_CHECKSUM_SHA256' => 'dasdasdasdasdas' + ], + '' + ); + + + try { + $this->notification->getData(); + $this->fail('Expected an exception'); + } catch (InvalidResponseException $e) { + $this->assertEquals('Invalid response from payment gateway', $e->getMessage()); + } + + } + + public function testNotificationOnInvalidRequest() + { + $this->assertEquals('', $this->notification->getMessage()); + $this->assertEquals(null, $this->notification->getTransactionReference()); + } + + private function generateContent($data) + { + $content = json_encode($data); + $this->request->initialize( + ['test' => 1], + [], + [], + [], + [], + [ + 'HTTP_CONTENT_TYPE' => 'application/json', + 'HTTP_QUICKPAY_CHECKSUM_SHA256' => hash_hmac("sha256", $content, '123') + ], + $content + ); + } + +} diff --git a/tests/Mock/LinkRequestCreatePaymentLinkFailure.txt b/tests/Mock/LinkRequestCreatePaymentLinkFailure.txt new file mode 100644 index 0000000..4fa3710 --- /dev/null +++ b/tests/Mock/LinkRequestCreatePaymentLinkFailure.txt @@ -0,0 +1,10 @@ +HTTP/1.1 403 Forbidden +Server: nginx +Date: Sun, 24 Jan 2016 22:29:41 GMT +Content-Type: application/json +Content-Length: 2 +Connection: keep-alive +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{} diff --git a/tests/Mock/LinkRequestCreatePaymentLinkSuccess.txt b/tests/Mock/LinkRequestCreatePaymentLinkSuccess.txt new file mode 100644 index 0000000..9b6e542 --- /dev/null +++ b/tests/Mock/LinkRequestCreatePaymentLinkSuccess.txt @@ -0,0 +1,12 @@ +HTTP/1.1 201 Created +Server: nginx +Date: Sun, 24 Jan 2016 22:29:41 GMT +Content-Type: application/json +Content-Length: 31 +Connection: keep-alive +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "url": "http://test.link" +} diff --git a/tests/Mock/LinkRequestCreatePaymentSuccess.txt b/tests/Mock/LinkRequestCreatePaymentSuccess.txt new file mode 100644 index 0000000..0037e48 --- /dev/null +++ b/tests/Mock/LinkRequestCreatePaymentSuccess.txt @@ -0,0 +1,13 @@ +HTTP/1.1 201 Created +Server: nginx +Date: Sun, 24 Jan 2016 22:29:41 GMT +Content-Type: application/json +Content-Length: 43 +Connection: keep-alive +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "id": 123123123, + "order_id": "0010" +} From 5dac40dbed79732d5c4fa5625abc94bfa81872db Mon Sep 17 00:00:00 2001 From: Thomas Faurbye Nielsen Date: Fri, 15 Jul 2016 13:33:29 +0200 Subject: [PATCH 2/2] Re-adding the type parameter --- src/Message/PurchaseRequest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Message/PurchaseRequest.php b/src/Message/PurchaseRequest.php index 9329cb1..1222276 100755 --- a/src/Message/PurchaseRequest.php +++ b/src/Message/PurchaseRequest.php @@ -34,6 +34,7 @@ public function getQuickpayParams() "language" => $this->getLanguage(), "google_analytics_tracking_id" => $this->getGoogleAnalyticsTrackingID(), "autocapture" => 1, + "type" => $this->getType(), "payment_methods" => $this->getPaymentMethods() );