From a10d6fd785fd3791a239e7d77e3117abceeb768f Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Sun, 26 Nov 2017 09:14:46 +0000 Subject: [PATCH 01/17] GP-860 - WIP Apple Pay support --- .../WorldPayXML/ApplePayCreditCard.php | 20 ++++++ .../WorldPayXML/Message/PurchaseRequest.php | 69 ++++++++++++++----- tests/Omnipay/WorldPayXML/GatewayTest.php | 32 ++++++++- .../Mock/PurchaseSuccessApplePay.txt | 11 +++ 4 files changed, 115 insertions(+), 17 deletions(-) create mode 100644 src/Omnipay/WorldPayXML/ApplePayCreditCard.php create mode 100755 tests/Omnipay/WorldPayXML/Mock/PurchaseSuccessApplePay.txt diff --git a/src/Omnipay/WorldPayXML/ApplePayCreditCard.php b/src/Omnipay/WorldPayXML/ApplePayCreditCard.php new file mode 100644 index 0000000..6c83eaa --- /dev/null +++ b/src/Omnipay/WorldPayXML/ApplePayCreditCard.php @@ -0,0 +1,20 @@ +setParameter('userAgentHeader', $value); } + /** + * @param $appleToken + * @return PurchaseRequest + */ + public function setAppleToken($appleToken) + { + return $this->setParameter('appleToken', $appleToken); + } + + /** + * @return array + */ + public function getAppleToken() + { + return $this->getParameter('appleToken'); + } + /** * Get data * @@ -287,7 +304,10 @@ public function setUserAgentHeader($value) public function getData() { $this->validate('amount', 'card'); - $this->getCard()->validate(); + + if (!$this->getAppleToken()) { + $this->getCard()->validate(); + } // Else for Apple Pay, we use a dummy 'card' with partial metadata, which won't validate. $data = new \SimpleXMLElement(''); $data->addAttribute('version', self::VERSION); @@ -319,27 +339,44 @@ public function getData() CreditCard::BRAND_VISA => 'VISA-SSL' ); - $card = $payment->addChild($codes[$this->getCard()->getBrand()]); - $card->addChild('cardNumber', $this->getCard()->getNumber()); + if ($this->getCard()->getBrand() === 'apple') { + // With Apple Pay we have no card number so can't pattern match via getBrand() + $card = $payment->addChild('APPLEPAY-SSL'); + + $appleData = $this->getAppleToken(); - $expiry = $card->addChild('expiryDate')->addChild('date'); - $expiry->addAttribute('month', $this->getCard()->getExpiryDate('m')); - $expiry->addAttribute('year', $this->getCard()->getExpiryDate('Y')); + $card->addAttribute('data', $appleData['paymentData']['data']); + $card->addAttribute('signature', $appleData['paymentData']['signature']); + $card->addAttribute('version', $appleData['paymentData']['version']); - $card->addChild('cardHolderName', $this->getCard()->getName()); + $header = $card->addChild('header'); + $header->addAttribute('applicationData', $appleData['paymentData']['header']['applicationData']); + $header->addAttribute('ephemeralPublicKey', $appleData['paymentData']['header']['ephemeralPublicKey']); + $header->addAttribute('publicKeyHash', $appleData['paymentData']['header']['publicKeyHash']); + $header->addAttribute('transactionId', $appleData['paymentData']['header']['transactionId']); + } else { + $card = $payment->addChild($codes[$this->getCard()->getBrand()]); + $card->addChild('cardNumber', $this->getCard()->getNumber()); - if ( + $expiry = $card->addChild('expiryDate')->addChild('date'); + $expiry->addAttribute('month', $this->getCard()->getExpiryDate('m')); + $expiry->addAttribute('year', $this->getCard()->getExpiryDate('Y')); + + $card->addChild('cardHolderName', $this->getCard()->getName()); + + if ( $this->getCard()->getBrand() == CreditCard::BRAND_MAESTRO - || $this->getCard()->getBrand() == CreditCard::BRAND_SWITCH - ) { - $start = $card->addChild('startDate')->addChild('date'); - $start->addAttribute('month', $this->getCard()->getStartDate('m')); - $start->addAttribute('year', $this->getCard()->getStartDate('Y')); + || $this->getCard()->getBrand() == CreditCard::BRAND_SWITCH + ) { + $start = $card->addChild('startDate')->addChild('date'); + $start->addAttribute('month', $this->getCard()->getStartDate('m')); + $start->addAttribute('year', $this->getCard()->getStartDate('Y')); - $card->addChild('issueNumber', $this->getCard()->getIssueNumber()); - } + $card->addChild('issueNumber', $this->getCard()->getIssueNumber()); + } - $card->addChild('cvc', $this->getCard()->getCvv()); + $card->addChild('cvc', $this->getCard()->getCvv()); + } $address = $card->addChild('cardAddress')->addChild('address'); $address->addChild('street', $this->getCard()->getAddress1()); diff --git a/tests/Omnipay/WorldPayXML/GatewayTest.php b/tests/Omnipay/WorldPayXML/GatewayTest.php index 95980f1..02c8596 100755 --- a/tests/Omnipay/WorldPayXML/GatewayTest.php +++ b/tests/Omnipay/WorldPayXML/GatewayTest.php @@ -24,7 +24,7 @@ public function setUp() 'lastName' => 'User', 'number' => '4111111111111111', 'expiryMonth' => '12', - 'expiryYear' => '2016', + 'expiryYear' => '2026', 'cvv' => '123', ) ), @@ -51,4 +51,34 @@ public function testPurchaseError() $this->assertFalse($response->isSuccessful()); $this->assertSame('CARD EXPIRED', $response->getMessage()); } + + public function testApplePaySuccess() + { + $applePayOptions = array( + 'amount' => '10.00', + 'card' => new ApplePayCreditCard(), + 'appleToken' => array( + 'transactionIdentifier' => '5394..00', + 'paymentData' => array( + 'data' => 'kdHd..GQ==', + 'signature' => 'MIAGCSqGSIb3DQEH...AAA', + 'version' => 'EC_v1', + 'header' => array( + 'applicationData' => '94ee0..C2', + 'ephemeralPublicKey' => 'MFkwE..Q==', + 'publicKeyHash' => 'dxCK..6o=', + 'transactionId' => 'd3b28af..f8', + ), + ), + ), + 'transactionId' => 'T0211010', + ); + + $this->setMockHttpResponse('PurchaseSuccessApplePay.txt'); + + $response = $this->gateway->purchase($applePayOptions)->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertEquals('T0211011', $response->getTransactionReference()); + } } diff --git a/tests/Omnipay/WorldPayXML/Mock/PurchaseSuccessApplePay.txt b/tests/Omnipay/WorldPayXML/Mock/PurchaseSuccessApplePay.txt new file mode 100755 index 0000000..a6c1b74 --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Mock/PurchaseSuccessApplePay.txt @@ -0,0 +1,11 @@ +HTTP/1.1 200 OK +Connection: close +Server: VPS-3.033.00 +Date: Sat, 23 Feb 2013 05:17:32 GMT +Content-type: text/xml +Content-length: 721 + + + +APPLEPAY-SSL AUTHORISED \ No newline at end of file From 024a5075ff8ae524c6171dbb5dbf03f629b4a1c0 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Sun, 26 Nov 2017 09:17:30 +0000 Subject: [PATCH 02/17] Copy .gitignore and Travis config from CR Hosted adapter. Update Composer and check in lock file. --- .gitignore | 2 + .travis.yml | 18 + composer.json | 5 + composer.lock | 1434 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1459 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ef0e14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor/ +.idea/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4df3287 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: php +php: + - '5.6' + - '7.0' + - '7.1' + +install: + - composer install + +script: + - composer test + +git: + depth: 3 + +cache: + directories: + - $HOME/.composer/cache diff --git a/composer.json b/composer.json index 8ad28a8..3a6b263 100755 --- a/composer.json +++ b/composer.json @@ -16,12 +16,17 @@ { "name": "Dave Nash", "email": "dave.nash@teaandcode.com" + }, + { + "name": "Noel Light-Hilary", + "email": "n.light-hilary@comicrelief.com" } ], "autoload": { "psr-0": { "Omnipay\\WorldPayXML\\" : "src/" } }, "require": { + "php": "^5.6|^7", "guzzle/plugin-cookie": "~3.7", "omnipay/common": "~2.3" }, diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..420a2b3 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1434 @@ +{ + "_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" + ], + "content-hash": "e9c6517d5e4611757382faacafdd311c", + "packages": [ + { + "name": "guzzle/common", + "version": "v3.9.2", + "target-dir": "Guzzle/Common", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/common.git", + "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/common/zipball/2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc", + "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/event-dispatcher": ">=2.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Common": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Common libraries used by Guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "collection", + "common", + "event", + "exception" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-08-11T04:32:36+00:00" + }, + { + "name": "guzzle/http", + "version": "v3.9.2", + "target-dir": "Guzzle/Http", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/http.git", + "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/http/zipball/1e8dd1e2ba9dc42332396f39fbfab950b2301dc5", + "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5", + "shasum": "" + }, + "require": { + "guzzle/common": "self.version", + "guzzle/parser": "self.version", + "guzzle/stream": "self.version", + "php": ">=5.3.2" + }, + "suggest": { + "ext-curl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Http": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "HTTP libraries used by Guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "client", + "curl", + "http", + "http client" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-08-11T04:32:36+00:00" + }, + { + "name": "guzzle/parser", + "version": "v3.9.2", + "target-dir": "Guzzle/Parser", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/parser.git", + "reference": "6874d171318a8e93eb6d224cf85e4678490b625c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c", + "reference": "6874d171318a8e93eb6d224cf85e4678490b625c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Parser": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Interchangeable parsers used by Guzzle", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "URI Template", + "cookie", + "http", + "message", + "url" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-02-05T18:29:46+00:00" + }, + { + "name": "guzzle/plugin-cookie", + "version": "v3.9.2", + "target-dir": "Guzzle/Plugin/Cookie", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/plugin-cookie.git", + "reference": "d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/plugin-cookie/zipball/d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589", + "reference": "d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589", + "shasum": "" + }, + "require": { + "guzzle/http": "self.version", + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Plugin\\Cookie": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle cookie plugin", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "plugin" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-02-07T18:36:58+00:00" + }, + { + "name": "guzzle/stream", + "version": "v3.9.2", + "target-dir": "Guzzle/Stream", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/stream.git", + "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/stream/zipball/60c7fed02e98d2c518dae8f97874c8f4622100f0", + "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0", + "shasum": "" + }, + "require": { + "guzzle/common": "self.version", + "php": ">=5.3.2" + }, + "suggest": { + "guzzle/http": "To convert Guzzle request objects to PHP streams" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Stream": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle stream wrapper component", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "component", + "stream" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-05-01T21:36:02+00:00" + }, + { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, + { + "name": "omnipay/common", + "version": "v2.3.3", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/omnipay-common.git", + "reference": "e4c54a314a2529c1008ad3f77e9eef26ed1f311b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/omnipay-common/zipball/e4c54a314a2529c1008ad3f77e9eef26ed1f311b", + "reference": "e4c54a314a2529c1008ad3f77e9eef26ed1f311b", + "shasum": "" + }, + "require": { + "guzzle/http": "~3.1", + "php": ">=5.3.2", + "symfony/http-foundation": "~2.1" + }, + "require-dev": { + "omnipay/tests": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + }, + "gateways": [ + "AuthorizeNet_AIM", + "AuthorizeNet_SIM", + "Buckaroo", + "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", + "TwoCheckout", + "WorldPay", + "Alipay Bank", + "AliPay Dual Func", + "Alipay Express", + "Alipay Mobile Express", + "Alipay Secured", + "Alipay Wap Express", + "Cybersource", + "DataCash", + "Ecopayz", + "Neteller", + "Pacnet", + "PaymentSense", + "Realex Remote", + "SecPay (PayPoint.net)", + "Sisow", + "Skrill", + "YandexMoney", + "YandexMoneyIndividual" + ] + }, + "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": "2015-01-11T04:54:29+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.3.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/271d8c27c3ec5ecee6e2ac06016232e249d638d9", + "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~3.3", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-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": "2017-11-05T15:47:03+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v2.8.31", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "984fa8301472a2857b1b2397f7ad1126fb83b229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/984fa8301472a2857b1b2397f7ad1126fb83b229", + "reference": "984fa8301472a2857b1b2397f7ad1126fb83b229", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php54": "~1.0", + "symfony/polyfill-php55": "~1.0" + }, + "require-dev": { + "symfony/expression-language": "~2.4|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-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": "2017-11-13T18:11:59+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-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": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/polyfill-php54", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/d7810a14b2c6c1aff415e1bb755f611b3d5327bc", + "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php54\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "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 backporting some PHP 5.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/b64e7f0c37ecf144ecc16668936eef94e628fbfd", + "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd", + "shasum": "" + }, + "require": { + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + }, + "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 backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-10-11T12:05:26+00:00" + } + ], + "packages-dev": [ + { + "name": "guzzle/plugin-mock", + "version": "v3.9.2", + "target-dir": "Guzzle/Plugin/Mock", + "source": { + "type": "git", + "url": "https://github.com/Guzzle3/plugin-mock.git", + "reference": "36efdbf98fb3fbffb0942bc91fad749fbcffe0a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Guzzle3/plugin-mock/zipball/36efdbf98fb3fbffb0942bc91fad749fbcffe0a6", + "reference": "36efdbf98fb3fbffb0942bc91fad749fbcffe0a6", + "shasum": "" + }, + "require": { + "guzzle/http": "self.version", + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7-dev" + } + }, + "autoload": { + "psr-0": { + "Guzzle\\Plugin\\Mock": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle Mock plugin", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "mock", + "plugin" + ], + "abandoned": "guzzle/guzzle", + "time": "2014-02-25T04:11:22+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", + "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "1.3.3", + "satooshi/php-coveralls": "dev-master" + }, + "type": "library", + "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": "2015-05-11T14:41:42+00:00" + }, + { + "name": "mockery/mockery", + "version": "0.9.9", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", + "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": "2017-02-28T12:52:32+00:00" + }, + { + "name": "omnipay/tests", + "version": "v2.1.0", + "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-07T09:35:23+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "1.2.18", + "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-02T10:13:14+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "8ebba84e5bd74fc5fdeb916b38749016c7232f93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/8ebba84e5bd74fc5fdeb916b38749016c7232f93", + "reference": "8ebba84e5bd74fc5fdeb916b38749016c7232f93", + "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": "2017-11-24T15:00:59+00:00" + }, + { + "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-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-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": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2017-02-26T11:10:40+00:00" + }, + { + "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-03T05:10:30+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "3.7.38", + "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-17T09:04:17+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "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": "2013-01-13T10:24:48+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "1.5.6", + "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-04T22:32:15+00:00" + }, + { + "name": "symfony/yaml", + "version": "v2.8.31", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "d819bf267e901727141fe828ae888486fd21236e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d819bf267e901727141fe828ae888486fd21236e", + "reference": "d819bf267e901727141fe828ae888486fd21236e", + "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": "2017-11-05T15:25:56+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^5.6|^7" + }, + "platform-dev": [] +} From 2c6a74e2e0861b49032593c7be7cdfd24e5b3c88 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 10:41:45 +0000 Subject: [PATCH 03/17] GP-860 - remove composer.lock for consistency with other adapters --- composer.lock | 1434 ------------------------------------------------- 1 file changed, 1434 deletions(-) delete mode 100644 composer.lock diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 420a2b3..0000000 --- a/composer.lock +++ /dev/null @@ -1,1434 +0,0 @@ -{ - "_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" - ], - "content-hash": "e9c6517d5e4611757382faacafdd311c", - "packages": [ - { - "name": "guzzle/common", - "version": "v3.9.2", - "target-dir": "Guzzle/Common", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/common.git", - "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/common/zipball/2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc", - "reference": "2e36af7cf2ce3ea1f2d7c2831843b883a8e7b7dc", - "shasum": "" - }, - "require": { - "php": ">=5.3.2", - "symfony/event-dispatcher": ">=2.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Common": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Common libraries used by Guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "collection", - "common", - "event", - "exception" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-08-11T04:32:36+00:00" - }, - { - "name": "guzzle/http", - "version": "v3.9.2", - "target-dir": "Guzzle/Http", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/http.git", - "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/http/zipball/1e8dd1e2ba9dc42332396f39fbfab950b2301dc5", - "reference": "1e8dd1e2ba9dc42332396f39fbfab950b2301dc5", - "shasum": "" - }, - "require": { - "guzzle/common": "self.version", - "guzzle/parser": "self.version", - "guzzle/stream": "self.version", - "php": ">=5.3.2" - }, - "suggest": { - "ext-curl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Http": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "HTTP libraries used by Guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "client", - "curl", - "http", - "http client" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-08-11T04:32:36+00:00" - }, - { - "name": "guzzle/parser", - "version": "v3.9.2", - "target-dir": "Guzzle/Parser", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/parser.git", - "reference": "6874d171318a8e93eb6d224cf85e4678490b625c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/parser/zipball/6874d171318a8e93eb6d224cf85e4678490b625c", - "reference": "6874d171318a8e93eb6d224cf85e4678490b625c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Parser": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Interchangeable parsers used by Guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "URI Template", - "cookie", - "http", - "message", - "url" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-02-05T18:29:46+00:00" - }, - { - "name": "guzzle/plugin-cookie", - "version": "v3.9.2", - "target-dir": "Guzzle/Plugin/Cookie", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/plugin-cookie.git", - "reference": "d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/plugin-cookie/zipball/d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589", - "reference": "d8c3bee4152e7888d7bd7b1718f0ec40ee7d6589", - "shasum": "" - }, - "require": { - "guzzle/http": "self.version", - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Plugin\\Cookie": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle cookie plugin", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "plugin" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-02-07T18:36:58+00:00" - }, - { - "name": "guzzle/stream", - "version": "v3.9.2", - "target-dir": "Guzzle/Stream", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/stream.git", - "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/stream/zipball/60c7fed02e98d2c518dae8f97874c8f4622100f0", - "reference": "60c7fed02e98d2c518dae8f97874c8f4622100f0", - "shasum": "" - }, - "require": { - "guzzle/common": "self.version", - "php": ">=5.3.2" - }, - "suggest": { - "guzzle/http": "To convert Guzzle request objects to PHP streams" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Stream": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle stream wrapper component", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "component", - "stream" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-05-01T21:36:02+00:00" - }, - { - "name": "ircmaxell/password-compat", - "version": "v1.0.4", - "source": { - "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "4.*" - }, - "type": "library", - "autoload": { - "files": [ - "lib/password.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" - } - ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", - "keywords": [ - "hashing", - "password" - ], - "time": "2014-11-20T16:49:30+00:00" - }, - { - "name": "omnipay/common", - "version": "v2.3.3", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/omnipay-common.git", - "reference": "e4c54a314a2529c1008ad3f77e9eef26ed1f311b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/omnipay-common/zipball/e4c54a314a2529c1008ad3f77e9eef26ed1f311b", - "reference": "e4c54a314a2529c1008ad3f77e9eef26ed1f311b", - "shasum": "" - }, - "require": { - "guzzle/http": "~3.1", - "php": ">=5.3.2", - "symfony/http-foundation": "~2.1" - }, - "require-dev": { - "omnipay/tests": "~2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - }, - "gateways": [ - "AuthorizeNet_AIM", - "AuthorizeNet_SIM", - "Buckaroo", - "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", - "TwoCheckout", - "WorldPay", - "Alipay Bank", - "AliPay Dual Func", - "Alipay Express", - "Alipay Mobile Express", - "Alipay Secured", - "Alipay Wap Express", - "Cybersource", - "DataCash", - "Ecopayz", - "Neteller", - "Pacnet", - "PaymentSense", - "Realex Remote", - "SecPay (PayPoint.net)", - "Sisow", - "Skrill", - "YandexMoney", - "YandexMoneyIndividual" - ] - }, - "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": "2015-01-11T04:54:29+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v3.3.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/271d8c27c3ec5ecee6e2ac06016232e249d638d9", - "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-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": "2017-11-05T15:47:03+00:00" - }, - { - "name": "symfony/http-foundation", - "version": "v2.8.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "984fa8301472a2857b1b2397f7ad1126fb83b229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/984fa8301472a2857b1b2397f7ad1126fb83b229", - "reference": "984fa8301472a2857b1b2397f7ad1126fb83b229", - "shasum": "" - }, - "require": { - "php": ">=5.3.9", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php54": "~1.0", - "symfony/polyfill-php55": "~1.0" - }, - "require-dev": { - "symfony/expression-language": "~2.4|~3.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-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": "2017-11-13T18:11:59+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-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": "2017-10-11T12:05:26+00:00" - }, - { - "name": "symfony/polyfill-php54", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php54.git", - "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/d7810a14b2c6c1aff415e1bb755f611b3d5327bc", - "reference": "d7810a14b2c6c1aff415e1bb755f611b3d5327bc", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php54\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "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 backporting some PHP 5.4+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2017-10-11T12:05:26+00:00" - }, - { - "name": "symfony/polyfill-php55", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php55.git", - "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/b64e7f0c37ecf144ecc16668936eef94e628fbfd", - "reference": "b64e7f0c37ecf144ecc16668936eef94e628fbfd", - "shasum": "" - }, - "require": { - "ircmaxell/password-compat": "~1.0", - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php55\\": "" - }, - "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 backporting some PHP 5.5+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2017-10-11T12:05:26+00:00" - } - ], - "packages-dev": [ - { - "name": "guzzle/plugin-mock", - "version": "v3.9.2", - "target-dir": "Guzzle/Plugin/Mock", - "source": { - "type": "git", - "url": "https://github.com/Guzzle3/plugin-mock.git", - "reference": "36efdbf98fb3fbffb0942bc91fad749fbcffe0a6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Guzzle3/plugin-mock/zipball/36efdbf98fb3fbffb0942bc91fad749fbcffe0a6", - "reference": "36efdbf98fb3fbffb0942bc91fad749fbcffe0a6", - "shasum": "" - }, - "require": { - "guzzle/http": "self.version", - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle\\Plugin\\Mock": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle Mock plugin", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "Guzzle", - "mock", - "plugin" - ], - "abandoned": "guzzle/guzzle", - "time": "2014-02-25T04:11:22+00:00" - }, - { - "name": "hamcrest/hamcrest-php", - "version": "v1.2.2", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", - "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpunit/php-file-iterator": "1.3.3", - "satooshi/php-coveralls": "dev-master" - }, - "type": "library", - "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": "2015-05-11T14:41:42+00:00" - }, - { - "name": "mockery/mockery", - "version": "0.9.9", - "source": { - "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", - "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", - "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": "2017-02-28T12:52:32+00:00" - }, - { - "name": "omnipay/tests", - "version": "v2.1.0", - "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-07T09:35:23+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "1.2.18", - "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-02T10:13:14+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "8ebba84e5bd74fc5fdeb916b38749016c7232f93" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/8ebba84e5bd74fc5fdeb916b38749016c7232f93", - "reference": "8ebba84e5bd74fc5fdeb916b38749016c7232f93", - "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": "2017-11-24T15:00:59+00:00" - }, - { - "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-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-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": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "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-03T05:10:30+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "3.7.38", - "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-17T09:04:17+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "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": "2013-01-13T10:24:48+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "1.5.6", - "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-04T22:32:15+00:00" - }, - { - "name": "symfony/yaml", - "version": "v2.8.31", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "d819bf267e901727141fe828ae888486fd21236e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/d819bf267e901727141fe828ae888486fd21236e", - "reference": "d819bf267e901727141fe828ae888486fd21236e", - "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": "2017-11-05T15:25:56+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^5.6|^7" - }, - "platform-dev": [] -} From 39f1cf82d900979cc79a402693d9aefe8e7b0a69 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 10:42:01 +0000 Subject: [PATCH 04/17] GP-860 - ignore future `composer.lock`s for consistency with other adapters --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8ef0e14..7d6c274 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ vendor/ .idea/ + +# Ignore version lock file as lib's not standalone +composer.lock From 5581fe72772b720199afc4d8a05028f113eca95e Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 10:46:02 +0000 Subject: [PATCH 05/17] GP-860 - explicitly test `ApplePayCreditCard::getBrand()` --- tests/Omnipay/WorldPayXML/GatewayTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Omnipay/WorldPayXML/GatewayTest.php b/tests/Omnipay/WorldPayXML/GatewayTest.php index 02c8596..4efec4b 100755 --- a/tests/Omnipay/WorldPayXML/GatewayTest.php +++ b/tests/Omnipay/WorldPayXML/GatewayTest.php @@ -54,6 +54,10 @@ public function testPurchaseError() public function testApplePaySuccess() { + $card = new ApplePayCreditCard(); + + $this->assertEquals('apple', $card->getBrand()); + $applePayOptions = array( 'amount' => '10.00', 'card' => new ApplePayCreditCard(), From 14d1a58590e48227a2bebd819ec449bfd6db47ea Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 10:50:14 +0000 Subject: [PATCH 06/17] Update PHP minimum version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ecf179..d52eb5f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **WorldPay XML Direct driver for the Omnipay PHP payment processing library** [Omnipay](https://github.com/omnipay/omnipay) is a framework agnostic, -multi-gateway payment processing library for PHP 5.3+. This package implements +multi-gateway payment processing library for PHP 5.6+. This package implements WorldPay XML Direct support for Omnipay. ## Installation From 4d2da2afeefa6febd3166bb6c39878aaed29e67b Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 10:54:08 +0000 Subject: [PATCH 07/17] GP-860 - change name to `comicrelief` for Packagist for dev branch --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3a6b263..7e4e0b1 100755 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "teaandcode/omnipay-worldpay-xml", + "name": "comicrelief/omnipay-worldpay-xml", "type": "library", "description": "WorldPay XML driver for the Omnipay payment processing library", "keywords": [ @@ -10,7 +10,7 @@ "worldpay", "payment" ], - "homepage": "https://github.com/teaandcode/omnipay-worldpay-xml", + "homepage": "https://github.com/comicrelief/omnipay-worldpay-xml", "license": "MIT", "authors": [ { From 76b19c2220cd82349c72aa8a0c92e0b04ce7bf85 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 12:52:17 +0000 Subject: [PATCH 08/17] GP-860 - Create Apple Pay payload in correct format. Unit test Apple and regular card `PurchaseRequest` payload creation. --- .../WorldPayXML/Message/PurchaseRequest.php | 41 ++++----- .../Message/PurchaseRequestTest.php | 92 +++++++++++++++++++ 2 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php diff --git a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php index 43a1388..a43ff20 100755 --- a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php +++ b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php @@ -326,7 +326,7 @@ public function getData() $payment = $order->addChild('paymentDetails'); - $codes = array( + $codes = [ CreditCard::BRAND_AMEX => 'AMEX-SSL', CreditCard::BRAND_DANKORT => 'DANKORT-SSL', CreditCard::BRAND_DINERS_CLUB => 'DINERS-SSL', @@ -337,23 +337,24 @@ public function getData() CreditCard::BRAND_MASTERCARD => 'ECMC-SSL', CreditCard::BRAND_SWITCH => 'MAESTRO-SSL', CreditCard::BRAND_VISA => 'VISA-SSL' - ); + ]; if ($this->getCard()->getBrand() === 'apple') { // With Apple Pay we have no card number so can't pattern match via getBrand() $card = $payment->addChild('APPLEPAY-SSL'); - $appleData = $this->getAppleToken(); - - $card->addAttribute('data', $appleData['paymentData']['data']); - $card->addAttribute('signature', $appleData['paymentData']['signature']); - $card->addAttribute('version', $appleData['paymentData']['version']); + $appleData = $this->getAppleToken()['paymentData']; $header = $card->addChild('header'); - $header->addAttribute('applicationData', $appleData['paymentData']['header']['applicationData']); - $header->addAttribute('ephemeralPublicKey', $appleData['paymentData']['header']['ephemeralPublicKey']); - $header->addAttribute('publicKeyHash', $appleData['paymentData']['header']['publicKeyHash']); - $header->addAttribute('transactionId', $appleData['paymentData']['header']['transactionId']); + + $header->addChild('applicationData', $appleData['header']['applicationData']); + $header->addChild('ephemeralPublicKey', $appleData['header']['ephemeralPublicKey']); + $header->addChild('publicKeyHash', $appleData['header']['publicKeyHash']); + $header->addChild('transactionId', $appleData['header']['transactionId']); + + $card->addChild('data', $appleData['data']); + $card->addChild('signature', $appleData['signature']); + $card->addChild('version', $appleData['version']); } else { $card = $payment->addChild($codes[$this->getCard()->getBrand()]); $card->addChild('cardNumber', $this->getCard()->getNumber()); @@ -446,10 +447,10 @@ public function sendData($data) $this->getMerchant() . ':' . $this->getPassword() ); - $headers = array( + $headers = [ 'Authorization' => 'Basic ' . $authorisation, 'Content-Type' => 'text/xml; charset=utf-8' - ); + ]; $cookieJar = new ArrayCookieJar(); @@ -459,14 +460,12 @@ public function sendData($data) $url = parse_url($this->getEndpoint()); $cookieJar->add( - new Cookie( - array( - 'domain' => $url['host'], - 'name' => 'machine', - 'path' => '/', - 'value' => $redirectCookie - ) - ) + new Cookie([ + 'domain' => $url['host'], + 'name' => 'machine', + 'path' => '/', + 'value' => $redirectCookie + ]) ); } diff --git a/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php b/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php new file mode 100644 index 0000000..324f044 --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php @@ -0,0 +1,92 @@ +purchase = new PurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->purchase->setAmount(7.45); + $this->purchase->setCurrency('GBP'); + } + + public function testDirectCardPayload() + { + $this->purchase->setCard(new CreditCard([ + 'billingFirstName' => 'Vince', + 'billingLastName' => 'Staples', + 'shippingFirstName' => 'Vince', + 'shippingLastName' => 'Staples', + 'email' => 'cr+vs@noellh.com', + 'address1' => '745 THORNBURY CLOSE', + 'address2' => '', + 'city' => 'LONDON', + 'country' => 'GB', + 'postcode' => 'N16 8UX', + 'number' => '4111111111111111', + 'expiryMonth' => '12', + 'expiryYear' => '2026', + 'cvv' => '123', + ])); + + $data = $this->purchase->getData(); + + $this->assertEquals('745', $data->submit->order->amount->attributes()['value']); + $this->assertEquals('GBP', $data->submit->order->amount->attributes()['currencyCode']); + $this->assertEquals('2', $data->submit->order->amount->attributes()['exponent']); + $this->assertEquals('745 THORNBURY CLOSE', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->street); + $this->assertEquals('N16 8UX', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->postalCode); + $this->assertEquals('GB', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->countryCode); + + $this->assertEquals('4111111111111111', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardNumber); + $this->assertEquals('12', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->expiryDate->date->attributes()['month']); + $this->assertEquals('2026', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->expiryDate->date->attributes()['year']); + $this->assertEquals('123', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cvc); + } + + public function testApplePayPayload() + { + $this->purchase->setCard(new ApplePayCreditCard()); + $this->purchase->setAppleToken([ + 'transactionIdentifier' => '5394..00', + 'paymentData' => [ + 'data' => 'kdHd..GQ==', + 'signature' => 'MIAGCSqGSIb3DQEH...AAA', + 'version' => 'EC_v1', + 'header' => [ + 'applicationData' => '94ee0..C2', + 'ephemeralPublicKey' => 'MFkwE..Q==', + 'publicKeyHash' => 'dxCK..6o=', + 'transactionId' => 'd3b28af..f8', + ], + ], + ]); + + $data = $this->purchase->getData(); + + $this->assertEquals('745', $data->submit->order->amount->attributes()['value']); + $this->assertEquals('GBP', $data->submit->order->amount->attributes()['currencyCode']); + $this->assertEquals('2', $data->submit->order->amount->attributes()['exponent']); + + $this->assertEquals('kdHd..GQ==', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->data); + $this->assertEquals('94ee0..C2', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->applicationData); + $this->assertEquals('MFkwE..Q==', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->ephemeralPublicKey); + $this->assertEquals('dxCK..6o=', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->publicKeyHash); + $this->assertEquals('d3b28af..f8', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->transactionId); + $this->assertEquals('MIAGCSqGSIb3DQEH...AAA', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->signature); + $this->assertEquals('EC_v1', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->version); + + $this->assertEmpty($data->submit->order->billingAddress); + } +} From fd726898e7111c857385fcc47c6851d8d20e89f7 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 12:52:42 +0000 Subject: [PATCH 09/17] Code style updates --- src/Omnipay/WorldPayXML/Gateway.php | 8 ++-- .../WorldPayXML/Message/RedirectResponse.php | 4 +- src/Omnipay/WorldPayXML/Message/Response.php | 4 +- tests/Omnipay/WorldPayXML/GatewayTest.php | 38 +++++++++---------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/Omnipay/WorldPayXML/Gateway.php b/src/Omnipay/WorldPayXML/Gateway.php index 62e7d2b..5ef7fec 100755 --- a/src/Omnipay/WorldPayXML/Gateway.php +++ b/src/Omnipay/WorldPayXML/Gateway.php @@ -30,12 +30,12 @@ public function getName() */ public function getDefaultParameters() { - return array( + return [ 'installation' => '', 'merchant' => '', 'password' => '', 'testMode' => false, - ); + ]; } /** @@ -286,10 +286,10 @@ public function setUserIP($value) * @access public * @return \Omnipay\WorldPayXML\Message\PurchaseRequest */ - public function purchase(array $parameters = array()) + public function purchase(array $parameters = []) { return $this->createRequest( - '\Omnipay\WorldPayXML\Message\PurchaseRequest', + \Omnipay\WorldPayXML\Message\PurchaseRequest::class, $parameters ); } diff --git a/src/Omnipay/WorldPayXML/Message/RedirectResponse.php b/src/Omnipay/WorldPayXML/Message/RedirectResponse.php index 2d98c38..36690fe 100755 --- a/src/Omnipay/WorldPayXML/Message/RedirectResponse.php +++ b/src/Omnipay/WorldPayXML/Message/RedirectResponse.php @@ -47,10 +47,10 @@ public function getRedirectEcho() */ public function getRedirectData() { - return array( + return [ 'PaReq' => $this->data->requestInfo->request3DSecure->paRequest, 'TermUrl' => $this->request->getTermUrl() - ); + ]; } /** diff --git a/src/Omnipay/WorldPayXML/Message/Response.php b/src/Omnipay/WorldPayXML/Message/Response.php index 0cfb834..2ffd773 100755 --- a/src/Omnipay/WorldPayXML/Message/Response.php +++ b/src/Omnipay/WorldPayXML/Message/Response.php @@ -44,7 +44,7 @@ public function __construct(RequestInterface $request, $data) */ public function getMessage() { - $codes = array( + $codes = [ 0 => 'AUTHORISED', 2 => 'REFERRED', 3 => 'INVALID ACCEPTOR', @@ -90,7 +90,7 @@ public function getMessage() 92 => 'CREDITCARD TYPE NOT PROCESSED BY ACQUIRER', 94 => 'DUPLICATE REQUEST ERROR', 97 => 'SECURITY BREACH' - ); + ]; $message = 'PENDING'; diff --git a/tests/Omnipay/WorldPayXML/GatewayTest.php b/tests/Omnipay/WorldPayXML/GatewayTest.php index 4efec4b..5f29dee 100755 --- a/tests/Omnipay/WorldPayXML/GatewayTest.php +++ b/tests/Omnipay/WorldPayXML/GatewayTest.php @@ -16,20 +16,18 @@ public function setUp() $this->getHttpRequest() ); - $this->options = array( + $this->options = [ 'amount' => '10.00', - 'card' => new CreditCard( - array( - 'firstName' => 'Example', - 'lastName' => 'User', - 'number' => '4111111111111111', - 'expiryMonth' => '12', - 'expiryYear' => '2026', - 'cvv' => '123', - ) - ), + 'card' => new CreditCard([ + 'firstName' => 'Example', + 'lastName' => 'User', + 'number' => '4111111111111111', + 'expiryMonth' => '12', + 'expiryYear' => '2026', + 'cvv' => '123', + ]), 'transactionId' => 'T0211010', - ); + ]; } public function testPurchaseSuccess() @@ -58,25 +56,25 @@ public function testApplePaySuccess() $this->assertEquals('apple', $card->getBrand()); - $applePayOptions = array( + $applePayOptions = [ 'amount' => '10.00', 'card' => new ApplePayCreditCard(), - 'appleToken' => array( + 'appleToken' => [ 'transactionIdentifier' => '5394..00', - 'paymentData' => array( + 'paymentData' => [ 'data' => 'kdHd..GQ==', 'signature' => 'MIAGCSqGSIb3DQEH...AAA', 'version' => 'EC_v1', - 'header' => array( + 'header' => [ 'applicationData' => '94ee0..C2', 'ephemeralPublicKey' => 'MFkwE..Q==', 'publicKeyHash' => 'dxCK..6o=', 'transactionId' => 'd3b28af..f8', - ), - ), - ), + ], + ], + ], 'transactionId' => 'T0211010', - ); + ]; $this->setMockHttpResponse('PurchaseSuccessApplePay.txt'); From 59bbf8614de2ac34ecab496ba51bb3fb8aa83639 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 13:00:27 +0000 Subject: [PATCH 10/17] GP-860 - Define `composer test` for Travis, including PSR2 style check. Fix line length style violations. --- composer.json | 13 ++++++++ .../Message/PurchaseRequestTest.php | 31 ++++++++++--------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 7e4e0b1..3f2d626 100755 --- a/composer.json +++ b/composer.json @@ -33,9 +33,22 @@ "require-dev": { "omnipay/tests": "~2.0" }, + "scripts": { + "test": [ + "phpunit", + "@lint" + ], + "lint": [ + "phpcs --standard=PSR2 --encoding=utf-8 src tests" + ] + }, "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } + }, + "config": { + "optimize-autoloader": true, + "sort-packages": true } } diff --git a/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php b/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php index 324f044..6997539 100644 --- a/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php +++ b/tests/Omnipay/WorldPayXML/Message/PurchaseRequestTest.php @@ -45,14 +45,16 @@ public function testDirectCardPayload() $this->assertEquals('745', $data->submit->order->amount->attributes()['value']); $this->assertEquals('GBP', $data->submit->order->amount->attributes()['currencyCode']); $this->assertEquals('2', $data->submit->order->amount->attributes()['exponent']); - $this->assertEquals('745 THORNBURY CLOSE', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->street); - $this->assertEquals('N16 8UX', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->postalCode); - $this->assertEquals('GB', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardAddress->address->countryCode); - $this->assertEquals('4111111111111111', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cardNumber); - $this->assertEquals('12', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->expiryDate->date->attributes()['month']); - $this->assertEquals('2026', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->expiryDate->date->attributes()['year']); - $this->assertEquals('123', (string) $data->submit->order->paymentDetails->{'VISA-SSL'}->cvc); + $visaDetails = $data->submit->order->paymentDetails->{'VISA-SSL'}; + $this->assertEquals('745 THORNBURY CLOSE', $visaDetails->cardAddress->address->street); + $this->assertEquals('N16 8UX', $visaDetails->cardAddress->address->postalCode); + $this->assertEquals('GB', $visaDetails->cardAddress->address->countryCode); + + $this->assertEquals('4111111111111111', $visaDetails->cardNumber); + $this->assertEquals('12', $visaDetails->expiryDate->date->attributes()['month']); + $this->assertEquals('2026', $visaDetails->expiryDate->date->attributes()['year']); + $this->assertEquals('123', $visaDetails->cvc); } public function testApplePayPayload() @@ -79,13 +81,14 @@ public function testApplePayPayload() $this->assertEquals('GBP', $data->submit->order->amount->attributes()['currencyCode']); $this->assertEquals('2', $data->submit->order->amount->attributes()['exponent']); - $this->assertEquals('kdHd..GQ==', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->data); - $this->assertEquals('94ee0..C2', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->applicationData); - $this->assertEquals('MFkwE..Q==', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->ephemeralPublicKey); - $this->assertEquals('dxCK..6o=', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->publicKeyHash); - $this->assertEquals('d3b28af..f8', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->header->transactionId); - $this->assertEquals('MIAGCSqGSIb3DQEH...AAA', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->signature); - $this->assertEquals('EC_v1', $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}->version); + $appleDetails = $data->submit->order->paymentDetails->{'APPLEPAY-SSL'}; + $this->assertEquals('kdHd..GQ==', $appleDetails->data); + $this->assertEquals('94ee0..C2', $appleDetails->header->applicationData); + $this->assertEquals('MFkwE..Q==', $appleDetails->header->ephemeralPublicKey); + $this->assertEquals('dxCK..6o=', $appleDetails->header->publicKeyHash); + $this->assertEquals('d3b28af..f8', $appleDetails->header->transactionId); + $this->assertEquals('MIAGCSqGSIb3DQEH...AAA', $appleDetails->signature); + $this->assertEquals('EC_v1', $appleDetails->version); $this->assertEmpty($data->submit->order->billingAddress); } From 48f56d9481fab53a0d4d9331f6ffb6c17e69fa33 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 13:45:42 +0000 Subject: [PATCH 11/17] GP-860 - separately unit test getters from loaded Apple Pay mock success response --- .../Omnipay/WorldPayXML/Message/ResponseTest.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/Omnipay/WorldPayXML/Message/ResponseTest.php b/tests/Omnipay/WorldPayXML/Message/ResponseTest.php index 3e98db8..70a9d3b 100755 --- a/tests/Omnipay/WorldPayXML/Message/ResponseTest.php +++ b/tests/Omnipay/WorldPayXML/Message/ResponseTest.php @@ -7,7 +7,7 @@ class ResponseTest extends TestCase { /** - * @expectedException Omnipay\Common\Exception\InvalidResponseException + * @expectedException \Omnipay\Common\Exception\InvalidResponseException */ public function testConstructEmpty() { @@ -28,6 +28,20 @@ public function testPurchaseSuccess() $this->assertEquals('AUTHORISED', $response->getMessage()); } + public function testPurchaseSuccessApplePay() + { + $httpResponse = $this->getMockHttpResponse('PurchaseSuccessApplePay.txt'); + $response = new Response( + $this->getMockRequest(), + $httpResponse->getBody() + ); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertEquals('T0211011', $response->getTransactionReference()); + $this->assertEquals('AUTHORISED', $response->getMessage()); + } + public function testPurchaseFailure() { $httpResponse = $this->getMockHttpResponse('PurchaseFailure.txt'); From caa6f21367ba6fb7640fade2dd76ee3ed73c8e37 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Tue, 28 Nov 2017 15:48:49 +0000 Subject: [PATCH 12/17] Return Composer name & home to `teaandcode` org, to enable merging to original repo --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 3f2d626..7b6621c 100755 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "comicrelief/omnipay-worldpay-xml", + "name": "teaandcode/omnipay-worldpay-xml", "type": "library", "description": "WorldPay XML driver for the Omnipay payment processing library", "keywords": [ @@ -10,7 +10,7 @@ "worldpay", "payment" ], - "homepage": "https://github.com/comicrelief/omnipay-worldpay-xml", + "homepage": "https://github.com/teaandcode/omnipay-worldpay-xml", "license": "MIT", "authors": [ { From ee6e58dbb43bbba3a02499ac83ec76380dc5f7e8 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 29 Nov 2017 15:23:44 +0000 Subject: [PATCH 13/17] GP-860 - Port features from `comicrelief/omnipay-worldpay-cg-hosted`: * Support more secure 'username', distinct from merchant code * Detect and handle errors better, especially generic CDATA text in an --- src/Omnipay/WorldPayXML/Gateway.php | 22 +++ .../WorldPayXML/Message/PurchaseRequest.php | 23 +++- src/Omnipay/WorldPayXML/Message/Response.php | 125 +++++++++++++----- tests/Omnipay/WorldPayXML/GatewayTest.php | 42 +++++- .../WorldPayXML/Message/ResponseTest.php | 62 +++++++++ .../Mock/PurchaseErrorDuplicateOrder.txt | 11 ++ .../WorldPayXML/Mock/PurchaseErrorGeneric.txt | 11 ++ .../Mock/PurchaseErrorSecurityViolation.txt | 11 ++ .../Mock/PurchaseUnauthenticated.txt | 28 ++++ 9 files changed, 297 insertions(+), 38 deletions(-) create mode 100755 tests/Omnipay/WorldPayXML/Mock/PurchaseErrorDuplicateOrder.txt create mode 100755 tests/Omnipay/WorldPayXML/Mock/PurchaseErrorGeneric.txt create mode 100755 tests/Omnipay/WorldPayXML/Mock/PurchaseErrorSecurityViolation.txt create mode 100755 tests/Omnipay/WorldPayXML/Mock/PurchaseUnauthenticated.txt diff --git a/src/Omnipay/WorldPayXML/Gateway.php b/src/Omnipay/WorldPayXML/Gateway.php index 5ef7fec..92ae800 100755 --- a/src/Omnipay/WorldPayXML/Gateway.php +++ b/src/Omnipay/WorldPayXML/Gateway.php @@ -134,6 +134,28 @@ public function setPaResponse($value) return $this->setParameter('pa_response', $value); } + + /** + * Get the separate username if configured (more secure approach for basic auth) or fallback to merchant if not + * + * @return string + */ + public function getUsername() + { + return $this->parameters->get('username', $this->getParameter('merchant')); + } + + /** + * Set basic auth username + * + * @param string $value + * @return Gateway + */ + public function setUsername($value) + { + return $this->setParameter('username', $value); + } + /** * Get password * diff --git a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php index a43ff20..483be17 100755 --- a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php +++ b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php @@ -110,6 +110,27 @@ public function setMerchant($value) return $this->setParameter('merchant', $value); } + /** + * Get the separate username if configured (more secure approach for basic auth) or fallback to merchant if not + * + * @return string + */ + public function getUsername() + { + return $this->parameters->get('username', $this->getParameter('merchant')); + } + + /** + * Set basic auth username + * + * @param string $value + * @return AbstractRequest + */ + public function setUsername($value) + { + return $this->setParameter('username', $value); + } + /** * Get pa response * @@ -444,7 +465,7 @@ public function sendData($data) $document->appendChild($node); $authorisation = base64_encode( - $this->getMerchant() . ':' . $this->getPassword() + $this->getUsername() . ':' . $this->getPassword() ); $headers = [ diff --git a/src/Omnipay/WorldPayXML/Message/Response.php b/src/Omnipay/WorldPayXML/Message/Response.php index 2ffd773..83195b1 100755 --- a/src/Omnipay/WorldPayXML/Message/Response.php +++ b/src/Omnipay/WorldPayXML/Message/Response.php @@ -12,13 +12,21 @@ */ class Response extends AbstractResponse { + /** @var string */ + protected static $PAYMENT_STATUS_AUTHORISED = 'AUTHORISED'; + /** @var string */ + protected static $PAYMENT_STATUS_CAPTURED = 'CAPTURED'; + /** @var string */ + protected static $PAYMENT_STATUS_SETTLED_BY_MERCHANT = 'SETTLED_BY_MERCHANT'; + /** @var string */ + protected static $PAYMENT_STATUS_SENT_FOR_AUTHORISATION = 'SENT_FOR_AUTHORISATION'; + /** @var string */ + protected static $PAYMENT_STATUS_CANCELLED = 'CANCELLED'; + /** - * Constructor - * * @param RequestInterface $request Request * @param string $data Data - * - * @access public + * @throws InvalidResponseException if non-XML response received */ public function __construct(RequestInterface $request, $data) { @@ -29,11 +37,17 @@ public function __construct(RequestInterface $request, $data) } $responseDom = new DOMDocument; - $responseDom->loadXML($data); + if (!@$responseDom->loadXML($data)) { + throw new InvalidResponseException('Non-XML notification response received'); + } - $this->data = simplexml_import_dom( - $responseDom->documentElement->firstChild->firstChild + $this->data = @simplexml_import_dom( + $responseDom->documentElement->firstChild // or ); + + if (empty($this->data)) { + throw new InvalidResponseException('Could not import response XML: ' . $data); + } } /** @@ -92,73 +106,118 @@ public function getMessage() 97 => 'SECURITY BREACH' ]; - $message = 'PENDING'; - if (isset($this->data->error)) { - $message = 'ERROR: ' . $this->data->error; + return 'ERROR: ' . $this->data->error; // Cast to string to get CDATA content } - if (isset($this->data->payment->ISO8583ReturnCode)) { - $returnCode = $this->data->payment->ISO8583ReturnCode->attributes(); + $payment = $this->getOrder()->payment; + if (isset($payment->ISO8583ReturnCode)) { + $returnCode = $payment->ISO8583ReturnCode->attributes(); foreach ($returnCode as $name => $value) { if ($name == 'code') { - $message = $codes[intval($value)]; + return $codes[intval($value)]; } } } if ($this->isSuccessful()) { - $message = $codes[0]; + return $codes[0]; } - return $message; + return 'PENDING'; } /** - * Get transaction reference + * Get transaction reference provided with order (the ID in Omnipay parlance), and sent back with notifications. * - * @access public - * @return string + * @return string|null */ - public function getTransactionReference() + public function getTransactionId() { - $attributes = $this->data->attributes(); + if (empty($this->getOrder())) { + return null; + } + + $attributes = $this->getOrder()->attributes(); if (isset($attributes['orderCode'])) { return $attributes['orderCode']; } + + return null; } /** - * Get is redirect + * Get *your* reference a.k.a Omnipay transaction ID (!) * - * @access public - * @return boolean + * @return string + * @deprecated This was named inconsistently with other Omnipay adapters. Use getTransactionId(), whose name + * reflects the actual contents returned. */ - public function isRedirect() + public function getTransactionReference() + { + return $this->getTransactionId(); + } + + /** + * @return string|null + */ + public function getErrorCode() { - if (isset($this->data->requestInfo->request3DSecure->issuerURL)) { - return true; + if (!isset($this->data->error) || empty($this->data->error->attributes()['code'])) { + return null; + } + + return (string) $this->data->error->attributes()['code']; + } + + /** + * @return null|\SimpleXMLElement + */ + public function getOrder() + { + if (isset($this->data->orderStatusEvent)) { + return $this->data->orderStatusEvent; // Notifications + } + + if (isset($this->data->orderStatus)) { + return $this->data->orderStatus; // Order responses } - return false; + return null; } /** - * Get is successful + * Get is redirect * * @access public * @return boolean */ + public function isRedirect() + { + return isset($this->data->requestInfo->request3DSecure->issuerURL); + } + + /** + * Whether transaction's last state indicates success + * + * @return bool + */ public function isSuccessful() { - if (isset($this->data->payment->lastEvent)) { - if (strtoupper($this->data->payment->lastEvent) == 'AUTHORISED') { - return true; - } + if (!isset($this->getOrder()->payment->lastEvent)) { + return false; } - return false; + return in_array( + strtoupper($this->getOrder()->payment->lastEvent), + [ + self::$PAYMENT_STATUS_AUTHORISED, + self::$PAYMENT_STATUS_CAPTURED, + self::$PAYMENT_STATUS_SETTLED_BY_MERCHANT, + ], + true + ); } } diff --git a/tests/Omnipay/WorldPayXML/GatewayTest.php b/tests/Omnipay/WorldPayXML/GatewayTest.php index 5f29dee..403b5fc 100755 --- a/tests/Omnipay/WorldPayXML/GatewayTest.php +++ b/tests/Omnipay/WorldPayXML/GatewayTest.php @@ -7,6 +7,13 @@ class GatewayTest extends GatewayTestCase { + /** @var Gateway */ + protected $gateway; + /** @var array */ + private $parameters; + /** @var CreditCard */ + private $card; + public function setUp() { parent::setUp(); @@ -15,8 +22,11 @@ public function setUp() $this->getHttpClient(), $this->getHttpRequest() ); + $this->gateway->setMerchant('ACMECO'); + $this->gateway->setTestMode(true); + $this->gateway->setInstallation('ABC123'); - $this->options = [ + $this->parameters = [ 'amount' => '10.00', 'card' => new CreditCard([ 'firstName' => 'Example', @@ -34,7 +44,12 @@ public function testPurchaseSuccess() { $this->setMockHttpResponse('PurchaseSuccess.txt'); - $response = $this->gateway->purchase($this->options)->send(); + $purchase = $this->gateway->purchase($this->parameters); + + // Confirm basic auth uses merchant code to authenticate when there's no username. + $this->assertEquals('ACMECO', $purchase->getUsername()); + + $response = $purchase->send(); $this->assertTrue($response->isSuccessful()); $this->assertEquals('T0211010', $response->getTransactionReference()); @@ -44,7 +59,7 @@ public function testPurchaseError() { $this->setMockHttpResponse('PurchaseFailure.txt'); - $response = $this->gateway->purchase($this->options)->send(); + $response = $this->gateway->purchase($this->parameters)->send(); $this->assertFalse($response->isSuccessful()); $this->assertSame('CARD EXPIRED', $response->getMessage()); @@ -78,9 +93,28 @@ public function testApplePaySuccess() $this->setMockHttpResponse('PurchaseSuccessApplePay.txt'); - $response = $this->gateway->purchase($applePayOptions)->send(); + $purchase = $this->gateway->purchase($applePayOptions); + + // Confirm basic auth uses merchant code to authenticate when there's no username. + $this->assertEquals('ACMECO', $purchase->getUsername()); + + $response = $purchase->send(); $this->assertTrue($response->isSuccessful()); $this->assertEquals('T0211011', $response->getTransactionReference()); } + + /** + * Confirm basic auth uses a username when set rather than merchant code. + */ + public function testUsernameAuthSetup() + { + $gatewayWithUsername = clone $this->gateway; + $gatewayWithUsername->setUsername('MYSECRETUSERNAME987'); + + $purchase = $gatewayWithUsername->purchase($this->parameters); + $purchase->setCard($this->card); + + $this->assertEquals('MYSECRETUSERNAME987', $purchase->getUsername()); + } } diff --git a/tests/Omnipay/WorldPayXML/Message/ResponseTest.php b/tests/Omnipay/WorldPayXML/Message/ResponseTest.php index 70a9d3b..71b7770 100755 --- a/tests/Omnipay/WorldPayXML/Message/ResponseTest.php +++ b/tests/Omnipay/WorldPayXML/Message/ResponseTest.php @@ -55,4 +55,66 @@ public function testPurchaseFailure() $this->assertEquals('T0211234', $response->getTransactionReference()); $this->assertSame('CARD EXPIRED', $response->getMessage()); } + + public function testPurchaseErrorGeneric() + { + $httpResponse = $this->getMockHttpResponse('PurchaseErrorGeneric.txt'); + + $response = new Response( + $this->getMockRequest(), + $httpResponse->getBody() + ); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('ERROR: Nasty internal error!', $response->getMessage()); + $this->assertNull($response->getErrorCode()); + } + + public function testPurchaseErrorDuplicateOrder() + { + $httpResponse = $this->getMockHttpResponse('PurchaseErrorDuplicateOrder.txt'); + + $response = new Response( + $this->getMockRequest(), + $httpResponse->getBody() + ); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('ERROR: Duplicate Order', $response->getMessage()); + $this->assertSame('5', $response->getErrorCode()); + } + + /** + * You can get this e.g. if you are authenticated but your merchant code in the body is wrong. + */ + public function testPurchaseErrorSecurityFailure() + { + $httpResponse = $this->getMockHttpResponse('PurchaseErrorSecurityViolation.txt'); + + $response = new Response( + $this->getMockRequest(), + $httpResponse->getBody() + ); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('ERROR: Security violation', $response->getMessage()); + $this->assertSame('4', $response->getErrorCode()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidResponseException + * @expectedExceptionMessage Could not import response XML: + */ + public function testPurchaseUnauthenticated() + { + $httpResponse = $this->getMockHttpResponse('PurchaseUnauthenticated.txt'); + + new Response( + $this->getMockRequest(), + $httpResponse->getBody() + ); + } } diff --git a/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorDuplicateOrder.txt b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorDuplicateOrder.txt new file mode 100755 index 0000000..1738ea6 --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorDuplicateOrder.txt @@ -0,0 +1,11 @@ +HTTP/1.1 200 OK +Connection: close +Server: VPS-3.033.00 +Date: Sat, 23 Feb 2013 05:17:32 GMT +Content-type: text/xml +Content-length: 341 + + + + diff --git a/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorGeneric.txt b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorGeneric.txt new file mode 100755 index 0000000..fa1641f --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorGeneric.txt @@ -0,0 +1,11 @@ +HTTP/1.1 200 OK +Connection: close +Server: VPS-3.033.00 +Date: Sat, 23 Feb 2013 05:17:32 GMT +Content-type: text/xml +Content-length: 376 + + + +Nasty internal error! diff --git a/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorSecurityViolation.txt b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorSecurityViolation.txt new file mode 100755 index 0000000..93fa6c2 --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Mock/PurchaseErrorSecurityViolation.txt @@ -0,0 +1,11 @@ +HTTP/1.1 200 OK +Connection: close +Server: VPS-3.033.00 +Date: Sat, 23 Feb 2013 05:17:32 GMT +Content-type: text/xml +Content-length: 344 + + + + diff --git a/tests/Omnipay/WorldPayXML/Mock/PurchaseUnauthenticated.txt b/tests/Omnipay/WorldPayXML/Mock/PurchaseUnauthenticated.txt new file mode 100755 index 0000000..3f70a89 --- /dev/null +++ b/tests/Omnipay/WorldPayXML/Mock/PurchaseUnauthenticated.txt @@ -0,0 +1,28 @@ +HTTP/1.1 401 Unauthorized +Connection: close +Server: VPS-3.033.00 +Date: Sat, 23 Feb 2013 05:17:32 GMT +Content-type: text/html +Content-length: 767 + + + + + + 401: Requires Authentication + + + + +
+ Requires Authentication +
Status: 401
+

