From afa187edb8630d42214d852a1dae0441b164ce4f Mon Sep 17 00:00:00 2001 From: Nicky Robinson Date: Thu, 10 Aug 2017 12:16:45 -0400 Subject: [PATCH] Initial commit to public github --- .gitignore | 12 + .travis.yml | 32 + CONTRIBUTING.md | 28 + LICENSE | 21 + Makefile | 36 + README.md | 101 +++ composer-psalm.json | 34 + composer.json | 33 + phpunit.xml.dist | 25 + psalm.xml | 36 + psalm_plugins/StringChecker.php | 65 ++ src/Constants.php | 21 + src/CreditCard.php | 42 ++ src/ExtendedGateway.php | 191 ++++++ src/Gateway.php | 142 ++++ src/HostedCheckoutGateway.php | 101 +++ src/Message/AbstractRequest.php | 404 +++++++++++ src/Message/ExtendedAbstractRequest.php | 96 +++ .../ExtendedCancelSubscriptionRequest.php | 68 ++ src/Message/ExtendedFetchCustomerRequest.php | 66 ++ ...ExtendedFetchSubscriptionChargeRequest.php | 106 +++ .../ExtendedFetchSubscriptionRequest.php | 94 +++ .../ExtendedFetchSubscriptionsRequest.php | 93 +++ .../ExtendedFetchTransactionRequest.php | 92 +++ .../ExtendedReactivateSubscriptionRequest.php | 77 +++ src/Message/ExtendedRefundRequest.php | 148 +++++ .../ExtendedTestChargeSubscriptionRequest.php | 91 +++ .../ExtendedUpdateSubscriptionRequest.php | 125 ++++ .../FetchCanceledSubscriptionsRequest.php | 48 ++ src/Message/FetchSubscriptionsRequest.php | 48 ++ src/Message/FetchTransactionsRequest.php | 98 +++ .../HostedCheckoutDecryptReturnUrlRequest.php | 104 +++ src/Message/HostedCheckoutPurchaseRequest.php | 181 +++++ .../HostedCheckoutPurchaseResponse.php | 62 ++ src/Message/IPNCallback.php | 277 ++++++++ src/Message/Response.php | 629 ++++++++++++++++++ src/Subscription.php | 167 +++++ src/SubscriptionCharge.php | 215 ++++++ src/Transaction.php | 456 +++++++++++++ src/UrlParameter.php | 119 ++++ src/UrlParameterBag.php | 103 +++ tests/CreditCardTest.php | 38 ++ tests/ExtendedGatewayTest.php | 237 +++++++ tests/Framework/DataFaker.php | 506 ++++++++++++++ tests/Framework/MockPlugin.php | 59 ++ tests/Framework/TestCase.php | 150 +++++ tests/Framework/tests/DataFakerTest.php | 358 ++++++++++ tests/GatewayTest.php | 151 +++++ tests/HostedCheckoutGatewayTest.php | 92 +++ tests/Message/AbstractRequestTest.php | 209 ++++++ tests/Message/ExtendedAbstractRequestTest.php | 68 ++ .../ExtendedCancelSubscriptionRequestTest.php | 117 ++++ .../ExtendedFetchCustomerRequestTest.php | 109 +++ ...ndedFetchSubscriptionChargeRequestTest.php | 152 +++++ .../ExtendedFetchSubscriptionRequestTest.php | 243 +++++++ .../ExtendedFetchSubscriptionsRequestTest.php | 155 +++++ .../ExtendedFetchTransactionRequestTest.php | 218 ++++++ ...endedReactivateSubscriptionRequestTest.php | 115 ++++ tests/Message/ExtendedRefundRequestTest.php | 193 ++++++ ...endedTestChargeSubscriptionRequestTest.php | 125 ++++ .../ExtendedUpdateSubscriptionRequestTest.php | 148 +++++ .../FetchCanceledSubscriptionsRequestTest.php | 234 +++++++ .../Message/FetchSubscriptionsRequestTest.php | 191 ++++++ .../Message/FetchTransactionsRequestTest.php | 196 ++++++ ...tedCheckoutDecryptReturnUrlRequestTest.php | 161 +++++ .../HostedCheckoutPurchaseRequestTest.php | 233 +++++++ tests/Message/IPNCallbackTest.php | 281 ++++++++ .../ExtendedCancelSubscriptionFailure.txt | 15 + .../ExtendedCancelSubscriptionSuccess.txt | 6 + tests/Mock/ExtendedFetchCustomerFailure.txt | 9 + tests/Mock/ExtendedFetchCustomerSuccess.txt | 69 ++ ...ExtendedFetchSubscriptionChargeFailure.txt | 15 + ...ExtendedFetchSubscriptionChargeSuccess.txt | 19 + .../Mock/ExtendedFetchSubscriptionFailure.txt | 16 + ...etchSubscriptionMultipleChargesSuccess.txt | 50 ++ ...tchSubscriptionOverriddenChargeSuccess.txt | 38 ++ .../Mock/ExtendedFetchSubscriptionSuccess.txt | 41 ++ .../ExtendedFetchSubscriptionsFailure.txt | 17 + .../ExtendedFetchSubscriptionsSuccess.txt | 94 +++ .../Mock/ExtendedFetchTransactionFailure.txt | 17 + ...etchTransactionMultipleInvoicesSuccess.txt | 108 +++ .../Mock/ExtendedFetchTransactionSuccess.txt | 83 +++ .../ExtendedReactivateSubscriptionFailure.txt | 15 + .../ExtendedReactivateSubscriptionSuccess.txt | 7 + tests/Mock/ExtendedRefundFailure.txt | 17 + tests/Mock/ExtendedRefundSuccess.txt | 6 + .../ExtendedTestChargeSubscriptionFailure.txt | 17 + .../ExtendedTestChargeSubscriptionSuccess.txt | 6 + .../ExtendedUpdateSubscriptionFailure.txt | 15 + .../ExtendedUpdateSubscriptionSuccess.txt | 7 + .../FetchCanceledSubscriptionsFailure.txt | 17 + .../FetchCanceledSubscriptionsSuccess.txt | 72 ++ tests/Mock/FetchSubscriptionsFailure.txt | 17 + tests/Mock/FetchSubscriptionsSuccess.txt | 55 ++ tests/Mock/FetchTransactionsFailure.txt | 17 + tests/Mock/FetchTransactionsSuccess.txt | 123 ++++ .../HostedCheckoutDecryptReturnUrlFailure.txt | 16 + .../HostedCheckoutDecryptReturnUrlSuccess.txt | 13 + tests/Mock/HostedCheckoutPurchaseFailure.txt | 17 + tests/Mock/HostedCheckoutPurchaseSuccess.txt | 14 + tests/SubscriptionChargeTest.php | 129 ++++ tests/SubscriptionTest.php | 113 ++++ tests/TransactionTest.php | 217 ++++++ tests/UrlParameterBagTest.php | 172 +++++ tests/UrlParameterTest.php | 100 +++ 105 files changed, 11405 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 composer-psalm.json create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 psalm.xml create mode 100644 psalm_plugins/StringChecker.php create mode 100644 src/Constants.php create mode 100644 src/CreditCard.php create mode 100644 src/ExtendedGateway.php create mode 100644 src/Gateway.php create mode 100644 src/HostedCheckoutGateway.php create mode 100644 src/Message/AbstractRequest.php create mode 100644 src/Message/ExtendedAbstractRequest.php create mode 100644 src/Message/ExtendedCancelSubscriptionRequest.php create mode 100644 src/Message/ExtendedFetchCustomerRequest.php create mode 100644 src/Message/ExtendedFetchSubscriptionChargeRequest.php create mode 100644 src/Message/ExtendedFetchSubscriptionRequest.php create mode 100644 src/Message/ExtendedFetchSubscriptionsRequest.php create mode 100644 src/Message/ExtendedFetchTransactionRequest.php create mode 100644 src/Message/ExtendedReactivateSubscriptionRequest.php create mode 100644 src/Message/ExtendedRefundRequest.php create mode 100644 src/Message/ExtendedTestChargeSubscriptionRequest.php create mode 100644 src/Message/ExtendedUpdateSubscriptionRequest.php create mode 100644 src/Message/FetchCanceledSubscriptionsRequest.php create mode 100644 src/Message/FetchSubscriptionsRequest.php create mode 100644 src/Message/FetchTransactionsRequest.php create mode 100644 src/Message/HostedCheckoutDecryptReturnUrlRequest.php create mode 100644 src/Message/HostedCheckoutPurchaseRequest.php create mode 100644 src/Message/HostedCheckoutPurchaseResponse.php create mode 100644 src/Message/IPNCallback.php create mode 100644 src/Message/Response.php create mode 100644 src/Subscription.php create mode 100644 src/SubscriptionCharge.php create mode 100644 src/Transaction.php create mode 100644 src/UrlParameter.php create mode 100644 src/UrlParameterBag.php create mode 100644 tests/CreditCardTest.php create mode 100644 tests/ExtendedGatewayTest.php create mode 100644 tests/Framework/DataFaker.php create mode 100644 tests/Framework/MockPlugin.php create mode 100644 tests/Framework/TestCase.php create mode 100644 tests/Framework/tests/DataFakerTest.php create mode 100644 tests/GatewayTest.php create mode 100644 tests/HostedCheckoutGatewayTest.php create mode 100644 tests/Message/AbstractRequestTest.php create mode 100644 tests/Message/ExtendedAbstractRequestTest.php create mode 100644 tests/Message/ExtendedCancelSubscriptionRequestTest.php create mode 100644 tests/Message/ExtendedFetchCustomerRequestTest.php create mode 100644 tests/Message/ExtendedFetchSubscriptionChargeRequestTest.php create mode 100644 tests/Message/ExtendedFetchSubscriptionRequestTest.php create mode 100644 tests/Message/ExtendedFetchSubscriptionsRequestTest.php create mode 100644 tests/Message/ExtendedFetchTransactionRequestTest.php create mode 100644 tests/Message/ExtendedReactivateSubscriptionRequestTest.php create mode 100644 tests/Message/ExtendedRefundRequestTest.php create mode 100644 tests/Message/ExtendedTestChargeSubscriptionRequestTest.php create mode 100644 tests/Message/ExtendedUpdateSubscriptionRequestTest.php create mode 100644 tests/Message/FetchCanceledSubscriptionsRequestTest.php create mode 100644 tests/Message/FetchSubscriptionsRequestTest.php create mode 100644 tests/Message/FetchTransactionsRequestTest.php create mode 100644 tests/Message/HostedCheckoutDecryptReturnUrlRequestTest.php create mode 100644 tests/Message/HostedCheckoutPurchaseRequestTest.php create mode 100644 tests/Message/IPNCallbackTest.php create mode 100644 tests/Mock/ExtendedCancelSubscriptionFailure.txt create mode 100644 tests/Mock/ExtendedCancelSubscriptionSuccess.txt create mode 100644 tests/Mock/ExtendedFetchCustomerFailure.txt create mode 100644 tests/Mock/ExtendedFetchCustomerSuccess.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionChargeFailure.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionChargeSuccess.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionFailure.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionMultipleChargesSuccess.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionOverriddenChargeSuccess.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionSuccess.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionsFailure.txt create mode 100644 tests/Mock/ExtendedFetchSubscriptionsSuccess.txt create mode 100644 tests/Mock/ExtendedFetchTransactionFailure.txt create mode 100644 tests/Mock/ExtendedFetchTransactionMultipleInvoicesSuccess.txt create mode 100644 tests/Mock/ExtendedFetchTransactionSuccess.txt create mode 100644 tests/Mock/ExtendedReactivateSubscriptionFailure.txt create mode 100644 tests/Mock/ExtendedReactivateSubscriptionSuccess.txt create mode 100644 tests/Mock/ExtendedRefundFailure.txt create mode 100644 tests/Mock/ExtendedRefundSuccess.txt create mode 100644 tests/Mock/ExtendedTestChargeSubscriptionFailure.txt create mode 100644 tests/Mock/ExtendedTestChargeSubscriptionSuccess.txt create mode 100644 tests/Mock/ExtendedUpdateSubscriptionFailure.txt create mode 100644 tests/Mock/ExtendedUpdateSubscriptionSuccess.txt create mode 100644 tests/Mock/FetchCanceledSubscriptionsFailure.txt create mode 100644 tests/Mock/FetchCanceledSubscriptionsSuccess.txt create mode 100644 tests/Mock/FetchSubscriptionsFailure.txt create mode 100644 tests/Mock/FetchSubscriptionsSuccess.txt create mode 100644 tests/Mock/FetchTransactionsFailure.txt create mode 100644 tests/Mock/FetchTransactionsSuccess.txt create mode 100644 tests/Mock/HostedCheckoutDecryptReturnUrlFailure.txt create mode 100644 tests/Mock/HostedCheckoutDecryptReturnUrlSuccess.txt create mode 100644 tests/Mock/HostedCheckoutPurchaseFailure.txt create mode 100644 tests/Mock/HostedCheckoutPurchaseSuccess.txt create mode 100644 tests/SubscriptionChargeTest.php create mode 100644 tests/SubscriptionTest.php create mode 100644 tests/TransactionTest.php create mode 100644 tests/UrlParameterBagTest.php create mode 100644 tests/UrlParameterTest.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a5ddff --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Files created by OSX +._* +.DS_Store + +# Emacs back up files +*~ +*# + +composer.lock +composer-psalm.lock +composer.phar +/vendor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6e9d4a7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: php +matrix: + include: + - php: 5.3 + env: + - TEST_SUITE='no_psalm' + - php: 5.4 + env: + - TEST_SUITE='no_psalm' + - php: 5.5 + env: + - TEST_SUITE='no_psalm' + - php: 5.6 + env: + - TEST_SUITE='with_psalm' + - COMPOSER='composer-psalm.json' + - php: 7.0 + env: + - TEST_SUITE='with_psalm' + - COMPOSER='composer-psalm.json' + - php: 7.1 + env: + - TEST_SUITE='with_psalm' + - COMPOSER='composer-psalm.json' +install: composer install +script: make $TEST_SUITE +notifications: + email: false + slack: + rooms: + secure: Lt+vBT6MMM0MQSmkdBRlr0LqhA6ZB+sJJm0AkwOMWCIWNa3GSTnPztOvy3+G/mEnpQaXFHwctu4vuDNi/tXaIGndKgFjrmfkNS+ZMGWoQrxe3hjY4jZUSPhOJldoD0StER7ka0tf0frPQKd3baRV5JBr2KH1O8sZ3JlP/RCO3HKXL50VSYNA0oXJQmJocazqQQT0BWO4oQLHz2XtNLNQMJBG+zhN8tDvnqkDlUhuO0INHkBvRvmqiQ5dN25IR5OemRgrVrYWZzejfoxzTONXB+9SlBU9zwphvqTEwiHw9xE1VQDIoCv9o13y9qsS7xt2ojIMScWWJioaq03uPy/vI+tnT98Oaa1tJGDQkdbN83Am28KDAY5BA6445RSuyNPGoQXoHtzqFLBpPV+xzwMb+gBYPxQ71U3YFkFavwlHvEPUU/wslTdFkTHbRXXEuRgYeVpH7O3ZbxW3xRnWwzWPB7SXcb6CkMmX+ByuyS5x4The59Y5AvYjp5fGlHZgv8aqhqOPWz8PdEj5qqK6+2VCsVuwU55hmS4zATZjPGyZLqFnOpSBw5raQq0iSeSKoq683p4iCGWoiUYdaXi+DcWjfJCo4UbbGvWSbTzLeRkEA44bdY3Noeg8dkccfaOqZQF/FoVMhD04WNkmn2int4gvlRHF9RbHjrah+gaRAxLSFvk= + on_pull_requests: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f67ba38 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing Guidelines + +## Steps +* Fork the project. +* Make your feature addition or bug fix. +* Add tests for it. This is important so we don't break it in a future version unintentionally. +* Commit just the modifications, do not mess with the composer.json file. +* Ensure your code is nicely formatted in the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) +style and that all tests pass. +* Send the pull request. +* Check that the Travis CI build passed. If not, rinse and repeat. **Note:** This repo uses [Psalm](https://github.com/vimeo/psalm) to statically analyze all the code. Psalm runs on all the builds for PHP 5.5+. + +**NOTE:** This repo requires pull-request reviews for all changes on branches bound for production in accordance with Vimeo policy. + +## Testing locally +To install Psalm and run the full test suite locally, download [Composer](https://getcomposer.org/) into the repository and then run: + +``` +make install +make +``` + +If you use PHP 5.3 or 5.4 locally (which are not supported by the latest version of Psalm), you can skip Psalm by running: + +``` +make install_no_psalm +make no_psalm +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9cee4f6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Vimeo, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..511cb81 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +# Test + +all: with_psalm + +no_psalm: style test + +with_psalm: style psalm test + +style: + vendor/bin/phpcs --standard=PSR2 src && vendor/bin/phpcs --standard=PSR2 --error-severity=1 --warning-severity=6 tests + +test: + vendor/bin/phpunit + +psalm: + vendor/bin/psalm + +# Install + +install: install_with_psalm + +install_with_psalm: + COMPOSER=composer-psalm.json php composer.phar install + +install_no_psalm: + php composer.phar install + +# Update + +update: update_with_psalm + +update_with_psalm: + COMPOSER=composer-psalm.json php composer.phar update + +update_no_psalm: + php composer.phar update diff --git a/README.md b/README.md new file mode 100644 index 0000000..9baf964 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# Omnipay: BlueSnap + +**BlueSnap driver for the Omnipay PHP payment processing library** + +_NOTE: At this time, this driver only provides full support for BlueSnap's [BuyNow Hosted Checkout](https://home.bluesnap.com/features-tools/flexible-integration-options/hosted-checkout/) product. But you can add support for more parts of the API!_ + +[![Build Status](https://travis-ci.org/vimeo/omnipay-bluesnap.png?branch=master)](https://travis-ci.org/vimeo/omnipay-bluesnap) +[![Latest Stable Version](https://poser.pugx.org/vimeo/omnipay-bluesnap/version.png)](https://packagist.org/packages/vimeo/omnipay-bluesnap) +[![Total Downloads](https://poser.pugx.org/vimeo/omnipay-bluesnap/d/total.png)](https://packagist.org/packages/vimeo/omnipay-bluesnap) + +[Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment processing library for PHP 5.3+. This package implements BlueSnap support for Omnipay. + +[BlueSnap](https://bluesnap.com/) is a payment services provider based in Waltham, Massachusetts. In addition to traditional payment gateway services, they provide hosted solutions and a range of global payment methods. + +## Installation + +Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply add it to your `composer.json` file: + +```json +{ + "require": { + "vimeo/omnipay-bluesnap": "2.0.*" + } +} +``` + +And run composer to update your dependencies: + +``` +$ curl -s http://getcomposer.org/installer | php +$ php composer.phar update +``` + +_(Note that we recommend pinning the minor version. While `v2.*` will remain fully compatible with Omnipay 2, features added in addition to the base Omnipay features, such as subscriptions, may have breaking changes in a minor version bump.)_ + +## Basic Usage + +The following gateways are provided by this package: + +* BlueSnap_HostedCheckout, for [BlueSnap's BuyNow Hosted Checkout](https://support.bluesnap.com/v2.2.7/docs/intro-extended-api) page. + +Some features of the following gateways are provided, but not enough to use them on their own. Feel free to contribute! + +* BlueSnap, for BlueSnap's traditional [Payment API](https://developers.bluesnap.com/v8976-JSON/docs). This gateway is almost entirely unimplemented at this time, except for parts of the [Reporting API](https://developers.bluesnap.com/v8976-Tools/docs). +* BlueSnap\_Extended, for the BlueSnap [Extended Payment API](https://support.bluesnap.com/v2.2.7/docs/intro-extended-api). This is the API you should use if you're hosting your product catalog with BlueSnap. It powers the BuyNow Hosted Checkout, as well as other products. Enough of this API is implemented in this driver to power the BlueSnap\_HostedCheckout gateway. + +### Simple Example + +```php +// Set up the gateway +$gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); +$gateway->setUsername('your_username'); +$gateway->setPassword('y0ur_p4ssw0rd'); +$gateway->setTestMode(false); + +// Start the purchase process +$purchaseResponse = $gateway->purchase(array( + 'storeReference' => '12345', + 'planReference' => '1234567', + 'currency' => 'USD' +))->send(); + +if ($purchaseResponse->isSuccessful()) { + $purchaseResponse->redirect(); +} else { + // error handling +} + +// Now the user is filling out info on BlueSnap's hosted checkout page. Then they get +// redirected back to your site. If you set parameters in the return/callback URL, you +// can access those here. + +// Once the transaction has been captured, you'll receive an IPN callback, which you can +// handle like so: + +$ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); +if ($ipnCallback->isCharge()) { + echo 'Transaction reference: ' . $ipnCallback->getTransactionReference() . PHP_EOL; + echo 'Amount: ' . $ipnCallback->getAmount() . PHP_EOL; + echo 'Currency: ' . $ipnCallback->getCurrency() . PHP_EOL; +} elseif ($ipnCallback->isCancellation()) { + // etc. +} +``` + +More documentation and examples are provided in the Gateway source files. + +For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) repository. + +## Test Mode + +BlueSnap accounts have a separate username and password for test mode. There is also a separate test mode endpoint, which this library will use when set to test mode. + +## Support + +This driver is very new and at this point may not be completely reliable. If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/Vimeo/omnipay-bluesnap/issues), or better yet, fork the library and submit a pull request. + +If you are having general issues with Omnipay, we suggest posting on [Stack Overflow](http://stackoverflow.com/). Be sure to add the +[omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. + +If you want to keep up to date with release announcements, discuss ideas for the project, or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which you can subscribe to. diff --git a/composer-psalm.json b/composer-psalm.json new file mode 100644 index 0000000..52647ac --- /dev/null +++ b/composer-psalm.json @@ -0,0 +1,34 @@ +{ + "name": "vimeo/omnipay-bluesnap", + "type": "library", + "description": "BlueSnap driver for the Omnipay payment processing library", + "keywords": [ + "gateway", + "merchant", + "omnipay", + "pay", + "payment", + "bluesnap" + ], + "homepage": "https://github.com/vimeo/omnipay-bluesnap", + "license": "MIT", + "authors": [ + { + "name": "Nicky Robinson", + "email": "ncalebrobinson@gmail.com" + } + ], + "autoload": { + "psr-4": { + "Omnipay\\BlueSnap\\Test\\" : "tests/", + "Omnipay\\BlueSnap\\" : "src/" + } + }, + "require": { + "omnipay/common": "~2.0" + }, + "require-dev": { + "omnipay/tests": "~2.0", + "vimeo/psalm": "0.3.*" + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bc9f132 --- /dev/null +++ b/composer.json @@ -0,0 +1,33 @@ +{ + "name": "vimeo/omnipay-bluesnap", + "type": "library", + "description": "BlueSnap driver for the Omnipay payment processing library", + "keywords": [ + "gateway", + "merchant", + "omnipay", + "pay", + "payment", + "bluesnap" + ], + "homepage": "https://github.com/vimeo/omnipay-bluesnap", + "license": "MIT", + "authors": [ + { + "name": "Nicky Robinson", + "email": "ncalebrobinson@gmail.com" + } + ], + "autoload": { + "psr-4": { + "Omnipay\\BlueSnap\\Test\\" : "tests/", + "Omnipay\\BlueSnap\\" : "src/" + } + }, + "require": { + "omnipay/common": "~2.0" + }, + "require-dev": { + "omnipay/tests": "~2.0" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..22c6279 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests/ + + + + + + + + ./src + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..cf33380 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/psalm_plugins/StringChecker.php b/psalm_plugins/StringChecker.php new file mode 100644 index 0000000..60f9430 --- /dev/null +++ b/psalm_plugins/StringChecker.php @@ -0,0 +1,65 @@ + $suppressed_issues + * @return null|false + */ + public function checkExpression( + StatementsChecker $statements_checker, + \PhpParser\Node\Expr $stmt, + Context $context, + CodeLocation $code_location, + array $suppressed_issues + ) { + if ($stmt instanceof \PhpParser\Node\Scalar\String_) { + $class_or_class_method = '/^\\\?Omnipay(\\\[A-Z][A-Za-z0-9]+)+(::[A-Za-z0-9]+)?$/'; + + if (preg_match($class_or_class_method, $stmt->value)) { + $fq_class_name = preg_split('/[:]/', $stmt->value)[0]; + + $project_checker = $statements_checker->getFileChecker()->project_checker; + if (Checker\ClassChecker::checkFullyQualifiedClassLikeName( + $project_checker, + $fq_class_name, + $code_location, + $suppressed_issues + ) === false + ) { + return false; + } + + if ($fq_class_name !== $stmt->value) { + if (Checker\MethodChecker::checkMethodExists( + $project_checker, + $stmt->value, + $code_location, + $suppressed_issues + ) + ) { + return false; + } + } + } + } + } +} + +return new StringChecker; diff --git a/src/Constants.php b/src/Constants.php new file mode 100644 index 0000000..226ea2c --- /dev/null +++ b/src/Constants.php @@ -0,0 +1,21 @@ +getParameter('brand')); + if ($brand) { + return $brand; + } + + /** + * @var string|null + */ + return parent::getBrand(); + } + + /** + * Sets the card brand + * + * @param string $value + * @return static + */ + public function setBrand($value) + { + /** + * @var static + */ + return $this->setParameter('brand', $value); + } +} diff --git a/src/ExtendedGateway.php b/src/ExtendedGateway.php new file mode 100644 index 0000000..a3da322 --- /dev/null +++ b/src/ExtendedGateway.php @@ -0,0 +1,191 @@ +createRequest('\Omnipay\BlueSnap\Message\ExtendedFetchCustomerRequest', $parameters); + } + + /** + * Fetch a BlueSnap transaction object. + * Their extended payment API calls transactions "orders" + * + * See Message\ExtendedFetchTransactionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedFetchTransactionRequest + */ + public function fetchTransaction(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedFetchTransactionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedFetchTransactionRequest', $parameters); + } + + /** + * Fetch a BlueSnap subscription object. + * + * See Message\ExtendedFetchSubscriptionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionRequest + */ + public function fetchSubscription(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionRequest', $parameters); + } + + /** + * Fetch BlueSnap subscription objects by customer or in a time range. + * + * See Message\ExtendedFetchSubscriptionsRequest for more details on fetching + * by customer. See Message\FetchSubscriptionsRequest for more details on + * fetching by time range. The correct request will be made depending on the + * parameters passed. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\AbstractRequest + */ + public function fetchSubscriptions(array $parameters = array()) + { + if (isset($parameters['customerReference'])) { + /** + * @var \Omnipay\BlueSnap\Message\AbstractRequest + */ + return $this->createRequest( + '\Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionsRequest', + $parameters + ); + } + return parent::fetchSubscriptions($parameters); + } + + /** + * Fetch a BlueSnap subscription charge object. + * + * See Message\ExtendedFetchSubscriptionChargeRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionChargeRequest + */ + public function fetchSubscriptionCharge(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionChargeRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionChargeRequest', $parameters); + } + + /** + * Update a subscription + * + * See Message\ExtendedUpdateSubscriptionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedUpdateSubscriptionRequest + */ + public function updateSubscription(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedUpdateSubscriptionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedUpdateSubscriptionRequest', $parameters); + } + + /** + * Cancel a subscription + * + * See Message\ExtendedCancelSubscriptionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedCancelSubscriptionRequest + */ + public function cancelSubscription(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedCancelSubscriptionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedCancelSubscriptionRequest', $parameters); + } + + /** + * Reactivate a subscription that has previously been canceled + * + * See Message\ExtendedReactivateSubscriptionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedReactivateSubscriptionRequest + */ + public function reactivateSubscription(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedReactivateSubscriptionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedReactivateSubscriptionRequest', $parameters); + } + + /** + * Make a test charge against a subscription. This only works in test mode. + * + * See Message\ExtendedTestChargeSubscriptionRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedTestChargeSubscriptionRequest + */ + public function testChargeSubscription(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedTestChargeSubscriptionRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedTestChargeSubscriptionRequest', $parameters); + } + + /** + * Refund a transaction + * + * See Message\ExtendedRefundRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\ExtendedRefundRequest + */ + public function refund(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedRefundRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\ExtendedRefundRequest', $parameters); + } +} diff --git a/src/Gateway.php b/src/Gateway.php new file mode 100644 index 0000000..407ba0e --- /dev/null +++ b/src/Gateway.php @@ -0,0 +1,142 @@ + '', + 'password' => '', + 'testMode' => false, + ); + } + + /** + * Gets the username for making API calls + * + * @return string|null + */ + public function getUsername() + { + return strval($this->getParameter('username')) ?: null; + } + + /** + * Sets the username for making API calls + * + * @param string $value + * @return static + */ + public function setUsername($value) + { + return $this->setParameter('username', $value); + } + + /** + * Gets the password for making API calls + * + * @return string|null + */ + public function getPassword() + { + return strval($this->getParameter('password')) ?: null; + } + + /** + * Sets the password for making API calls + * + * @param string $value + * @return static + */ + public function setPassword($value) + { + return $this->setParameter('password', $value); + } + + /** + * Fetch all transactions in a time range. + * + * See Message\FetchTransactionsRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\FetchTransactionsRequest + */ + public function fetchTransactions(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\FetchTransactionsRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\FetchTransactionsRequest', $parameters); + } + + /** + * Fetch all active subscriptions in a time range. + * + * See Message\FetchSubscriptionsRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\FetchSubscriptionsRequest + */ + public function fetchSubscriptions(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\FetchSubscriptionsRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\FetchSubscriptionsRequest', $parameters); + } + + /** + * Fetch all canceled subscriptions in a time range. + * + * See Message\FetchCanceledSubscriptionsRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\FetchCanceledSubscriptionsRequest + */ + public function fetchCanceledSubscriptions(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\FetchCanceledSubscriptionsRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\FetchCanceledSubscriptionsRequest', $parameters); + } + + /** + * Parse an IPN callback URL for easier handling. Note that this does NOT + * make an API request. + * + * See Message\IPNCallback for more details. + * + * @param string|array $url + * @return \Omnipay\BlueSnap\Message\IPNCallback + */ + public function parseIPNCallback($url) + { + return new IPNCallback($url); + } +} diff --git a/src/HostedCheckoutGateway.php b/src/HostedCheckoutGateway.php new file mode 100644 index 0000000..056cdda --- /dev/null +++ b/src/HostedCheckoutGateway.php @@ -0,0 +1,101 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567', + * 'currency' => 'JPY' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Then they get redirected back + * // to your site, where you can decrypt the parameters in the return URL if you wish: + * + * $decryptResponse = $gateway->decryptReturnUrl($_SERVER['REQUEST_URI'])->send(); + * if ($decryptResponse->isSuccessful()) { + * var_dump($decryptResponse->getDecryptedParameters()); + * } + * + * // Once the transaction has been captured, you'll receive an IPN callback, which you can + * // handle like so: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * echo 'Transaction reference: ' . $ipnCallback->getTransactionReference() . PHP_EOL; + * echo 'Amount: ' . $ipnCallback->getAmount() . PHP_EOL; + * echo 'Currency: ' . $ipnCallback->getCurrency() . PHP_EOL; + * } elseif ($ipnCallback->isCancellation()) { + * // etc. + * } + * + */ +class HostedCheckoutGateway extends ExtendedGateway +{ + /** + * @return string + */ + public function getName() + { + return 'BlueSnap Hosted Checkout'; + } + + /** + * Initiate a purchase. This request returns a redirect response with the store URL. + * + * See Message\HostedCheckoutPurchaseRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\HostedCheckoutPurchaseRequest + */ + public function purchase(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\HostedCheckoutPurchaseRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\HostedCheckoutPurchaseRequest', $parameters); + } + + /** + * Decrypts an encrypted return URL. + * + * See Message\HostedCheckoutDecryptReturnUrlRequest for more details. + * + * @param array $parameters + * @return \Omnipay\BlueSnap\Message\HostedCheckoutDecryptReturnUrlRequest + */ + public function decryptReturnUrl(array $parameters = array()) + { + /** + * @var \Omnipay\BlueSnap\Message\HostedCheckoutDecryptReturnUrlRequest + */ + return $this->createRequest('\Omnipay\BlueSnap\Message\HostedCheckoutDecryptReturnUrlRequest', $parameters); + } +} diff --git a/src/Message/AbstractRequest.php b/src/Message/AbstractRequest.php new file mode 100644 index 0000000..64301ed --- /dev/null +++ b/src/Message/AbstractRequest.php @@ -0,0 +1,404 @@ +getParameter('username')) ?: null; + } + + /** + * Sets the username for making API calls + * + * @param string $value + * @return static + */ + public function setUsername($value) + { + return $this->setParameter('username', $value); + } + + /** + * Gets the password for making API calls + * + * @return string|null + */ + public function getPassword() + { + return strval($this->getParameter('password')) ?: null; + } + + /** + * Sets the password for making API calls + * + * @param string $value + * @return static + */ + public function setPassword($value) + { + return $this->setParameter('password', $value); + } + + /** + * Gets the gateway's identifier for the transaction + * + * @return string|null + */ + public function getTransactionReference() + { + return strval($this->getParameter('transactionReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the transaction + * + * @param string $value + * @return static + */ + public function setTransactionReference($value) + { + return $this->setParameter('transactionReference', $value); + } + + /** + * Gets the gateway's identifier for the customer + * + * @return string|null + */ + public function getCustomerReference() + { + return strval($this->getParameter('customerReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the customer + * + * @param string $value + * @return static + */ + public function setCustomerReference($value) + { + return $this->setParameter('customerReference', $value); + } + + /** + * Gets the gateway's identifier for the subscription + * + * @return string|null + */ + public function getSubscriptionReference() + { + return strval($this->getParameter('subscriptionReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the subscription + * + * @param string $value + * @return static + */ + public function setSubscriptionReference($value) + { + return $this->setParameter('subscriptionReference', $value); + } + + /** + * Gets the gateway's identifier for the subscription charge + * + * @return string|null + */ + public function getSubscriptionChargeReference() + { + return strval($this->getParameter('subscriptionChargeReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the subscription charge + * + * @param string $value + * @return static + */ + public function setSubscriptionChargeReference($value) + { + return $this->setParameter('subscriptionChargeReference', $value); + } + + /** + * Gets the next charge date for the subscription + * + * @return \DateTime|null + */ + public function getNextChargeDate() + { + /** + * @var \DateTime|null + */ + return $this->getParameter('nextChargeDate') ?: null; + } + + /** + * Sets the next charge date for the subscription + * NOTE: BlueSnap does not let you specify times, only dates. + * The DateTime provided MUST be in the Etc/GMT+8 time zone. + * + * @param \DateTime $value + * @return static + * @throws InvalidRequestException if the time zone is incorrect + */ + public function setNextChargeDate($value) + { + $this->validateTimeZone($value); + return $this->setParameter('nextChargeDate', $value); + } + + /** + * Gets the date/time for the beginning of the range of transactions or + * subscriptions to be returned + * The DateTime returned will be in the Etc/GMT+8 time zone. + * + * @return \DateTime|null + */ + public function getStartTime() + { + /** + * @var \DateTime|null + */ + return $this->getParameter('startTime') ?: null; + } + + /** + * Sets the date/time for the beginning of the range of transactions or + * subscriptions to be returned + * NOTE: BlueSnap does not let you specify times, only dates. + * The DateTime provided MUST be in the Etc/GMT+8 time zone. + * + * @param \DateTime $value + * @return static + * @throws InvalidRequestException if the time zone is incorrect + */ + public function setStartTime($value) + { + $this->validateTimeZone($value); + return $this->setParameter('startTime', $value); + } + + /** + * Gets the date/time for the end of the range of transactions or + * subscriptions to be returned + * The DateTime returned will be in the Etc/GMT+8 time zone. + * + * @return \DateTime|null + */ + public function getEndTime() + { + /** + * @var \DateTime|null + */ + return $this->getParameter('endTime') ?: null; + } + + /** + * Sets the date/time for the end of the range of transactions or + * subscriptions to be returned + * NOTE: BlueSnap does not let you specify times, only dates. + * The DateTime provided MUST be in the Etc/GMT+8 time zone. + * + * @param \DateTime $value + * @return static + * @throws InvalidRequestException if the time zone is incorrect + */ + public function setEndTime($value) + { + $this->validateTimeZone($value); + return $this->setParameter('endTime', $value); + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return ($this->getTestMode() === false ? self::LIVE_ENDPOINT : self::TEST_ENDPOINT) . '/services/2'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + abstract public function getHttpMethod(); + + /** + * This method is only overriden to provide type hinting for static type checking + * by Psalm. + * This is necessary because Omnipay\Common\AbstractRequest::setParameter says it + * returns AbstractRequest instead of static. + * + * @param string $key + * @param mixed $value + * @return static + */ + protected function setParameter($key, $value) + { + /** + * @var static + */ + return parent::setParameter($key, $value); + } + + /** + * Throws an exception if the datetime is not in the Etc/GMT+8 time zone. + * + * @param DateTime $datetime + * @return void + * @throws InvalidRequestException + */ + protected function validateTimeZone(DateTime $datetime) + { + if ($datetime->getTimeZone()->getName() !== Constants::BLUESNAP_TIME_ZONE) { + throw new InvalidRequestException( + 'Dates must be provided in the ' . Constants::BLUESNAP_TIME_ZONE . ' time zone' + ); + } + } + + /** + * Makes the request + * + * @param SimpleXMLElement|null $data + * @return Response + * @throws RuntimeException if $data is invalid XML + * @psalm-suppress TypeDoesNotContainType psalm bug with SimpleXMLElement: https://github.com/vimeo/psalm/issues/145 + */ + public function sendData($data) + { + if ($data instanceof SimpleXMLElement) { + $data->addAttribute('xmlns', self::XMLNS); + /** + * @var string|false + */ + $data = $data->asXML(); + + if ($data === false) { + throw new RuntimeException('Request data is not valid XML'); + } + } + + // don't throw exceptions for errors + $this->httpClient->getEventDispatcher()->addListener( + // @codingStandardsIgnoreStart + 'request.error', + /** + * @param array{response: \Guzzle\Http\Message\Response} $event + * @return void + */ + function ($event) { + // @codingStandardsIgnoreEnd + if ($event['response']->isClientError()) { + $event->stopPropagation(); + } + } + ); + + $httpRequest = $this->httpClient->createRequest( + $this->getHttpMethod(), + $this->getEndpoint(), + null, + $data + ); + + /** + * @var \Guzzle\Http\Message\RequestInterface + */ + $httpRequest = $httpRequest + ->setHeader( + 'Authorization', + 'Basic ' . base64_encode(($this->getUsername() ?: '') . ':' . ($this->getPassword() ?: '')) + ) + ->setHeader('Content-Type', 'application/xml') + ->setHeader('bluesnap-version', self::API_VERSION); + $httpResponse = $httpRequest->send(); + + // responses can be XML, JSON, or plain text depending on the request and whether it's successful + try { + if (strpos($httpResponse->getContentType(), 'json') !== false) { + $responseData = $httpResponse->json(); + } else { + $responseData = $httpResponse->xml(); + } + } catch (\Guzzle\Common\Exception\RuntimeException $e) { + $responseData = trim((string) $httpResponse->getBody(true)); + } + + /** + * @var Response + */ + $this->response = new static::$RESPONSE_CLASS($this, $responseData); + + $this->response->setCode((string) $httpResponse->getStatusCode()); + + if ($httpResponse->hasHeader('Request-Id')) { + $request_id_header = $httpResponse->getHeader('Request-Id'); + $this->response->setRequestId($request_id_header ? strval($request_id_header) : null); + } + + return $this->response; + } + + /** + * Redefining to tell Psalm this function is variadic + * + * @return void + * @psalm-variadic + */ + public function validate() + { + call_user_func_array('parent::' . __FUNCTION__, func_get_args()); + } + + /** + * Overriding to provide a more precise return type + * + * @return Response + */ + public function send() + { + /** + * @var Response + */ + return parent::send(); + } +} diff --git a/src/Message/ExtendedAbstractRequest.php b/src/Message/ExtendedAbstractRequest.php new file mode 100644 index 0000000..e1ffd2e --- /dev/null +++ b/src/Message/ExtendedAbstractRequest.php @@ -0,0 +1,96 @@ +getParameter('storeReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the store (BlueSnap calls this the store ID) + * + * @param string $value + * @return static + */ + public function setStoreReference($value) + { + return $this->setParameter('storeReference', $value); + } + + /** + * Gets the gateway's identifier for the plan (Bluesnap contract) + * + * @return string|null + */ + public function getPlanReference() + { + return strval($this->getParameter('planReference')) ?: null; + } + + /** + * Sets the gateway's identifier for the plan (Bluesnap contract) + * + * @param string $value + * @return static + */ + public function setPlanReference($value) + { + return $this->setParameter('planReference', $value); + } + + /** + * Gets the parameters for the store URL + * + * @return UrlParameterBag|null + */ + public function getStoreParameters() + { + /** + * @var UrlParameterBag|null + */ + return $this->getParameter('storeParameters'); + } + + /** + * Sets the parameters for the store URL + * + * @param UrlParameterBag|array $parameters + * @return static + */ + public function setStoreParameters($parameters) + { + if ($parameters && !$parameters instanceof UrlParameterBag) { + $parameters = new UrlParameterBag($parameters); + } + + return $this->setParameter('storeParameters', $parameters); + } + + /** + * Overriding to provide a more precise return type + * + * @return Response + */ + public function send() + { + /** + * @var Response + */ + return parent::send(); + } +} diff --git a/src/Message/ExtendedCancelSubscriptionRequest.php b/src/Message/ExtendedCancelSubscriptionRequest.php new file mode 100644 index 0000000..1828f70 --- /dev/null +++ b/src/Message/ExtendedCancelSubscriptionRequest.php @@ -0,0 +1,68 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you could cancel the + * // subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $cancelResponse = $gateway->cancelSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($cancelResponse->isSuccessful()) { + * // do stuff + * } else { + * // error handling + * } + * } + * + */ +class ExtendedCancelSubscriptionRequest extends ExtendedUpdateSubscriptionRequest +{ + /** + * @return SimpleXMLElement + */ + public function getData() + { + $this->validate('subscriptionReference'); + + $data = new SimpleXMLElement(''); + $data->{'subscription-id'} = $this->getSubscriptionReference(); + $data->status = 'C'; + + return $data; + } +} diff --git a/src/Message/ExtendedFetchCustomerRequest.php b/src/Message/ExtendedFetchCustomerRequest.php new file mode 100644 index 0000000..dc6ee4c --- /dev/null +++ b/src/Message/ExtendedFetchCustomerRequest.php @@ -0,0 +1,66 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_Extended'); // BlueSnap_HostedCheckout works too + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Customer gets created when they go through the offsite checkout + * // Alternatively, you could add support to this driver for the BlueSnap Create Shopper request + * + * // Now we want to fetch the customer + * $response = $gateway->fetchCustomer(array( + * 'customerId' => $customerResponse->getCustomerId() + * ))->send(); + * + * if ($response->isSuccessful()) { + * echo 'Customer Reference: " . $response->getCustomerReference()) . PHP_EOL; + * // Right now, this is all that can be grabbed from this response, so it's not + * // super useful. But more functionality could be added to the driver. + * } + * + * + */ +class ExtendedFetchCustomerRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('customerReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/shoppers/' . strval($this->getCustomerReference()); + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedFetchSubscriptionChargeRequest.php b/src/Message/ExtendedFetchSubscriptionChargeRequest.php new file mode 100644 index 0000000..8bddf30 --- /dev/null +++ b/src/Message/ExtendedFetchSubscriptionChargeRequest.php @@ -0,0 +1,106 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can fetch the subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $subscriptionResponse = $gateway->fetchSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($subscriptionResponse->isSuccessful()) { + * $subscriptionChargeReferences = $subscriptionResponse->getSubscriptionChargeReferences(); + * + * // Now we can fetch each subscription charge + * + * foreach ($subscriptionChargeReferences as $subscriptionChargeReference) { + * $subscriptionChargeResponse = $gateway->fetchSubscriptionCharge(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference(), + * 'subscriptionChargeReference' => $subscriptionChargeReference + * ))->send(); + * + * if ($subscriptionChargeResponse->isSuccessful()) { + * echo 'Currency: ' . $subscriptionChargeResponse->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $subscriptionChargeResponse->getAmount() . PHP_EOL; + * echo 'Date Created: ' . $subscriptionChargeResponse->getDateCreated()->format('Y-m-d') . PHP_EOL; + * echo 'Transaction Reference: ' . $subscriptionChargeResponse->getTransactionReference() . PHP_EOL; + * } else { + * // error handling + * } + * } + * } else { + * // error handling + * } + * } + * + */ +class ExtendedFetchSubscriptionChargeRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('subscriptionReference'); + $this->validate('subscriptionChargeReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/subscriptions/' . strval($this->getSubscriptionReference()) + . '/subscription-charges/' . strval($this->getSubscriptionChargeReference()); + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedFetchSubscriptionRequest.php b/src/Message/ExtendedFetchSubscriptionRequest.php new file mode 100644 index 0000000..a765711 --- /dev/null +++ b/src/Message/ExtendedFetchSubscriptionRequest.php @@ -0,0 +1,94 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can fetch the subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $subscriptionResponse = $gateway->fetchSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($subscriptionResponse->isSuccessful()) { + * echo 'Currency: ' . $subscriptionResponse->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $subscriptionResponse->getAmount() . PHP_EOL; + * echo 'Next charge date: ' . $subscriptionResponse->getNextChargeDate()->format('Y-m-d') . PHP_EOL; + * echo 'Customer Reference: ' . $subscriptionResponse->getCustomerReference() . PHP_EOL; + * foreach ($subscriptionResponse->getSubscriptionCharges() as $charge) { + * echo 'Transaction reference ' . $charge->getTransactionReference() . PHP_EOL; + * echo 'Charge Amount ' . $charge->getAmount() . PHP_EOL; + * echo 'Charge currency ' . $charge->getCurrency() . PHP_EOL; + * echo 'Charge date ' . $charge->getDate()->format('Y-m-d') . PHP_EOL; + * } + * } else { + * // error handling + * } + * } + * + */ +class ExtendedFetchSubscriptionRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('subscriptionReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() + . '/subscriptions/' + . strval($this->getSubscriptionReference()) + . '?fulldescription=true'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedFetchSubscriptionsRequest.php b/src/Message/ExtendedFetchSubscriptionsRequest.php new file mode 100644 index 0000000..9655c3d --- /dev/null +++ b/src/Message/ExtendedFetchSubscriptionsRequest.php @@ -0,0 +1,93 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can fetch the subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $subscriptionResponse = $gateway->fetchSubscriptions(array( + * 'customerReference' => $ipnCallback->getCustomerReference() + * ))->send(); + * + * if ($subscriptionResponse->isSuccessful()) { + * foreach ($subscriptionResponse->getSubscriptions() as $subscription) { + * echo 'Subscription reference ' . $subscription->getSubscriptionReference() . PHP_EOL; + * echo 'Subscription Amount ' . $subscription->getAmount() . PHP_EOL; + * echo 'Subscription currency ' . $subscription->getCurrency() . PHP_EOL; + * echo 'Subscription status ' . $subscription->getStatus() . PHP_EOL; + * } + * } else { + * // error handling + * } + * } + * + */ +class ExtendedFetchSubscriptionsRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('customerReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() + . '/tools/shopper-subscriptions-retriever' + . '?shopperid=' . strval($this->getCustomerReference()) + . '&fulldescription=true'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedFetchTransactionRequest.php b/src/Message/ExtendedFetchTransactionRequest.php new file mode 100644 index 0000000..09175da --- /dev/null +++ b/src/Message/ExtendedFetchTransactionRequest.php @@ -0,0 +1,92 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can fetch the transaction: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $transactionResponse = $gateway->fetchTransaction(array( + * 'transactionReference' => $ipnCallback->getTransactionReference() + * ))->send(); + * + * if ($transactionResponse->isSuccessful()) { + * echo 'Currency: ' . $transactionResponse->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $transactionResponse->getAmount() . PHP_EOL; + * echo 'Date created: ' . $transactionResponse->getDateCreated()->format('Y-m-d') . PHP_EOL; + * echo 'Customer Reference: ' . $transactionResponse->getCustomerReference() . PHP_EOL; + * echo 'Custom parameter "foo": ' . $transactionResponse->getCustomParameter('foo') . PHP_EOL; + * var_dump($transactionResponse->getCard()); + * } else { + * // error handling + * } + * } + * + */ +class ExtendedFetchTransactionRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('transactionReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/orders/resolve?invoiceId=' + . strval($this->getTransactionReference()); + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedReactivateSubscriptionRequest.php b/src/Message/ExtendedReactivateSubscriptionRequest.php new file mode 100644 index 0000000..a691570 --- /dev/null +++ b/src/Message/ExtendedReactivateSubscriptionRequest.php @@ -0,0 +1,77 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you could cancel the + * // subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $cancelResponse = $gateway->cancelSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($cancelResponse->isSuccessful()) { + * // Now you can reactivate the subscription + * $reactivateResponse = $gateway->reactivateSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($reactivateResponse->isSuccessful()) { + * // do stuff + * } else { + * // error handling + * } + * } else { + * // error handling + * } + * } + * + */ +class ExtendedReactivateSubscriptionRequest extends ExtendedUpdateSubscriptionRequest +{ + /** + * @return SimpleXMLElement + */ + public function getData() + { + $this->validate('subscriptionReference'); + + $data = new SimpleXMLElement(''); + $data->{'subscription-id'} = $this->getSubscriptionReference(); + $data->status = 'A'; + + return $data; + } +} diff --git a/src/Message/ExtendedRefundRequest.php b/src/Message/ExtendedRefundRequest.php new file mode 100644 index 0000000..aff6d78 --- /dev/null +++ b/src/Message/ExtendedRefundRequest.php @@ -0,0 +1,148 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can refund the transaction: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $refundResponse = $gateway->refund(array( + * 'transactionReference' => $ipnCallback->getTransactionReference() + * ))->send(); + * + * if ($refundResponse->isSuccessful()) { + * // do stuff + * } else { + * // error handling + * } + * } + * + */ +class ExtendedRefundRequest extends ExtendedAbstractRequest +{ + /** + * Gets the refund reason + * + * @return string|null + */ + public function getReason() + { + return strval($this->getParameter('reason')) ?: null; + } + + /** + * Sets the refund reason + * + * @param string $value + * @return static + */ + public function setReason($value) + { + return $this->setParameter('reason', $value); + } + + /** + * Gets whether subscriptions should be canceled + * + * @return bool|null + */ + public function getCancelSubscriptions() + { + /** + * @var bool|null + */ + return $this->getParameter('cancelSubscriptions'); + } + + /** + * Sets whether subscriptions should be canceled (default false) + * + * @param bool $value + * @return static + */ + public function setCancelSubscriptions($value) + { + return $this->setParameter('cancelSubscriptions', $value); + } + + /** + * @return null + */ + public function getData() + { + $this->validate('transactionReference'); + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + $params = array( + 'invoiceId' => $this->getTransactionReference() + ); + $amount = $this->getAmount(); + if (isset($amount)) { + $params['amount'] = $amount; + } + $reason = $this->getReason(); + if (isset($reason)) { + $params['reason'] = $reason; + } + // false is default + $params['cancelSubscriptions'] = $this->getCancelSubscriptions() ? 'true' : 'false'; + + return parent::getEndpoint() . '/orders/refund?' . http_build_query($params); + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_PUT; + } +} diff --git a/src/Message/ExtendedTestChargeSubscriptionRequest.php b/src/Message/ExtendedTestChargeSubscriptionRequest.php new file mode 100644 index 0000000..de3221f --- /dev/null +++ b/src/Message/ExtendedTestChargeSubscriptionRequest.php @@ -0,0 +1,91 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(true); // test mode must be true + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you can charge the subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $chargeResponse = $gateway->testChargeSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference() + * ))->send(); + * + * if ($chargeResponse->isSuccessful()) { + * // do stuff + * } else { + * // error handling + * } + * } + * + */ +class ExtendedTestChargeSubscriptionRequest extends ExtendedAbstractRequest +{ + /** + * @return null + */ + public function getData() + { + $this->validate('subscriptionReference'); + if (!$this->getTestMode()) { + throw new InvalidRequestException( + 'You cannot make a test subscription charge if you\'re not in test mode' + ); + } + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/subscriptions/' + . strval($this->getSubscriptionReference()) . '/run-specific'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/ExtendedUpdateSubscriptionRequest.php b/src/Message/ExtendedUpdateSubscriptionRequest.php new file mode 100644 index 0000000..7a5cefb --- /dev/null +++ b/src/Message/ExtendedUpdateSubscriptionRequest.php @@ -0,0 +1,125 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback, at which point you could update the + * // subscription: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * $updateResponse = $gateway->updateSubscription(array( + * 'subscriptionReference' => $ipnCallback->getSubscriptionReference(), + * 'planReference' => '1234567', + * 'currency' => 'GBP', + * 'amount' => '123.12', + * 'nextChargeDate' => new DateTime('2018-09-01', new DateTimeZone('Etc/GMT+8')) + * ))->send(); + * + * if ($updateResponse->isSuccessful()) { + * // do stuff + * } else { + * // error handling + * } + * } + * + */ +class ExtendedUpdateSubscriptionRequest extends ExtendedAbstractRequest +{ + /** + * @return SimpleXMLElement + */ + public function getData() + { + $this->validate('subscriptionReference'); + + $data = new SimpleXMLElement(''); + + $data->{'subscription-id'} = $this->getSubscriptionReference(); + + $newPrice = $this->getAmount(); + $newCurrency = $this->getCurrency(); + if (isset($newPrice)) { + $data->{'override-recurring-charge'}->amount = $newPrice; + } + if (isset($newCurrency)) { + $data->{'override-recurring-charge'}->currency = $newCurrency; + } + + $newNextChargeDate = $this->getNextChargeDate(); + if (isset($newNextChargeDate)) { + $data->{'next-charge-date'} = $newNextChargeDate->format('d-M-y'); + } + + $planReference = $this->getPlanReference(); + if (isset($planReference)) { + $data->{'underlying-sku-id'} = $planReference; + } + + return $data; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/subscriptions/' . strval($this->getSubscriptionReference()); + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_PUT; + } +} diff --git a/src/Message/FetchCanceledSubscriptionsRequest.php b/src/Message/FetchCanceledSubscriptionsRequest.php new file mode 100644 index 0000000..3111f88 --- /dev/null +++ b/src/Message/FetchCanceledSubscriptionsRequest.php @@ -0,0 +1,48 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap'); // BlueSnap_Extended and + * // BlueSnap_HostedCheckout work too + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Lots of users make lots of purchases and some of them are canceled... + * + * // Now we fetch those canceled subscriptions: + * $response = $gateway->fetchCanceledSubscriptions(array( + * 'startTime' => new DateTime('2016-09-01', new DateTimeZone('Etc/GMT+8')), + * 'startTime' => new DateTime('2016-09-02', new DateTimeZone('Etc/GMT+8')) + * ))->send(); + * + * if ($response->isSuccessful()) { + * foreach ($response->getSubscriptions() as $subscription) { + * echo 'Subscription reference: ' . $subscription->getSubscriptionReference() . PHP_EOL; + * echo 'Currency: ' . $subscription->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $subscription->getAmount() . PHP_EOL; + * } + * } else { + * // error handling + * } + * + */ +class FetchCanceledSubscriptionsRequest extends FetchSubscriptionsRequest +{ + const REPORT_NAME = 'CanceledSubscriptions'; +} diff --git a/src/Message/FetchSubscriptionsRequest.php b/src/Message/FetchSubscriptionsRequest.php new file mode 100644 index 0000000..5f6ac60 --- /dev/null +++ b/src/Message/FetchSubscriptionsRequest.php @@ -0,0 +1,48 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap'); // BlueSnap_Extended and + * // BlueSnap_HostedCheckout work too + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Lots of users make lots of purchases... + * + * // Now we fetch those subscriptions: + * $response = $gateway->fetchSubscriptions(array( + * 'startTime' => new DateTime('2016-09-01', new DateTimeZone('Etc/GMT+8')), + * 'startTime' => new DateTime('2016-09-02', new DateTimeZone('Etc/GMT+8')) + * ))->send(); + * + * if ($response->isSuccessful()) { + * foreach ($response->getSubscriptions() as $subscription) { + * echo 'Subscription reference: ' . $subscription->getSubscriptionReference() . PHP_EOL; + * echo 'Currency: ' . $subscription->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $subscription->getAmount() . PHP_EOL; + * } + * } else { + * // error handling + * } + * + */ +class FetchSubscriptionsRequest extends FetchTransactionsRequest +{ + const REPORT_NAME = 'ActiveSubscriptions'; +} diff --git a/src/Message/FetchTransactionsRequest.php b/src/Message/FetchTransactionsRequest.php new file mode 100644 index 0000000..660d5e9 --- /dev/null +++ b/src/Message/FetchTransactionsRequest.php @@ -0,0 +1,98 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap'); // BlueSnap_Extended and + * // BlueSnap_HostedCheckout work too + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Lots of users make lots of purchases... + * + * // Now we fetch those transactions: + * $response = $gateway->fetchTransactions(array( + * 'startTime' => new DateTime('2016-09-01', new DateTimeZone('Etc/GMT+8')), + * 'startTime' => new DateTime('2016-09-02', new DateTimeZone('Etc/GMT+8')) + * ))->send(); + * + * if ($response->isSuccessful()) { + * foreach ($response->getTransactions() as $transaction) { + * echo 'Transaction reference: ' . $transaction->getTransactionReference() . PHP_EOL; + * echo 'Customer reference: ' . $customer->getCustomerReference() . PHP_EOL; + * echo 'Currency: ' . $transaction->getCurrency() . PHP_EOL; + * echo 'Amount: ' . $transaction->getAmount() . PHP_EOL; + * echo 'Date: ' . $transaction->getDate()->format('Y-m-d') . PHP_EOL; + * echo 'Custom parameter 1: ' . $transaction->getCustomParameter1() . PHP_EOL; + * echo 'Custom parameter 8: ' . $transaction->getCustomParameter8() . PHP_EOL; + * } + * } else { + * // error handling + * } + * + */ +class FetchTransactionsRequest extends AbstractRequest +{ + const REPORT_NAME = 'TransactionDetail'; + + /** + * @return null + */ + public function getData() + { + $this->validate('startTime'); + $this->validate('endTime'); + + if ($this->getStartTime() > $this->getEndTime()) { + throw new InvalidRequestException('startTime cannot be greater than endTime'); + } + + return null; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + $startTime = $this->getStartTime(); + $endTime = $this->getEndTime(); + $endpoint = parent::getEndpoint() . '/report/' . (string) static::REPORT_NAME; + + // this should always be true + if ($startTime && $endTime) { + $endpoint .= '?period=CUSTOM' + . '&from_date=' . urlencode((string) $startTime->format('m/d/Y')) + . '&to_date=' . urlencode((string) $endTime->format('m/d/Y')); + } + return $endpoint; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_GET; + } +} diff --git a/src/Message/HostedCheckoutDecryptReturnUrlRequest.php b/src/Message/HostedCheckoutDecryptReturnUrlRequest.php new file mode 100644 index 0000000..fa355bd --- /dev/null +++ b/src/Message/HostedCheckoutDecryptReturnUrlRequest.php @@ -0,0 +1,104 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Then they get redirected back + * // to your site, where you can decrypt the parameters in the return URL: + * + * $decryptResponse = $gateway->decryptReturnUrl(array( + * 'returnUrl' => $_SERVER['REQUEST_URI'] + * ))->send(); + * if ($decryptResponse->isSuccessful()) { + * var_dump($decryptResponse->getDecryptedParameters()); + * } + * + */ +class HostedCheckoutDecryptReturnUrlRequest extends ExtendedAbstractRequest +{ + /** + * @return SimpleXMLElement + */ + public function getData() + { + $this->validate('returnUrl'); + $returnUrl = $this->getReturnUrl() ?: ''; + + // if returnUrl is a full URL, find the query string, otherwise assume it's all a query string + /** + * @var array|false + */ + $urlParts = parse_url($returnUrl); + $queryString = isset($urlParts['query']) ? (string) $urlParts['query'] : $returnUrl; + + // find the encrypted parameters in the query string; + // if not there, assume the whole thing is the encrypted parameters + parse_str($queryString, $queryParams); + /** + * @var string + */ + $encryptedToken = isset($queryParams['encParams']) ? $queryParams['encParams'] : $returnUrl; + + $data = new SimpleXMLElement(''); + $data->{'encrypted-token'} = $encryptedToken; + + return $data; + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/tools/param-decryption'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_POST; + } +} diff --git a/src/Message/HostedCheckoutPurchaseRequest.php b/src/Message/HostedCheckoutPurchaseRequest.php new file mode 100644 index 0000000..473eccc --- /dev/null +++ b/src/Message/HostedCheckoutPurchaseRequest.php @@ -0,0 +1,181 @@ + 'value'. A list of parameters is + * available at https://support.bluesnap.com/docs/buynow-parameters + * + * + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567', + * 'currency' => 'JPY', + * 'returnUrl' => 'https://www.example.com/thanks', + * 'storeParameters' => array( + * 'sku1234567priceamount' => '10.00', // optional price override of plan 1234567 + * 'language' => 'JAPANESE' // force store language to be Japanese + * ) + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Then they get redirected back + * // to your site, where you can decrypt the parameters in the return URL if you wish: + * + * $decryptResponse = $gateway->decryptReturnUrl(array( + * 'returnUrl' => $_SERVER['REQUEST_URI'] + * ))->send(); + * if ($decryptResponse->isSuccessful()) { + * var_dump($decryptResponse->getDecryptedParameters()); + * } + * + * // Once the transaction has been captured, you'll receive an IPN callback, which you can + * // handle like so: + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * if ($ipnCallback->isCharge()) { + * echo 'Transaction reference: ' . $ipnCallback->getTransactionReference() . PHP_EOL; + * echo 'Amount: ' . $ipnCallback->getAmount() . PHP_EOL; + * echo 'Currency: ' . $ipnCallback->getCurrency() . PHP_EOL; + * } elseif ($ipnCallback->isCancellation()) { + * // etc. + * } + * + */ +class HostedCheckoutPurchaseRequest extends ExtendedAbstractRequest +{ + /** + * @var string + */ + protected static $RESPONSE_CLASS = '\Omnipay\BlueSnap\Message\HostedCheckoutPurchaseResponse'; + + /** + * @return SimpleXMLElement + */ + public function getData() + { + $this->validate('storeReference'); + + // planReference is not required to allow people to set different quantities or + // multiple plans by specifying them in parameters. One day a nicer format for + // specifying multiple plans could be provided. + $planReference = $this->getPlanReference(); + $parameters = $this->getStoreParameters(); + $currency = $this->getCurrency(); + $returnUrl = $this->getReturnUrl(); + + $data = new SimpleXMLElement(''); + $parametersElement = $data->addChild('parameters'); + if (isset($planReference)) { + $this->addParameter($parametersElement, 'sku' . (string) $planReference, '1'); + } + if (isset($currency)) { + $this->addParameter($parametersElement, 'currency', $currency); + } + if (isset($returnUrl)) { + $this->addParameter($parametersElement, 'thankyou.backtosellerurl', urlencode($returnUrl)); + } + if (isset($parameters)) { + /** + * @var \Omnipay\BlueSnap\UrlParameter + */ + foreach ($parameters as $parameter) { + $parameterElement = $parametersElement->addChild('parameter'); + $parameterElement->addChild('param-key', (string) $parameter->getKey()); + $parameterElement->addChild('param-value', (string) $parameter->getValue()); + } + } + + return $data; + } + + /** + * Add a parameter to the parameters XML + * + * @param SimpleXMLElement $parameters + * @param string $key + * @param string $value + * @return void + */ + protected function addParameter(SimpleXMLElement $parameters, $key, $value) + { + $element = $parameters->addChild('parameter'); + $element->addChild('param-key', $key); + $element->addChild('param-value', $value); + } + + /** + * Return the API endpoint. + * + * @return string + */ + public function getEndpoint() + { + return parent::getEndpoint() . '/tools/param-encryption'; + } + + /** + * Returns the HTTP method to be used for this request + * + * @return string + */ + public function getHttpMethod() + { + return Constants::HTTP_METHOD_POST; + } + + /** + * Overriding to provide a more precise return type + * + * @return HostedCheckoutPurchaseResponse + */ + public function send() + { + /** + * @var HostedCheckoutPurchaseResponse + */ + return parent::send(); + } +} diff --git a/src/Message/HostedCheckoutPurchaseResponse.php b/src/Message/HostedCheckoutPurchaseResponse.php new file mode 100644 index 0000000..251660c --- /dev/null +++ b/src/Message/HostedCheckoutPurchaseResponse.php @@ -0,0 +1,62 @@ +isSuccessful(); + } + + /** + * Returns the BuyNow Hosted Checkout store URL + * + * @return string + * @psalm-suppress MixedPropertyFetch + */ + public function getRedirectUrl() + { + /** + * @var HostedCheckoutPurchaseRequest + */ + $request = $this->getRequest(); + + return 'https://' + . (!$request->getTestMode() ? 'checkout' : 'sandbox') + . '.bluesnap.com/buynow/checkout?' + . 'storeId=' . strval($request->getStoreReference()) + . '&enc=' . $this->data->{'encrypted-token'}; + } + + /** + * Returns the redirect method + * + * @return string + */ + public function getRedirectMethod() + { + return Constants::HTTP_METHOD_GET; + } + + /** + * Gets the redirect form data array, if the redirect method is POST. + * + * @return array + */ + public function getRedirectData() + { + return array(); + } +} diff --git a/src/Message/IPNCallback.php b/src/Message/IPNCallback.php new file mode 100644 index 0000000..a5503bd --- /dev/null +++ b/src/Message/IPNCallback.php @@ -0,0 +1,277 @@ + + * // Set up the gateway + * $gateway = \Omnipay\Omnipay::create('BlueSnap_HostedCheckout'); + * $gateway->setUsername('your_username'); + * $gateway->setPassword('y0ur_p4ssw0rd'); + * $gateway->setTestMode(false); + * + * // Start the purchase process + * $purchaseResponse = $gateway->purchase(array( + * 'storeReference' => '12345', + * 'planReference' => '1234567' + * ))->send(); + * + * if ($purchaseResponse->isSuccessful()) { + * echo "Redirecting to: " . $purchaseResponse->getRedirectUrl() . PHP_EOL; + * $purchaseResponse->redirect(); + * } else { + * // error handling + * } + * + * // Now the user is filling out info on BlueSnap's site. Once the transaction has been + * // captured, you'll receive an IPN callback. + * + * // not a request, so no ->send() call + * $ipnCallback = $gateway->parseIPNCallback($_SERVER['REQUEST_URI']); + * // OR: $ipnCallback = $gateway->parseIPNCallback($_POST); + * if ($ipnCallback->isCharge()) { + * echo 'Transaction reference: ' . $ipnCallback->getTransactionReference() . PHP_EOL; + * echo 'Subscription reference: ' . $ipnCallback->getSubscriptionReference() . PHP_EOL; + * echo 'Plan reference: ' . $ipnCallback->getPlanReference() . PHP_EOL; + * echo 'Customer reference: ' . $ipnCallback->getCustomerReference() . PHP_EOL; + * echo 'Amount: ' . $ipnCallback->getAmount() . PHP_EOL; + * echo 'Currency: ' . $ipnCallback->getCurrency() . PHP_EOL; + * echo 'Date: ' . $ipnCallback->getDate()->format('Y-m-d') . PHP_EOL; + * echo 'Misc. parameter: ' . $ipnCallback->getParameter('paramName') . PHP_EOL; + * } elseif ($ipnCallback->isCancellation()) { + * // do stuff + * } elseif ($ipnCallback->isCancellationRequest()) { + * // do stuff + * } elseif ($ipnCallback->isChargeback()) { + * // do stuff + * } elseif ($ipnCallback->isSubscriptionCharge()) { + * // do stuff + * } elseif ($ipnCallback->isRefund()) { + * // do stuff + * } elseif ($ipnCallback->isChargeFailure()) { + * // do stuff + * } elseif ($ipnCallback->isSubscriptionChargeFailure()) { + * // do stuff + * } + * + */ +class IPNCallback +{ + /** + * @var array + */ + protected $queryParams; + + /** + * Build and parse the IPN callback. + * $ipn can be a full URL, just the query string, or the value of the $_POST variable. + * + * @param string|array $ipn + */ + public function __construct($ipn) + { + if (is_array($ipn)) { + $this->queryParams = $ipn; + return; + } + + /** + * @var array|false + */ + $urlParts = parse_url($ipn); + $queryString = isset($urlParts['query']) ? (string) $urlParts['query'] : $ipn; + + parse_str($queryString, $this->queryParams); + } + + /** + * Is this a CHARGE IPN? Charge IPNs are fired when a transaction is successfully + * captured. For subscription charges, see isSubscriptionCharge. + * + * @return bool + */ + public function isCharge() + { + return $this->getIPNType() === 'CHARGE'; + } + + /** + * Is this a CANCELLATION IPN? Cancellation IPNs are fired when a recurring charge + * is cancelled. + * + * @return bool + */ + public function isCancellation() + { + return $this->getIPNType() === 'CANCELLATION'; + } + + /** + * Is this a CANCEL_ON_RENEWAL IPN? This IPN is fired when a user cancels or opts out + * of their subscription. The subscription will be automatically canceled at the end of + * the billing period. + * + * @return bool + */ + public function isCancellationRequest() + { + return $this->getIPNType() === 'CANCEL_ON_RENEWAL'; + } + + /** + * Is this a CHARGEBACK IPN? Chargeback IPNs are fired when a transaction has a chargeback. + * + * @return bool + */ + public function isChargeback() + { + return $this->getIPNType() === 'CHARGEBACK'; + } + + /** + * Is this a RECURRING, or subscription charge, IPN? This IPN is fired when a subscription + * is successfully charged for the second time, and all times thereafter. For the first charge, + * see isCharge. + * + * @return bool + */ + public function isSubscriptionCharge() + { + return $this->getIPNType() === 'RECURRING'; + } + + /** + * Is this a REFUND IPN? Refund IPNs are fired when a transaction is refunded + * + * @return bool + */ + public function isRefund() + { + return $this->getIPNType() === 'REFUND'; + } + + /** + * Is this a CC_CHARGE_FAILED, or charge failure, IPN? This IPN is fired when a credit + * card payment fails. For subscriptions, also see isSubscriptionChargeFailure. + * + * @return bool + */ + public function isChargeFailure() + { + return $this->getIPNType() === 'CC_CHARGE_FAILED'; + } + + /** + * Is this a SUBSCRIPTION_CHARGE_FAILURE IPN? This IPN is fired when a credit + * card charge fails for the second or subsequent charges for a subscription. + * For the first charge, see isChargeFailure. + * + * @return bool + */ + public function isSubscriptionChargeFailure() + { + return $this->getIPNType() === 'SUBSCRIPTION_CHARGE_FAILURE'; + } + + /** + * Get the type of the IPN + * + * @return string|null + */ + protected function getIPNType() + { + return $this->getParameter('transactionType'); + } + + /** + * Returns the gateway's identifier for the transaction + * + * @return string|null + */ + public function getTransactionReference() + { + return $this->getParameter('referenceNumber') ?: null; + } + + /** + * Returns the gateway's identifier for the subscription + * + * @return string|null + */ + public function getSubscriptionReference() + { + return $this->getParameter('subscriptionId') ?: null; + } + + /** + * Returns the gateway's identifier for the plan (Bluesnap contract) + * + * @return string|null + */ + public function getPlanReference() + { + return $this->getParameter('contractId') ?: null; + } + + /** + * Returns the gateway's identifier for the customer + * + * @return string|null + */ + public function getCustomerReference() + { + return $this->getParameter('accountId') ?: null; + } + + /** + * Returns the transaction amount + * + * @return string|null + */ + public function getAmount() + { + $amount = $this->getParameter('invoiceAmount'); + return $amount === '' ? null : $amount; + } + + /** + * Returns the transaction currency + * + * @return string|null + */ + public function getCurrency() + { + return $this->getParameter('currency') ?: null; + } + + /** + * Returns the time and date of the IPN callback + * + * @return DateTime|null + */ + public function getDate() + { + $date = $this->getParameter('transactionDate'); + return $date ? new DateTime($date, new DateTimeZone(Constants::BLUESNAP_TIME_ZONE)) : null; + } + + /** + * Get the value of a parameter returned in the IPN callback + * + * @param string $parameter + * @return string|null + */ + public function getParameter($parameter) + { + return isset($this->queryParams[$parameter]) ? $this->queryParams[$parameter] : null; + } +} diff --git a/src/Message/Response.php b/src/Message/Response.php new file mode 100644 index 0000000..12681b1 --- /dev/null +++ b/src/Message/Response.php @@ -0,0 +1,629 @@ +getCode() ?: '', 0, 1) === '2'; + } + + /** + * Get the ID from the HTTP request + * + * @return string|null + */ + public function getRequestId() + { + return $this->requestId; + } + + /** + * Set the ID from the HTTP request + * + * @param string|null $requestId + * @return static + */ + public function setRequestId($requestId) + { + $this->requestId = $requestId; + return $this; + } + + /** + * Get the HTTP response code + * + * @return string|null + */ + public function getCode() + { + return $this->code; + } + + /** + * Set the HTTP response code + * + * @param string $code + * @return static + */ + public function setCode($code) + { + $this->code = $code; + return $this; + } + + /** + * Get the error message from the response. Returns null if request was successful. + * + * @return string|null + */ + public function getMessage() + { + if (!$this->isSuccessful()) { + if ($this->data instanceof SimpleXMLElement && isset($this->data->message->description)) { + return (string) $this->data->message->description; + } + // some error responses are plain text instead of XML + return (string) $this->data; + } + + return null; + } + + /** + * Get the gateway's identifier for the customer + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getCustomerReference() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + if (isset($this->data->{'shopper-id'})) { + return (string) $this->data->{'shopper-id'}; + } + if (isset($this->data->{'shopper-info'}->{'shopper-id'})) { + return (string) $this->data->{'shopper-info'}->{'shopper-id'}; + } + if (isset($this->data->{'ordering-shopper'}->{'shopper-id'})) { + return (string) $this->data->{'ordering-shopper'}->{'shopper-id'}; + } + return null; + } + + /** + * Get the gateway's identifier for the transaction + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getTransactionReference() + { + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return (string) $invoice->{'invoice-id'}; + } + if ($this->data instanceof SimpleXMLElement + && isset($this->data->{'charge-invoice-info'}->{'invoice-id'})) { + return (string) $this->data->{'charge-invoice-info'}->{'invoice-id'}; + } + + return null; + } + + /** + * Get the gateway's identifier for the subscription + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getSubscriptionReference() + { + if ($this->data instanceof SimpleXMLElement && isset($this->data->{'subscription-id'})) { + return (string) $this->data->{'subscription-id'}; + } + return null; + } + + /** + * Get the monetary amount of a transaction or subscription + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getAmount() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return (string) $invoice->{'financial-transactions'}->{'financial-transaction'}->amount; + } + // if an override charge is set, that's the current amount, not the catalog (original) one + if (isset($this->data->{'override-recurring-charge'}->amount)) { + return (string) $this->data->{'override-recurring-charge'}->amount; + } + if (isset($this->data->{'catalog-recurring-charge'}->amount)) { + return (string) $this->data->{'catalog-recurring-charge'}->amount; + } + if (isset($this->data->{'charge-invoice-info'}->{'invoice-amount'})) { + return (string) $this->data->{'charge-invoice-info'}->{'invoice-amount'}; + } + return null; + } + + /** + * Get the tax amount of a transaction or subscription + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getTax() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + // if an override charge is set, that's the current amount, not the catalog (original) one + if (isset($this->data->{'cart'}->tax)) { + return (string) $this->data->{'cart'}->tax; + } + return null; + } + /** + * Get the currency of a transaction or subscription + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getCurrency() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return (string) $invoice->{'financial-transactions'}->{'financial-transaction'}->currency; + } + // if an override charge is set, that's the current currency, not the catalog (original) one + if (isset($this->data->{'override-recurring-charge'}->currency)) { + return (string) $this->data->{'override-recurring-charge'}->currency; + } + if (isset($this->data->{'catalog-recurring-charge'}->currency)) { + return (string) $this->data->{'catalog-recurring-charge'}->currency; + } + if (isset($this->data->{'charge-invoice-info'}->{'invoice-currency'})) { + return (string) $this->data->{'charge-invoice-info'}->{'invoice-currency'}; + } + return null; + } + + /** + * Get an array of subscription charges from a subscription. + * will return the references of all charges made on that subscription. + * The empty array will be returned if there are no charges. + * + * @return array|null + * @psalm-suppress MixedPropertyFetch + * @psalm-suppress MixedAssignment + */ + public function getSubscriptionCharges() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + + $subscriptionCharges = array(); + if (isset($this->data->{'subscription-charges'})) { + foreach ($this->data->{'subscription-charges'}->children() as $charge) { + if (isset($charge->{'charge-invoice-info'})) { + $params = array( + 'date' => new DateTime( + (string) $charge->{'charge-invoice-info'}->{'date-created'}, + new DateTimeZone(Constants::BLUESNAP_TIME_ZONE) + ), + 'transactionReference' => (string) $charge->{'charge-invoice-info'}->{'invoice-id'}, + 'amount' => (string) $charge->{'charge-invoice-info'}->{'invoice-amount'}, + 'currency' => (string) $charge->{'charge-invoice-info'}->{'invoice-currency'}, + 'customerReference' => (string) $this->getCustomerReference(), + 'subscriptionReference' => (string) $this->getSubscriptionReference() + ); + $subscriptionCharges[] = new SubscriptionCharge($params); + } + } + } + return !empty($subscriptionCharges) ? $subscriptionCharges : null; + } + + + /** + * Function to get a subscription status. + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getStatus() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + // Check if we have invoice and invoice status + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return (string)$invoice->{'financial-transactions'}->{'financial-transaction'}->{'status'}; + } + // check if status element is set and return + if (isset($this->data->{'status'})) { + return (string) $this->data->{'status'}; + } + return null; + } + + /** + * Function to get a plan reference. + * + * @return string|null + * @psalm-suppress MixedPropertyFetch + */ + public function getPlanReference() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + // Check if we have invoice and invoice plan reference (Bluesnap contract) + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return (string) $invoice->{'financial-transactions'} + ->{'financial-transaction'} + ->{'skus'} + ->{'sku'} + ->{'sku-id'}; + } + // check if underlying-sku-id element is set and return + if (isset($this->data->{'underlying-sku-id'})) { + return (string) $this->data->{'underlying-sku-id'}; + } + return null; + } + + /** + * Get date the transaction or charge was created. + * NOTE: BlueSnap only returns dates, not times. + * The DateTime returned will be in the Etc/GMT+8 time zone. + * + * @return DateTime|null + * @psalm-suppress MixedPropertyFetch + */ + public function getDateCreated() + { + if (!$this->data instanceof SimpleXMLElement) { + return null; + } + + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement && isset($invoice->{'invoice-id'})) { + return new DateTime( + $invoice->{'financial-transactions'}->{'financial-transaction'}->{'date-created'}, + new DateTimeZone(Constants::BLUESNAP_TIME_ZONE) + ); + } + + $subscriptionCharges = $this->getSubscriptionCharges(); + if (!empty($subscriptionCharges)) { + return $subscriptionCharges[0]->getDate(); + } + + if (isset($this->data->{'charge-invoice-info'}->{'date-created'})) { + return new DateTime( + $this->data->{'charge-invoice-info'}->{'date-created'}, + new DateTimeZone(Constants::BLUESNAP_TIME_ZONE) + ); + } + return null; + } + + /** + * Get the date of the next charge for a subscription + * NOTE: BlueSnap only returns dates, not times. + * The DateTime returned will be in the Etc/GMT+8 time zone. + * + * @return DateTime|null + * @psalm-suppress MixedPropertyFetch + */ + public function getNextChargeDate() + { + if ($this->data instanceof SimpleXMLElement && isset($this->data->{'next-charge-date'})) { + return new DateTime( + $this->data->{'next-charge-date'}, + new DateTimeZone(Constants::BLUESNAP_TIME_ZONE) + ); + } + return null; + } + + /** + * @return array|null + */ + public function getTransactions() + { + if (!isset($this->data['data'])) { + return null; + } + $transactions = array(); + /** + * @var array + */ + foreach ($this->data['data'] as $row) { + $params = array( + 'transactionReference' => $row['Invoice ID'], + 'date' => new DateTime($row['Transaction Date'], new DateTimeZone(Constants::BLUESNAP_TIME_ZONE)), + 'currency' => $row['Auth. Currency'], + 'amount' => $row['Merchant Sales (Auth Currency)'], + 'customerReference' => $row['Shopper ID'] + ); + // grab all the custom parameters + foreach ($row as $field => $value) { + if (strpos($field, 'Custom Field') !== false && $value !== '') { + $index = explode(' ', $field)[2]; + $params['customParameter' . $index] = $value; + } + } + $transactions[] = new Transaction($params); + } + return $transactions; + } + + /** + * @return array|null + * @psalm-suppress MixedPropertyFetch + * @psalm-suppress MixedAssignment + */ + public function getSubscriptions() + { + // data can be SimpleXMLElement or JSON object + if (!isset($this->data['data']) && !isset($this->data)) { + return null; + } + + $subscriptions = array(); + if ($this->data instanceof SimpleXMLElement && isset($this->data->{'subscriptions'})) { + foreach ($this->data->{'subscriptions'}->children() as $sub) { + $subscriptions[] = new Subscription(array( + 'subscriptionReference' => (string) $sub->{'subscription-id'}, + 'currency' => (string) $sub->{'catalog-recurring-charge'}->currency, + 'amount' => (string) $sub->{'catalog-recurring-charge'}->amount, + 'status' => (string) $sub->{'status'} + )); + } + return $subscriptions; + } + + if (is_array($this->data)) { + /** @var array */ + foreach ($this->data['data'] as $row) { + $subscriptions[] = new Subscription(array( + 'subscriptionReference' => $row['Subscription ID'], + 'currency' => $row['Auth. Currency'], + 'amount' => isset($row['Price (Auth. Currency)']) + ? $row['Price (Auth. Currency)'] + : $row['Last Charge Price (Auth. Currency)'] + )); + } + } + return $subscriptions; + } + + /** + * Get the decrypted parameters from the return url after a HostedCheckoutDecryptReturnUrlRequest + * Returns an array of paramName => paramValue + * + * @return array|null + * @psalm-suppress MixedPropertyFetch + */ + public function getDecryptedParameters() + { + if ($this->data instanceof SimpleXMLElement && isset($this->data->{'decrypted-token'})) { + parse_str((string) $this->data->{'decrypted-token'}, $result); + return $result ?: null; + } + return null; + } + + /** + * Gets the credit card from a fetch transaction or subscription request + * + * @return null|CreditCard + */ + public function getCard() + { + $cardParams = array(); + + $cardXml = null; + $invoice = $this->getInvoice(); + if ($invoice instanceof SimpleXMLElement + && isset($invoice->{'financial-transactions'}->{'financial-transaction'}->{'credit-card'}) + ) { + /** + * @var SimpleXMLElement + */ + $cardXml = $invoice->{'financial-transactions'}->{'financial-transaction'}->{'credit-card'}; + } elseif ($this->data instanceof SimpleXMLElement && isset($this->data->{'credit-card'})) { + /** + * @var SimpleXMLElement + */ + $cardXml = $this->data->{'credit-card'}; + } + + if ($cardXml) { + if (isset($cardXml->{'card-type'})) { + $cardParams['brand'] = strtolower((string) $cardXml->{'card-type'}); + } + if (isset($cardXml->{'card-last-four-digits'})) { + $cardParams['number'] = (string) $cardXml->{'card-last-four-digits'}; + } + if (isset($cardXml->{'expiration-month'})) { + $cardParams['expiryMonth'] = (string) $cardXml->{'expiration-month'}; + } + if (isset($cardXml->{'expiration-year'})) { + $cardParams['expiryYear'] = (string) $cardXml->{'expiration-year'}; + } + } + + if ($invoice instanceof SimpleXMLElement + && isset($invoice->{'financial-transactions'}->{'financial-transaction'}->{'invoice-contact-info'}) + ) { + /** + * @var SimpleXMLElement + */ + $contactXml = $invoice->{'financial-transactions'}->{'financial-transaction'}->{'invoice-contact-info'}; + if (isset($contactXml->{'first-name'})) { + $cardParams['firstName'] = (string) $contactXml->{'first-name'}; + } + if (isset($contactXml->{'last-name'})) { + $cardParams['lastName'] = (string) $contactXml->{'last-name'}; + } + if (isset($contactXml->email)) { + $cardParams['email'] = (string) $contactXml->email; + } + if (isset($contactXml->state)) { + $cardParams['state'] = (string) $contactXml->state; + } + if (isset($contactXml->country)) { + $cardParams['country'] = (string) $contactXml->country; + } + if (isset($contactXml->zip)) { + $cardParams['postcode'] = (string) $contactXml->zip; + } + } + + if (!empty($cardParams)) { + return new CreditCard($cardParams); + } + return null; + } + + /** + * Get the value of a custom parameter by name + * + * @param string $name + * @return string|null + */ + public function getCustomParameter($name) + { + if (!$this->data instanceof SimpleXMLElement + || !$this->data->cart instanceof SimpleXMLElement + || !isset($this->data->cart->{'cart-item'})) { + return null; + } + + /** + * @var SimpleXMLElement + */ + $parameters = $this->data->cart->{'cart-item'}->{'sku-parameter'}; + /** + * @var SimpleXMLElement + */ + foreach ($parameters as $parameter) { + if ($name === (string) $parameter->{'param-name'}) { + return (string) $parameter->{'param-value'}; + } + } + return null; + } + + /** + * Returns the invoice element corresponding to the requested transaction + * + * When you fetch an order, it may contain multiple invoices (for example, + * one for each subscription charge), so this function selects the correct + * one. + * + * @return SimpleXMLElement|null + */ + protected function getInvoice() + { + if ($this->invoice) { + return $this->invoice; + } + + $this->invoice = null; + // find the invoice that was reqeusted + $request = $this->getRequest(); + $transactionReference = $request->getTransactionReference(); + + if ($this->data instanceof SimpleXMLElement && isset($this->data->{'post-sale-info'}->invoices)) { + /** + * @var SimpleXMLElement + */ + $invoices = $this->data->{'post-sale-info'}->invoices; + /** + * @var SimpleXMLElement + */ + foreach ($invoices->children() as $invoice) { + if (strval($invoice->{'invoice-id'}) === $transactionReference) { + $this->invoice = $invoice; + break; + } + } + } + return $this->invoice; + } + + /** + * Overriding to provide more specific return type + * + * @return \Omnipay\BlueSnap\Message\AbstractRequest + */ + public function getRequest() + { + /** + * @var \Omnipay\BlueSnap\Message\AbstractRequest + */ + return parent::getRequest(); + } +} diff --git a/src/Subscription.php b/src/Subscription.php new file mode 100644 index 0000000..a7b30ed --- /dev/null +++ b/src/Subscription.php @@ -0,0 +1,167 @@ +initialize($parameters); + } + + /** + * Initialize this subscription with the specified parameters + * + * @param array $parameters An array of parameters to set on this object + * @return static + */ + public function initialize($parameters = array()) + { + $this->parameters = new ParameterBag; + + Helper::initialize($this, $parameters); + + return $this; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters->all(); + } + + /** + * @param string $key + * @return mixed + */ + protected function getParameter($key) + { + return $this->parameters->get($key); + } + + /** + * @param string $key + * @param mixed $value + * @return static + */ + protected function setParameter($key, $value) + { + $this->parameters->set($key, $value); + + return $this; + } + + /** + * Get the subscription reference + * + * @return null|string + */ + public function getSubscriptionReference() + { + /** + * @var null|string + */ + return $this->getParameter('subscriptionReference'); + } + + /** + * Set the subscription reference + * + * @param string $value + * @return static + */ + public function setSubscriptionReference($value) + { + return $this->setParameter('subscriptionReference', $value); + } + + /** + * Get the currency + * + * @return null|string + */ + public function getCurrency() + { + /** + * @var null|string + */ + return $this->getParameter('currency'); + } + + /** + * Set the currency + * + * @param string $value + * @return static + */ + public function setCurrency($value) + { + return $this->setParameter('currency', $value); + } + + /** + * Get the monetary amount + * + * @return null|string + */ + public function getAmount() + { + /** + * @var null|string + */ + return $this->getParameter('amount'); + } + + /** + * Set the monetary amount + * + * @param string $value + * @return static + */ + public function setAmount($value) + { + return $this->setParameter('amount', $value); + } + + /** + * Get the subscription status + * + * @return null|string + */ + public function getStatus() + { + /** + * @var null|string + */ + return $this->getParameter('status'); + } + + /** + * Set the subscription status + * + * @param string $value + * @return static + */ + public function setStatus($value) + { + return $this->setParameter('status', $value); + } +} diff --git a/src/SubscriptionCharge.php b/src/SubscriptionCharge.php new file mode 100644 index 0000000..2e83c92 --- /dev/null +++ b/src/SubscriptionCharge.php @@ -0,0 +1,215 @@ +initialize($parameters); + } + + /** + * Initialize this subscription charge with the specified parameters + * + * @param array $parameters An array of parameters to set on this object + * @return static + */ + public function initialize($parameters = array()) + { + $this->parameters = new ParameterBag; + + Helper::initialize($this, $parameters); + + return $this; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters->all(); + } + + /** + * @param string $key + * @return mixed + */ + protected function getParameter($key) + { + return $this->parameters->get($key); + } + + /** + * @param string $key + * @param mixed $value + * @return static + */ + protected function setParameter($key, $value) + { + $this->parameters->set($key, $value); + + return $this; + } + + /** + * Get the transaction reference + * + * @return null|string + */ + public function getTransactionReference() + { + /** + * @var null|string + */ + return $this->getParameter('transactionReference'); + } + + /** + * Set the transaction reference + * + * @param string $value + * @return static + */ + public function setTransactionReference($value) + { + return $this->setParameter('transactionReference', $value); + } + + /** + * Get the currency + * + * @return null|string + */ + public function getCurrency() + { + /** + * @var null|string + */ + return $this->getParameter('currency'); + } + + /** + * Set the currency + * + * @param string $value + * @return static + */ + public function setCurrency($value) + { + return $this->setParameter('currency', $value); + } + + /** + * Get the monetary amount + * + * @return null|string + */ + public function getAmount() + { + /** + * @var null|string + */ + return $this->getParameter('amount'); + } + + /** + * Set the monetary amount + * + * @param string $value + * @return static + */ + public function setAmount($value) + { + return $this->setParameter('amount', $value); + } + + /** + * Get the customer reference + * + * @return null|string + */ + public function getCustomerReference() + { + /** + * @var null|string + */ + return $this->getParameter('customerReference'); + } + + /** + * Set the customer reference + * + * @param string $value + * @return static + */ + public function setCustomerReference($value) + { + return $this->setParameter('customerReference', $value); + } + + /** + * Gets the date the subscription charge was created on + * + * @return \DateTime|null + */ + public function getDate() + { + /** + * @var \DateTime|null + */ + return $this->getParameter('date') ?: null; + } + + /** + * Sets the date the subscription charge was created on + * + * @param \DateTime $value + * @return static + */ + public function setDate($value) + { + return $this->setParameter('date', $value); + } + + /** + * Gets subscription reference + * + * @return string|null + */ + public function getSubscriptionReference() + { + /** + * @var string|null + */ + return $this->getParameter('subscriptionReference') ?: null; + } + + /** + * Sets the subscription reference + * + * @param string $value + * @return static + */ + public function setSubscriptionReference($value) + { + return $this->setParameter('subscriptionReference', $value); + } +} diff --git a/src/Transaction.php b/src/Transaction.php new file mode 100644 index 0000000..931231f --- /dev/null +++ b/src/Transaction.php @@ -0,0 +1,456 @@ +initialize($parameters); + } + + /** + * Initialize this transaction with the specified parameters + * + * @param array $parameters An array of parameters to set on this object + * @return static + */ + public function initialize($parameters = array()) + { + $this->parameters = new ParameterBag; + + Helper::initialize($this, $parameters); + + return $this; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters->all(); + } + + /** + * @param string $key + * @return mixed + */ + protected function getParameter($key) + { + return $this->parameters->get($key); + } + + /** + * @param string $key + * @param mixed $value + * @return static + */ + protected function setParameter($key, $value) + { + $this->parameters->set($key, $value); + + return $this; + } + + /** + * Get the transaction reference + * + * @return null|string + */ + public function getTransactionReference() + { + /** + * @var null|string + */ + return $this->getParameter('transactionReference'); + } + + /** + * Set the transaction reference + * + * @param string $value + * @return static + */ + public function setTransactionReference($value) + { + return $this->setParameter('transactionReference', $value); + } + + /** + * Get the currency + * + * @return null|string + */ + public function getCurrency() + { + /** + * @var null|string + */ + return $this->getParameter('currency'); + } + + /** + * Set the currency + * + * @param string $value + * @return static + */ + public function setCurrency($value) + { + return $this->setParameter('currency', $value); + } + + /** + * Get the monetary amount + * + * @return null|string + */ + public function getAmount() + { + /** + * @var null|string + */ + return $this->getParameter('amount'); + } + + /** + * Set the monetary amount + * + * @param string $value + * @return static + */ + public function setAmount($value) + { + return $this->setParameter('amount', $value); + } + + /** + * Get the customer reference + * + * @return null|string + */ + public function getCustomerReference() + { + /** + * @var null|string + */ + return $this->getParameter('customerReference'); + } + + /** + * Set the customer reference + * + * @param string $value + * @return static + */ + public function setCustomerReference($value) + { + return $this->setParameter('customerReference', $value); + } + + /** + * Gets the date the transaction was created on + * + * @return \DateTime|null + */ + public function getDate() + { + /** + * @var \DateTime|null + */ + return $this->getParameter('date') ?: null; + } + + /** + * Sets the date the transaction was created on + * + * @param \DateTime $value + * @return static + * @throws InvalidRequestException if the time zone is incorrect + */ + public function setDate($value) + { + return $this->setParameter('date', $value); + } + + /** + * Gets transaction status + * + * @return string|null + */ + public function getStatus() + { + /** + * @var string|null + */ + return $this->getParameter('status') ?: null; + } + + /** + * Sets the transaction status + * + * @param string $value + * @return static + */ + public function setStatus($value) + { + return $this->setParameter('status', $value); + } + + /** + * Get custom parameter #1 + * + * @return null|string + */ + public function getCustomParameter1() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter1'); + } + + /** + * Set custom parameter #1 + * + * @param string $value + * @return static + */ + public function setCustomParameter1($value) + { + return $this->setParameter('customParameter1', $value); + } + + /** + * Get custom parameter #2 + * + * @return null|string + */ + public function getCustomParameter2() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter2'); + } + + /** + * Set custom parameter #2 + * + * @param string $value + * @return static + */ + public function setCustomParameter2($value) + { + return $this->setParameter('customParameter2', $value); + } + + /** + * Get custom parameter #3 + * + * @return null|string + */ + public function getCustomParameter3() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter3'); + } + + /** + * Set custom parameter #3 + * + * @param string $value + * @return static + */ + public function setCustomParameter3($value) + { + return $this->setParameter('customParameter3', $value); + } + + /** + * Get custom parameter #4 + * + * @return null|string + */ + public function getCustomParameter4() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter4'); + } + + /** + * Set custom parameter #4 + * + * @param string $value + * @return static + */ + public function setCustomParameter4($value) + { + return $this->setParameter('customParameter4', $value); + } + + /** + * Get custom parameter #5 + * + * @return null|string + */ + public function getCustomParameter5() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter5'); + } + + /** + * Set custom parameter #5 + * + * @param string $value + * @return static + */ + public function setCustomParameter5($value) + { + return $this->setParameter('customParameter5', $value); + } + + /** + * Get custom parameter #6 + * + * @return null|string + */ + public function getCustomParameter6() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter6'); + } + + /** + * Set custom parameter #6 + * + * @param string $value + * @return static + */ + public function setCustomParameter6($value) + { + return $this->setParameter('customParameter6', $value); + } + + /** + * Get custom parameter #7 + * + * @return null|string + */ + public function getCustomParameter7() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter7'); + } + + /** + * Set custom parameter #7 + * + * @param string $value + * @return static + */ + public function setCustomParameter7($value) + { + return $this->setParameter('customParameter7', $value); + } + + /** + * Get custom parameter #8 + * + * @return null|string + */ + public function getCustomParameter8() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter8'); + } + + /** + * Set custom parameter #8 + * + * @param string $value + * @return static + */ + public function setCustomParameter8($value) + { + return $this->setParameter('customParameter8', $value); + } + + /** + * Get custom parameter #9 + * + * @return null|string + */ + public function getCustomParameter9() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter9'); + } + + /** + * Set custom parameter #9 + * + * @param string $value + * @return static + */ + public function setCustomParameter9($value) + { + return $this->setParameter('customParameter9', $value); + } + + /** + * Get custom parameter #10 + * + * @return null|string + */ + public function getCustomParameter10() + { + /** + * @var null|string + */ + return $this->getParameter('customParameter10'); + } + + /** + * Set custom parameter #10 + * + * @param string $value + * @return static + */ + public function setCustomParameter10($value) + { + return $this->setParameter('customParameter10', $value); + } +} diff --git a/src/UrlParameter.php b/src/UrlParameter.php new file mode 100644 index 0000000..2aef106 --- /dev/null +++ b/src/UrlParameter.php @@ -0,0 +1,119 @@ + $parameters + */ + public function __construct($parameters = array()) + { + $this->initialize($parameters); + } + + /** + * Initialize this UrlParameter with the specified parameters + * + * @param array $parameters + * @return static + */ + public function initialize($parameters = array()) + { + $this->parameters = new ParameterBag; + + Helper::initialize($this, $parameters); + + return $this; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters->all(); + } + + /** + * @param string $key + * @return mixed + */ + protected function getParameter($key) + { + return $this->parameters->get($key); + } + + /** + * @param string $key + * @param mixed $value + * @return static + */ + protected function setParameter($key, $value) + { + $this->parameters->set($key, $value); + + return $this; + } + + /** + * Get the UrlParameter key + * + * @return null|string + */ + public function getKey() + { + return strval($this->getParameter('key')) ?: null; + } + + /** + * Set the UrlParameter key + * + * @param string $value + * @return static + */ + public function setKey($value) + { + return $this->setParameter('key', $value); + } + + /** + * Get the UrlParameter value + * + * @return null|string + */ + public function getValue() + { + /** + * @var null|string + */ + return $this->getParameter('value'); + } + + /** + * Set the UrlParameter value + * + * @param string $value + * @return static + */ + public function setValue($value) + { + return $this->setParameter('value', $value); + } +} diff --git a/src/UrlParameterBag.php b/src/UrlParameterBag.php new file mode 100644 index 0000000..e400117 --- /dev/null +++ b/src/UrlParameterBag.php @@ -0,0 +1,103 @@ + + */ + protected $parameters; + + /** + * Constructor + * + * @param array $parameters + */ + public function __construct(array $parameters = array()) + { + $this->replace($parameters); + } + + /** + * Return all the UrlParameters + * + * @return array + */ + public function all() + { + return $this->parameters; + } + + /** + * Replace the contents of this bag with the specified UrlParameters. + * $parameters can be an array of UrlParameters, an array of + * `['key' => XXX, 'value' => XXX]` pairs, or an array of values + * indexed by key. + * + * @param array $parameters + * @return void + * @psalm-suppress MixedAssignment because we're accepting many different types of params + */ + public function replace(array $parameters = array()) + { + $this->parameters = array(); + + foreach ($parameters as $key => $value) { + if (is_array($value) || $value instanceof UrlParameter) { + $this->add($value); + } else { + $this->add(array( + 'key' => $key, + 'value' => $value + )); + } + } + } + + /** + * Add an UrlParameter to the bag + * Can add an UrlParameter object or an associative array of UrlParameter + * parameters (`['key' => XXX, 'value' => XXX]`) + * + * @param UrlParameter|array $parameter + * @return void + */ + public function add($parameter) + { + if ($parameter instanceof UrlParameter) { + $this->parameters[] = $parameter; + } else { + $this->parameters[] = new UrlParameter($parameter); + } + } + + /** + * Returns an iterator for UrlParameters + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->parameters); + } + + /** + * Returns the number of UrlParameters + * + * @return int + */ + public function count() + { + return count($this->parameters); + } +} diff --git a/tests/CreditCardTest.php b/tests/CreditCardTest.php new file mode 100644 index 0000000..deeadb6 --- /dev/null +++ b/tests/CreditCardTest.php @@ -0,0 +1,38 @@ +faker = new DataFaker(); + $this->card = new CreditCard(); + } + + /** + * @return void + */ + public function testBrand() + { + $brand = $this->faker->cardBrand(); + $this->assertSame($this->card, $this->card->setBrand($brand)); + $this->assertSame($brand, $this->card->getBrand()); + } +} diff --git a/tests/ExtendedGatewayTest.php b/tests/ExtendedGatewayTest.php new file mode 100644 index 0000000..9340dee --- /dev/null +++ b/tests/ExtendedGatewayTest.php @@ -0,0 +1,237 @@ +getHttpClient(); + /** + * @var \Symfony\Component\HttpFoundation\Request + */ + $httpRequest = $this->getHttpRequest(); + $this->gateway = new ExtendedGateway($httpClient, $httpRequest); + $this->gateway->setTestMode(true); + $this->faker = new DataFaker(); + } + + /** + * @return void + */ + public function testGetName() + { + $this->assertSame('BlueSnap Extended', $this->gateway->getName()); + } + + /** + * @return void + * @psalm-suppress MixedAssignment because that is exactly what this function allows + */ + public function testCreation() + { + $gateway = Omnipay::create('BlueSnap_Extended'); + $this->assertInstanceOf('Omnipay\BlueSnap\ExtendedGateway', $gateway); + } + + /** + * @return void + */ + public function testFetchCustomer() + { + $customerReference = $this->faker->customerReference(); + $request = $this->gateway->fetchCustomer( + array( + 'customerReference' => $customerReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedFetchCustomerRequest', $request); + $this->assertSame($customerReference, $request->getCustomerReference()); + } + + /** + * @return void + */ + public function testFetchTransaction() + { + $transactionReference = $this->faker->transactionReference(); + $request = $this->gateway->fetchTransaction( + array( + 'transactionReference' => $transactionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedFetchTransactionRequest', $request); + $this->assertSame($transactionReference, $request->getTransactionReference()); + } + + /** + * @return void + */ + public function testFetchSubscription() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $request = $this->gateway->fetchSubscription( + array( + 'subscriptionReference' => $subscriptionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testFetchSubscriptionCharge() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $subscriptionChargeReference = $this->faker->subscriptionChargeReference(); + $request = $this->gateway->fetchSubscriptionCharge( + array( + 'subscriptionReference' => $subscriptionReference, + 'subscriptionChargeReference' => $subscriptionChargeReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionChargeRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + $this->assertSame($subscriptionChargeReference, $request->getSubscriptionChargeReference()); + } + + /** + * @return void + */ + public function testUpdateSubscription() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $nextChargeDate = $this->faker->datetime(); + + $request = $this->gateway->updateSubscription( + array( + 'subscriptionReference' => $subscriptionReference, + 'currency' => $currency, + 'amount' => $amount, + 'nextChargeDate' => $nextChargeDate + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedUpdateSubscriptionRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + $this->assertSame($currency, $request->getCurrency()); + $this->assertSame($amount, $request->getAmount()); + $this->assertSame($nextChargeDate, $request->getNextChargeDate()); + } + + /** + * @return void + */ + public function testCancelSubscription() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $request = $this->gateway->cancelSubscription( + array( + 'subscriptionReference' => $subscriptionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedCancelSubscriptionRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testReactivateSubscription() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $request = $this->gateway->reactivateSubscription( + array( + 'subscriptionReference' => $subscriptionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedReactivateSubscriptionRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testTestChargeSubscription() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $request = $this->gateway->testChargeSubscription( + array( + 'subscriptionReference' => $subscriptionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedTestChargeSubscriptionRequest', $request); + $this->assertSame($subscriptionReference, $request->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testRefund() + { + $transactionReference = $this->faker->transactionReference(); + $request = $this->gateway->refund( + array( + 'transactionReference' => $transactionReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedRefundRequest', $request); + $this->assertSame($transactionReference, $request->getTransactionReference()); + } + + /** + * @return void + */ + public function testFetchSubscriptionsByTimeRange() + { + $startTime = $this->faker->datetime(); + $endTime = $this->faker->datetime(); + $request = $this->gateway->fetchSubscriptions( + array( + 'startTime' => $startTime, + 'endTime' => $endTime + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\FetchSubscriptionsRequest', $request); + $this->assertSame($startTime, $request->getStartTime()); + $this->assertSame($endTime, $request->getEndTime()); + } + + /** + * @return void + */ + public function testFetchSubscriptionsByCustomer() + { + $customerReference = $this->faker->customerReference(); + $request = $this->gateway->fetchSubscriptions( + array( + 'customerReference' => $customerReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\ExtendedFetchSubscriptionsRequest', $request); + $this->assertSame($customerReference, $request->getCustomerReference()); + } +} diff --git a/tests/Framework/DataFaker.php b/tests/Framework/DataFaker.php new file mode 100644 index 0000000..df19966 --- /dev/null +++ b/tests/Framework/DataFaker.php @@ -0,0 +1,506 @@ +getDecimals(); + + $integerComponent = strval($this->intBetween($currencyPrecision > 0 ? 0 : 1, 999)); + + if ($currencyPrecision === 0) { + return $integerComponent; + } + + $decimalComponent = $this->intBetween( + $integerComponent > 0 ? 0 : 1, + intval(str_repeat('9', $currencyPrecision)) + ); + $decimalComponent = str_pad(strval($decimalComponent), $currencyPrecision, '0', STR_PAD_LEFT); + + return $integerComponent . '.' . $decimalComponent; + } + + /** + * Return a three letter currency code + * + * @return string + */ + public function currency() + { + $currencies = array_keys(Currency::all()); + /** + * @var string + */ + return $currencies[$this->intBetween(0, count($currencies) - 1)]; + } + + /** + * Return a name (first or last) + * + * @return string + */ + public function name() + { + return ucfirst($this->randomCharacters(self::ALPHABET_LOWER, $this->intBetween(3, 10))); + } + + /** + * Return an ip address + * + * @return string + */ + public function ipAddress() + { + return implode('.', array( + $this->intBetween(0, 255), + $this->intBetween(0, 255), + $this->intBetween(0, 255), + $this->intBetween(0, 255) + )); + } + + /** + * Return an email address + * + * @return string + */ + public function email() + { + return $this->randomCharacters(self::DIGITS . self::ALPHABET_LOWER, $this->intBetween(3, 10)) + . '@example.' + . $this->topLevelDomain(); + } + + /** + * Return a url + * + * @return string + */ + public function url() + { + return 'http://www.example.' + . $this->topLevelDomain() + . '/' + . $this->randomCharacters(self::DIGITS . self::ALPHABET_LOWER . '%', $this->intBetween(0, 10)); + } + + /** + * Returns a query string. If $numParams is not set, a random number + * of parameters will be chosen. + * + * @param int $numParams + * @return string + */ + public function queryString($numParams = null) + { + $numParams = $numParams ?: $this->intBetween(1, 10); + $params = array(); + for ($i = 0; $i < $numParams; $i++) { + $paramName = $this->randomCharacters(self::ALPHABET_LOWER . self::ALPHABET_UPPER, $this->intBetween(4, 10)); + $paramValue = $this->randomCharacters(self::ALPHABET_LOWER . self::DIGITS, $this->intBetween(1, 10)); + $params[$paramName] = $paramValue; + } + return http_build_query($params); + } + + /** + * @return string + */ + protected function topLevelDomain() + { + switch ($this->intBetween(0, 3)) { + case 0: + return 'com'; + + case 1: + return 'org'; + + case 2: + return 'net'; + + default: + return 'edu'; + } + } + + /** + * Return a two-letter region (eg country or state) code + * + * @return string + */ + public function region() + { + return $this->randomCharacters(self::ALPHABET_UPPER, 2); + } + + /** + * Return a 5 digit postal code + * + * @return string + */ + public function postcode() + { + do { + $result = $this->randomCharacters(self::DIGITS, 5); + } while ($result == 0); + return $result; + } + + /** + * Return a string of random characters from $characterSet that is + * $numCharacters long + * + * @param string $characterSet + * @param int $numCharacters + * @return string + */ + public function randomCharacters($characterSet, $numCharacters) + { + if ($numCharacters < 0) { + throw new InvalidArgumentException( + 'Parameter numCharacters must be positive or zero, saw ' . strval($numCharacters) + ); + } + if (empty($characterSet)) { + throw new InvalidArgumentException('characterSet must not be empty'); + } + + $result = ''; + $setLength = strlen($characterSet); + for ($i = 0; $i < $numCharacters; $i++) { + $result .= $characterSet[$this->intBetween(0, $setLength - 1)]; + } + + return $result; + } + + /** + * Return a timestamp in the format used by BlueSnap's API responses + * + * @return string + */ + public function timestamp() + { + $now = time(); + return date('d-M-y', $this->intBetween($now - 100000000, $now + 100000000)); + } + + /** + * Return a DateTime (no time will be set, only a date, because that's all BlueSnap supports) + * + * @return DateTime + */ + public function datetime() + { + return new DateTime($this->timestamp()); + } + + /** + * @return string + */ + public function username() + { + return 'API_' . $this->randomCharacters(self::DIGITS, $this->intBetween(20, 24)); + } + + /** + * @return string + */ + public function password() + { + return $this->randomCharacters(self::ALPHABET_LOWER . self::DIGITS, $this->intBetween(8, 16)); + } + + /** + * Return a customer reference + * + * @return string + */ + public function customerReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(6, 10)); + } while ($result == 0); + return $result; + } + + /** + * Return a transaction reference + * + * @return string + */ + public function transactionReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(6, 10)); + } while ($result == 0); + return $result; + } + + /** + * Return a subscription reference + * + * @return string + */ + public function subscriptionReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(6, 10)); + } while ($result == 0); + return $result; + } + + /** + * Return a subscription charge reference + * + * @return string + */ + public function subscriptionChargeReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(3, 10)); + } while ($result == 0); + return $result; + } + + /** + * Return a store reference + * + * @return string + */ + public function storeReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(3, 7)); + } while ($result == 0); + return $result; + } + + /** + * Return a plan reference + * + * @return string + */ + public function planReference() + { + do { + $result = $this->randomCharacters(self::DIGITS, $this->intBetween(6, 10)); + } while ($result == 0); + return $result; + } + + /** + * Return a UrlParameter + * + * @return UrlParameter + */ + public function urlParameter() + { + return new UrlParameter($this->urlParameterAsArray()); + } + + /** + * Return a UrlParameter as an array + * + * @return array + */ + public function urlParameterAsArray() + { + return array( + 'key' => $this->randomCharacters( + DataFaker::ALPHABET_LOWER, + $this->intBetween(3, 15) + ), + 'value' => $this->randomCharacters( + DataFaker::ALPHABET_LOWER . DataFaker::DIGITS, + $this->intBetween(1, 3) + ) + ); + } + + /** + * Return some UrlParameters + * + * @return UrlParameterBag + */ + public function urlParameters() + { + $urlParameters = new UrlParameterBag(); + for ($i = 0; $i < $this->intBetween(1, 5); $i++) { + $urlParameters->add($this->urlParameter()); + } + return $urlParameters; + } + + /** + * Return some UrlParameters as an array + * + * @return array + */ + public function urlParametersAsArray() + { + $urlParameters = array(); + for ($i = 0; $i < $this->intBetween(1, 5); $i++) { + $urlParameters[] = $this->urlParameterAsArray(); + } + return $urlParameters; + } + + /** + * Return encrypted URL parameters + * + * @return string + */ + public function encryptedUrlParameters() + { + do { + $result = $this->randomCharacters( + self::DIGITS . self::ALPHABET_LOWER . self::ALPHABET_UPPER, + $this->intBetween(40, 100) + ); + } while ($result == 0); + return $result; + } + + /** + * Return a custom parameter for a transaction + * + * @return string + */ + public function customParameter() + { + do { + $result = $this->randomCharacters( + self::DIGITS . self::ALPHABET_UPPER . self::ALPHABET_LOWER, + $this->intBetween(1, 20) + ); + } while ($result == 0); + return $result; + } + + /** + * Return a credit card brand + * + * @return string + */ + public function cardBrand() + { + $card = new \Omnipay\Common\CreditCard(); + /** + * @var string + */ + return array_rand($card->getSupportedBrands()); + } + + /** + * Return a fake card + * + * @return CreditCard + */ + public function card() + { + $now = new DateTime(); + $now2 = clone $now; + return new CreditCard(array( + 'number' => $this->intBetween(0, 1) ? '4242424242424242' : '3530111333300000', + 'expiryMonth' => str_pad(strval($this->intBetween(1, 12)), 2, '0', STR_PAD_LEFT), + 'expiryYear' => strval($this->intBetween( + intval($now->modify('+1 year')->format('Y')), + intval($now2->modify('+50 year')->format('Y')) + )), + 'brand' => $this->cardBrand(), + 'country' => $this->region(), + 'state' => $this->region(), + 'postcode' => $this->postcode(), + 'email' => $this->email(), + 'firstName' => $this->name(), + 'lastName' => $this->name() + )); + } + + /** + * Return transaction status + * + * @return string + */ + public function transactionStatus() + { + $statuses = array('Approved', 'Canceled', 'Declined', 'Pending', 'Error'); + $index = $this->intBetween(0, 4); + return $statuses[$index]; + } + /** + * Return subscription status + * + * @return string + */ + public function subscriptionStatus() + { + $statuses = array('A', 'C', 'D'); + $index = $this->intBetween(0, 2); + return $statuses[$index]; + } +} diff --git a/tests/Framework/MockPlugin.php b/tests/Framework/MockPlugin.php new file mode 100644 index 0000000..f703168 --- /dev/null +++ b/tests/Framework/MockPlugin.php @@ -0,0 +1,59 @@ + $substitutions default array() + * @return Response|false + * @throws InvalidArgumentException if the file is not found + */ + public static function getMockFile($path, $substitutions = array()) + { + if (!file_exists($path)) { + throw new InvalidArgumentException('Unable to open mock file: ' . $path); + } + + $fileContents = file_get_contents($path) ?: ''; + foreach ($substitutions as $search => $replace) { + $fileContents = str_replace('[' . $search . ']', $replace, $fileContents); + } + + /** + * @var Response|false + */ + return Response::fromMessage($fileContents); + } + + /** + * Add a response to the end of the queue + * + * @param Response|string $response Response object or path to response file + * @return MockPlugin + * @throws InvalidArgumentException if a string or Response is not passed + * @psalm-suppress FailedTypeResolution because we want run time checks + */ + public function addResponse($response) + { + if (!($response instanceof Response)) { + if (!is_string($response)) { + throw new InvalidArgumentException('Invalid response'); + } + $response = self::getMockFile($response); + } + + $this->queue[] = $response; + + return $this; + } +} diff --git a/tests/Framework/TestCase.php b/tests/Framework/TestCase.php new file mode 100644 index 0000000..dc395c3 --- /dev/null +++ b/tests/Framework/TestCase.php @@ -0,0 +1,150 @@ + $substitutions + * @return Response|false + */ + public function getMockHttpResponse($path, $substitutions = array()) + { + if ($path instanceof Response) { + return $path; + } + + $ref = new ReflectionObject($this); + $dir = dirname($ref->getFileName() ?: ''); + + $fullPath = $dir . '/Mock/' . $path; + // if mock file doesn't exist, check parent directory + if (!file_exists($fullPath) && file_exists($dir . '/../Mock/' . $path)) { + $fullPath = $dir . '/../Mock/' . $path; + } + + return MockPlugin::getMockFile($fullPath, $substitutions); + } + + /** + * Set a mock response from a mock file on the next client request. + * + * This method assumes that mock response files are located under the + * tests/Mock/ subdirectory. A mock response is added to the next + * request sent by the client. + * + * An array of path can be provided and the next x number of client requests are + * mocked in the order of the array where x = the array length. + * + * This is an override of the default Omnipay function that adds support for + * setting an array of substitutions that can be used for randomizing test data. + * For example, if $substitutions is array('NAME' => 'Fake Name'), + * then the function will replace all instances of '[NAME]' in the + * response with 'Fake Name'. Substitutions are not required. + * + * @param array|string $paths + * @param array $substitutions + * + * @return MockPlugin + */ + public function setMockHttpResponse($paths, $substitutions = array()) + { + $this->substitutableMockHttpRequests = array(); + $that = $this; + $mock = new MockPlugin(null, true); + $this->getHttpClient()->getEventDispatcher()->removeSubscriber($mock); + $mock->getEventDispatcher()->addListener( + 'mock.request', + // @codingStandardsIgnoreStart + /** + * @param Event $event + * @return void + */ + function (Event $event) use ($that) { + // @codingStandardsIgnoreEnd + /** + * @var \Guzzle\Http\Message\Request + */ + $request = $event->offsetGet('request'); + $that->addMockedHttpRequest($request); + } + ); + + if (is_string($paths)) { + $paths = array($paths); + } + foreach ($paths as $path) { + $mock->addResponse($this->getMockHttpResponse($path, $substitutions) ?: ''); + } + + $this->getHttpClient()->getEventDispatcher()->addSubscriber($mock); + + return $mock; + } + + /** + * Mark a request as being mocked + * + * @param GuzzleRequestInterface $request + * @return static + */ + public function addMockedHttpRequest(GuzzleRequestInterface $request) + { + $this->substitutableMockHttpRequests[] = $request; + return $this; + } + + + /** + * Get all of the mocked requests + * + * @return array + */ + public function getMockedRequests() + { + return $this->substitutableMockHttpRequests; + } +} diff --git a/tests/Framework/tests/DataFakerTest.php b/tests/Framework/tests/DataFakerTest.php new file mode 100644 index 0000000..265741e --- /dev/null +++ b/tests/Framework/tests/DataFakerTest.php @@ -0,0 +1,358 @@ +faker = new DataFaker(); + } + + /** + * @return void + */ + public function testIntBetween() + { + $int = $this->faker->intBetween(-3, 3); + $this->assertTrue(is_int($int)); + $this->assertTrue(-3 <= $int); + $this->assertTrue(3 >= $int); + + $int = $this->faker->intBetween(100, 200); + $this->assertTrue(is_int($int)); + $this->assertTrue(100 <= $int); + $this->assertTrue(200 >= $int); + } + + /** + * @return void + */ + public function testBool() + { + $this->assertTrue(is_bool($this->faker->bool())); + } + + /** + * @return void + */ + public function testMonetaryAmount() + { + $amount = $this->faker->monetaryAmount('USD'); + $this->assertTrue(is_string($amount)); + $this->assertEquals($amount, strval(floatval($amount))); + $this->assertTrue($amount > 0); + $parts = explode('.', $amount); + $this->assertSame(2, count($parts)); + $this->assertSame(2, strlen($parts[1])); + + $amount = $this->faker->monetaryAmount('KRW'); + $this->assertTrue(is_string($amount)); + $this->assertTrue(ctype_digit($amount)); + $this->assertTrue($amount > 0); + } + + /** + * @return void + */ + public function testCurrency() + { + $this->assertNotNull(Currency::find($this->faker->currency())); + } + + /** + * @return void + */ + public function testName() + { + $name = $this->faker->name(); + $this->assertTrue(is_string($name)); + $this->assertTrue(strlen($name) > 0); + $this->assertTrue(strpos($name, ' ') === false); + } + + /** + * @return void + */ + public function testIpAddress() + { + $this->assertTrue(ip2long($this->faker->ipAddress()) !== false); + } + + /** + * @return void + */ + public function testEmail() + { + $email = $this->faker->email(); + $this->assertTrue(is_string($email)); + + $parts = explode('@example.', $email); + $this->assertSame(2, count($parts)); + $this->assertTrue(0 < strlen($parts[0])); + $this->assertSame(3, strlen($parts[1])); + } + + /** + * @return void + */ + public function testUrl() + { + $url = $this->faker->url(); + $this->assertTrue(is_string($url)); + $this->assertSame(0, strpos($url, 'http://www.example.')); + $this->assertTrue(strlen('http://www.example.') + 3 <= strlen($url)); + } + + /** + * @return void + */ + public function testQueryString() + { + $queryString = $this->faker->queryString(); + $this->assertTrue(is_string($queryString)); + parse_str($queryString, $parsedString); + $this->assertTrue(is_array($parsedString)); + $this->assertTrue(count($parsedString) >= 1); + } + + /** + * @return void + */ + public function testRegion() + { + $region = $this->faker->region(); + $this->assertTrue(is_string($region)); + $this->assertSame(2, strlen($region)); + $this->assertTrue(ctype_upper($region)); + } + + /** + * @return void + */ + public function testPostcode() + { + $postcode = $this->faker->postcode(); + $this->assertTrue(is_string($postcode)); + $this->assertSame(5, strlen($postcode)); + $this->assertTrue(ctype_digit($postcode)); + } + + /** + * @return void + */ + public function testRandomCharacters() + { + $length = $this->faker->intBetween(1, 100); + $chars = $this->faker->randomCharacters('a', $length); + $this->assertTrue(is_string($chars)); + $this->assertSame($length, strlen($chars)); + $this->assertSame(str_repeat('a', $length), $chars); + + $chars = $this->faker->randomCharacters('abc', $length); + $this->assertSame($length, strlen($chars)); + $chars_array = str_split($chars); + foreach ($chars_array as $char) { + $this->assertTrue(in_array($char, array('a', 'b', 'c'))); + } + } + + /** + * @return void + */ + public function testTimestamp() + { + $timestamp = $this->faker->timestamp(); + $this->assertTrue(is_string($timestamp)); + $this->assertTrue(strpos($timestamp, '00') === false); + $datetime = new DateTime($timestamp); + $this->assertSame($timestamp, $datetime->format('d-M-y')); + } + + /** + * @return void + */ + public function testUsername() + { + $username = $this->faker->username(); + $this->assertTrue(is_string($username)); + $this->assertTrue(strlen($username) > 0); + } + + /** + * @return void + */ + public function testPassword() + { + $password = $this->faker->password(); + $this->assertTrue(is_string($password)); + $this->assertTrue(strlen($password) > 0); + } + + /** + * @return void + */ + public function testCustomerReference() + { + $reference = $this->faker->customerReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testTransactionReference() + { + $reference = $this->faker->transactionReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testSubscriptionReference() + { + $reference = $this->faker->subscriptionReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testSubscriptionChargeReference() + { + $reference = $this->faker->subscriptionChargeReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testStoreReference() + { + $reference = $this->faker->storeReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testPlanReference() + { + $reference = $this->faker->planReference(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 0); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testUrlParameter() + { + $urlParameter = $this->faker->urlParameter(); + $this->assertInstanceOf('Omnipay\BlueSnap\UrlParameter', $urlParameter); + $this->assertTrue(is_string($urlParameter->getKey())); + $this->assertTrue(is_string($urlParameter->getValue())); + } + + /** + * @return void + */ + public function testUrlParameterAsArray() + { + $urlParameterArray = $this->faker->urlParameterAsArray(); + $urlParameter = new UrlParameter($urlParameterArray); + $this->assertTrue(is_string($urlParameter->getKey())); + $this->assertTrue(is_string($urlParameter->getValue())); + } + + /** + * @return void + */ + public function testUrlParameters() + { + $urlParameters = $this->faker->urlParameters(); + $this->assertInstanceOf('Omnipay\BlueSnap\UrlParameterBag', $urlParameters); + $this->assertTrue(0 < $urlParameters->count()); + } + + /** + * @return void + */ + public function testUrlParametersAsArray() + { + $urlParametersArray = $this->faker->urlParametersAsArray(); + $urlParameters = new UrlParameterBag($urlParametersArray); + $this->assertTrue(0 < $urlParameters->count()); + } + + /** + * @return void + */ + public function testEncryptedUrlParameters() + { + $reference = $this->faker->encryptedUrlParameters(); + $this->assertTrue(is_string($reference)); + $this->assertTrue(strlen($reference) > 20); + $this->assertNotEquals(0, $reference); + } + + /** + * @return void + */ + public function testCustomParameterReference() + { + $parameter = $this->faker->customParameter(); + $this->assertTrue(is_string($parameter)); + $this->assertTrue(strlen($parameter) > 0); + $this->assertNotEquals(0, $parameter); + } + + /** + * @return void + */ + public function testCardBrand() + { + $brand = $this->faker->cardBrand(); + $this->assertTrue(is_string($brand)); + $this->assertTrue(strlen($brand) > 0); + $card = new \Omnipay\Common\CreditCard(); + $brands = $card->getSupportedBrands(); + $this->assertTrue(isset($brands[$brand])); + } + + /** + * @return void + */ + public function testCard() + { + $card = $this->faker->card(); + $this->assertInstanceOf('\Omnipay\BlueSnap\CreditCard', $card); + $this->assertNull($card->validate()); + } +} diff --git a/tests/GatewayTest.php b/tests/GatewayTest.php new file mode 100644 index 0000000..143609d --- /dev/null +++ b/tests/GatewayTest.php @@ -0,0 +1,151 @@ +getHttpClient(); + /** + * @var \Symfony\Component\HttpFoundation\Request + */ + $httpRequest = $this->getHttpRequest(); + $this->gateway = new Gateway($httpClient, $httpRequest); + $this->gateway->setTestMode(true); + $this->faker = new DataFaker(); + } + + /** + * @return void + */ + public function testGetName() + { + $this->assertSame('BlueSnap', $this->gateway->getName()); + } + + /** + * @return void + * @psalm-suppress MixedAssignment because that is exactly what this function allows + */ + public function testCreation() + { + $gateway = Omnipay::create('BlueSnap_Extended'); + $this->assertInstanceOf('Omnipay\BlueSnap\ExtendedGateway', $gateway); + } + + /** + * @return void + */ + public function testUsername() + { + $username = $this->faker->username(); + $this->assertSame($this->gateway, $this->gateway->setUsername($username)); + $this->assertSame($username, $this->gateway->getUsername()); + } + + /** + * @return void + */ + public function testPassword() + { + $password = $this->faker->password(); + $this->assertSame($this->gateway, $this->gateway->setPassword($password)); + $this->assertSame($password, $this->gateway->getPassword()); + } + + /** + * @return void + */ + public function testTestMode() + { + $testMode = $this->faker->bool(); + $this->assertSame($this->gateway, $this->gateway->setTestMode($testMode)); + $this->assertSame($testMode, $this->gateway->getTestMode()); + } + + /** + * @return void + */ + public function testFetchTransactions() + { + $startTime = $this->faker->datetime(); + $endTime = $this->faker->datetime(); + $request = $this->gateway->fetchTransactions( + array( + 'startTime' => $startTime, + 'endTime' => $endTime + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\FetchTransactionsRequest', $request); + $this->assertSame($startTime, $request->getStartTime()); + $this->assertSame($endTime, $request->getEndTime()); + } + + /** + * @return void + */ + public function testFetchSubscriptions() + { + $startTime = $this->faker->datetime(); + $endTime = $this->faker->datetime(); + $request = $this->gateway->fetchSubscriptions( + array( + 'startTime' => $startTime, + 'endTime' => $endTime + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\FetchSubscriptionsRequest', $request); + $this->assertSame($startTime, $request->getStartTime()); + $this->assertSame($endTime, $request->getEndTime()); + } + + /** + * @return void + */ + public function testFetchCanceledSubscriptions() + { + $startTime = $this->faker->datetime(); + $endTime = $this->faker->datetime(); + $request = $this->gateway->fetchCanceledSubscriptions( + array( + 'startTime' => $startTime, + 'endTime' => $endTime + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\FetchCanceledSubscriptionsRequest', $request); + $this->assertSame($startTime, $request->getStartTime()); + $this->assertSame($endTime, $request->getEndTime()); + } + + /** + * @return void + */ + public function testParseIPNCallback() + { + $queryString = $this->faker->queryString(); + $result = $this->gateway->parseIPNCallback($queryString); + + $this->assertInstanceOf('Omnipay\BlueSnap\Message\IPNCallback', $result); + } +} diff --git a/tests/HostedCheckoutGatewayTest.php b/tests/HostedCheckoutGatewayTest.php new file mode 100644 index 0000000..e098e02 --- /dev/null +++ b/tests/HostedCheckoutGatewayTest.php @@ -0,0 +1,92 @@ +getHttpClient(); + /** + * @var \Symfony\Component\HttpFoundation\Request + */ + $httpRequest = $this->getHttpRequest(); + $this->gateway = new HostedCheckoutGateway($httpClient, $httpRequest); + $this->gateway->setTestMode(true); + $this->faker = new DataFaker(); + } + + /** + * @return void + */ + public function testGetName() + { + $this->assertSame('BlueSnap Hosted Checkout', $this->gateway->getName()); + } + + /** + * @return void + * @psalm-suppress MixedAssignment because that is exactly what this function allows + */ + public function testCreation() + { + $gateway = Omnipay::create('BlueSnap_HostedCheckout'); + $this->assertInstanceOf('Omnipay\BlueSnap\HostedCheckoutGateway', $gateway); + } + + /** + * @return void + */ + public function testPurchase() + { + $storeReference = $this->faker->storeReference(); + $planReference = $this->faker->planReference(); + $request = $this->gateway->purchase( + array( + 'storeReference' => $storeReference, + 'planReference' => $planReference + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\HostedCheckoutPurchaseRequest', $request); + $this->assertSame($storeReference, $request->getStoreReference()); + $this->assertSame($planReference, $request->getPlanReference()); + } + + /** + * @return void + */ + public function testDecryptReturnUrl() + { + $returnUrl = $this->faker->url(); + /** + * @var \Omnipay\BlueSnap\Message\HostedCheckoutDecryptReturnUrlRequest + */ + $request = $this->gateway->decryptReturnUrl( + array( + 'returnUrl' => $returnUrl + ) + ); + $this->assertInstanceOf('Omnipay\BlueSnap\Message\HostedCheckoutDecryptReturnUrlRequest', $request); + $this->assertSame($returnUrl, $request->getReturnUrl()); + } +} diff --git a/tests/Message/AbstractRequestTest.php b/tests/Message/AbstractRequestTest.php new file mode 100644 index 0000000..4335fb4 --- /dev/null +++ b/tests/Message/AbstractRequestTest.php @@ -0,0 +1,209 @@ +faker = new DataFaker(); + + /** + * @var AbstractRequest + */ + $this->request = Mockery::mock('\Omnipay\BlueSnap\Message\AbstractRequest')->makePartial(); + $this->request->initialize(); + $this->request->setTestMode(true); + } + + /** + * @return void + */ + public function testUsername() + { + $username = $this->faker->username(); + $this->assertSame($this->request, $this->request->setUsername($username)); + $this->assertSame($username, $this->request->getUsername()); + } + + /** + * @return void + */ + public function testPassword() + { + $password = $this->faker->password(); + $this->assertSame($this->request, $this->request->setPassword($password)); + $this->assertSame($password, $this->request->getPassword()); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame('https://sandbox.bluesnap.com/services/2', $this->request->getEndpoint()); + $this->request->setTestMode(false); + $this->assertSame('https://ws.bluesnap.com/services/2', $this->request->getEndpoint()); + } + + /** + * @return void + */ + public function testCustomerReference() + { + $customerReference = $this->faker->customerReference(); + $this->assertSame($this->request, $this->request->setCustomerReference($customerReference)); + $this->assertSame($customerReference, $this->request->getCustomerReference()); + } + + /** + * @return void + */ + public function testTransactionReference() + { + $transactionReference = $this->faker->transactionReference(); + $this->assertSame($this->request, $this->request->setTransactionReference($transactionReference)); + $this->assertSame($transactionReference, $this->request->getTransactionReference()); + } + + /** + * @return void + */ + public function testSubscriptionReference() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $this->assertSame($this->request, $this->request->setSubscriptionReference($subscriptionReference)); + $this->assertSame($subscriptionReference, $this->request->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testSubscriptionChargeReference() + { + $subscriptionChargeReference = $this->faker->subscriptionChargeReference(); + $this->assertSame($this->request, $this->request->setSubscriptionChargeReference($subscriptionChargeReference)); + $this->assertSame($subscriptionChargeReference, $this->request->getSubscriptionChargeReference()); + } + + /** + * @return void + */ + public function testCurrency() + { + $currency = $this->faker->currency(); + $this->assertSame($this->request, $this->request->setCurrency($currency)); + $this->assertSame($currency, $this->request->getCurrency()); + } + + /** + * @return void + */ + public function testAmount() + { + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $this->request->setCurrency($currency); + $this->assertSame($this->request, $this->request->setAmount($amount)); + $this->assertSame($amount, $this->request->getAmount()); + } + + /** + * @return void + */ + public function testNextChargeDate() + { + $nextChargeDate = $this->faker->datetime(); + $this->assertSame($this->request, $this->request->setNextChargeDate($nextChargeDate)); + $this->assertSame($nextChargeDate, $this->request->getNextChargeDate()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage Dates must be provided in the Etc/GMT+8 time zone + */ + public function testNextChargeDateWrongTimeZone() + { + $nextChargeDate = $this->faker->datetime(); + $nextChargeDate->setTimezone(new DateTimeZone('Europe/London')); + $this->request->setNextChargeDate($nextChargeDate); + } + + /** + * @return void + */ + public function testReturnUrl() + { + $returnUrl = $this->faker->url(); + $this->assertSame($this->request, $this->request->setReturnUrl($returnUrl)); + $this->assertSame($returnUrl, $this->request->getReturnUrl()); + } + + /** + * @return void + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testStartTime() + { + $startTime = $this->faker->datetime(); + $this->assertSame($this->request, $this->request->setStartTime($startTime)); + $this->assertSame($startTime, $this->request->getStartTime()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage Dates must be provided in the Etc/GMT+8 time zone + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testStartTimeWrongTimeZone() + { + $startTime = $this->faker->datetime(); + $startTime->setTimezone(new DateTimeZone('Europe/London')); + $this->request->setStartTime($startTime); + } + + /** + * @return void + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testEndTime() + { + $endTime = $this->faker->datetime(); + $this->assertSame($this->request, $this->request->setEndTime($endTime)); + $this->assertSame($endTime, $this->request->getEndTime()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage Dates must be provided in the Etc/GMT+8 time zone + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testEndTimeWrongTimeZone() + { + $endTime = $this->faker->datetime(); + $endTime->setTimezone(new DateTimeZone('Europe/London')); + $this->request->setEndTime($endTime); + } +} diff --git a/tests/Message/ExtendedAbstractRequestTest.php b/tests/Message/ExtendedAbstractRequestTest.php new file mode 100644 index 0000000..96f4086 --- /dev/null +++ b/tests/Message/ExtendedAbstractRequestTest.php @@ -0,0 +1,68 @@ +faker = new DataFaker(); + + /** + * @var Mockery\MockInterface + */ + $this->request = Mockery::mock( + '\Omnipay\BlueSnap\Message\ExtendedAbstractRequest' + )->makePartial(); + $this->request->initialize(); + } + + /** + * @return void + */ + public function testStoreReference() + { + $storeReference = $this->faker->storeReference(); + $this->assertSame($this->request, $this->request->setStoreReference($storeReference)); + $this->assertSame($storeReference, $this->request->getStoreReference()); + } + + /** + * @return void + */ + public function testPlanReference() + { + $planReference = $this->faker->planReference(); + $this->assertSame($this->request, $this->request->setPlanReference($planReference)); + $this->assertSame($planReference, $this->request->getPlanReference()); + } + + /** + * @return void + */ + public function testStoreParameters() + { + $storeParameters = $this->faker->urlParameters(); + $this->assertSame($this->request, $this->request->setStoreParameters($storeParameters)); + $this->assertEquals($storeParameters, $this->request->getStoreParameters()); + } +} diff --git a/tests/Message/ExtendedCancelSubscriptionRequestTest.php b/tests/Message/ExtendedCancelSubscriptionRequestTest.php new file mode 100644 index 0000000..82282d6 --- /dev/null +++ b/tests/Message/ExtendedCancelSubscriptionRequestTest.php @@ -0,0 +1,117 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + + $this->request = new ExtendedCancelSubscriptionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' . strval($this->subscriptionReference), + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('PUT', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame('subscription', $data->getName()); + $this->assertSame($this->subscriptionReference, (string) $data->{'subscription-id'}); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedCancelSubscriptionSuccess.txt', array( + 'SUBSCRIPTION_REFERENCE' => $this->subscriptionReference, + )); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('204', $response->getCode()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $subscriptionReference = $this->faker->subscriptionReference(); + + $this->setMockHttpResponse('ExtendedCancelSubscriptionFailure.txt', array( + 'SUBSCRIPTION_REFERENCE' => $subscriptionReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'User API_1234567890123456789012 is not authorized to update subscription ID ' + . $subscriptionReference . '.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedFetchCustomerRequestTest.php b/tests/Message/ExtendedFetchCustomerRequestTest.php new file mode 100644 index 0000000..5ea01ba --- /dev/null +++ b/tests/Message/ExtendedFetchCustomerRequestTest.php @@ -0,0 +1,109 @@ +faker = new DataFaker(); + $this->customerReference = $this->faker->customerReference(); + + $this->request = new ExtendedFetchCustomerRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setCustomerReference($this->customerReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/shoppers/' . strval($this->customerReference), + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The customerReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataCustomerRequired() + { + $this->request->setCustomerReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedFetchCustomerSuccess.txt', array( + 'CUSTOMER_REFERENCE' => $this->customerReference + )); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame($this->customerReference, $response->getCustomerReference()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedFetchCustomerFailure.txt', array( + 'CUSTOMER_REFERENCE' => $this->customerReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + $this->assertSame( + 'User: API_1234567890123456789012 is not authorized to view shopper: ' . $this->customerReference . '.', + $response->getMessage() + ); + } +} diff --git a/tests/Message/ExtendedFetchSubscriptionChargeRequestTest.php b/tests/Message/ExtendedFetchSubscriptionChargeRequestTest.php new file mode 100644 index 0000000..a6cf86c --- /dev/null +++ b/tests/Message/ExtendedFetchSubscriptionChargeRequestTest.php @@ -0,0 +1,152 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + $this->subscriptionChargeReference = $this->faker->subscriptionChargeReference(); + + $this->request = new ExtendedFetchSubscriptionChargeRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + $this->request->setSubscriptionChargeReference($this->subscriptionChargeReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' . $this->subscriptionReference + . '/subscription-charges/' . $this->subscriptionChargeReference, + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionChargeReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionChargeRequired() + { + $this->request->setSubscriptionChargeReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $dateCreated = $this->faker->timestamp(); + $transactionReference = $this->faker->transactionReference(); + + $this->setMockHttpResponse('ExtendedFetchSubscriptionChargeSuccess.txt', array( + 'AMOUNT' => $amount, + 'CURRENCY' => $currency, + 'DATE_CREATED' => $dateCreated, + 'TRANSACTION_REFERENCE' => $transactionReference + )); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + // the response does not include the subscriptionChargeReference + $this->assertSame($currency, $response->getCurrency()); + $this->assertSame($amount, $response->getAmount()); + $responseDateCreated = $response->getDateCreated(); + $this->assertEquals(new DateTime($dateCreated), $responseDateCreated); + $this->assertEquals( + 'Etc/GMT+8', + $responseDateCreated ? $responseDateCreated->getTimezone()->getName() : null + ); + $this->assertSame($transactionReference, $response->getTransactionReference()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedFetchSubscriptionChargeFailure.txt', array( + 'SUBSCRIPTION_CHARGE_REFERENCE' => $this->subscriptionChargeReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'Subscription Charge retrieval service failure because subscriptionCharge ID: ' + . $this->subscriptionChargeReference . ' was not found.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedFetchSubscriptionRequestTest.php b/tests/Message/ExtendedFetchSubscriptionRequestTest.php new file mode 100644 index 0000000..8e4090d --- /dev/null +++ b/tests/Message/ExtendedFetchSubscriptionRequestTest.php @@ -0,0 +1,243 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + + $this->request = new ExtendedFetchSubscriptionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' + . strval($this->subscriptionReference) + . '?fulldescription=true', + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $customerReference = $this->faker->customerReference(); + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $subscriptionChargeReference = $this->faker->subscriptionChargeReference(); + $nextChargeDate = $this->faker->timestamp(); + $status = $this->faker->subscriptionStatus(); + $fakeCard = $this->faker->card(); + $cardBrand = $fakeCard->getBrand(); + $cardLastFour = $fakeCard->getNumberLastFour(); + $planReference = $this->faker->planReference(); + $chargeCurrency = $this->faker->currency(); + $chargeAmount = $this->faker->monetaryAmount($chargeCurrency); + $dateCreated = $this->faker->timestamp(); + $transactionReference = $this->faker->transactionReference(); + + $this->setMockHttpResponse('ExtendedFetchSubscriptionSuccess.txt', array( + 'SUBSCRIPTION_REFERENCE' => $this->subscriptionReference, + 'CUSTOMER_REFERENCE' => $customerReference, + 'PLAN_REFERENCE' => $planReference, + 'AMOUNT' => $amount, + 'CURRENCY' => $currency, + 'SUBSCRIPTION_CHARGE_REFERENCE' => $subscriptionChargeReference, + 'NEXT_CHARGE_DATE' => $nextChargeDate, + 'STATUS' => $status, + 'CARD_LAST_FOUR' => $cardLastFour, + 'CARD_BRAND' => ucfirst($cardBrand ?: ''), + 'TRANSACTION_REFERENCE' => $transactionReference, + 'DATE_CREATED' => $dateCreated, + 'CHARGE_AMOUNT' => $chargeAmount, + 'CHARGE_CURRENCY' => $chargeCurrency + )); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame($customerReference, $response->getCustomerReference()); + $this->assertSame($planReference, $response->getPlanReference()); + $this->assertSame($currency, $response->getCurrency()); + $this->assertSame($amount, $response->getAmount()); + $this->assertSame($status, $response->getStatus()); + $responseNextChargeDate = $response->getNextChargeDate(); + $this->assertEquals(new DateTime($nextChargeDate), $responseNextChargeDate); + $this->assertEquals( + 'Etc/GMT+8', + $responseNextChargeDate ? $responseNextChargeDate->getTimezone()->getName() : null + ); + $card = $response->getCard(); + $this->assertInstanceOf('\Omnipay\BlueSnap\CreditCard', $card); + if ($card === null) { + // so psalm knows the things below won't be hit + return; + } + $subscriptionCharges = $response->getSubscriptionCharges(); + $this->assertNotNull($subscriptionCharges); + if ($subscriptionCharges === null) { + // so psalm knows the things below won't be hit + return; + } + foreach ($subscriptionCharges as $charge) { + $this->assertSame($chargeAmount, $charge->getAmount()); + $this->assertSame($chargeCurrency, $charge->getCurrency()); + $this->assertSame($transactionReference, $charge->getTransactionReference()); + $chargeDate = $charge->getDate(); + $this->assertEquals(new DateTime($dateCreated), $chargeDate); + } + $this->assertSame($cardLastFour, $card->getNumberLastFour()); + $this->assertSame($cardBrand, $card->getBrand()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendWithOverriddenChargeSuccess() + { + $customerReference = $this->faker->customerReference(); + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $subscriptionChargeReference = $this->faker->subscriptionChargeReference(); + $nextChargeDate = $this->faker->timestamp(); + + $this->setMockHttpResponse('ExtendedFetchSubscriptionOverriddenChargeSuccess.txt', array( + 'SUBSCRIPTION_REFERENCE' => $this->subscriptionReference, + 'CUSTOMER_REFERENCE' => $customerReference, + 'AMOUNT' => $amount, + 'CURRENCY' => $currency, + 'SUBSCRIPTION_CHARGE_REFERENCE' => $subscriptionChargeReference, + 'NEXT_CHARGE_DATE' => $nextChargeDate + )); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame($this->subscriptionReference, $response->getSubscriptionReference()); + $this->assertSame($customerReference, $response->getCustomerReference()); + $this->assertSame($currency, $response->getCurrency()); + $this->assertSame($amount, $response->getAmount()); + $responseNextChargeDate = $response->getNextChargeDate(); + $this->assertEquals(new DateTime($nextChargeDate), $responseNextChargeDate); + $this->assertEquals( + 'Etc/GMT+8', + $responseNextChargeDate ? $responseNextChargeDate->getTimezone()->getName() : null + ); + $this->assertNull($response->getMessage()); + } + + /** + * Tests making a request for a subscription with multiple charges + * @return void + */ + public function testSendMultipleChargesSuccess() + { + $transactionReference1 = $this->faker->transactionReference(); + $transactionReference2 = $this->faker->transactionReference(); + + $this->setMockHttpResponse('ExtendedFetchSubscriptionMultipleChargesSuccess.txt', array( + 'TRANSACTION_REFERENCE_1' => $transactionReference1, + 'TRANSACTION_REFERENCE_2' => $transactionReference2 + )); + + $response = $this->request->send(); + $subscriptionCharges = $response->getSubscriptionCharges(); + $this->assertNotNull($subscriptionCharges); + if ($subscriptionCharges === null) { + // so psalm knows the things below won't be hit + return; + } + $references = array(); + foreach ($subscriptionCharges as $charge) { + $references[] = $charge->getTransactionReference(); + } + $this->assertSame( + array($transactionReference1, $transactionReference2), + $references + ); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedFetchSubscriptionFailure.txt', array( + 'SUBSCRIPTION_REFERENCE' => $this->subscriptionReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'User API_1234567890123456789012 is not authorized to retrieve subscription ID ' + . $this->subscriptionReference . '.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedFetchSubscriptionsRequestTest.php b/tests/Message/ExtendedFetchSubscriptionsRequestTest.php new file mode 100644 index 0000000..f4cbd95 --- /dev/null +++ b/tests/Message/ExtendedFetchSubscriptionsRequestTest.php @@ -0,0 +1,155 @@ +faker = new DataFaker(); + $this->customerReference = $this->faker->customerReference(); + + $this->request = new ExtendedFetchSubscriptionsRequest( + $this->getHttpClient(), + $this->getHttpRequest() + ); + $this->request->setCustomerReference($this->customerReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/tools/shopper-subscriptions-retriever' + . '?shopperid=' . strval($this->customerReference) + . '&fulldescription=true', + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The customerReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataCustomerRequired() + { + $this->request->setCustomerReference(null); + $this->request->getData(); + } + + + /** + * @return void + */ + public function testSendSuccess() + { + /** + * @var array> + */ + $fakeSubscriptions = array(); + for ($i = 1; $i <= 2; $i++) { + $customerReference = $this->customerReference; + $currency = $this->faker->currency(); + $fakeSubscriptions[$i] = array( + 'CUSTOMER_REFERENCE' => $customerReference, + 'SUBSCRIPTION_REFERENCE' => $this->faker->subscriptionReference(), + 'CURRENCY' => $currency, + 'AMOUNT' => $this->faker->monetaryAmount($currency), + 'STATUS' => $this->faker->subscriptionStatus(), + 'PLAN_REFERENCE' => $this->faker->planReference() + ); + } + + $replacements = array(); + foreach ($fakeSubscriptions as $i => $row) { + foreach ($row as $field => $value) { + $replacements[$field . '_' . (string) $i] = $value; + } + } + + $this->setMockHttpResponse('ExtendedFetchSubscriptionsSuccess.txt', $replacements); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $subscriptions = $response->getSubscriptions(); + $this->assertSame(2, count($subscriptions)); + if ($subscriptions) { + foreach ($subscriptions as $i => $subscription) { + $fakeSubscription = $fakeSubscriptions[intval($i) + 1]; + $this->assertSame( + $fakeSubscription['SUBSCRIPTION_REFERENCE'], + $subscription->getSubscriptionReference() + ); + $this->assertSame($fakeSubscription['CURRENCY'], $subscription->getCurrency()); + $this->assertSame($fakeSubscription['AMOUNT'], $subscription->getAmount()); + } + } + $this->assertNull($response->getMessage()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedFetchSubscriptionsFailure.txt', array( + 'CUSTOMER_REFERENCE' => $this->customerReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'User API_1234567890123456789012 is not authorized to retrieve subscription history for SHOPPER ID ' + . $this->customerReference . '.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedFetchTransactionRequestTest.php b/tests/Message/ExtendedFetchTransactionRequestTest.php new file mode 100644 index 0000000..a3bbd82 --- /dev/null +++ b/tests/Message/ExtendedFetchTransactionRequestTest.php @@ -0,0 +1,218 @@ +faker = new DataFaker(); + $this->transactionReference = $this->faker->transactionReference(); + + $this->request = new ExtendedFetchTransactionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setTransactionReference($this->transactionReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/orders/resolve?invoiceId=' . strval($this->transactionReference), + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The transactionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataTransactionRequired() + { + $this->request->setTransactionReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $customerReference = $this->faker->customerReference(); + $planReference = $this->faker->planReference(); + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $tax = $this->faker->monetaryAmount($currency); + $dateCreated = $this->faker->timestamp(); + $fakeCard = $this->faker->card(); + $cardBrand = $fakeCard->getBrand(); + $cardLastFour = $fakeCard->getNumberLastFour(); + $expiryMonth = $fakeCard->getExpiryMonth(); + $expiryYear = $fakeCard->getExpiryYear(); + $firstName = $fakeCard->getFirstName(); + $lastName = $fakeCard->getLastName(); + $email = $fakeCard->getEmail(); + $state = $fakeCard->getState(); + $country = $fakeCard->getCountry(); + $postcode = $fakeCard->getPostcode(); + $status = $this->faker->transactionStatus(); + $custom1_name = $this->faker->name(); + $custom1_value = $this->faker->customParameter(); + $custom2_name = $this->faker->name(); + $custom2_value = $this->faker->customParameter(); + + $this->setMockHttpResponse('ExtendedFetchTransactionSuccess.txt', array( + 'TRANSACTION_REFERENCE' => $this->transactionReference, + 'CUSTOMER_REFERENCE' => $customerReference, + 'PLAN_REFERENCE' => $planReference, + 'AMOUNT' => $amount, + 'TAX' => $tax, + 'CURRENCY' => $currency, + 'DATE_CREATED' => $dateCreated, + 'CARD_LAST_FOUR' => $cardLastFour, + 'CARD_BRAND' => ucfirst($cardBrand ?: ''), + 'EXPIRY_MONTH' => $expiryMonth, + 'EXPIRY_YEAR' => $expiryYear, + 'FIRST_NAME' => $firstName, + 'LAST_NAME' => $lastName, + 'EMAIL' => $email, + 'STATE' => $state, + 'COUNTRY' => $country, + 'POSTCODE' => $postcode, + 'STATUS' => $status, + 'CUSTOM_1_NAME' => $custom1_name, + 'CUSTOM_1_VALUE' => $custom1_value, + 'CUSTOM_2_NAME' => $custom2_name, + 'CUSTOM_2_VALUE' => $custom2_value + )); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame($this->transactionReference, $response->getTransactionReference()); + $this->assertSame($customerReference, $response->getCustomerReference()); + $this->assertSame($currency, $response->getCurrency()); + $this->assertSame($amount, $response->getAmount()); + $this->assertSame($tax, $response->getTax()); + $this->assertSame($status, $response->getStatus()); + $this->assertSame($custom1_value, $response->getCustomParameter($custom1_name)); + $this->assertSame($custom2_value, $response->getCustomParameter($custom2_name)); + $responseDateCreated = $response->getDateCreated(); + $this->assertEquals(new DateTime($dateCreated), $responseDateCreated); + $this->assertEquals( + 'Etc/GMT+8', + $responseDateCreated ? $responseDateCreated->getTimezone()->getName() : null + ); + $card = $response->getCard(); + $this->assertInstanceOf('\Omnipay\BlueSnap\CreditCard', $card); + if ($card === null) { + // so psalm knows the things below won't be hit + return; + } + $this->assertSame($cardLastFour, $card->getNumberLastFour()); + $this->assertSame($cardBrand, $card->getBrand()); + $this->assertSame($expiryMonth, $card->getExpiryMonth()); + $this->assertSame($expiryYear, $card->getExpiryYear()); + $this->assertSame($firstName, $card->getFirstName()); + $this->assertSame($lastName, $card->getLastName()); + $this->assertSame($email, $card->getEmail()); + $this->assertSame($country, $card->getCountry()); + $this->assertSame($postcode, $card->getPostcode()); + $this->assertNull($response->getMessage()); + } + + /** + * Tests when the response returned includes multiple invoices + * + * @return void + */ + public function testSendMultipleInvoicesSuccess() + { + $customerReference = $this->faker->customerReference(); + $currency = $this->faker->currency(); + $amount = $this->faker->monetaryAmount($currency); + $dateCreated = $this->faker->timestamp(); + + $this->setMockHttpResponse('ExtendedFetchTransactionMultipleInvoicesSuccess.txt', array( + 'TRANSACTION_REFERENCE' => $this->transactionReference, + 'CUSTOMER_REFERENCE' => $customerReference, + 'AMOUNT' => $amount, + 'CURRENCY' => $currency, + 'DATE_CREATED' => $dateCreated + )); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame($this->transactionReference, $response->getTransactionReference()); + $this->assertSame($customerReference, $response->getCustomerReference()); + $this->assertSame($currency, $response->getCurrency()); + $this->assertSame($amount, $response->getAmount()); + $responseDateCreated = $response->getDateCreated(); + $this->assertEquals(new DateTime($dateCreated), $responseDateCreated); + $this->assertEquals( + 'Etc/GMT+8', + $responseDateCreated ? $responseDateCreated->getTimezone()->getName() : null + ); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedFetchTransactionFailure.txt', array( + 'TRANSACTION_REFERENCE' => $this->transactionReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + $this->assertSame( + 'Order retrieval service failure. Order ID: ' . $this->transactionReference . ' is not found.', + $response->getMessage() + ); + } +} diff --git a/tests/Message/ExtendedReactivateSubscriptionRequestTest.php b/tests/Message/ExtendedReactivateSubscriptionRequestTest.php new file mode 100644 index 0000000..c274ec9 --- /dev/null +++ b/tests/Message/ExtendedReactivateSubscriptionRequestTest.php @@ -0,0 +1,115 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + + $this->request = new ExtendedReactivateSubscriptionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' . strval($this->subscriptionReference), + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('PUT', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame('subscription', $data->getName()); + $this->assertSame($this->subscriptionReference, (string) $data->{'subscription-id'}); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedReactivateSubscriptionSuccess.txt'); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('204', $response->getCode()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $subscriptionReference = $this->faker->subscriptionReference(); + + $this->setMockHttpResponse('ExtendedReactivateSubscriptionFailure.txt', array( + 'SUBSCRIPTION_REFERENCE' => $subscriptionReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'User API_1234567890123456789012 is not authorized to update subscription ID ' + . $subscriptionReference . '.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedRefundRequestTest.php b/tests/Message/ExtendedRefundRequestTest.php new file mode 100644 index 0000000..8bd5ac3 --- /dev/null +++ b/tests/Message/ExtendedRefundRequestTest.php @@ -0,0 +1,193 @@ +faker = new DataFaker(); + $this->transactionReference = $this->faker->transactionReference(); + $this->currency = $this->faker->currency(); + $this->amount = $this->faker->monetaryAmount($this->currency); + $this->reason = $this->faker->randomCharacters( + DataFaker::ALPHABET_LOWER . ' ', + $this->faker->intBetween(6, 30) + ); + $this->cancelSubscriptions = $this->faker->bool(); + $this->request = new ExtendedRefundRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setTransactionReference($this->transactionReference); + $this->request->setCurrency($this->currency); + $this->request->setAmount($this->amount); + $this->request->setReason($this->reason); + $this->request->setCancelSubscriptions($this->cancelSubscriptions); + } + + /** + * @return void + */ + public function testEndpoint() + { + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/orders/refund' + . '?invoiceId=' . $this->transactionReference + . '&amount=' . urlencode((string) $this->amount) + . '&reason=' . urlencode((string) $this->reason) + . '&cancelSubscriptions=' . ($this->cancelSubscriptions ? 'true' : 'false'), + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testEndpointDefaultCancelSubscriptions() + { + $this->request->setCancelSubscriptions(null); + + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/orders/refund' + . '?invoiceId=' . $this->transactionReference + . '&amount=' . urlencode((string) $this->amount) + . '&reason=' . urlencode((string) $this->reason) + . '&cancelSubscriptions=false', + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('PUT', $this->request->getHttpMethod()); + } + + /** + * @return void + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testReason() + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedRefundRequest + */ + $request = Mockery::mock('\Omnipay\BlueSnap\Message\ExtendedRefundRequest')->makePartial(); + $request->initialize(); + + $this->assertSame($request, $request->setReason($this->reason)); + $this->assertSame($this->reason, $request->getReason()); + } + + /** + * @return void + * @psalm-suppress TooManyArguments because Mockery is variadic + */ + public function testCancelSubscriptions() + { + /** + * @var \Omnipay\BlueSnap\Message\ExtendedRefundRequest + */ + $request = Mockery::mock('\Omnipay\BlueSnap\Message\ExtendedRefundRequest')->makePartial(); + $request->initialize(); + + $this->assertSame($request, $request->setCancelSubscriptions($this->cancelSubscriptions)); + $this->assertSame($this->cancelSubscriptions, $request->getCancelSubscriptions()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The transactionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataTransactionReferenceRequired() + { + $this->request->setTransactionReference(null); + $this->request->getData(); + } + + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedRefundSuccess.txt'); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('204', $response->getCode()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedRefundFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + $this->assertSame('Invoice has already been fully refunded.', $response->getMessage()); + } +} diff --git a/tests/Message/ExtendedTestChargeSubscriptionRequestTest.php b/tests/Message/ExtendedTestChargeSubscriptionRequestTest.php new file mode 100644 index 0000000..1932a7e --- /dev/null +++ b/tests/Message/ExtendedTestChargeSubscriptionRequestTest.php @@ -0,0 +1,125 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + + $this->request = new ExtendedTestChargeSubscriptionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + $this->request->setTestMode(true); + } + + /** + * @return void + */ + public function testEndpoint() + { + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' + . strval($this->subscriptionReference) . '/run-specific', + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage You cannot make a test subscription charge if you're not in test mode + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataTestModeRequired() + { + $this->request->setTestMode(false); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedTestChargeSubscriptionSuccess.txt'); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('204', $response->getCode()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('ExtendedTestChargeSubscriptionFailure.txt', array( + 'SUBSCRIPTION_REFERENCE' => $this->subscriptionReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'Call to runSpecificSubscription failed, subscriptionId ' . $this->subscriptionReference . '.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/ExtendedUpdateSubscriptionRequestTest.php b/tests/Message/ExtendedUpdateSubscriptionRequestTest.php new file mode 100644 index 0000000..e4db1ac --- /dev/null +++ b/tests/Message/ExtendedUpdateSubscriptionRequestTest.php @@ -0,0 +1,148 @@ +faker = new DataFaker(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + $this->planReference = $this->faker->planReference(); + $this->currency = $this->faker->currency(); + $this->amount = $this->faker->monetaryAmount($this->currency); + $this->nextChargeDate = $this->faker->datetime(); + + $this->request = new ExtendedUpdateSubscriptionRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setSubscriptionReference($this->subscriptionReference); + $this->request->setPlanReference($this->planReference); + $this->request->setAmount($this->amount); + $this->request->setCurrency($this->currency); + $this->request->setNextChargeDate($this->nextChargeDate); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/subscriptions/' . strval($this->subscriptionReference), + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('PUT', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame('subscription', $data->getName()); + $this->assertSame($this->subscriptionReference, (string) $data->{'subscription-id'}); + $this->assertSame($this->planReference, (string) $data->{'underlying-sku-id'}); + $this->assertSame($this->currency, (string) $data->{'override-recurring-charge'}->currency); + $this->assertSame($this->amount, (string) $data->{'override-recurring-charge'}->amount); + $this->assertSame($this->nextChargeDate->format('d-M-y'), (string) $data->{'next-charge-date'}); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The subscriptionReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setSubscriptionReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->setMockHttpResponse('ExtendedUpdateSubscriptionSuccess.txt'); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('204', $response->getCode()); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $customerReference = $this->faker->customerReference(); + + $this->setMockHttpResponse('ExtendedUpdateSubscriptionFailure.txt', array( + 'CUSTOMER_REFERENCE' => $customerReference + )); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('403', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'The shopper: ' . $customerReference . ' has not given prior consent to certain' + . ' additional charges and so this operation cannot be processed.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/FetchCanceledSubscriptionsRequestTest.php b/tests/Message/FetchCanceledSubscriptionsRequestTest.php new file mode 100644 index 0000000..539fe32 --- /dev/null +++ b/tests/Message/FetchCanceledSubscriptionsRequestTest.php @@ -0,0 +1,234 @@ +faker = new DataFaker(); + $this->startTime = $this->faker->datetime(); + do { + $this->endTime = $this->faker->datetime(); + } while ($this->endTime == $this->startTime); + if ($this->endTime < $this->startTime) { + $temp = $this->endTime; + $this->endTime = $this->startTime; + $this->startTime = $temp; + } + + $this->request = new FetchCanceledSubscriptionsRequest($this->getHttpClient(), $this->getHttpRequest()); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/report/CanceledSubscriptions?period=CUSTOM' + . '&from_date=' . urlencode((string) $this->startTime->format('m/d/Y')) + . '&to_date=' . urlencode((string) $this->endTime->format('m/d/Y')), + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testStartTime() + { + $startTime = $this->faker->datetime(); + $this->assertSame($this->request, $this->request->setStartTime($startTime)); + $this->assertSame($startTime, $this->request->getStartTime()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage Dates must be provided in the Etc/GMT+8 time zone + */ + public function testStartTimeWrongTimeZone() + { + $startTime = $this->faker->datetime(); + $startTime->setTimezone(new DateTimeZone('Europe/London')); + $this->request->setStartTime($startTime); + } + + /** + * @return void + */ + public function testEndTime() + { + $endTime = $this->faker->datetime(); + $this->assertSame($this->request, $this->request->setEndTime($endTime)); + $this->assertSame($endTime, $this->request->getEndTime()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage Dates must be provided in the Etc/GMT+8 time zone + */ + public function testEndTimeWrongTimeZone() + { + $endTime = $this->faker->datetime(); + $endTime->setTimezone(new DateTimeZone('Europe/London')); + $this->request->setEndTime($endTime); + } + + /** + * @return void + */ + public function testGetData() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage startTime cannot be greater than endTime + */ + public function testGetDataStartDateGreater() + { + $this->request->setStartTime($this->endTime); + $this->request->setEndTime($this->startTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The startTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataStartTimeRequired() + { + $this->request->setEndTime($this->endTime); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The endTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataEndTimeRequired() + { + $this->request->setStartTime($this->startTime); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + /** + * @var array> + */ + $fakeSubscriptions = array(); + for ($i = 1; $i <= 2; $i++) { + $currency = $this->faker->currency(); + $fakeSubscriptions[$i] = array( + 'SUBSCRIPTION_REFERENCE' => $this->faker->subscriptionReference(), + 'CURRENCY' => $currency, + 'AMOUNT' => $this->faker->monetaryAmount($currency) + ); + } + + $replacements = array(); + foreach ($fakeSubscriptions as $i => $row) { + foreach ($row as $field => $value) { + $replacements[$field . '_' . (string) $i] = $value; + } + } + + $this->setMockHttpResponse('FetchCanceledSubscriptionsSuccess.txt', $replacements); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $subscriptions = $response->getSubscriptions(); + $this->assertSame(2, count($subscriptions)); + if ($subscriptions) { + foreach ($subscriptions as $i => $subscription) { + $fakeSubscription = $fakeSubscriptions[intval($i) + 1]; + $this->assertSame( + $fakeSubscription['SUBSCRIPTION_REFERENCE'], + $subscription->getSubscriptionReference() + ); + $this->assertSame($fakeSubscription['CURRENCY'], $subscription->getCurrency()); + $this->assertSame($fakeSubscription['AMOUNT'], $subscription->getAmount()); + } + } + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->setMockHttpResponse('FetchCanceledSubscriptionsFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + $this->assertSame('Invalid Date Range', $response->getMessage()); + } +} diff --git a/tests/Message/FetchSubscriptionsRequestTest.php b/tests/Message/FetchSubscriptionsRequestTest.php new file mode 100644 index 0000000..8bbf2d7 --- /dev/null +++ b/tests/Message/FetchSubscriptionsRequestTest.php @@ -0,0 +1,191 @@ +faker = new DataFaker(); + $this->startTime = $this->faker->datetime(); + do { + $this->endTime = $this->faker->datetime(); + } while ($this->endTime == $this->startTime); + if ($this->endTime < $this->startTime) { + $temp = $this->endTime; + $this->endTime = $this->startTime; + $this->startTime = $temp; + } + + $this->request = new FetchSubscriptionsRequest($this->getHttpClient(), $this->getHttpRequest()); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/report/ActiveSubscriptions?period=CUSTOM' + . '&from_date=' . urlencode((string) $this->startTime->format('m/d/Y')) + . '&to_date=' . urlencode((string) $this->endTime->format('m/d/Y')), + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage startTime cannot be greater than endTime + */ + public function testGetDataStartDateGreater() + { + $this->request->setStartTime($this->endTime); + $this->request->setEndTime($this->startTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The startTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataStartTimeRequired() + { + $this->request->setEndTime($this->endTime); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The endTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataEndTimeRequired() + { + $this->request->setStartTime($this->startTime); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + /** + * @var array> + */ + $fakeSubscriptions = array(); + for ($i = 1; $i <= 2; $i++) { + $currency = $this->faker->currency(); + $fakeSubscriptions[$i] = array( + 'SUBSCRIPTION_REFERENCE' => $this->faker->subscriptionReference(), + 'CURRENCY' => $currency, + 'AMOUNT' => $this->faker->monetaryAmount($currency) + ); + } + + $replacements = array(); + foreach ($fakeSubscriptions as $i => $row) { + foreach ($row as $field => $value) { + $replacements[$field . '_' . (string) $i] = $value; + } + } + + $this->setMockHttpResponse('FetchSubscriptionsSuccess.txt', $replacements); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $subscriptions = $response->getSubscriptions(); + $this->assertSame(2, count($subscriptions)); + if ($subscriptions) { + foreach ($subscriptions as $i => $subscription) { + $fakeSubscription = $fakeSubscriptions[intval($i) + 1]; + $this->assertSame( + $fakeSubscription['SUBSCRIPTION_REFERENCE'], + $subscription->getSubscriptionReference() + ); + $this->assertSame($fakeSubscription['CURRENCY'], $subscription->getCurrency()); + $this->assertSame($fakeSubscription['AMOUNT'], $subscription->getAmount()); + } + } + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->setMockHttpResponse('FetchSubscriptionsFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + $this->assertSame('Invalid Date Range', $response->getMessage()); + } +} diff --git a/tests/Message/FetchTransactionsRequestTest.php b/tests/Message/FetchTransactionsRequestTest.php new file mode 100644 index 0000000..72aaed1 --- /dev/null +++ b/tests/Message/FetchTransactionsRequestTest.php @@ -0,0 +1,196 @@ +faker = new DataFaker(); + $this->startTime = $this->faker->datetime(); + do { + $this->endTime = $this->faker->datetime(); + } while ($this->endTime == $this->startTime); + if ($this->endTime < $this->startTime) { + $temp = $this->endTime; + $this->endTime = $this->startTime; + $this->startTime = $temp; + } + + $this->request = new FetchTransactionsRequest($this->getHttpClient(), $this->getHttpRequest()); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + // @codingStandardsIgnoreStart + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/report/TransactionDetail?period=CUSTOM' + . '&from_date=' . urlencode((string) $this->startTime->format('m/d/Y')) + . '&to_date=' . urlencode((string) $this->endTime->format('m/d/Y')), + $this->request->getEndpoint() + ); + // @codingStandardsIgnoreEnd + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @return void + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage startTime cannot be greater than endTime + */ + public function testGetDataStartDateGreater() + { + $this->request->setStartTime($this->endTime); + $this->request->setEndTime($this->startTime); + + $this->assertNull($this->request->getData()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The startTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataStartTimeRequired() + { + $this->request->setEndTime($this->endTime); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The endTime parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataEndTimeRequired() + { + $this->request->setStartTime($this->startTime); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + /** + * @var array> + */ + $fakeTransactions = array(); + for ($i = 1; $i <= 2; $i++) { + $currency = $this->faker->currency(); + $fakeTransactions[$i] = array( + 'TRANSACTION_REFERENCE' => $this->faker->transactionReference(), + 'DATE' => $this->faker->datetime()->format('m/d/Y'), + 'CURRENCY' => $currency, + 'AMOUNT' => $this->faker->monetaryAmount($currency), + 'CUSTOMER_REFERENCE' => $this->faker->customerReference(), + 'CUSTOM_1' => $this->faker->customParameter(), + 'CUSTOM_2' => $this->faker->customParameter() + ); + } + + $replacements = array(); + foreach ($fakeTransactions as $i => $row) { + foreach ($row as $field => $value) { + $replacements[$field . '_' . (string) $i] = $value; + } + } + + $this->setMockHttpResponse('FetchTransactionsSuccess.txt', $replacements); + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $transactions = $response->getTransactions(); + $this->assertSame(2, count($transactions)); + if ($transactions) { + foreach ($transactions as $i => $transaction) { + $fakeTransaction = $fakeTransactions[intval($i) + 1]; + $date = $transaction->getDate(); + $this->assertSame($fakeTransaction['TRANSACTION_REFERENCE'], $transaction->getTransactionReference()); + $this->assertSame($fakeTransaction['DATE'], $date ? $date->format('m/d/Y') : ''); + $this->assertSame($fakeTransaction['CURRENCY'], $transaction->getCurrency()); + $this->assertSame($fakeTransaction['AMOUNT'], $transaction->getAmount()); + $this->assertSame($fakeTransaction['CUSTOMER_REFERENCE'], $transaction->getCustomerReference()); + $this->assertSame($fakeTransaction['CUSTOM_1'], $transaction->getCustomParameter1()); + $this->assertSame($fakeTransaction['CUSTOM_2'], $transaction->getCustomParameter2()); + } + } + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->request->setStartTime($this->startTime); + $this->request->setEndTime($this->endTime); + + $this->setMockHttpResponse('FetchTransactionsFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + $this->assertSame('Invalid Date Range', $response->getMessage()); + } +} diff --git a/tests/Message/HostedCheckoutDecryptReturnUrlRequestTest.php b/tests/Message/HostedCheckoutDecryptReturnUrlRequestTest.php new file mode 100644 index 0000000..7dbe91a --- /dev/null +++ b/tests/Message/HostedCheckoutDecryptReturnUrlRequestTest.php @@ -0,0 +1,161 @@ +faker = new DataFaker(); + $this->encryptedToken = $this->faker->randomCharacters( + DataFaker::ALPHABET_UPPER . DataFaker::ALPHABET_LOWER . DataFaker::DIGITS, + $this->faker->intBetween(20, 60) + ); + $this->returnUrl = $this->faker->url() . '?encParams=' . $this->encryptedToken; + + $this->request = new HostedCheckoutDecryptReturnUrlRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setReturnUrl($this->returnUrl); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/tools/param-decryption', + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('POST', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame('param-decryption', $data->getName()); + $this->assertSame($this->encryptedToken, (string) $data->{'encrypted-token'}); + } + + /** + * @return void + */ + public function testGetDataQueryStringOnly() + { + $this->request->setReturnUrl('encParams=' . $this->encryptedToken); + $data = $this->request->getData(); + + $this->assertSame('param-decryption', $data->getName()); + $this->assertSame($this->encryptedToken, (string) $data->{'encrypted-token'}); + } + + /** + * @return void + */ + public function testGetDataEncryptedTokenOnly() + { + $this->request->setReturnUrl($this->encryptedToken); + $data = $this->request->getData(); + + $this->assertSame('param-decryption', $data->getName()); + $this->assertSame($this->encryptedToken, (string) $data->{'encrypted-token'}); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The returnUrl parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataReturnUrlRequired() + { + $this->request->setReturnUrl(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $param1 = $this->faker->randomCharacters(DataFaker::ALPHABET_LOWER, $this->faker->intBetween(3, 10)); + $value1 = $this->faker->customerReference(); + $param2 = $this->faker->randomCharacters(DataFaker::ALPHABET_LOWER, $this->faker->intBetween(3, 10)); + $value2 = $this->faker->transactionReference(); + + $this->setMockHttpResponse('HostedCheckoutDecryptReturnUrlSuccess.txt', array( + 'PARAM_1' => $param1, + 'VALUE_1' => $value1, + 'PARAM_2' => $param2, + 'VALUE_2' => $value2 + )); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertEquals( + array( + $param1 => $value1, + $param2 => $value2 + ), + $response->getDecryptedParameters() + ); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('HostedCheckoutDecryptReturnUrlFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'Parameter Decryption service failed due to problematic input. We recommend checking' + . ' the parameter-encyption token input and try again or contact merchant support.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/HostedCheckoutPurchaseRequestTest.php b/tests/Message/HostedCheckoutPurchaseRequestTest.php new file mode 100644 index 0000000..8577c5c --- /dev/null +++ b/tests/Message/HostedCheckoutPurchaseRequestTest.php @@ -0,0 +1,233 @@ +faker = new DataFaker(); + $this->storeReference = $this->faker->storeReference(); + $this->planReference = $this->faker->planReference(); + $this->currency = $this->faker->currency(); + $this->returnUrl = $this->faker->url(); + $this->parameters = $this->faker->urlParameters(); + + $this->request = new HostedCheckoutPurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setTestMode(true); + $this->request->setStoreReference($this->storeReference); + $this->request->setPlanReference($this->planReference); + $this->request->setCurrency($this->currency); + $this->request->setReturnUrl($this->returnUrl); + $this->request->setStoreParameters($this->parameters); + } + + /** + * @return void + */ + public function testEndpoint() + { + $this->assertSame( + 'https://sandbox.bluesnap.com/services/2/tools/param-encryption', + $this->request->getEndpoint() + ); + } + + /** + * @return void + */ + public function testHttpMethod() + { + $this->assertSame('POST', $this->request->getHttpMethod()); + } + + /** + * @return void + */ + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame('param-encryption', $data->getName()); + + // loop through the XML and make sure all the keys and values are present + $expectedParameters = array( + array( + 'key' => 'sku' . $this->planReference, + 'value' => '1', + 'found' => false + ), + array ( + 'key' => 'currency', + 'value' => $this->currency, + 'found' => false + ), + array ( + 'key' => 'thankyou.backtosellerurl', + 'value' => urlencode($this->returnUrl), + 'found' => false + ) + ); + /** + * @var UrlParameter + */ + foreach ($this->parameters as $parameter) { + $expectedParameters[] = array( + 'key' => $parameter->getKey(), + 'value' => $parameter->getValue(), + 'found' => false + ); + } + + $keyJustFound = null; + $keyCount = 0; + $valueCount = 0; + + /** + * @var \SimpleXMLElement + */ + $parameters = $data->parameters; + + /** + * @var \SimpleXMLElement + */ + foreach ($parameters->children() as $parameter) { + /** + * @var \SimpleXMLElement + */ + foreach ($parameter->children() as $keyOrValue) { + if ($keyJustFound) { + $value = $keyOrValue; + $valueCount++; + + // make sure every key has a value + $this->assertEquals('param-value', $value->getName()); + foreach ($expectedParameters as &$expectedParameter) { + if ($expectedParameter['key'] === $keyJustFound && !$expectedParameter['found']) { + // make sure that value is correct + $this->assertEquals($expectedParameter['value'], (string) $value); + $expectedParameter['found'] = true; + break; + } + } + $keyJustFound = null; + } else { + $key = $keyOrValue; + $keyCount++; + + $this->assertSame('param-key', $key->getName()); + $keyJustFound = (string) $key; + } + } + } + + $numParams = count($expectedParameters); + $this->assertSame($numParams, $keyCount); + $this->assertSame($numParams, $valueCount); + + // make sure each parameter was found + foreach ($expectedParameters as $expectedParameter) { + $this->assertTrue( + $expectedParameter['found'], + 'Failed to find parameter with key ' . strval($expectedParameter['key']) + ); + } + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The storeReference parameter is required + * @return void + * @psalm-suppress NullArgument we're wiping it out for testing purposes + */ + public function testGetDataSubscriptionRequired() + { + $this->request->setStoreReference(null); + $this->request->getData(); + } + + /** + * @return void + */ + public function testSendSuccess() + { + $encryptedToken = $this->faker->encryptedUrlParameters(); + + $this->setMockHttpResponse('HostedCheckoutPurchaseSuccess.txt', array( + 'ENCRYPTED_TOKEN' => $encryptedToken + )); + + $response = $this->request->send(); + $this->assertTrue($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $this->assertSame('200', $response->getCode()); + $this->assertSame('GET', $response->getRedirectMethod()); + $this->assertSame( + 'https://sandbox.bluesnap.com/buynow/checkout?storeId=' . $this->storeReference . '&enc=' . $encryptedToken, + $response->getRedirectUrl() + ); + $this->assertNull($response->getMessage()); + } + + /** + * @return void + */ + public function testSendFailure() + { + $this->setMockHttpResponse('HostedCheckoutPurchaseFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('400', $response->getCode()); + // @codingStandardsIgnoreStart + $this->assertSame( + 'Parameter Encryption service failed due to problematic input. Missing Data Protection Key: ' + . 'please define it in the Console and try again.', + $response->getMessage() + ); + // @codingStandardsIgnoreEnd + } +} diff --git a/tests/Message/IPNCallbackTest.php b/tests/Message/IPNCallbackTest.php new file mode 100644 index 0000000..9d62761 --- /dev/null +++ b/tests/Message/IPNCallbackTest.php @@ -0,0 +1,281 @@ +faker = new DataFaker(); + $this->url = $this->faker->url(); + $this->queryString = $this->faker->queryString(); + } + + /** + * Makes sure that a full URL, query string, or $_POST variable all yield the same result + * + * @return void + */ + public function testInputFormats() + { + $queryStringCallback = new IPNCallback($this->queryString); + $fullUrlCallback = new IPNCallback($this->faker->url() . '?' . $this->queryString); + parse_str($this->queryString, $post); + /** @var array */ + $post = $post; + $postCallback = new IPNCallback($post); + + $reflectionIPNCallback = new ReflectionClass('\Omnipay\BlueSnap\Message\IPNCallback'); + $reflectionQueryParams = $reflectionIPNCallback->getProperty('queryParams'); + $reflectionQueryParams->setAccessible(true); + + $queryStringQueryParams = (array) $reflectionQueryParams->getValue($queryStringCallback); + $fullUrlQueryParams = (array) $reflectionQueryParams->getValue($fullUrlCallback); + $postQueryParams = (array) $reflectionQueryParams->getValue($postCallback); + + $this->assertSame($queryStringQueryParams, $fullUrlQueryParams); + $this->assertSame($queryStringQueryParams, $postQueryParams); + } + + /** + * @return void + */ + public function testIsCharge() + { + $callback = new IPNCallback($this->queryString . '&transactionType=CHARGE'); + $this->assertTrue($callback->isCharge()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=CHARGE&' . $this->queryString); + $this->assertTrue($callback->isCharge()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isCharge()); + } + + /** + * @return void + */ + public function testIsCancellation() + { + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertTrue($callback->isCancellation()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=CANCELLATION&' . $this->queryString); + $this->assertTrue($callback->isCancellation()); + $callback = new IPNCallback($this->queryString . '&transactionType=CHARGE'); + $this->assertFalse($callback->isCancellation()); + } + + /** + * @return void + */ + public function testIsSubscriptionCancellation() + { + $callback = new IPNCallback($this->queryString . '&transactionType=CANCEL_ON_RENEWAL'); + $this->assertTrue($callback->isCancellationRequest()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=CANCEL_ON_RENEWAL&' . $this->queryString); + $this->assertTrue($callback->isCancellationRequest()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isCancellationRequest()); + } + + /** + * @return void + */ + public function testIsChargeback() + { + $callback = new IPNCallback($this->queryString . '&transactionType=CHARGEBACK'); + $this->assertTrue($callback->isChargeback()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=CHARGEBACK&' . $this->queryString); + $this->assertTrue($callback->isChargeback()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isChargeback()); + } + + /** + * @return void + */ + public function testIsSubscriptionCharge() + { + $callback = new IPNCallback($this->queryString . '&transactionType=RECURRING'); + $this->assertTrue($callback->isSubscriptionCharge()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=RECURRING&' . $this->queryString); + $this->assertTrue($callback->isSubscriptionCharge()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isSubscriptionCharge()); + } + + /** + * @return void + */ + public function testIsRefund() + { + $callback = new IPNCallback($this->queryString . '&transactionType=REFUND'); + $this->assertTrue($callback->isRefund()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=REFUND&' . $this->queryString); + $this->assertTrue($callback->isRefund()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isRefund()); + } + + /** + * @return void + */ + public function testIsChargeFailure() + { + $callback = new IPNCallback($this->queryString . '&transactionType=CC_CHARGE_FAILED'); + $this->assertTrue($callback->isChargeFailure()); + $callback = new IPNCallback($this->faker->url() . '?transactionType=CC_CHARGE_FAILED&' . $this->queryString); + $this->assertTrue($callback->isChargeFailure()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isChargeFailure()); + } + + /** + * @return void + */ + public function testIsSubscriptionChargeFailure() + { + $callback = new IPNCallback($this->queryString . '&transactionType=SUBSCRIPTION_CHARGE_FAILURE'); + $this->assertTrue($callback->isSubscriptionChargeFailure()); + $callback = new IPNCallback( + $this->faker->url() . '?transactionType=SUBSCRIPTION_CHARGE_FAILURE&' . $this->queryString + ); + $this->assertTrue($callback->isSubscriptionChargeFailure()); + $callback = new IPNCallback($this->queryString . '&transactionType=CANCELLATION'); + $this->assertFalse($callback->isSubscriptionChargeFailure()); + } + + /** + * @return void + */ + public function testTransactionReference() + { + $transactionReference = $this->faker->transactionReference(); + $callback = new IPNCallback($this->queryString . '&referenceNumber=' . $transactionReference); + $this->assertSame($transactionReference, $callback->getTransactionReference()); + $callback = new IPNCallback( + $this->faker->url() . '?referenceNumber=' . $transactionReference . '&' . $this->queryString + ); + $this->assertSame($transactionReference, $callback->getTransactionReference()); + } + + /** + * @return void + */ + public function testSubscriptionReference() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $callback = new IPNCallback($this->queryString . '&subscriptionId=' . $subscriptionReference); + $this->assertSame($subscriptionReference, $callback->getSubscriptionReference()); + $callback = new IPNCallback( + $this->faker->url() . '?subscriptionId=' . $subscriptionReference . '&' . $this->queryString + ); + $this->assertSame($subscriptionReference, $callback->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testPlanReference() + { + $planReference = $this->faker->planReference(); + $callback = new IPNCallback($this->queryString . '&contractId=' . $planReference); + $this->assertSame($planReference, $callback->getplanReference()); + $callback = new IPNCallback( + $this->faker->url() . '?contractId=' . $planReference . '&' . $this->queryString + ); + $this->assertSame($planReference, $callback->getPlanReference()); + } + + /** + * @return void + */ + public function testCustomerReference() + { + $customerReference = $this->faker->customerReference(); + $callback = new IPNCallback($this->queryString . '&accountId=' . $customerReference); + $this->assertSame($customerReference, $callback->getCustomerReference()); + $callback = new IPNCallback( + $this->faker->url() . '?accountId=' . $customerReference . '&' . $this->queryString + ); + $this->assertSame($customerReference, $callback->getCustomerReference()); + } + + /** + * @return void + */ + public function testAmount() + { + $amount = $this->faker->monetaryAmount($this->faker->currency()); + $callback = new IPNCallback($this->queryString . '&invoiceAmount=' . $amount); + $this->assertSame($amount, $callback->getAmount()); + $callback = new IPNCallback( + $this->faker->url() . '?invoiceAmount=' . $amount . '&' . $this->queryString + ); + $this->assertSame($amount, $callback->getAmount()); + } + + /** + * @return void + */ + public function testCurrency() + { + $currency = $this->faker->currency(); + $callback = new IPNCallback($this->queryString . '¤cy=' . $currency); + $this->assertSame($currency, $callback->getCurrency()); + $callback = new IPNCallback( + $this->faker->url() . '?currency=' . $currency . '&' . $this->queryString + ); + $this->assertSame($currency, $callback->getCurrency()); + } + + /** + * @return void + */ + public function testDate() + { + $date = $this->faker->datetime(); + $dateString = urlencode($date->format('m/d/Y h:i A') ?: ''); + $callback = new IPNCallback($this->queryString . '&transactionDate=' . $dateString); + $this->assertEquals($date, $callback->getDate()); + $callback = new IPNCallback( + $this->faker->url() . '?transactionDate=' . $dateString . '&' . $this->queryString + ); + $this->assertEquals($date, $callback->getDate()); + } + + /** + * @return void + */ + public function testGetParameter() + { + $parameterString = $this->faker->queryString(1); + $parameterParts = explode('=', $parameterString); + $parameterName = $parameterParts[0]; + $parameterValue = $parameterParts[1]; + $callback = new IPNCallback($this->queryString . '&' . $parameterString); + $this->assertSame($parameterValue, $callback->getParameter($parameterName)); + $callback = new IPNCallback($this->faker->url() . '?' . $parameterString . '&' . $this->queryString); + $this->assertSame($parameterValue, $callback->getParameter($parameterName)); + } +} diff --git a/tests/Mock/ExtendedCancelSubscriptionFailure.txt b/tests/Mock/ExtendedCancelSubscriptionFailure.txt new file mode 100644 index 0000000..3689228 --- /dev/null +++ b/tests/Mock/ExtendedCancelSubscriptionFailure.txt @@ -0,0 +1,15 @@ +HTTP/1.1 403 Forbidden +Date: Mon, 24 Apr 2017 17:20:56 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 280 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + USER_NOT_AUTHORIZED + User API_1234567890123456789012 is not authorized to update subscription ID [SUBSCRIPTION_REFERENCE]. + + diff --git a/tests/Mock/ExtendedCancelSubscriptionSuccess.txt b/tests/Mock/ExtendedCancelSubscriptionSuccess.txt new file mode 100644 index 0000000..f5ab88c --- /dev/null +++ b/tests/Mock/ExtendedCancelSubscriptionSuccess.txt @@ -0,0 +1,6 @@ +HTTP/1.1 204 No Content +Date: Mon, 24 Apr 2017 17:17:26 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 0 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains diff --git a/tests/Mock/ExtendedFetchCustomerFailure.txt b/tests/Mock/ExtendedFetchCustomerFailure.txt new file mode 100644 index 0000000..9d08b31 --- /dev/null +++ b/tests/Mock/ExtendedFetchCustomerFailure.txt @@ -0,0 +1,9 @@ +HTTP/1.1 403 Forbidden +Date: Mon, 17 Apr 2017 15:02:26 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 73 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + +User: API_1234567890123456789012 is not authorized to view shopper: [CUSTOMER_REFERENCE]. diff --git a/tests/Mock/ExtendedFetchCustomerSuccess.txt b/tests/Mock/ExtendedFetchCustomerSuccess.txt new file mode 100644 index 0000000..20dc86e --- /dev/null +++ b/tests/Mock/ExtendedFetchCustomerSuccess.txt @@ -0,0 +1,69 @@ +HTTP/1.1 200 OK +Date: Thu, 13 Apr 2017 18:11:22 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + [CUSTOMER_REFERENCE] + + First + Last + test@example.org + 160-0000 + jp + + + First + Last + 160-0000 + jp + + + + true + First + Last + test@example.org + 160-0000 + jp + + + + + + + [FIRST_NAME] + [LAST_NAME] + [POSTCODE] + [COUNTRY] + + + [CARD_LAST_FOUR] + [CARD_BRAND] + CREDIT + [EXPIRY_MONTH] + [EXPIRY_YEAR] + + + ND + U + U + U + + + + + + + 12345 + JPY + en + false + + diff --git a/tests/Mock/ExtendedFetchSubscriptionChargeFailure.txt b/tests/Mock/ExtendedFetchSubscriptionChargeFailure.txt new file mode 100644 index 0000000..9005bb5 --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionChargeFailure.txt @@ -0,0 +1,15 @@ +HTTP/1.1 403 Forbidden +Date: Thu, 20 Apr 2017 19:26:04 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 296 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + USER_NOT_AUTHORIZED + Subscription Charge retrieval service failure because subscriptionCharge ID: [SUBSCRIPTION_CHARGE_REFERENCE] was not found. + + diff --git a/tests/Mock/ExtendedFetchSubscriptionChargeSuccess.txt b/tests/Mock/ExtendedFetchSubscriptionChargeSuccess.txt new file mode 100644 index 0000000..60286d7 --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionChargeSuccess.txt @@ -0,0 +1,19 @@ +HTTP/1.1 200 OK +Date: Thu, 20 Apr 2017 19:25:52 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + + [DATE_CREATED] + [TRANSACTION_REFERENCE] + [AMOUNT] + [CURRENCY] + + diff --git a/tests/Mock/ExtendedFetchSubscriptionFailure.txt b/tests/Mock/ExtendedFetchSubscriptionFailure.txt new file mode 100644 index 0000000..250a5f1 --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionFailure.txt @@ -0,0 +1,16 @@ +HTTP/1.1 403 Forbidden +Date: Mon, 17 Apr 2017 21:55:32 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 298 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + USER_NOT_AUTHORIZED + 90009 + User API_1234567890123456789012 is not authorized to retrieve subscription ID [SUBSCRIPTION_REFERENCE]. + + diff --git a/tests/Mock/ExtendedFetchSubscriptionMultipleChargesSuccess.txt b/tests/Mock/ExtendedFetchSubscriptionMultipleChargesSuccess.txt new file mode 100644 index 0000000..5fd1e47 --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionMultipleChargesSuccess.txt @@ -0,0 +1,50 @@ +HTTP/1.1 200 OK +Date: Mon, 17 Apr 2017 21:55:18 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + [SUBSCRIPTION_REFERENCE] + A + 1234567 + [CUSTOMER_REFERENCE] + + 0000 + JCB + + + [CURRENCY] + [AMOUNT] + + ANNUALLY + [NEXT_CHARGE_DATE] + true + + SUCCESS + + + + + + 11-Nov-15 + [TRANSACTION_REFERENCE_1] + 5.00 + USD + + + + + + 11-Nov-14 + [TRANSACTION_REFERENCE_2] + 5.00 + USD + + + + diff --git a/tests/Mock/ExtendedFetchSubscriptionOverriddenChargeSuccess.txt b/tests/Mock/ExtendedFetchSubscriptionOverriddenChargeSuccess.txt new file mode 100644 index 0000000..d0d807a --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionOverriddenChargeSuccess.txt @@ -0,0 +1,38 @@ +HTTP/1.1 200 OK +Date: Wed, 26 Apr 2017 16:26:23 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=07DB2D2D2C9B5821247DA007DAF2DAC2; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +F5: /Common/Sandbox-vlan10-https 10.11.10.150%10 443 +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + [SUBSCRIPTION_REFERENCE] + A + 1234567 + [CUSTOMER_REFERENCE] + + 0000 + JCB + + + USD + 200.00 + + + [CURRENCY] + [AMOUNT] + + ANNUALLY + [NEXT_CHARGE_DATE] + true + + SUCCESS + + + https://sandbox.bluesnap.com:443/services/2/subscriptions/[SUBSCRIPTION_REFERENCE]/subscription-charges/[SUBSCRIPTION_CHARGE_REFERENCE] + + diff --git a/tests/Mock/ExtendedFetchSubscriptionSuccess.txt b/tests/Mock/ExtendedFetchSubscriptionSuccess.txt new file mode 100644 index 0000000..00c978e --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionSuccess.txt @@ -0,0 +1,41 @@ +HTTP/1.1 200 OK +Date: Mon, 17 Apr 2017 21:55:18 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + [SUBSCRIPTION_REFERENCE] + [STATUS] + [PLAN_REFERENCE] + [CUSTOMER_REFERENCE] + + [CARD_LAST_FOUR] + [CARD_BRAND] + + + [CURRENCY] + [AMOUNT] + + ANNUALLY + [NEXT_CHARGE_DATE] + true + + SUCCESS + + + + + + [DATE_CREATED] + [TRANSACTION_REFERENCE] + [CHARGE_AMOUNT] + [CHARGE_CURRENCY] + + + + diff --git a/tests/Mock/ExtendedFetchSubscriptionsFailure.txt b/tests/Mock/ExtendedFetchSubscriptionsFailure.txt new file mode 100644 index 0000000..dc0815f --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionsFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 403 Forbidden Request +Date: Thu, 27 Apr 2017 16:16:06 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 225 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVALID_INPUT + 21001 + User API_1234567890123456789012 is not authorized to retrieve subscription history for SHOPPER ID [CUSTOMER_REFERENCE]. + + diff --git a/tests/Mock/ExtendedFetchSubscriptionsSuccess.txt b/tests/Mock/ExtendedFetchSubscriptionsSuccess.txt new file mode 100644 index 0000000..0f6f4bb --- /dev/null +++ b/tests/Mock/ExtendedFetchSubscriptionsSuccess.txt @@ -0,0 +1,94 @@ +HTTP/1.1 200 OK +Date: Thu, 13 Apr 2017 18:11:22 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + [CUSTOMER_REFERENCE_1] + + + + [SUBSCRIPTION_REFERENCE_1] + [STATUS_1] + [PLAN_REFERENCE_1] + [CUSTOMER_REFERENCE_1] + + 1111 + Visa + CREDIT + CLASSIC + + + [CURRENCY_1] + [AMOUNT_1] + + MONTHLY + 30-Sep-17 + true + + SUCCESS + + + + + [SUBSCRIPTION_REFERENCE_2] + [STATUS_2] + [PLAN_REFERENCE_2] + [CUSTOMER_REFERENCE_2] + + 1111 + Visa + CREDIT + CLASSIC + + + [CURRENCY_2] + [AMOUNT_2] + + ONDEMAND + true + + SUCCESS + + + + + + 11-Nov-15 + 38442304 + 5.00 + USD + + + + + some text + + + 11-Nov-15 + 38442336 + 1.00 + USD + + + + + some text + + + 11-Nov-15 + 38442334 + 1.00 + USD + + + + + + diff --git a/tests/Mock/ExtendedFetchTransactionFailure.txt b/tests/Mock/ExtendedFetchTransactionFailure.txt new file mode 100644 index 0000000..581184b --- /dev/null +++ b/tests/Mock/ExtendedFetchTransactionFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Mon, 17 Apr 2017 21:49:11 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 269 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + ORDER_NOT_FOUND + 10000 + Order retrieval service failure. Order ID: [TRANSACTION_REFERENCE] is not found. + + diff --git a/tests/Mock/ExtendedFetchTransactionMultipleInvoicesSuccess.txt b/tests/Mock/ExtendedFetchTransactionMultipleInvoicesSuccess.txt new file mode 100644 index 0000000..0464aeb --- /dev/null +++ b/tests/Mock/ExtendedFetchTransactionMultipleInvoicesSuccess.txt @@ -0,0 +1,108 @@ +HTTP/1.1 200 OK +Date: Fri, 28 Apr 2017 19:01:26 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + 1234567 + + [CUSTOMER_REFERENCE] + + + USD + + + 1234567 + Product Name + + 1 + https://sandbox.bluesnap.com:443/services/2/subscriptions/[SUBSCRIPTION_REFERENCE] + 123.12 + + 0.00 + 0 + 123.12 + + + + + 12345678 + https://sandbox.bluesnap.com/jsp/show_invoice.jsp?ref=1234567890ABCDEF1234567890ABCDEF + + + Approved + 21-Apr-17 + 21-Apr-17 + 123.23 + USD + BLS*Merchant Name + Credit Card + PLIMUS_ACCOUNT + + 0000 + JCB + CREDIT + 2 + 2019 + + + + First + Last + test@example.org + jp + + + + 1234567 + + + + + + + [TRANSACTION_REFERENCE] + https://sandbox.bluesnap.com/jsp/show_invoice.jsp?ref=1234567890ABCDEF1234567890ABCDEF + + + Approved + 21-Apr-17 + [DATE_CREATED] + [AMOUNT] + [CURRENCY] + BLS*Merchant Name + Credit Card + PLIMUS_ACCOUNT + + 0000 + JCB + CREDIT + 2 + 2019 + + + + First + Last + test@example.org + jp + + + + 1234567 + + + + + + + + + + + diff --git a/tests/Mock/ExtendedFetchTransactionSuccess.txt b/tests/Mock/ExtendedFetchTransactionSuccess.txt new file mode 100644 index 0000000..0e3ebf7 --- /dev/null +++ b/tests/Mock/ExtendedFetchTransactionSuccess.txt @@ -0,0 +1,83 @@ +HTTP/1.1 200 OK +Date: Mon, 17 Apr 2017 21:43:33 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + 1234567 + + [CUSTOMER_REFERENCE] + + + USD + + + [PLAN_REFERENCE] + Product Name + + 1 + + [CUSTOM_1_NAME] + [CUSTOM_1_VALUE] + + + [CUSTOM_2_NAME] + [CUSTOM_2_VALUE] + + https://sandbox.bluesnap.com:443/services/2/subscriptions/[SUBSCRIPTION_REFERENCE] + 123.12 + + [TAX] + 0 + 123.12 + + + + + [TRANSACTION_REFERENCE] + https://sandbox.bluesnap.com/jsp/show_invoice.jsp?ref=1234567890ABCDEF1234567890ABCDEF + + + [STATUS] + 17-Apr-17 + [DATE_CREATED] + [AMOUNT] + [CURRENCY] + BLS*Merchant Name + Credit Card + PLIMUS_ACCOUNT + + [CARD_LAST_FOUR] + [CARD_BRAND] + CREDIT + [EXPIRY_MONTH] + [EXPIRY_YEAR] + + + + [FIRST_NAME] + [LAST_NAME] + [EMAIL] + [STATE] + [COUNTRY] + [POSTCODE] + + + + [PLAN_REFERENCE] + + + + + + + + + + + diff --git a/tests/Mock/ExtendedReactivateSubscriptionFailure.txt b/tests/Mock/ExtendedReactivateSubscriptionFailure.txt new file mode 100644 index 0000000..d077f95 --- /dev/null +++ b/tests/Mock/ExtendedReactivateSubscriptionFailure.txt @@ -0,0 +1,15 @@ +HTTP/1.1 403 Forbidden +Date: Mon, 24 Apr 2017 17:21:08 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 280 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + USER_NOT_AUTHORIZED + User API_1234567890123456789012 is not authorized to update subscription ID [SUBSCRIPTION_REFERENCE]. + + diff --git a/tests/Mock/ExtendedReactivateSubscriptionSuccess.txt b/tests/Mock/ExtendedReactivateSubscriptionSuccess.txt new file mode 100644 index 0000000..67c9ced --- /dev/null +++ b/tests/Mock/ExtendedReactivateSubscriptionSuccess.txt @@ -0,0 +1,7 @@ +HTTP/1.1 204 No Content +Date: Wed, 26 Apr 2017 15:58:04 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 0 +F5: /Common/Sandbox-vlan10-https 10.11.10.50%10 443 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains diff --git a/tests/Mock/ExtendedRefundFailure.txt b/tests/Mock/ExtendedRefundFailure.txt new file mode 100644 index 0000000..a2883fd --- /dev/null +++ b/tests/Mock/ExtendedRefundFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Mon, 01 May 2017 17:08:13 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 264 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVOICE_ALREADY_FULLY_REFUNDED + 14022 + Invoice has already been fully refunded. + + diff --git a/tests/Mock/ExtendedRefundSuccess.txt b/tests/Mock/ExtendedRefundSuccess.txt new file mode 100644 index 0000000..994b9bf --- /dev/null +++ b/tests/Mock/ExtendedRefundSuccess.txt @@ -0,0 +1,6 @@ +HTTP/1.1 204 No Content +Date: Mon, 01 May 2017 17:12:57 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 0 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains diff --git a/tests/Mock/ExtendedTestChargeSubscriptionFailure.txt b/tests/Mock/ExtendedTestChargeSubscriptionFailure.txt new file mode 100644 index 0000000..94deca1 --- /dev/null +++ b/tests/Mock/ExtendedTestChargeSubscriptionFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Fri, 28 Apr 2017 14:44:33 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 280 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + SERVER_GENERAL_FAILURE + 10000 + Call to runSpecificSubscription failed, subscriptionId [SUBSCRIPTION_REFERENCE]. + + diff --git a/tests/Mock/ExtendedTestChargeSubscriptionSuccess.txt b/tests/Mock/ExtendedTestChargeSubscriptionSuccess.txt new file mode 100644 index 0000000..b8f60c4 --- /dev/null +++ b/tests/Mock/ExtendedTestChargeSubscriptionSuccess.txt @@ -0,0 +1,6 @@ +HTTP/1.1 204 No Content +Date: Fri, 28 Apr 2017 14:44:25 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 0 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains diff --git a/tests/Mock/ExtendedUpdateSubscriptionFailure.txt b/tests/Mock/ExtendedUpdateSubscriptionFailure.txt new file mode 100644 index 0000000..7c670f4 --- /dev/null +++ b/tests/Mock/ExtendedUpdateSubscriptionFailure.txt @@ -0,0 +1,15 @@ +HTTP/1.1 403 Forbidden +Date: Fri, 21 Apr 2017 20:40:47 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 317 +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + USER_NOT_AUTHORIZED + The shopper: [CUSTOMER_REFERENCE] has not given prior consent to certain additional charges and so this operation cannot be processed. + + diff --git a/tests/Mock/ExtendedUpdateSubscriptionSuccess.txt b/tests/Mock/ExtendedUpdateSubscriptionSuccess.txt new file mode 100644 index 0000000..4705533 --- /dev/null +++ b/tests/Mock/ExtendedUpdateSubscriptionSuccess.txt @@ -0,0 +1,7 @@ +HTTP/1.1 204 No Content +Date: Wed, 26 Apr 2017 16:25:39 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 0 +F5: /Common/Sandbox-vlan10-https 10.11.10.50%10 443 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains diff --git a/tests/Mock/FetchCanceledSubscriptionsFailure.txt b/tests/Mock/FetchCanceledSubscriptionsFailure.txt new file mode 100644 index 0000000..53139be --- /dev/null +++ b/tests/Mock/FetchCanceledSubscriptionsFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Thu, 27 Apr 2017 16:16:06 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 225 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVALID_INPUT + 21001 + Invalid Date Range + + diff --git a/tests/Mock/FetchCanceledSubscriptionsSuccess.txt b/tests/Mock/FetchCanceledSubscriptionsSuccess.txt new file mode 100644 index 0000000..8d38372 --- /dev/null +++ b/tests/Mock/FetchCanceledSubscriptionsSuccess.txt @@ -0,0 +1,72 @@ +HTTP/1.1 200 OK +Date: Fri, 28 Apr 2017 13:56:17 GMT +Server: Apache +Set-Cookie: JSESSIONID=BA3B4F3C45857D1D43209F4D0E4335D4; Path=/services/; Secure; HttpOnly +page-size: 5000 +total-row-count: 1 +start-row: 1 +Content-Length: 740 +Vary: Accept-Encoding +Content-Type: application/json;charset=utf-8 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + +{ + "data": [ + { + "Original Invoice ID": "1234567890", + "Last Charge Invoice ID": "1234567890", + "Subscription ID": "[SUBSCRIPTION_REFERENCE_1]", + "First Name": "First", + "Last Name": "Last", + "Email Address": "test@example.org", + "Product Name": "Product Name", + "Contract Name": "Contract Name", + "Last Charge Price (Auth. Currency)": "[AMOUNT_1]", + "Auth. Currency": "[CURRENCY_1]", + "Last Charge Date": "04/17/2017", + "Cancel Reason": "Subscription #[SUBSCRIPTION_REFERENCE_1] has been canceled by vendor", + "PayPal Subscription ID": "", + "Original PayPal Subscription ID": "", + "Vendor ID": "", + "Vendor Name": "" + }, + { + "Original Invoice ID": "1234567890", + "Last Charge Invoice ID": "1234567890", + "Subscription ID": "[SUBSCRIPTION_REFERENCE_2]", + "First Name": "First", + "Last Name": "Last", + "Email Address": "test@example.org", + "Product Name": "Product Name", + "Contract Name": "Contract Name", + "Last Charge Price (Auth. Currency)": "[AMOUNT_2]", + "Auth. Currency": "[CURRENCY_2]", + "Last Charge Date": "04/17/2017", + "Cancel Reason": "Subscription #[SUBSCRIPTION_REFERENCE_2] has been canceled by vendor", + "PayPal Subscription ID": "", + "Original PayPal Subscription ID": "", + "Vendor ID": "", + "Vendor Name": "" + } + ], + "title": "Canceled Subscriptions", + "params": [ + { + "name": "Period", + "value": "CUSTOM" + }, + { + "name": "From date", + "value": "04/01/2017" + }, + { + "name": "To date", + "value": "05/01/2017" + }, + { + "name": "Merchant Id", + "value": "123456" + } + ], + "date_range": "04/01/2017 - 05/01/2017" +} diff --git a/tests/Mock/FetchSubscriptionsFailure.txt b/tests/Mock/FetchSubscriptionsFailure.txt new file mode 100644 index 0000000..53139be --- /dev/null +++ b/tests/Mock/FetchSubscriptionsFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Thu, 27 Apr 2017 16:16:06 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 225 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVALID_INPUT + 21001 + Invalid Date Range + + diff --git a/tests/Mock/FetchSubscriptionsSuccess.txt b/tests/Mock/FetchSubscriptionsSuccess.txt new file mode 100644 index 0000000..8bc5e46 --- /dev/null +++ b/tests/Mock/FetchSubscriptionsSuccess.txt @@ -0,0 +1,55 @@ +HTTP/1.1 200 OK +Date: Thu, 27 Apr 2017 17:54:23 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +page-size: 5000 +total-row-count: 3 +start-row: 1 +Content-Length: 1165 +Vary: Accept-Encoding +Content-Type: application/json;charset=utf-8 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + +{ + "data": [ + { + "Invoice ID": "1234567890", + "Subscription ID": "[SUBSCRIPTION_REFERENCE_1]", + "First Name": "First", + "Last Name": "Last", + "Email Address": "test@example.com", + "Product Name": "Product Name", + "Contract Name": "Contract Name", + "Price (Auth. Currency)": "[AMOUNT_1]", + "Auth. Currency": "[CURRENCY_1]", + "Last Charge Date": "04/27/2017", + "Next Charge Date": "06/01/2019", + "PayPal Subscription ID": "", + "Vendor ID": "", + "Vendor Name": "" + }, + { + "Invoice ID": "1234567899", + "Subscription ID": "[SUBSCRIPTION_REFERENCE_2]", + "First Name": "First", + "Last Name": "Last", + "Email Address": "test@example.org", + "Product Name": "Product Name", + "Contract Name": "Contract Name", + "Price (Auth. Currency)": "[AMOUNT_2]", + "Auth. Currency": "[CURRENCY_2]", + "Last Charge Date": "04/17/2017", + "Next Charge Date": "04/26/2017", + "PayPal Subscription ID": "", + "Vendor ID": "", + "Vendor Name": "" + } + ], + "title": "Active Subscriptions", + "params": [ + { + "name": "Merchant Id", + "value": "123456" + } + ] +} diff --git a/tests/Mock/FetchTransactionsFailure.txt b/tests/Mock/FetchTransactionsFailure.txt new file mode 100644 index 0000000..53139be --- /dev/null +++ b/tests/Mock/FetchTransactionsFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Thu, 27 Apr 2017 16:16:06 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 225 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVALID_INPUT + 21001 + Invalid Date Range + + diff --git a/tests/Mock/FetchTransactionsSuccess.txt b/tests/Mock/FetchTransactionsSuccess.txt new file mode 100644 index 0000000..37e32e6 --- /dev/null +++ b/tests/Mock/FetchTransactionsSuccess.txt @@ -0,0 +1,123 @@ +HTTP/1.1 200 OK +Date: Wed, 26 Apr 2017 21:12:09 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +page-size: 5000 +total-row-count: 10 +start-row: 1 +Vary: Accept-Encoding +Transfer-Encoding: chunked +Content-Type: application/json;charset=utf-8 +F5: /Common/Sandbox-vlan10-https 10.11.10.50%10 443 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + +{ + "data": [ + { + "Payment ID": "12345", + "Invoice ID": "[TRANSACTION_REFERENCE_1]", + "Original Invoice ID": "[TRANSACTION_REFERENCE_1]", + "Merchant Transaction ID": "", + "Transaction Type": "Sale", + "Transaction Date": "[DATE_1]", + "Purchase Date": "", + "Refund / Chargeback Reason": "", + "Product": "Product Name", + "Product ID": "123456", + "Contract": "Contract Name", + "Contract ID": "1234567", + "SKU Type": "Recurring contract", + "Payment Frequency": "Yearly", + "Recurring Cycle Group": "First Time", + "Recurring Cycle Number": "1", + "Payment Type": "Credit Card", + "Card Network": "Unknown", + "Qty": "1", + "Auth. Currency": "[CURRENCY_1]", + "Merchant Sales (Auth Currency)": "[AMOUNT_1]", + "Merchant Sales (USD)": "123.45", + "Shopper ID": "[CUSTOMER_REFERENCE_1]", + "Shopper First Name": "First", + "Shopper Last Name": "Last", + "Shopper Email": "test@example.com", + "Shopper Country": "Japan", + "Company Name": "", + "Vendor ID": "", + "Vendor Name": "", + "Soft Descriptor": "BLS*Company Name", + "Custom Field 1": "[CUSTOM_1_1]", + "Custom Field 2": "[CUSTOM_2_1]", + "Custom Field 3": "", + "Custom Field 4": "", + "Custom Field 5": "", + "Custom Field 6": "", + "Custom Field 7": "", + "Custom Field 8": "", + "Custom Field 9": "", + "Custom Field 10": "" + }, + { + "Payment ID": "12345", + "Invoice ID": "[TRANSACTION_REFERENCE_2]", + "Original Invoice ID": "[TRANSACTION_REFERENCE_2]", + "Merchant Transaction ID": "", + "Transaction Type": "Sale", + "Transaction Date": "[DATE_2]", + "Purchase Date": "", + "Refund / Chargeback Reason": "", + "Product": "Product Name", + "Product ID": "123456", + "Contract": "Contract Name", + "Contract ID": "1234567", + "SKU Type": "One-time contract", + "Payment Frequency": "Once", + "Recurring Cycle Group": "First Time", + "Recurring Cycle Number": "1", + "Payment Type": "Credit Card", + "Card Network": "Unknown", + "Qty": "1", + "Auth. Currency": "[CURRENCY_2]", + "Merchant Sales (Auth Currency)": "[AMOUNT_2]", + "Merchant Sales (USD)": "12.34", + "Shopper ID": "[CUSTOMER_REFERENCE_2]", + "Shopper First Name": "First", + "Shopper Last Name": "Last", + "Shopper Email": "test@example.org", + "Shopper Country": "Japan", + "Company Name": "", + "Vendor ID": "", + "Vendor Name": "", + "Soft Descriptor": "BLS*Company Name", + "Custom Field 1": "[CUSTOM_1_2]", + "Custom Field 2": "[CUSTOM_2_2]", + "Custom Field 3": "", + "Custom Field 4": "", + "Custom Field 5": "", + "Custom Field 6": "", + "Custom Field 7": "", + "Custom Field 8": "", + "Custom Field 9": "", + "Custom Field 10": "" + } + ], + "title": "Transaction Detail", + "params": [ + { + "name": "Period", + "value": "CUSTOM" + }, + { + "name": "From date", + "value": "[START_TIME]" + }, + { + "name": "To date", + "value": "[END_TIME]" + }, + { + "name": "Merchant Id", + "value": "123456" + } + ], + "date_range": "[START_TIME] - [END_TIME]" +} diff --git a/tests/Mock/HostedCheckoutDecryptReturnUrlFailure.txt b/tests/Mock/HostedCheckoutDecryptReturnUrlFailure.txt new file mode 100644 index 0000000..ab1ad53 --- /dev/null +++ b/tests/Mock/HostedCheckoutDecryptReturnUrlFailure.txt @@ -0,0 +1,16 @@ +HTTP/1.1 400 Bad Request +Date: Fri, 28 Apr 2017 18:27:27 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 374 +Connection: close +Content-Type: application/xml +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + INVALID_ENCRYPTION_TOKEN_OR_PASSWORD + Parameter Decryption service failed due to problematic input. We recommend checking the parameter-encyption token input and try again or contact merchant support. + + diff --git a/tests/Mock/HostedCheckoutDecryptReturnUrlSuccess.txt b/tests/Mock/HostedCheckoutDecryptReturnUrlSuccess.txt new file mode 100644 index 0000000..835d18d --- /dev/null +++ b/tests/Mock/HostedCheckoutDecryptReturnUrlSuccess.txt @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Date: Fri, 28 Apr 2017 18:27:10 GMT +Server: Apache +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + [PARAM_1]=[VALUE_1]&[PARAM_2]=[VALUE_2] + diff --git a/tests/Mock/HostedCheckoutPurchaseFailure.txt b/tests/Mock/HostedCheckoutPurchaseFailure.txt new file mode 100644 index 0000000..1a76471 --- /dev/null +++ b/tests/Mock/HostedCheckoutPurchaseFailure.txt @@ -0,0 +1,17 @@ +HTTP/1.1 400 Bad Request +Date: Tue, 25 Apr 2017 17:41:49 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Content-Length: 341 +Connection: close +Content-Type: application/xml +F5: /Common/Sandbox-vlan10-https 10.11.10.150%10 443 +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + + ENCRYPTION_PASSWORD_REQUIRED + Parameter Encryption service failed due to problematic input. Missing Data Protection Key: please define it in the Console and try again. + + diff --git a/tests/Mock/HostedCheckoutPurchaseSuccess.txt b/tests/Mock/HostedCheckoutPurchaseSuccess.txt new file mode 100644 index 0000000..aae3776 --- /dev/null +++ b/tests/Mock/HostedCheckoutPurchaseSuccess.txt @@ -0,0 +1,14 @@ +HTTP/1.1 200 OK +Date: Tue, 25 Apr 2017 17:19:27 GMT +Server: BlueSnap-Sandbox-UK +Set-Cookie: JSESSIONID=1234567890ABCDEF1234567890ABCDEF; Path=/services/; Secure; HttpOnly +Transfer-Encoding: chunked +Content-Type: application/xml +F5: /Common/Sandbox-vlan10-https 10.11.10.50%10 443 +Vary: Accept-Encoding +Strict-Transport-Security: max-age=31536000 ; includeSubDomains + + + + [ENCRYPTED_TOKEN] + diff --git a/tests/SubscriptionChargeTest.php b/tests/SubscriptionChargeTest.php new file mode 100644 index 0000000..443ed1a --- /dev/null +++ b/tests/SubscriptionChargeTest.php @@ -0,0 +1,129 @@ +faker = new DataFaker(); + $this->subscriptionCharge = new SubscriptionCharge(); + $this->transactionReference = $this->faker->transactionReference(); + } + + /** + * @return void + */ + public function testConstructWithParams() + { + $subscriptionCharge = new SubscriptionCharge(array( + 'transactionReference' => $this->transactionReference + )); + $this->assertSame($this->transactionReference, $subscriptionCharge->getTransactionReference()); + } + + /** + * @return void + */ + public function testInitializeWithParams() + { + $this->assertSame($this->subscriptionCharge, $this->subscriptionCharge->initialize(array( + 'transactionReference' => $this->transactionReference + ))); + $this->assertSame($this->transactionReference, $this->subscriptionCharge->getTransactionReference()); + } + + /** + * @return void + */ + public function testGetParameters() + { + $this->assertSame( + $this->subscriptionCharge, + $this->subscriptionCharge->setTransactionReference($this->transactionReference) + ); + $this->assertSame( + array('transactionReference' => $this->transactionReference), + $this->subscriptionCharge->getParameters() + ); + } + + /** + * @return void + */ + public function testTransactionReference() + { + $this->assertSame( + $this->subscriptionCharge, + $this->subscriptionCharge->setTransactionReference($this->transactionReference) + ); + $this->assertSame($this->transactionReference, $this->subscriptionCharge->getTransactionReference()); + } + + /** + * @return void + */ + public function testCurrency() + { + $currency = $this->faker->currency(); + $this->assertSame($this->subscriptionCharge, $this->subscriptionCharge->setCurrency($currency)); + $this->assertSame($currency, $this->subscriptionCharge->getCurrency()); + } + + /** + * @return void + */ + public function testAmount() + { + $amount = $this->faker->monetaryAmount($this->faker->currency()); + $this->assertSame($this->subscriptionCharge, $this->subscriptionCharge->setAmount($amount)); + $this->assertSame($amount, $this->subscriptionCharge->getAmount()); + } + + /** + * @return void + */ + public function testSubscriptionReference() + { + $subscriptionReference = $this->faker->subscriptionReference(); + $this->assertSame( + $this->subscriptionCharge, + $this->subscriptionCharge->setSubscriptionReference($subscriptionReference) + ); + $this->assertSame($subscriptionReference, $this->subscriptionCharge->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testCustomerReference() + { + $customerReference = $this->faker->customerReference(); + $this->assertSame( + $this->subscriptionCharge, + $this->subscriptionCharge->setCustomerReference($customerReference) + ); + $this->assertSame($customerReference, $this->subscriptionCharge->getCustomerReference()); + } +} diff --git a/tests/SubscriptionTest.php b/tests/SubscriptionTest.php new file mode 100644 index 0000000..1bc3f33 --- /dev/null +++ b/tests/SubscriptionTest.php @@ -0,0 +1,113 @@ +faker = new DataFaker(); + $this->subscription = new Subscription(); + $this->subscriptionReference = $this->faker->subscriptionReference(); + } + + /** + * @return void + */ + public function testConstructWithParams() + { + $subscription = new Subscription(array( + 'subscriptionReference' => $this->subscriptionReference + )); + $this->assertSame($this->subscriptionReference, $subscription->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testInitializeWithParams() + { + $this->assertSame($this->subscription, $this->subscription->initialize(array( + 'subscriptionReference' => $this->subscriptionReference + ))); + $this->assertSame($this->subscriptionReference, $this->subscription->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testGetParameters() + { + $this->assertSame( + $this->subscription, + $this->subscription->setSubscriptionReference($this->subscriptionReference) + ); + $this->assertSame( + array('subscriptionReference' => $this->subscriptionReference), + $this->subscription->getParameters() + ); + } + + /** + * @return void + */ + public function testSubscriptionReference() + { + $this->assertSame( + $this->subscription, + $this->subscription->setSubscriptionReference($this->subscriptionReference) + ); + $this->assertSame($this->subscriptionReference, $this->subscription->getSubscriptionReference()); + } + + /** + * @return void + */ + public function testCurrency() + { + $currency = $this->faker->currency(); + $this->assertSame($this->subscription, $this->subscription->setCurrency($currency)); + $this->assertSame($currency, $this->subscription->getCurrency()); + } + + /** + * @return void + */ + public function testAmount() + { + $amount = $this->faker->monetaryAmount($this->faker->currency()); + $this->assertSame($this->subscription, $this->subscription->setAmount($amount)); + $this->assertSame($amount, $this->subscription->getAmount()); + } + + /** + * @return void + */ + public function testStatus() + { + $status = $this->faker->subscriptionStatus(); + $this->assertSame($this->subscription, $this->subscription->setStatus($status)); + $this->assertSame($status, $this->subscription->getStatus()); + } +} diff --git a/tests/TransactionTest.php b/tests/TransactionTest.php new file mode 100644 index 0000000..f87a45b --- /dev/null +++ b/tests/TransactionTest.php @@ -0,0 +1,217 @@ +faker = new DataFaker(); + $this->transaction = new Transaction(); + $this->transactionReference = $this->faker->transactionReference(); + } + + /** + * @return void + */ + public function testConstructWithParams() + { + $transaction = new Transaction(array( + 'transactionReference' => $this->transactionReference + )); + $this->assertSame($this->transactionReference, $transaction->getTransactionReference()); + } + + /** + * @return void + */ + public function testInitializeWithParams() + { + $this->assertSame($this->transaction, $this->transaction->initialize(array( + 'transactionReference' => $this->transactionReference + ))); + $this->assertSame($this->transactionReference, $this->transaction->getTransactionReference()); + } + + /** + * @return void + */ + public function testGetParameters() + { + $this->assertSame($this->transaction, $this->transaction->setTransactionReference($this->transactionReference)); + $this->assertSame( + array('transactionReference' => $this->transactionReference), + $this->transaction->getParameters() + ); + } + + /** + * @return void + */ + public function testTransactionReference() + { + $this->assertSame($this->transaction, $this->transaction->setTransactionReference($this->transactionReference)); + $this->assertSame($this->transactionReference, $this->transaction->getTransactionReference()); + } + + /** + * @return void + */ + public function testCurrency() + { + $currency = $this->faker->currency(); + $this->assertSame($this->transaction, $this->transaction->setCurrency($currency)); + $this->assertSame($currency, $this->transaction->getCurrency()); + } + + /** + * @return void + */ + public function testAmount() + { + $amount = $this->faker->monetaryAmount($this->faker->currency()); + $this->assertSame($this->transaction, $this->transaction->setAmount($amount)); + $this->assertSame($amount, $this->transaction->getAmount()); + } + + /** + * @return void + */ + public function testStatus() + { + $status = $this->faker->transactionStatus(); + $this->assertSame($this->transaction, $this->transaction->setStatus($status)); + $this->assertSame($status, $this->transaction->getStatus()); + } + + /** + * @return void + */ + public function testCustomerReference() + { + $customerReference = $this->faker->customerReference(); + $this->assertSame($this->transaction, $this->transaction->setCustomerReference($customerReference)); + $this->assertSame($customerReference, $this->transaction->getCustomerReference()); + } + + /** + * @return void + */ + public function testCustomParameter1() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter1($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter1()); + } + + /** + * @return void + */ + public function testCustomParameter2() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter2($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter2()); + } + + /** + * @return void + */ + public function testCustomParameter3() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter3($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter3()); + } + + /** + * @return void + */ + public function testCustomParameter4() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter4($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter4()); + } + + /** + * @return void + */ + public function testCustomParameter5() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter5($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter5()); + } + + /** + * @return void + */ + public function testCustomParameter6() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter6($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter6()); + } + + /** + * @return void + */ + public function testCustomParameter7() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter7($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter7()); + } + + /** + * @return void + */ + public function testCustomParameter8() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter8($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter8()); + } + + /** + * @return void + */ + public function testCustomParameter9() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter9($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter9()); + } + + /** + * @return void + */ + public function testCustomParameter10() + { + $customParameter = $this->faker->customParameter(); + $this->assertSame($this->transaction, $this->transaction->setCustomParameter10($customParameter)); + $this->assertSame($customParameter, $this->transaction->getCustomParameter10()); + } +} diff --git a/tests/UrlParameterBagTest.php b/tests/UrlParameterBagTest.php new file mode 100644 index 0000000..33c8d56 --- /dev/null +++ b/tests/UrlParameterBagTest.php @@ -0,0 +1,172 @@ +bag = new UrlParameterBag(); + $this->faker = new DataFaker(); + + $parameter = $this->faker->urlParameter(); + $this->key = strval($parameter->getKey()); + $this->value = $parameter->getValue(); + } + + /** + * @return void + */ + public function testConstruct() + { + $bag = new UrlParameterBag(array(array( + 'key' => $this->key, + 'value' => $this->value + ))); + $this->assertCount(1, $bag); + } + + /** + * Make sure all construction syntaxes return the same bag. + * + * @return void + */ + public function testConstructSyntax() + { + $parameter2 = $this->faker->urlParameter(); + $key2 = $parameter2->getKey(); + $value2 = $parameter2->getValue(); + + $bagFromArrays = new UrlParameterBag(array( + array( + 'key' => $this->key, + 'value' => $this->value + ), + array( + 'key' => $key2, + 'value' => $value2 + ) + )); + $bagFromObjects = new UrlParameterBag(array( + new UrlParameter(array( + 'key' => $this->key, + 'value' => $this->value + )), + new UrlParameter(array( + 'key' => $key2, + 'value' => $value2 + )), + )); + $bagFromSimplifiedArray = new UrlParameterBag(array( + $this->key => $this->value, + $key2 => $value2 + )); + + $this->assertEquals($bagFromArrays, $bagFromObjects); + $this->assertEquals($bagFromArrays, $bagFromSimplifiedArray); + } + + /** + * @return void + */ + public function testAll() + { + $parameters = array(new UrlParameter(), new UrlParameter()); + $bag = new UrlParameterBag($parameters); + + $this->assertSame($parameters, $bag->all()); + } + + /** + * @return void + */ + public function testReplace() + { + $parameters = array(new UrlParameter(), new UrlParameter()); + $this->bag->replace($parameters); + + $this->assertSame($parameters, $this->bag->all()); + } + + /** + * @return void + */ + public function testAddWithUrlParameter() + { + $parameter = new UrlParameter(); + $parameter->setKey($this->key); + $this->bag->add($parameter); + + $contents = $this->bag->all(); + $this->assertSame($parameter, $contents[0]); + } + + /** + * @return void + */ + public function testAddWithArray() + { + $parameter = array( + 'key' => $this->key, + 'value' => $this->value + ); + $this->bag->add($parameter); + + $contents = $this->bag->all(); + $this->assertInstanceOf('\Omnipay\BlueSnap\UrlParameter', $contents[0]); + $this->assertSame($this->key, $contents[0]->getKey()); + } + + /** + * @return void + * @psalm-suppress MixedAssignment because we're testing that they're the same + */ + public function testGetIterator() + { + $parameter = new UrlParameter(); + $parameter->setKey($this->key); + $this->bag->add($parameter); + + foreach ($this->bag as $bagParameter) { + $this->assertSame($parameter, $bagParameter); + } + } + + /** + * @return void + */ + public function testCount() + { + $count = $this->faker->intBetween(1, 5); + for ($i = 0; $i < $count; $i++) { + $this->bag->add(new UrlParameter()); + } + $this->assertSame($count, count($this->bag)); + } +} diff --git a/tests/UrlParameterTest.php b/tests/UrlParameterTest.php new file mode 100644 index 0000000..cff4521 --- /dev/null +++ b/tests/UrlParameterTest.php @@ -0,0 +1,100 @@ +parameter = new UrlParameter(); + $this->faker = new DataFaker(); + + $parameter = $this->faker->urlParameter(); + $key = $parameter->getKey(); + $value = $parameter->getValue(); + // this should always be true + if ($key !== null && $value !== null) { + $this->key = $key; + $this->value = $value; + } + } + + /** + * @return void + */ + public function testConstructWithParams() + { + $parameter = new UrlParameter(array( + 'key' => $this->key, + 'value' => $this->value + )); + $this->assertSame($this->key, $parameter->getKey()); + $this->assertSame($this->value, $parameter->getValue()); + } + + /** + * @return void + */ + public function testInitializeWithParams() + { + $this->assertSame($this->parameter, $this->parameter->initialize(array( + 'key' => $this->key, + 'value' => $this->value + ))); + $this->assertSame($this->key, $this->parameter->getKey()); + $this->assertSame($this->value, $this->parameter->getValue()); + } + + /** + * @return void + */ + public function testGetParameters() + { + $this->assertSame($this->parameter, $this->parameter->setKey($this->key)->setValue($this->value)); + $this->assertSame(array('key' => $this->key, 'value' => $this->value), $this->parameter->getParameters()); + } + + /** + * @return void + */ + public function testKey() + { + $this->assertSame($this->parameter, $this->parameter->setKey($this->key)); + $this->assertSame($this->key, $this->parameter->getKey()); + } + + /** + * @return void + */ + public function testValue() + { + $this->assertSame($this->parameter, $this->parameter->setValue($this->value)); + $this->assertSame($this->value, $this->parameter->getValue()); + } +}