+ This request requires HTTP authentication. + +
+

+
+ + From 4ed3a94a9d7dba7ff7d04ff9878af3d3310cfde3 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 29 Nov 2017 15:33:15 +0000 Subject: [PATCH 14/17] GP-860 - use constants for statuses --- src/Omnipay/WorldPayXML/Message/Response.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Omnipay/WorldPayXML/Message/Response.php b/src/Omnipay/WorldPayXML/Message/Response.php index 83195b1..8012327 100755 --- a/src/Omnipay/WorldPayXML/Message/Response.php +++ b/src/Omnipay/WorldPayXML/Message/Response.php @@ -13,15 +13,15 @@ class Response extends AbstractResponse { /** @var string */ - protected static $PAYMENT_STATUS_AUTHORISED = 'AUTHORISED'; + const PAYMENT_STATUS_AUTHORISED = 'AUTHORISED'; /** @var string */ - protected static $PAYMENT_STATUS_CAPTURED = 'CAPTURED'; + const PAYMENT_STATUS_CAPTURED = 'CAPTURED'; /** @var string */ - protected static $PAYMENT_STATUS_SETTLED_BY_MERCHANT = 'SETTLED_BY_MERCHANT'; + const PAYMENT_STATUS_SETTLED_BY_MERCHANT = 'SETTLED_BY_MERCHANT'; /** @var string */ - protected static $PAYMENT_STATUS_SENT_FOR_AUTHORISATION = 'SENT_FOR_AUTHORISATION'; + const PAYMENT_STATUS_SENT_FOR_AUTHORISATION = 'SENT_FOR_AUTHORISATION'; /** @var string */ - protected static $PAYMENT_STATUS_CANCELLED = 'CANCELLED'; + const PAYMENT_STATUS_CANCELLED = 'CANCELLED'; /** * @param RequestInterface $request Request @@ -213,9 +213,9 @@ public function isSuccessful() return in_array( strtoupper($this->getOrder()->payment->lastEvent), [ - self::$PAYMENT_STATUS_AUTHORISED, - self::$PAYMENT_STATUS_CAPTURED, - self::$PAYMENT_STATUS_SETTLED_BY_MERCHANT, + self::PAYMENT_STATUS_AUTHORISED, + self::PAYMENT_STATUS_CAPTURED, + self::PAYMENT_STATUS_SETTLED_BY_MERCHANT, ], true ); From 33b6dea2830f34ad6df141b75b01136ae5df7644 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Wed, 29 Nov 2017 15:52:14 +0000 Subject: [PATCH 15/17] GP-860 - fix element order and don't add `cardAddress` for Apple Pay --- .../WorldPayXML/Message/PurchaseRequest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php index 483be17..db83b7e 100755 --- a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php +++ b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php @@ -368,14 +368,14 @@ public function getData() $header = $card->addChild('header'); - $header->addChild('applicationData', $appleData['header']['applicationData']); $header->addChild('ephemeralPublicKey', $appleData['header']['ephemeralPublicKey']); $header->addChild('publicKeyHash', $appleData['header']['publicKeyHash']); $header->addChild('transactionId', $appleData['header']['transactionId']); + $header->addChild('applicationData', $appleData['header']['applicationData']); - $card->addChild('data', $appleData['data']); $card->addChild('signature', $appleData['signature']); $card->addChild('version', $appleData['version']); + $card->addChild('data', $appleData['data']); } else { $card = $payment->addChild($codes[$this->getCard()->getBrand()]); $card->addChild('cardNumber', $this->getCard()->getNumber()); @@ -398,12 +398,12 @@ public function getData() } $card->addChild('cvc', $this->getCard()->getCvv()); - } - $address = $card->addChild('cardAddress')->addChild('address'); - $address->addChild('street', $this->getCard()->getAddress1()); - $address->addChild('postalCode', $this->getCard()->getPostcode()); - $address->addChild('countryCode', $this->getCard()->getCountry()); + $address = $card->addChild('cardAddress')->addChild('address'); + $address->addChild('street', $this->getCard()->getAddress1()); + $address->addChild('postalCode', $this->getCard()->getPostcode()); + $address->addChild('countryCode', $this->getCard()->getCountry()); + } $session = $payment->addChild('session'); $session->addAttribute('shopperIPAddress', $this->getClientIP()); From 97758c62ea9bd16cffec0fe82ba85f3d30334010 Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Fri, 1 Dec 2017 15:33:30 +0000 Subject: [PATCH 16/17] Make applicationData optional to reflect Apple and Worldpay properties --- src/Omnipay/WorldPayXML/Message/PurchaseRequest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php index db83b7e..ede14de 100755 --- a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php +++ b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php @@ -371,7 +371,9 @@ public function getData() $header->addChild('ephemeralPublicKey', $appleData['header']['ephemeralPublicKey']); $header->addChild('publicKeyHash', $appleData['header']['publicKeyHash']); $header->addChild('transactionId', $appleData['header']['transactionId']); - $header->addChild('applicationData', $appleData['header']['applicationData']); + if (isset($appleData['header']['applicationData'])) { + $header->addChild('applicationData', $appleData['header']['applicationData']); + } $card->addChild('signature', $appleData['signature']); $card->addChild('version', $appleData['version']); From 27d0181f789da0f2679424415bc909696ce2ef6f Mon Sep 17 00:00:00 2001 From: Noel Light-Hilary Date: Mon, 4 Dec 2017 11:59:33 +0000 Subject: [PATCH 17/17] GP-860 - fix Apple Pay processing breaking due to blank attributes on `` --- .../WorldPayXML/Message/PurchaseRequest.php | 81 ++++++------------- 1 file changed, 25 insertions(+), 56 deletions(-) diff --git a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php index ede14de..50c31fb 100755 --- a/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php +++ b/src/Omnipay/WorldPayXML/Message/PurchaseRequest.php @@ -22,15 +22,12 @@ class PurchaseRequest extends AbstractRequest /** * @var \Guzzle\Plugin\Cookie\CookiePlugin - * - * @access protected */ protected $cookiePlugin; /** * Get accept header * - * @access public * @return string */ public function getAcceptHeader() @@ -42,9 +39,7 @@ public function getAcceptHeader() * Set accept header * * @param string $value Accept header - * - * @access public - * @return void + * @return PurchaseRequest */ public function setAcceptHeader($value) { @@ -54,7 +49,6 @@ public function setAcceptHeader($value) /** * Get cookie plugin * - * @access public * @return \Guzzle\Plugin\Cookie\CookiePlugin */ public function getCookiePlugin() @@ -65,7 +59,6 @@ public function getCookiePlugin() /** * Get installation * - * @access public * @return string */ public function getInstallation() @@ -77,9 +70,7 @@ public function getInstallation() * Set installation * * @param string $value Installation - * - * @access public - * @return void + * @return PurchaseRequest */ public function setInstallation($value) { @@ -89,7 +80,6 @@ public function setInstallation($value) /** * Get merchant * - * @access public * @return string */ public function getMerchant() @@ -101,9 +91,7 @@ public function getMerchant() * Set merchant * * @param string $value Merchant - * - * @access public - * @return void + * @return PurchaseRequest */ public function setMerchant($value) { @@ -134,7 +122,6 @@ public function setUsername($value) /** * Get pa response * - * @access public * @return string */ public function getPaResponse() @@ -146,9 +133,7 @@ public function getPaResponse() * Set pa response * * @param string $value Pa response - * - * @access public - * @return void + * @return PurchaseRequest */ public function setPaResponse($value) { @@ -158,7 +143,6 @@ public function setPaResponse($value) /** * Get password * - * @access public * @return string */ public function getPassword() @@ -170,9 +154,7 @@ public function getPassword() * Set password * * @param string $value Password - * - * @access public - * @return void + * @return PurchaseRequest */ public function setPassword($value) { @@ -182,7 +164,6 @@ public function setPassword($value) /** * Get redirect cookie * - * @access public * @return string */ public function getRedirectCookie() @@ -194,9 +175,7 @@ public function getRedirectCookie() * Set redirect cookie * * @param string $value Password - * - * @access public - * @return void + * @return PurchaseRequest */ public function setRedirectCookie($value) { @@ -206,7 +185,6 @@ public function setRedirectCookie($value) /** * Get redirect echo * - * @access public * @return string */ public function getRedirectEcho() @@ -218,9 +196,7 @@ public function getRedirectEcho() * Set redirect echo * * @param string $value Password - * - * @access public - * @return void + * @return PurchaseRequest */ public function setRedirectEcho($value) { @@ -230,7 +206,6 @@ public function setRedirectEcho($value) /** * Get session * - * @access public * @return string */ public function getSession() @@ -242,9 +217,7 @@ public function getSession() * Set session * * @param string $value Session - * - * @access public - * @return void + * @return PurchaseRequest */ public function setSession($value) { @@ -254,7 +227,6 @@ public function setSession($value) /** * Get term url * - * @access public * @return string */ public function getTermUrl() @@ -266,9 +238,7 @@ public function getTermUrl() * Set term url * * @param string $value Term url - * - * @access public - * @return void + * @return PurchaseRequest */ public function setTermUrl($value) { @@ -278,7 +248,6 @@ public function setTermUrl($value) /** * Get user agent header * - * @access public * @return string */ public function getUserAgentHeader() @@ -290,9 +259,7 @@ public function getUserAgentHeader() * Set user agent header * * @param string $value User agent header - * - * @access public - * @return void + * @return PurchaseRequest */ public function setUserAgentHeader($value) { @@ -319,7 +286,6 @@ public function getAppleToken() /** * Get data * - * @access public * @return \SimpleXMLElement */ public function getData() @@ -338,7 +304,8 @@ public function getData() $order->addAttribute('orderCode', $this->getTransactionId()); $order->addAttribute('installationId', $this->getInstallation()); - $order->addChild('description', $this->getDescription()); + $description = $this->getDescription() ? $this->getDescription() : 'Merchandise'; + $order->addChild('description', $description); $amount = $order->addChild('amount'); $amount->addAttribute('value', $this->getAmountInteger()); @@ -405,11 +372,13 @@ public function getData() $address->addChild('street', $this->getCard()->getAddress1()); $address->addChild('postalCode', $this->getCard()->getPostcode()); $address->addChild('countryCode', $this->getCard()->getCountry()); - } - $session = $payment->addChild('session'); - $session->addAttribute('shopperIPAddress', $this->getClientIP()); - $session->addAttribute('id', $this->getSession()); + $session = $payment->addChild('session'); // Empty tag is valid but setting an empty ID attr isn't + if ($this->getClientIp() && $this->getSession()) { + $session->addAttribute('shopperIPAddress', $this->getClientIP()); + $session->addAttribute('id', $this->getSession()); + } + } $paResponse = $this->getPaResponse(); @@ -446,8 +415,6 @@ public function getData() * Send data * * @param \SimpleXMLElement $data Data - * - * @access public * @return RedirectResponse */ public function sendData($data) @@ -502,10 +469,13 @@ public function sendData($data) ->post($this->getEndpoint(), $headers, $xml) ->send(); - return $this->response = new RedirectResponse( - $this, - $httpResponse->getBody() - ); + if ($this->getCard()->getBrand() === 'apple') { + $this->response = new Response($this, $httpResponse->getBody()); + } else { + $this->response = new RedirectResponse($this, $httpResponse->getBody()); + } + + return $this->response; } /** @@ -513,7 +483,6 @@ public function sendData($data) * * Returns endpoint depending on test mode * - * @access protected * @return string */ protected function getEndpoint()