├── .gitignore ├── .php_cs ├── .scrutinizer.yml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── chkipper.json ├── composer.json ├── config └── web.php ├── hidev.yml ├── history.md ├── phpunit.xml.dist ├── src ├── Collection.php ├── Currencies.php ├── MerchantAsset.php ├── Module.php ├── actions │ ├── ConfirmAction.php │ └── RequestAction.php ├── assets │ └── css │ │ └── selectPayment.css ├── controllers │ └── PayController.php ├── events │ └── TransactionInsertEvent.php ├── messages │ └── ru │ │ └── merchant.php ├── models │ ├── Currency.php │ ├── DepositForm.php │ ├── DepositRequest.php │ ├── MerchantTrait.php │ └── PurchaseRequest.php ├── transactions │ ├── Transaction.php │ ├── TransactionException.php │ └── TransactionRepositoryInterface.php ├── views │ └── pay │ │ ├── deposit-form.php │ │ ├── deposit.php │ │ └── return.php └── widgets │ ├── PayButton.php │ └── views │ └── pay-button.php ├── tests ├── _bootstrap.php └── unit │ ├── FakeGateway.php │ ├── FakeMerchant.php │ ├── FakeTransactionRepository.php │ └── ModuleTest.php └── version /.gitignore: -------------------------------------------------------------------------------- 1 | # hidev internals 2 | /.hidev/composer.json 3 | /.hidev/composer.lock 4 | /.hidev/runtime 5 | /.hidev/vendor 6 | 7 | # local config 8 | /.env 9 | /hidev-local.yml 10 | 11 | # IDE & OS files 12 | .*.swp 13 | .DS_Store 14 | .buildpath 15 | .idea 16 | .project 17 | .settings 18 | Thumbs.db 19 | nbproject 20 | 21 | # composer internals 22 | /composer.lock 23 | /vendor 24 | 25 | # php-cs-fixer cache 26 | .php_cs.cache 27 | 28 | # phpunit generated files 29 | coverage.clover 30 | 31 | # Binaries 32 | chkipper.phar 33 | composer.phar 34 | ocular.phar 35 | php-cs-fixer.phar 36 | phpunit-skelgen.phar 37 | phpunit.phar 38 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setUsingCache(true) 14 | ->setRiskyAllowed(true) 15 | ->setRules(array( 16 | '@Symfony' => true, 17 | 'header_comment' => [ 18 | 'header' => $header, 19 | 'separate' => 'bottom', 20 | 'location' => 'after_declare_strict', 21 | 'commentType' => 'PHPDoc', 22 | ], 23 | 'binary_operator_spaces' => [ 24 | 'align_double_arrow' => null, 25 | 'align_equals' => null, 26 | ], 27 | 'concat_space' => ['spacing' => 'one'], 28 | 'array_syntax' => ['syntax' => 'short'], 29 | 'blank_line_before_return' => false, 30 | 'phpdoc_align' => false, 31 | 'phpdoc_scalar' => false, 32 | 'phpdoc_separation' => false, 33 | 'phpdoc_to_comment' => false, 34 | 'method_argument_space' => false, 35 | 'ereg_to_preg' => true, 36 | 'blank_line_after_opening_tag' => true, 37 | 'single_blank_line_before_namespace' => true, 38 | 'ordered_imports' => true, 39 | 'phpdoc_order' => true, 40 | 'pre_increment' => true, 41 | 'strict_comparison' => true, 42 | 'strict_param' => true, 43 | 'no_multiline_whitespace_before_semicolons' => true, 44 | )) 45 | ->setFinder( 46 | PhpCsFixer\Finder::create() 47 | ->in(__DIR__) 48 | ->notPath('vendor') 49 | ->notPath('runtime') 50 | ->notPath('web/assets') 51 | ) 52 | ; 53 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | checks: 2 | php: 3 | code_rating: true 4 | duplication: true 5 | tools: 6 | php_code_coverage: 7 | enabled: true 8 | external_code_coverage: 9 | timeout: 600 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.6 4 | - 7 5 | - 7.1 6 | - hhvm 7 | dist: trusty 8 | matrix: 9 | allow_failures: 10 | - 11 | php: hhvm 12 | cache: 13 | directories: 14 | - $HOME/.composer/cache 15 | before_install: 16 | - 'composer self-update' 17 | - 'composer --version' 18 | - 'wget http://hiqdev.com/hidev/hidev.phar -O hidev.phar && chmod a+x hidev.phar' 19 | - './hidev.phar --version' 20 | - './hidev.phar travis/before-install' 21 | sudo: false 22 | install: 23 | - './hidev.phar travis/install' 24 | script: 25 | - './hidev.phar travis/script' 26 | after_script: 27 | - './hidev.phar travis/after-script' 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # hiqdev/yii2-merchant 2 | 3 | ## [0.1.0] - 2017-09-28 4 | 5 | - Refactored transactions storage ([@hiqsol], [@SilverFire], [@tafid]) 6 | - Changed design ([@tafid]) 7 | - Added commision support ([@SilverFire]) 8 | - Fixed translations ([@hiqsol], [@SilverFire], [@tafid]) 9 | - Fixed eCoin and Paxum ([@hiqsol]) 10 | - Fixed bugs ([@hiqsol], [@SilverFire], [@tafid]) 11 | - Fixed Travis build ([@hiqsol], [@SilverFire]) 12 | - Changed: redone with `php-merchant` ([@hiqsol], [@SilverFire]) 13 | - Fixed redirection to payment systems ([@hiqsol]) 14 | - Added `renderDeposit` facility ([@hiqsol]) 15 | - Added use of Payment Icons ([@hiqsol]) 16 | - Added tests and Travis CI ([@hiqsol]) 17 | - Chnaged: redone with Omnipay ([@SilverFire], [@hiqsol]) 18 | - Added basics ([@hiqsol]) 19 | 20 | ## [Development started] - 2015-10-21 21 | 22 | [@hiqsol]: https://github.com/hiqsol 23 | [sol@hiqdev.com]: https://github.com/hiqsol 24 | [@SilverFire]: https://github.com/SilverFire 25 | [d.naumenko.a@gmail.com]: https://github.com/SilverFire 26 | [@tafid]: https://github.com/tafid 27 | [andreyklochok@gmail.com]: https://github.com/tafid 28 | [@BladeRoot]: https://github.com/BladeRoot 29 | [bladeroot@gmail.com]: https://github.com/BladeRoot 30 | [Under development]: https://github.com/hiqdev/yii2-merchant/releases 31 | [0.1.0]: https://github.com/hiqdev/yii2-merchant/releases/tag/0.1.0 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2015-2017, HiQDev (http://hiqdev.com/) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of HiQDev nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Merchant 2 | 3 | **Yii2 extension for payment processing with Omnipay, Payum and more later** 4 | 5 | [![Latest Stable Version](https://poser.pugx.org/hiqdev/yii2-merchant/v/stable)](https://packagist.org/packages/hiqdev/yii2-merchant) 6 | [![Total Downloads](https://poser.pugx.org/hiqdev/yii2-merchant/downloads)](https://packagist.org/packages/hiqdev/yii2-merchant) 7 | [![Build Status](https://img.shields.io/travis/hiqdev/yii2-merchant.svg)](https://travis-ci.org/hiqdev/yii2-merchant) 8 | [![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/hiqdev/yii2-merchant.svg)](https://scrutinizer-ci.com/g/hiqdev/yii2-merchant/) 9 | [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/hiqdev/yii2-merchant.svg)](https://scrutinizer-ci.com/g/hiqdev/yii2-merchant/) 10 | [![Dependency Status](https://www.versioneye.com/php/hiqdev:yii2-merchant/dev-master/badge.svg)](https://www.versioneye.com/php/hiqdev:yii2-merchant/dev-master) 11 | 12 | This [Yii2] extension provides payment gateways integration with use of 13 | [Omnipay] and [Payum] payment processing libraries. 14 | 15 | [Yii2]: http://yiiframework.com/ 16 | [Omnipay]: http://omnipay.thephpleague.com/ 17 | [Payum]: http://payum.org/ 18 | 19 | ## Installation 20 | 21 | The preferred way to install this yii2-extension is through [composer](http://getcomposer.org/download/). 22 | 23 | Either run 24 | 25 | ```sh 26 | php composer.phar require "hiqdev/yii2-merchant" 27 | ``` 28 | 29 | or add 30 | 31 | ```json 32 | "hiqdev/yii2-merchant": "*" 33 | ``` 34 | 35 | to the require section of your composer.json. 36 | 37 | ## License 38 | 39 | This project is released under the terms of the BSD-3-Clause [license](LICENSE). 40 | Read more [here](http://choosealicense.com/licenses/bsd-3-clause). 41 | 42 | Copyright © 2015-2017, HiQDev (http://hiqdev.com/) 43 | -------------------------------------------------------------------------------- /chkipper.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hiqdev/yii2-merchant", 3 | "authors": { 4 | "hiqsol": { 5 | "name": "Andrii Vasyliev", 6 | "role": "Project lead", 7 | "email": "sol@hiqdev.com", 8 | "github": "https://github.com/hiqsol", 9 | "homepage": "http://hipanel.com/" 10 | }, 11 | "SilverFire": { 12 | "name": "Dmitry Naumenko", 13 | "role": "Lead backend developer", 14 | "email": "d.naumenko.a@gmail.com", 15 | "github": "https://github.com/SilverFire", 16 | "homepage": "http://silverfire.me/" 17 | }, 18 | "tafid": { 19 | "name": "Andrey Klochok", 20 | "role": "Lead frontend developer", 21 | "email": "andreyklochok@gmail.com", 22 | "github": "https://github.com/tafid", 23 | "homepage": "http://hiqdev.com/" 24 | }, 25 | "BladeRoot": { 26 | "name": "Yuriy Myronchuk", 27 | "role": "QA Lead", 28 | "email": "bladeroot@gmail.com", 29 | "github": "https://github.com/BladeRoot", 30 | "homepage": "http://hiqdev.com/" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hiqdev/yii2-merchant", 3 | "type": "yii2-extension", 4 | "description": "Yii2 extension for payment processing with Omnipay, Payum and more later", 5 | "keywords": [ 6 | "yii2", 7 | "merchant", 8 | "payment", 9 | "omnipay", 10 | "payum" 11 | ], 12 | "homepage": "https://github.com/hiqdev/yii2-merchant", 13 | "license": "BSD-3-Clause", 14 | "support": { 15 | "email": "support@hiqdev.com", 16 | "source": "https://github.com/hiqdev/yii2-merchant", 17 | "issues": "https://github.com/hiqdev/yii2-merchant/issues", 18 | "wiki": "https://github.com/hiqdev/yii2-merchant/wiki", 19 | "forum": "http://forum.hiqdev.com/" 20 | }, 21 | "authors": [ 22 | { 23 | "name": "Andrii Vasyliev", 24 | "role": "Project lead", 25 | "email": "sol@hiqdev.com", 26 | "homepage": "http://hipanel.com/" 27 | }, 28 | { 29 | "name": "Dmitry Naumenko", 30 | "role": "Lead backend developer", 31 | "email": "d.naumenko.a@gmail.com", 32 | "homepage": "http://silverfire.me/" 33 | }, 34 | { 35 | "name": "Andrey Klochok", 36 | "role": "Lead frontend developer", 37 | "email": "andreyklochok@gmail.com", 38 | "homepage": "http://hiqdev.com/" 39 | }, 40 | { 41 | "name": "Yuriy Myronchuk", 42 | "role": "QA Lead", 43 | "email": "bladeroot@gmail.com", 44 | "homepage": "http://hiqdev.com/" 45 | } 46 | ], 47 | "require": { 48 | "php": "^7.4||^8.0", 49 | "hiqdev/yii2-collection": "*", 50 | "hiqdev/payment-icons": "*", 51 | "hiqdev/php-merchant": "*" 52 | }, 53 | "require-dev": { 54 | "hiqdev/hidev-php": "*", 55 | "hiqdev/hidev-hiqdev": "*", 56 | "yiisoft/yii2": "*@dev" 57 | }, 58 | "autoload": { 59 | "psr-4": { 60 | "hiqdev\\yii2\\merchant\\": "src" 61 | } 62 | }, 63 | "autoload-dev": { 64 | "psr-4": { 65 | "hiqdev\\yii2\\merchant\\tests\\": "tests" 66 | } 67 | }, 68 | "extra": { 69 | "config-plugin": { 70 | "web": "config/web.php" 71 | } 72 | }, 73 | "repositories": [ 74 | { 75 | "type": "composer", 76 | "url": "https://asset-packagist.org" 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /config/web.php: -------------------------------------------------------------------------------- 1 | [ 13 | 'themeManager' => [ 14 | 'class' => \hiqdev\thememanager\ThemeManager::class, 15 | 'pathMap' => [ 16 | dirname(__DIR__) . '/src/views' => '$themedViewPaths', 17 | ], 18 | ], 19 | 'i18n' => [ 20 | 'translations' => [ 21 | 'merchant' => [ 22 | 'class' => \yii\i18n\PhpMessageSource::class, 23 | 'sourceLanguage' => 'en-US', 24 | 'basePath' => dirname(__DIR__) . '/src/messages', 25 | ], 26 | ], 27 | ], 28 | ], 29 | ]; 30 | -------------------------------------------------------------------------------- /hidev.yml: -------------------------------------------------------------------------------- 1 | package: 2 | type: yii2-extension 3 | name: yii2-merchant 4 | title: Yii2 extension for payment processing with Omnipay, Payum and more later 5 | headline: Yii2 Merchant 6 | keywords: yii2, merchant, payment, omnipay, payum 7 | namespace: hiqdev\yii2\merchant 8 | description: | 9 | This [Yii2] extension provides payment gateways integration with use of 10 | [Omnipay] and [Payum] payment processing libraries. 11 | 12 | [Yii2]: http://yiiframework.com/ 13 | [Omnipay]: http://omnipay.thephpleague.com/ 14 | [Payum]: http://payum.org/ 15 | -------------------------------------------------------------------------------- /history.md: -------------------------------------------------------------------------------- 1 | # hiqdev/yii2-merchant 2 | 3 | ## [0.1.0] - 2017-09-28 4 | 5 | - Refactored transactions storage 6 | - [e4c0085] 2017-09-28 fixed tests [@hiqsol] 7 | - [9723af5] 2017-09-28 csfixed [@hiqsol] 8 | - [47379d4] 2017-07-31 Updated Module to use hostname instead of servername [@SilverFire] 9 | - [2ee5644] 2017-06-20 renamed `web` config <- hisite [@hiqsol] 10 | - [ee8ca60] 2017-06-20 renamed `hidev.yml` [@hiqsol] 11 | - [7e76575] 2017-03-31 Removed redundant check in Module::saveTransaction() [@SilverFire] 12 | - [80f5213] 2017-03-31 Fixed case when tansaction is not found [@SilverFire] 13 | - [60eecd6] 2017-03-31 Renamed `status` to `success` in Transaction table [@SilverFire] 14 | - [d2116fd] 2017-03-30 Refactored transactions storage [@SilverFire] 15 | - [9d55e1d] 2017-03-29 fixed getting available merchants in `pay/deposit` [@hiqsol] 16 | - [35326fe] 2017-03-28 Updated PayButton and Deposit form to follow php-merchant API changes [@SilverFire] 17 | - [99a4950] 2017-03-28 Enhanced PayController::actionRequest() to check merchant presence [@SilverFire] 18 | - [2fd82c1] 2017-03-27 redone `Module::getCollection` function to fetch collection every time again [@hiqsol] 19 | - [f443293] 2017-03-27 csfixed [@SilverFire] 20 | - [9c8aaea] 2017-03-27 Added PHPUnit 6 compatibility [@SilverFire] 21 | - [250ba1e] 2017-03-23 Removed commented code [@tafid] 22 | - [a47e48a] 2017-03-22 Added to obtain available merchants to Deposit action [@tafid] 23 | - [8e34c11] 2017-02-16 Added extra config-plugin hisite config [@tafid] 24 | - [0455e49] 2017-02-01 PayButton refactord to trigger local event instead of a global one [@SilverFire] 25 | - [2e5cbd8] 2017-02-01 Implemented button comment rendering [@SilverFire] 26 | - Changed design 27 | - [56a4365] 2017-03-31 Removed box header from deposit view [@tafid] 28 | - [6e55765] 2017-03-31 Changed deposit and deposit-form views markup [@tafid] 29 | - [efaad49] 2017-03-27 Added responsive styles to merchant select [@tafid] 30 | - [37fbf3b] 2017-03-27 Removed inline css for deposit view and placed it to ccs file, call it from PayButton widget [@tafid] 31 | - [b338802] 2017-03-27 Changed box size in deposit view [@tafid] 32 | - [7a14b5d] 2017-03-22 Changed design [@tafid] 33 | - [937be79] 2017-02-16 Added extra css to PayButton marckup [@tafid] 34 | - [820df72] 2017-02-16 Added class clearly [@tafid] 35 | - [4ed4be1] 2017-02-16 Added Theme Manager settings [@tafid] 36 | - Added commision support 37 | - [4f1c26c] 2017-01-20 Added commission support [@SilverFire] 38 | - Fixed translations 39 | - [e1a9c7e] 2017-03-27 added i18n hisite config [@hiqsol] 40 | - [c17c7e0] 2017-03-27 Updated translations, fixed presentation logic [@SilverFire] 41 | - [a20b8c2] 2017-03-22 translations [@tafid] 42 | - [c8145a4] 2017-01-13 Translations updated [@SilverFire] 43 | - Fixed eCoin and Paxum 44 | - [33e91a1] 2016-07-13 rehideved [@hiqsol] 45 | - [9dc45c6] 2016-04-18 fixed comleting history [@hiqsol] 46 | - [a0213a0] 2016-03-25 fixed History functions [@hiqsol] 47 | - [77afc6c] 2016-03-25 fixed eCoin to work, it makes no notify just return [@hiqsol] 48 | - Fixed bugs 49 | - [87b761f] 2016-08-05 changed bumping to use `chkipper` [@hiqsol] 50 | - [e4fa5f9] 2016-07-13 csfixed [@hiqsol] 51 | - [0be4d2e] 2016-07-12 csfixed [@hiqsol] 52 | - [e367e59] 2016-06-30 Removed dependency on Err class [@SilverFire] 53 | - [d16a1ec] 2016-03-25 redone history functions: - id argument [@hiqsol] 54 | - [7e9b380] 2016-03-11 Added translations [@SilverFire] 55 | - [99618c7] 2016-02-11 Minor fix. Add Box view [@tafid] 56 | - [4254b94] 2016-02-04 phpcsfixed [@hiqsol] 57 | - [c66c63c] 2016-02-03 + localizePage to build proper url to /merchant/pay/return [@hiqsol] 58 | - [bca7393] 2016-02-03 pay/deposit - added the message for a case when no payments methods available [@SilverFire] 59 | - Fixed Travis build 60 | - [10c6932] 2016-01-30 fixed tests [@hiqsol] 61 | - [f8fa4aa] 2016-01-26 rehideved [@hiqsol] 62 | - [2616a6e] 2015-12-15 php-cs-fixed [@hiqsol] 63 | - [cae2de5] 2015-12-15 PayController - back ~> returnUrl, PHPDoc updated [@SilverFire] 64 | - [f394b3a] 2015-12-15 fixed tests [@hiqsol] 65 | - [f1ecb98] 2015-12-14 fixed travis: dont build 5.4, dont allow fail 7 [@hiqsol] 66 | - [72c57a8] 2015-12-14 trying hidev.phar [@hiqsol] 67 | - Changed: redone with `php-merchant` 68 | - [d914e86] 2015-12-16 + finishUrl [@hiqsol] 69 | - [099a0a7] 2015-12-14 Action check-return implemented [@SilverFire] 70 | - [eb568af] 2015-12-14 php-cs-fixed [@hiqsol] 71 | - [e3e8e2a] 2015-12-14 Deposit - added validation rules for sum attribute [@SilverFire] 72 | - [15dc2d9] 2015-12-14 Module tidied up more [@SilverFire] 73 | - [25703a6] 2015-12-14 Module tidied up [@SilverFire] 74 | - [d66f028] 2015-12-11 + return/cancel method set to POST [@hiqsol] 75 | - [b57d0fb] 2015-12-11 renamed `transactionId` <- `internalid` [@hiqsol] 76 | - [1d0f00e] 2015-12-11 + return/cancel method set to POST [@hiqsol] 77 | - [cbba2e2] 2015-12-11 renamed `transactionId` <- `internalid` [@hiqsol] 78 | - [278543e] 2015-12-11 + internalid and history [@hiqsol] 79 | - [957f3aa] 2015-12-09 simplified merchant creating [@hiqsol] 80 | - [fce8fd4] 2015-12-08 finishing redoing to php-merchant [@hiqsol] 81 | - [ff73135] 2015-12-08 redone with php-merchant [@hiqsol] 82 | - Fixed redirection to payment systems 83 | - [a2b0337] 2015-12-04 fixed bulidUrl to pass proper merchant [@hiqsol] 84 | - [294da33] 2015-12-03 fixed tests [@hiqsol] 85 | - [2befc31] 2015-12-03 fixed tests [@hiqsol] 86 | - [bc7177c] 2015-12-03 fixed redirection to payment systems [@hiqsol] 87 | - [9379eb2] 2015-12-03 + preparing data for Omnipay merchant unification [@hiqsol] 88 | - [247c544] 2015-12-03 fixed payment icons [@hiqsol] 89 | - Added `renderDeposit` facility 90 | - [c366ba7] 2015-12-01 + `renderDeposit` facility [@hiqsol] 91 | - Added use of Payment Icons 92 | - [79c0ce8] 2015-11-30 used Payment Icons [@hiqsol] 93 | - Added tests and Travis CI 94 | - [995394c] 2015-11-30 improved tests [@hiqsol] 95 | - [4f3ceb1] 2015-11-25 added tests and Travis CI [@hiqsol] 96 | - [277f5e6] 2015-11-25 fixed Module::createMerchant to properly pass data [@hiqsol] 97 | - Chnaged: redone with Omnipay 98 | - [bf5d311] 2015-11-23 Changed namespace to yii2-collection [@SilverFire] 99 | - [b6400ea] 2015-11-12 php-cs-fixed [@hiqsol] 100 | - [ef52743] 2015-11-12 php-cs-fixed [@hiqsol] 101 | - [024f9a1] 2015-11-12 still redoing to omnipay [@hiqsol] 102 | - [b941ed3] 2015-11-09 + require yii2-collection [@hiqsol] 103 | - [1d6f98b] 2015-11-09 started redoing to omnipay [@hiqsol] 104 | - [67aa249] 2015-11-09 improved package description [@hiqsol] 105 | - Added basics 106 | - [ce5afe7] 2015-11-07 added basics [@hiqsol] 107 | - [cf31f89] 2015-10-30 php-cs-fixed [@hiqsol] 108 | - [1b82630] 2015-10-30 finished translation [@hiqsol] 109 | - [961f39d] 2015-10-30 fixed composer type to yii2-extension [@hiqsol] 110 | - [66b9ec7] 2015-10-30 fixed composer type to yii2-extension; adding translations [@hiqsol] 111 | - [124f377] 2015-10-26 adding deposit views, model and action [@hiqsol] 112 | - [234edfc] 2015-10-26 + pay button rendering with merchant [@hiqsol] 113 | - [0614bd9] 2015-10-22 improved with `_loadMerchant` [@hiqsol] 114 | - [26d44b4] 2015-10-21 php-cs-fixed [@hiqsol] 115 | - [f538d37] 2015-10-21 hideved [@hiqsol] 116 | - [dfadf30] 2015-10-21 inited [@hiqsol] 117 | 118 | ## [Development started] - 2015-10-21 119 | 120 | [@hiqsol]: https://github.com/hiqsol 121 | [sol@hiqdev.com]: https://github.com/hiqsol 122 | [@SilverFire]: https://github.com/SilverFire 123 | [d.naumenko.a@gmail.com]: https://github.com/SilverFire 124 | [@tafid]: https://github.com/tafid 125 | [andreyklochok@gmail.com]: https://github.com/tafid 126 | [@BladeRoot]: https://github.com/BladeRoot 127 | [bladeroot@gmail.com]: https://github.com/BladeRoot 128 | [a0213a0]: https://github.com/hiqdev/yii2-merchant/commit/a0213a0 129 | [77afc6c]: https://github.com/hiqdev/yii2-merchant/commit/77afc6c 130 | [d16a1ec]: https://github.com/hiqdev/yii2-merchant/commit/d16a1ec 131 | [7e9b380]: https://github.com/hiqdev/yii2-merchant/commit/7e9b380 132 | [99618c7]: https://github.com/hiqdev/yii2-merchant/commit/99618c7 133 | [4254b94]: https://github.com/hiqdev/yii2-merchant/commit/4254b94 134 | [c66c63c]: https://github.com/hiqdev/yii2-merchant/commit/c66c63c 135 | [bca7393]: https://github.com/hiqdev/yii2-merchant/commit/bca7393 136 | [10c6932]: https://github.com/hiqdev/yii2-merchant/commit/10c6932 137 | [f8fa4aa]: https://github.com/hiqdev/yii2-merchant/commit/f8fa4aa 138 | [2616a6e]: https://github.com/hiqdev/yii2-merchant/commit/2616a6e 139 | [cae2de5]: https://github.com/hiqdev/yii2-merchant/commit/cae2de5 140 | [f394b3a]: https://github.com/hiqdev/yii2-merchant/commit/f394b3a 141 | [f1ecb98]: https://github.com/hiqdev/yii2-merchant/commit/f1ecb98 142 | [72c57a8]: https://github.com/hiqdev/yii2-merchant/commit/72c57a8 143 | [d914e86]: https://github.com/hiqdev/yii2-merchant/commit/d914e86 144 | [099a0a7]: https://github.com/hiqdev/yii2-merchant/commit/099a0a7 145 | [eb568af]: https://github.com/hiqdev/yii2-merchant/commit/eb568af 146 | [e3e8e2a]: https://github.com/hiqdev/yii2-merchant/commit/e3e8e2a 147 | [15dc2d9]: https://github.com/hiqdev/yii2-merchant/commit/15dc2d9 148 | [25703a6]: https://github.com/hiqdev/yii2-merchant/commit/25703a6 149 | [d66f028]: https://github.com/hiqdev/yii2-merchant/commit/d66f028 150 | [b57d0fb]: https://github.com/hiqdev/yii2-merchant/commit/b57d0fb 151 | [1d0f00e]: https://github.com/hiqdev/yii2-merchant/commit/1d0f00e 152 | [cbba2e2]: https://github.com/hiqdev/yii2-merchant/commit/cbba2e2 153 | [278543e]: https://github.com/hiqdev/yii2-merchant/commit/278543e 154 | [957f3aa]: https://github.com/hiqdev/yii2-merchant/commit/957f3aa 155 | [fce8fd4]: https://github.com/hiqdev/yii2-merchant/commit/fce8fd4 156 | [ff73135]: https://github.com/hiqdev/yii2-merchant/commit/ff73135 157 | [a2b0337]: https://github.com/hiqdev/yii2-merchant/commit/a2b0337 158 | [294da33]: https://github.com/hiqdev/yii2-merchant/commit/294da33 159 | [2befc31]: https://github.com/hiqdev/yii2-merchant/commit/2befc31 160 | [bc7177c]: https://github.com/hiqdev/yii2-merchant/commit/bc7177c 161 | [9379eb2]: https://github.com/hiqdev/yii2-merchant/commit/9379eb2 162 | [247c544]: https://github.com/hiqdev/yii2-merchant/commit/247c544 163 | [c366ba7]: https://github.com/hiqdev/yii2-merchant/commit/c366ba7 164 | [79c0ce8]: https://github.com/hiqdev/yii2-merchant/commit/79c0ce8 165 | [995394c]: https://github.com/hiqdev/yii2-merchant/commit/995394c 166 | [4f3ceb1]: https://github.com/hiqdev/yii2-merchant/commit/4f3ceb1 167 | [277f5e6]: https://github.com/hiqdev/yii2-merchant/commit/277f5e6 168 | [bf5d311]: https://github.com/hiqdev/yii2-merchant/commit/bf5d311 169 | [b6400ea]: https://github.com/hiqdev/yii2-merchant/commit/b6400ea 170 | [ef52743]: https://github.com/hiqdev/yii2-merchant/commit/ef52743 171 | [024f9a1]: https://github.com/hiqdev/yii2-merchant/commit/024f9a1 172 | [b941ed3]: https://github.com/hiqdev/yii2-merchant/commit/b941ed3 173 | [1d6f98b]: https://github.com/hiqdev/yii2-merchant/commit/1d6f98b 174 | [67aa249]: https://github.com/hiqdev/yii2-merchant/commit/67aa249 175 | [ce5afe7]: https://github.com/hiqdev/yii2-merchant/commit/ce5afe7 176 | [cf31f89]: https://github.com/hiqdev/yii2-merchant/commit/cf31f89 177 | [1b82630]: https://github.com/hiqdev/yii2-merchant/commit/1b82630 178 | [961f39d]: https://github.com/hiqdev/yii2-merchant/commit/961f39d 179 | [66b9ec7]: https://github.com/hiqdev/yii2-merchant/commit/66b9ec7 180 | [124f377]: https://github.com/hiqdev/yii2-merchant/commit/124f377 181 | [234edfc]: https://github.com/hiqdev/yii2-merchant/commit/234edfc 182 | [0614bd9]: https://github.com/hiqdev/yii2-merchant/commit/0614bd9 183 | [26d44b4]: https://github.com/hiqdev/yii2-merchant/commit/26d44b4 184 | [f538d37]: https://github.com/hiqdev/yii2-merchant/commit/f538d37 185 | [dfadf30]: https://github.com/hiqdev/yii2-merchant/commit/dfadf30 186 | [33e91a1]: https://github.com/hiqdev/yii2-merchant/commit/33e91a1 187 | [e4fa5f9]: https://github.com/hiqdev/yii2-merchant/commit/e4fa5f9 188 | [0be4d2e]: https://github.com/hiqdev/yii2-merchant/commit/0be4d2e 189 | [e367e59]: https://github.com/hiqdev/yii2-merchant/commit/e367e59 190 | [9dc45c6]: https://github.com/hiqdev/yii2-merchant/commit/9dc45c6 191 | [87b761f]: https://github.com/hiqdev/yii2-merchant/commit/87b761f 192 | [e4c0085]: https://github.com/hiqdev/yii2-merchant/commit/e4c0085 193 | [9723af5]: https://github.com/hiqdev/yii2-merchant/commit/9723af5 194 | [47379d4]: https://github.com/hiqdev/yii2-merchant/commit/47379d4 195 | [2ee5644]: https://github.com/hiqdev/yii2-merchant/commit/2ee5644 196 | [ee8ca60]: https://github.com/hiqdev/yii2-merchant/commit/ee8ca60 197 | [56a4365]: https://github.com/hiqdev/yii2-merchant/commit/56a4365 198 | [6e55765]: https://github.com/hiqdev/yii2-merchant/commit/6e55765 199 | [7e76575]: https://github.com/hiqdev/yii2-merchant/commit/7e76575 200 | [80f5213]: https://github.com/hiqdev/yii2-merchant/commit/80f5213 201 | [60eecd6]: https://github.com/hiqdev/yii2-merchant/commit/60eecd6 202 | [d2116fd]: https://github.com/hiqdev/yii2-merchant/commit/d2116fd 203 | [9d55e1d]: https://github.com/hiqdev/yii2-merchant/commit/9d55e1d 204 | [35326fe]: https://github.com/hiqdev/yii2-merchant/commit/35326fe 205 | [99a4950]: https://github.com/hiqdev/yii2-merchant/commit/99a4950 206 | [2fd82c1]: https://github.com/hiqdev/yii2-merchant/commit/2fd82c1 207 | [e1a9c7e]: https://github.com/hiqdev/yii2-merchant/commit/e1a9c7e 208 | [c17c7e0]: https://github.com/hiqdev/yii2-merchant/commit/c17c7e0 209 | [f443293]: https://github.com/hiqdev/yii2-merchant/commit/f443293 210 | [9c8aaea]: https://github.com/hiqdev/yii2-merchant/commit/9c8aaea 211 | [efaad49]: https://github.com/hiqdev/yii2-merchant/commit/efaad49 212 | [b338802]: https://github.com/hiqdev/yii2-merchant/commit/b338802 213 | [37fbf3b]: https://github.com/hiqdev/yii2-merchant/commit/37fbf3b 214 | [250ba1e]: https://github.com/hiqdev/yii2-merchant/commit/250ba1e 215 | [a47e48a]: https://github.com/hiqdev/yii2-merchant/commit/a47e48a 216 | [7a14b5d]: https://github.com/hiqdev/yii2-merchant/commit/7a14b5d 217 | [a20b8c2]: https://github.com/hiqdev/yii2-merchant/commit/a20b8c2 218 | [937be79]: https://github.com/hiqdev/yii2-merchant/commit/937be79 219 | [820df72]: https://github.com/hiqdev/yii2-merchant/commit/820df72 220 | [8e34c11]: https://github.com/hiqdev/yii2-merchant/commit/8e34c11 221 | [4ed4be1]: https://github.com/hiqdev/yii2-merchant/commit/4ed4be1 222 | [0455e49]: https://github.com/hiqdev/yii2-merchant/commit/0455e49 223 | [2e5cbd8]: https://github.com/hiqdev/yii2-merchant/commit/2e5cbd8 224 | [4f1c26c]: https://github.com/hiqdev/yii2-merchant/commit/4f1c26c 225 | [c8145a4]: https://github.com/hiqdev/yii2-merchant/commit/c8145a4 226 | [Under development]: https://github.com/hiqdev/yii2-merchant/releases 227 | [0.1.0]: https://github.com/hiqdev/yii2-merchant/releases/tag/0.1.0 228 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/unit/ 6 | 7 | 8 | 9 | 10 | ./src/ 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Collection.php: -------------------------------------------------------------------------------- 1 | module->createMerchant($id, $config); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Currencies.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | abstract class Currencies 13 | { 14 | /** 15 | * @return Currency[] 16 | */ 17 | abstract public function getList(): array; 18 | } 19 | -------------------------------------------------------------------------------- /src/MerchantAsset.php: -------------------------------------------------------------------------------- 1 | getAssetManager()->getPublishedUrl($this->sourcePath); 20 | 21 | return $path . '/' . $asset; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Module.php: -------------------------------------------------------------------------------- 1 | [ 31 | * 'merchant' => [ 32 | * 'class' => 'hiqdev\yii2\merchant\Module', 33 | * 'notifyPage' => '/my/notify/page', 34 | * 'collection' => [ 35 | * 'PayPal' => [ 36 | * 'purse' => $params['paypal_purse'], 37 | * 'secret' => $params['paypal_secret'], /// NEVER keep secret in source control 38 | * ], 39 | * 'webmoney_usd' => [ 40 | * 'gateway' => 'WebMoney', 41 | * 'purse' => $params['webmoney_purse'], 42 | * 'secret' => $params['webmoney_secret'], /// NEVER keep secret in source control 43 | * ], 44 | * ], 45 | * ], 46 | * ], 47 | * ``` 48 | * 49 | * @var string returns username for usage in merchant 50 | */ 51 | class Module extends \yii\base\Module 52 | { 53 | /** 54 | * The URL prefix that will be used as a key to save current URL in the session. 55 | * 56 | * @see rememberUrl() 57 | * @see previousUrl() 58 | * @see \yii\helpers\BaseUrl::remember() 59 | * @see \yii\helpers\BaseUrl::previous() 60 | */ 61 | const URL_PREFIX = 'merchant_url_'; 62 | 63 | /** 64 | * @var string|class-string merchant collection class name. Defaults to [[Collection]] 65 | */ 66 | public $purchaseRequestCollectionClass = Collection::class; 67 | /** 68 | * @var string currencies collection class name. Defaults to [[Collection]] 69 | */ 70 | public $currenciesCollectionClass; 71 | /** 72 | * @var string Deposit model class name. Defaults to [[DepositForm]] 73 | */ 74 | public $depositFromClass = DepositForm::class; 75 | /** 76 | * @var bool Whether to use payment processing only through Cashew 77 | */ 78 | public bool $cashewOnly = false; 79 | /** 80 | * @var TransactionRepositoryInterface 81 | */ 82 | protected $transactionRepository; 83 | 84 | public function __construct($id, $parent = null, TransactionRepositoryInterface $transactionRepository, array $config = []) 85 | { 86 | parent::__construct($id, $parent, $config); 87 | 88 | $this->transactionRepository = $transactionRepository; 89 | } 90 | 91 | public function setCollection(array $collection) 92 | { 93 | $this->_collection = $collection; 94 | } 95 | 96 | /** 97 | * @param DepositRequest $depositRequest 98 | * @return Collection 99 | * @throws InvalidConfigException 100 | */ 101 | public function getPurchaseRequestCollection($depositRequest = null) 102 | { 103 | return Yii::createObject([ 104 | 'class' => $this->purchaseRequestCollectionClass, 105 | 'module' => $this, 106 | 'depositRequest' => $depositRequest, 107 | ]); 108 | } 109 | 110 | /** 111 | * @return Currencies 112 | * @throws InvalidConfigException 113 | */ 114 | public function getAvailableCurrenciesCollection(): Currencies 115 | { 116 | return Yii::createObject([ 117 | 'class' => $this->currenciesCollectionClass, 118 | 'module' => $this, 119 | ]); 120 | } 121 | 122 | /** 123 | * @param string $merchant_name merchant id 124 | * @param DepositRequest $depositRequest 125 | * @return PurchaseRequest merchant instance 126 | */ 127 | public function getPurchaseRequest($merchant_name, DepositRequest $depositRequest) 128 | { 129 | return $this->getPurchaseRequestCollection($depositRequest)->get($merchant_name); 130 | } 131 | 132 | /** 133 | * Checks if merchant exists in the hub. 134 | * 135 | * @param string $id merchant id 136 | * @return bool whether merchant exist 137 | */ 138 | public function hasPurchaseRequest($id) 139 | { 140 | return $this->getPurchaseRequestCollection()->has($id); 141 | } 142 | 143 | /** 144 | * Method builds data for merchant request. 145 | * 146 | * @param DepositRequest $depositRequest 147 | */ 148 | public function prepareRequestData($depositRequest): void 149 | { 150 | $depositRequest->username = $this->getUsername(); 151 | $depositRequest->notifyUrl = $this->buildUrl('notify', $depositRequest); 152 | $depositRequest->returnUrl = $this->buildUrl('return', $depositRequest); 153 | $depositRequest->cancelUrl = $this->buildUrl('cancel', $depositRequest); 154 | $depositRequest->finishUrl = $this->buildUrl('finish', $depositRequest); 155 | } 156 | 157 | /** 158 | * @var string client login 159 | */ 160 | protected $_username; 161 | 162 | /** 163 | * Sets [[_username]]. 164 | * 165 | * @param $username 166 | */ 167 | public function setUsername($username) 168 | { 169 | $this->_username = $username; 170 | } 171 | 172 | /** 173 | * Gets [[_username]] when defined, otherwise - `Yii::$app->user->identity->username`, 174 | * otherwise `Yii::$app->user->identity->getId()`. 175 | * @throws InvalidConfigException 176 | * @return string 177 | */ 178 | public function getUsername() 179 | { 180 | if (isset($this->_username)) { 181 | return $this->_username; 182 | } elseif (($identity = Yii::$app->user->identity) !== null) { 183 | if ($identity->hasProperty('username')) { 184 | $this->_username = $identity->username; 185 | } else { 186 | $this->_username = $identity->getId(); 187 | } 188 | 189 | return $this->_username; 190 | } 191 | throw new InvalidConfigException('Unable to determine username'); 192 | } 193 | 194 | /** 195 | * @var string|array the URL that will be used for payment system notifications. Will be passed through [[Url::to()]] 196 | */ 197 | public $notifyPage = 'notify'; 198 | /** 199 | * @var string|array the URL that will be used to redirect client from the merchant after the success payment. 200 | * Will be passed through [[Url::to()]] 201 | */ 202 | public $returnPage = 'return'; 203 | /** 204 | * @var string|array the URL that will be used to redirect client from the merchant after the failed payment. 205 | * Will be passed through [[Url::to()]] 206 | */ 207 | public $cancelPage = 'cancel'; 208 | /** 209 | * @var string|array the URL that might be used to redirect used from the success or error page to the finish page. 210 | * Will be passed through [[Url::to()]] 211 | */ 212 | public $finishPage = 'finish'; 213 | 214 | /** 215 | * Builds URLs that will be passed in the request to the merchant. 216 | * 217 | * @param string $destination `notify`, `return`, `cancel` 218 | * @param DepositRequest $depositRequest 219 | * @return string URL 220 | */ 221 | public function buildUrl($destination, DepositRequest $depositRequest) 222 | { 223 | $page = [ 224 | $this->getPage($destination, $depositRequest), 225 | 'username' => $depositRequest->username, 226 | 'merchant' => $depositRequest->merchant, 227 | 'transactionId' => $depositRequest->id, 228 | ]; 229 | 230 | if (is_array($page)) { 231 | $page[0] = $this->localizePage($page[0]); 232 | } else { 233 | $page = $this->localizePage($page); 234 | } 235 | 236 | return Url::to($page, true); 237 | } 238 | 239 | /** 240 | * Builds url to `this_module/pay/$page` if page is not /full/page. 241 | * @param mixed $page 242 | * @return mixed 243 | */ 244 | public function localizePage($page) 245 | { 246 | return is_string($page) && $page[0] !== '/' ? ('/' . $this->id . '/pay/' . $page) : $page; 247 | } 248 | 249 | public function getPage($destination, DepositRequest $depositRequest) 250 | { 251 | $property = $destination . 'Url'; 252 | if ($depositRequest->$property) { 253 | return $depositRequest->$property; 254 | } 255 | 256 | $name = $destination . 'Page'; 257 | 258 | return $this->hasProperty($name) ? $this->{$name} : $destination; 259 | } 260 | 261 | /** 262 | * Saves the $url to session with [[URL_PREFIX]] key, trailed with $name. 263 | * 264 | * @param array|string $url 265 | * @param string $name the trailing part for the URL save key. Defaults to `back` 266 | * @void 267 | */ 268 | public function rememberUrl($url, $name = 'back') 269 | { 270 | Url::remember($url, static::URL_PREFIX . $name); 271 | } 272 | 273 | /** 274 | * Extracts the URL from session storage, saved with [[URL_PREFIX]] key, trailed with $name. 275 | * 276 | * @param string $name the trailing part for the URL save key. Defaults to `back` 277 | * @return string 278 | */ 279 | public function previousUrl($name = 'back') 280 | { 281 | return Url::previous(static::URL_PREFIX . $name); 282 | } 283 | 284 | /** 285 | * @var PayController The Payment controller 286 | */ 287 | protected $_payController; 288 | 289 | /** 290 | * @throws InvalidConfigException 291 | * 292 | * @return PayController 293 | */ 294 | public function getPayController() 295 | { 296 | if ($this->_payController === null) { 297 | $this->_payController = $this->createControllerById('pay'); 298 | } 299 | 300 | return $this->_payController; 301 | } 302 | 303 | /** 304 | * Renders page, that contains list of payment systems, that might be choosen by user. 305 | * Should be implemented in `PayController`. 306 | * 307 | * @param DepositForm $form 308 | * @return \yii\web\Response 309 | */ 310 | public function renderDeposit($form) 311 | { 312 | return $this->getPayController()->renderDeposit($form); 313 | } 314 | 315 | /** 316 | * @param Transaction $transaction 317 | * @return Transaction 318 | */ 319 | public function saveTransaction($transaction) 320 | { 321 | return $this->transactionRepository->save($transaction); 322 | } 323 | 324 | public function insertTransaction($id, $merchant, $data) 325 | { 326 | $transaction = $this->transactionRepository->create($id, $merchant, $data); 327 | 328 | return $this->transactionRepository->insert($transaction); 329 | } 330 | 331 | /** 332 | * @param string $id transaction ID 333 | * @return Transaction|null 334 | */ 335 | public function findTransaction($id) 336 | { 337 | try { 338 | return $this->transactionRepository->findById($id); 339 | } catch (TransactionException $e) { 340 | return null; 341 | } 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /src/actions/ConfirmAction.php: -------------------------------------------------------------------------------- 1 | controller->getMerchantModule(); 25 | } 26 | 27 | public function run() 28 | { 29 | $depositRequest = $this->loadDepositRequest(); 30 | $this->registerTransaction($depositRequest); 31 | $request = $this->createPurchaseRequest($depositRequest); 32 | 33 | return $this->handlePurchaseRequest($request); 34 | } 35 | 36 | /** 37 | * @return DepositRequest 38 | * @throws BadRequestHttpException 39 | */ 40 | protected function loadDepositRequest() 41 | { 42 | $depositRequest = new DepositRequest(); 43 | $depositRequest->load(Yii::$app->request->post()); 44 | if (!$depositRequest->validate()) { 45 | $errors = $depositRequest->getFirstErrors(); 46 | throw new BadRequestHttpException('Deposit request is not loaded: ' . reset($errors)); 47 | } 48 | 49 | $this->getMerchantModule()->prepareRequestData($depositRequest); 50 | 51 | return $depositRequest; 52 | } 53 | 54 | /** 55 | * @param DepositRequest $depositRequest 56 | * @return \hiqdev\yii2\merchant\models\PurchaseRequest 57 | */ 58 | protected function createPurchaseRequest($depositRequest) 59 | { 60 | $request = $this->getMerchantModule()->getPurchaseRequest($depositRequest->merchant, $depositRequest); 61 | 62 | return $request; 63 | } 64 | 65 | /** 66 | * @param DepositRequest $depositRequest 67 | */ 68 | protected function registerTransaction($depositRequest) 69 | { 70 | $this->trigger(self::EVENT_BEFORE_TRANSACTION_INSERT, new TransactionInsertEvent(['depositRequest' => $depositRequest])); 71 | 72 | $transaction = $this->getMerchantModule()->insertTransaction($depositRequest->id, $depositRequest->merchant, array_merge([ 73 | 'username' => $depositRequest->username, 74 | 'currency' => $depositRequest->currency, 75 | ], $depositRequest->toArray())); 76 | 77 | $this->trigger(self::EVENT_AFTER_TRANSACTION_INSERT, new TransactionInsertEvent([ 78 | 'depositRequest' => $depositRequest, 79 | 'transaction' => $transaction 80 | ])); 81 | } 82 | 83 | /** 84 | * @param PurchaseRequest $response 85 | * @return \yii\web\Response 86 | * @throws BadRequestHttpException 87 | */ 88 | protected function handlePurchaseRequest($response) 89 | { 90 | if ('GET' === $response->getFormMethod()) { 91 | return $this->controller->redirect($response->getFormAction()); 92 | } elseif ('POST' === $response->getFormMethod()) { 93 | $hiddenFields = ''; 94 | foreach ($response->getFormInputs() as $key => $value) { 95 | $hiddenFields .= sprintf( 96 | '', 97 | htmlentities($key, ENT_QUOTES, 'UTF-8', false), 98 | htmlentities($value, ENT_QUOTES, 'UTF-8', false) 99 | )."\n"; 100 | } 101 | 102 | $output = ' 103 | 104 | 105 | 106 | Redirecting... 107 | 108 | 109 |
110 |

Redirecting to payment page...

111 |

112 | %2$s 113 | 114 |

115 |
116 | 117 | '; 118 | $output = sprintf( 119 | $output, 120 | htmlentities($response->getFormAction(), ENT_QUOTES, 'UTF-8', false), 121 | $hiddenFields 122 | ); 123 | 124 | return $output; 125 | } 126 | 127 | throw new BadRequestHttpException(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/assets/css/selectPayment.css: -------------------------------------------------------------------------------- 1 | .products-list { 2 | list-style: none; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | .products-list > .item { 8 | border-radius: 3px; 9 | -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); 10 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); 11 | padding: 10px 0; 12 | background: #fff; 13 | } 14 | 15 | .products-list > .item:before, 16 | .products-list > .item:after { 17 | content: ' '; 18 | display: table; 19 | } 20 | 21 | .products-list > .item:after { 22 | clear: both; 23 | } 24 | 25 | .products-list .product-img { 26 | float: left; 27 | } 28 | 29 | .products-list .product-img img { 30 | width: 50px; 31 | height: 50px; 32 | } 33 | 34 | .products-list .product-info { 35 | margin-left: 60px; 36 | } 37 | 38 | .products-list .product-title { 39 | font-weight: 600; 40 | } 41 | 42 | .products-list .product-description { 43 | display: block; 44 | color: #999; 45 | overflow: hidden; 46 | white-space: nowrap; 47 | text-overflow: ellipsis; 48 | } 49 | 50 | .product-list-in-box > .item { 51 | -webkit-box-shadow: none; 52 | box-shadow: none; 53 | border-radius: 0; 54 | border-bottom: 1px solid #f4f4f4; 55 | } 56 | 57 | .product-list-in-box > .item:last-of-type { 58 | border-bottom-width: 0; 59 | } 60 | 61 | .products-list .product-img { 62 | margin-right: 15px; 63 | } 64 | 65 | .products-list button { 66 | border: none; 67 | text-align: left; 68 | background: none; 69 | outline: none; 70 | padding: 1rem; 71 | } 72 | 73 | .products-list button:hover { 74 | background: #f7f7f7; 75 | } 76 | 77 | .products-list .product-description { 78 | overflow: visible; 79 | } 80 | 81 | @media screen and (max-device-width: 480px) and (orientation: portrait){ 82 | .product-info > div > span { 83 | display: none; 84 | } 85 | .products-list .product-description { 86 | overflow: auto; 87 | white-space: normal; 88 | text-overflow: clip; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/controllers/PayController.php: -------------------------------------------------------------------------------- 1 | [ 36 | 'class' => RequestAction::class 37 | ] 38 | ]); 39 | } 40 | 41 | /** 42 | * @return Module|\yii\base\Module 43 | */ 44 | public function getMerchantModule() 45 | { 46 | return $this->module; 47 | } 48 | 49 | /** 50 | * Disable CSRF validation for POST requests we receive from outside 51 | * {@inheritdoc} 52 | */ 53 | public function beforeAction($action) 54 | { 55 | if (in_array($this->action->id, ['notify', 'return', 'cancel', 'proxy-notification'], true)) { 56 | Yii::$app->controller->enableCsrfValidation = false; 57 | } 58 | 59 | return parent::beforeAction($action); 60 | } 61 | 62 | /** 63 | * @return Response 64 | */ 65 | public function actionCancel() 66 | { 67 | Yii::$app->session->addFlash('error', Yii::t('merchant', 'Payment failed or cancelled')); 68 | 69 | return $this->redirect($this->getMerchantModule()->previousUrl() ?: ['deposit']); 70 | } 71 | 72 | /** 73 | * @param string|null $transactionId 74 | * 75 | * Parameters are NOT required because some merchants may NOT send them, or send in POST or JSON bode. 76 | * The main purpose of these parameters is handling of special routes using UrlManager 77 | * 78 | * @return string 79 | * @throws InvalidConfigException 80 | */ 81 | public function actionReturn(string $transactionId = null) 82 | { 83 | $transaction = $this->checkNotify($transactionId); 84 | if ($transaction === null) { 85 | return $this->actionCancel(); 86 | } 87 | 88 | return $this->render('return', [ 89 | 'transactionId' => $transaction->getId(), 90 | ]); 91 | } 92 | 93 | /** 94 | * @param string $transactionId 95 | * @throws BadRequestHttpException 96 | * @return array 97 | */ 98 | public function actionCheckReturn($transactionId) 99 | { 100 | Yii::$app->response->format = Response::FORMAT_JSON; 101 | $transaction = $this->getMerchantModule()->findTransaction($transactionId); 102 | 103 | if ($transaction === null) { 104 | throw new NotFoundHttpException('Transaction does not exist'); 105 | } 106 | 107 | if ($transaction->getParameter('username') !== $this->getMerchantModule()->getUsername()) { 108 | throw new BadRequestHttpException('Access denied', 403); 109 | } 110 | 111 | return [ 112 | 'status' => $transaction->getSuccess(), 113 | 'url' => $transaction->isConfirmed() 114 | ? Url::toRoute($this->successPaymentRedirectRoute) 115 | : Url::toRoute($this->failedPaymentRedirectRoute), 116 | ]; 117 | } 118 | 119 | /** 120 | * Action handles notifications from payment systems, 121 | * processes them and report success or error for the payment system. 122 | * 123 | * @param string|null $transactionId Parameters is NOT required because some merchants may NOT send it, or send in POST or JSON body. 124 | * The main purpose of these parameters is handling of special routes using UrlManager 125 | * 126 | * @return null|string 127 | * @throws InvalidConfigException 128 | */ 129 | public function actionNotify(string $transactionId = null) 130 | { 131 | $transaction = $this->checkNotify($transactionId); 132 | if ($transaction === null) { 133 | return 'Unknown transaction'; 134 | } 135 | 136 | Yii::$app->response->format = Response::FORMAT_RAW; 137 | 138 | return $transaction->isConfirmed() ? 'OK' : $transaction->getParameter('error'); 139 | } 140 | 141 | /** 142 | * Check notifications. 143 | * TODO: implement actual request check and proper handling. 144 | * 145 | * @param string|null $transactionId Parameters is NOT required because some merchants may NOT send it, or send in POST or JSON body. 146 | * The main purpose of these parameters is handling of special routes using UrlManager 147 | * 148 | * @return Transaction|null 149 | * @throws InvalidConfigException 150 | */ 151 | public function checkNotify(string $transactionId = null): ?Transaction 152 | { 153 | throw new InvalidConfigException('Method checkNotify must be implemented'); 154 | } 155 | 156 | public function actionProxyNotification() 157 | { 158 | throw new InvalidConfigException('Method actionProxyNotification must be implemented'); 159 | } 160 | 161 | public function actionDeposit() 162 | { 163 | $user = Yii::$app->user; 164 | if (!$user->isGuest && !$user->can('deposit')) { 165 | throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.')); 166 | } 167 | 168 | $merchantModule = $this->getMerchantModule(); 169 | 170 | $model = Yii::createObject($merchantModule->depositFromClass); 171 | $request = Yii::$app->request; 172 | if ($model->load($request->isPost ? $request->post() : $request->get()) && $model->validate()) { 173 | return $this->renderDeposit($model); 174 | } 175 | 176 | return $this->render('deposit-form', [ 177 | 'model' => $model, 178 | 'availableMerchants' => $this->getMerchantModule()->getPurchaseRequestCollection()->getItems(), 179 | 'availableCurrencies' => $this->getMerchantModule()->getAvailableCurrenciesCollection()->getList(), 180 | ]); 181 | } 182 | 183 | /** 184 | * Renders depositing buttons for given request data. 185 | * 186 | * @param DepositForm $form request data 187 | * @return Response|string 188 | * @throws InvalidConfigException 189 | */ 190 | public function renderDeposit(Model $form) 191 | { 192 | if ($this->getMerchantModule()->cashewOnly) { 193 | $request = $this->createDepositRequestWithForm($form); 194 | $request->id = bin2hex(random_bytes(8)); 195 | $request->merchant = sprintf('cashew_%s', strtolower($request->currency)); 196 | $this->getMerchantModule()->prepareRequestData($request); 197 | 198 | $requests = $this->getMerchantModule()->getPurchaseRequestCollection($request)->getItems(); 199 | if (isset($requests[$request->merchant])) { 200 | return $this->redirect($requests[$request->merchant]->form->getRedirectUrl()); 201 | } 202 | } 203 | $request = $this->createDepositRequestWithForm($form); 204 | $requests = $this->getMerchantModule()->getPurchaseRequestCollection($request)->getItems(); 205 | 206 | return $this->render('deposit', [ 207 | 'requests' => $requests, 208 | 'depositForm' => $form 209 | ]); 210 | } 211 | 212 | private function createDepositRequestWithForm(Model $form): DepositRequest 213 | { 214 | $request = new DepositRequest(); 215 | $request->amount = $form->amount; 216 | $request->currency = $form->currency; 217 | $request->finishUrl = $form->finishUrl; 218 | 219 | return $request; 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/events/TransactionInsertEvent.php: -------------------------------------------------------------------------------- 1 | 'Сумма', 30 | 'Available payment methods' => 'Доступные методы оплаты', 31 | 'Enter the amount of the replenishment in {currency}. For example: 8.79' => 'Введите сумму пополнения в {currency}. Например: 8,79', 32 | 'Choose the purse currency you want to replenish and enter the payment amount.' => 'Выберите валюту счёта, который хотите пополнить, и укажите сумму платежа.', 33 | 'Important information' => 'Важная информация', 34 | 'Select payment method' => 'Выберите способ оплаты', 35 | 'We support fully automatic account depositing with the following payment systems: {merchants}' => 'Мы принимаем к оплате в автоматическом режиме следующие платежные системы: {merchants}', 36 | 'Remember to return to the site after successful payment!' => 'Не забудьте вернуться на сайт после успешной оплаты!', 37 | 'Pay {amount} with {merchantLabel}' => 'Оплатить {amount} через {merchantLabel}', 38 | 'Proceed' => 'Продолжить', 39 | 'Recharge account' => 'Пополнить счёт', 40 | 'Account recharging' => 'Пополнение счёта', 41 | 'Waiting for confirmation from the payment system...' => 'Ожидаем подтверждения из платежной системы...', 42 | 'Payment result' => 'Результат оплаты', 43 | 'There are no payments methods available' => 'Нет доступных методов оплаты', 44 | 'Amount' => 'Сумма', 45 | 'Name' => 'Название', 46 | 'Payment System' => 'Платежная система', 47 | 'Purse' => 'Кошелек', 48 | 'Fee' => 'Комиссия платежной системы', 49 | 'Currency' => 'Валюта', 50 | 'Signature' => 'Подпись', 51 | 'Commission' => 'Комиссия', 52 | 'Payment failed or cancelled' => 'Платеж прошел неуспешно или был отменён', 53 | 'including commission {commission}' => 'включая комиссию {commission}', 54 | 'including VAT {rate}% — {sum}' => 'включая НДС {rate}% — {sum}', 55 | 'via account balance' => 'с помощью перевода с баланса', 56 | 'via bank card' => 'с помощью банковской карты', 57 | 'via phone' => 'с помощью телефона', 58 | ]; 59 | -------------------------------------------------------------------------------- /src/models/Currency.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Currency extends Model 15 | { 16 | /** @var string */ 17 | public $code; 18 | 19 | /** 20 | * Returns the symbol used for a currency. 21 | * 22 | * @param string|null $locale optional 23 | * 24 | * @return string|null the currency symbol or NULL if not found 25 | * @see https://stackoverflow.com/questions/13897516/get-currency-symbol-in-php 26 | */ 27 | public function getSymbol($locale = null): string 28 | { 29 | if (null === $locale) { 30 | $locale = Yii::$app->formatter->locale; 31 | } 32 | $fmt = new NumberFormatter($locale . "@currency={$this->code}", NumberFormatter::CURRENCY); 33 | $symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL); 34 | 35 | return $symbol; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/models/DepositForm.php: -------------------------------------------------------------------------------- 1 | 9999999999999, 'whenClient' => 'function (attribute, value) { 44 | if (value.includes(",")) { 45 | var form = attribute.$form; 46 | $("#" + attribute.id).val(value.replace(/[,]/g, ".")); 47 | form.yiiActiveForm("validate"); 48 | } 49 | return true; 50 | }'], 51 | [['currency'], 'default', 'value' => 'usd'], 52 | [['amount', 'currency'], 'required'], 53 | [['amount'], 'compare', 'operator' => '>', 'compareValue' => 0], 54 | ]; 55 | } 56 | 57 | public function attributes() 58 | { 59 | return ['amount', 'currency']; 60 | } 61 | 62 | /** 63 | * {@inheritdoc} 64 | */ 65 | public function attributeLabels() 66 | { 67 | return [ 68 | 'amount' => Yii::t('merchant', 'Amount'), 69 | 'currency' => Yii::t('merchant', 'Currency'), 70 | ]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/models/DepositRequest.php: -------------------------------------------------------------------------------- 1 | Yii::t('merchant', 'Name'), 45 | 'system' => Yii::t('merchant', 'Payment System'), 46 | 'purse' => Yii::t('merchant', 'Purse'), 47 | 'amount' => Yii::t('merchant', 'Amount'), 48 | 'fee' => Yii::t('merchant', 'Fee'), 49 | 'currency' => Yii::t('merchant', 'Currency'), 50 | 'signature' => Yii::t('merchant', 'Signature'), 51 | 'commission' => Yii::t('merchant', 'Commission'), 52 | ]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/models/PurchaseRequest.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class PurchaseRequest 23 | { 24 | public $id; 25 | 26 | public $merchant_name; 27 | public $system; 28 | public $label; 29 | 30 | public $amount; 31 | public $fee; 32 | public $commission_fee; 33 | 34 | public $vat_rate; 35 | public $vat_sum; 36 | 37 | public $currency; 38 | public $disableReason; 39 | 40 | public $paymentMethod; 41 | 42 | /** @var RedirectPurchaseResponse */ 43 | public $form; 44 | 45 | public function setForm(RedirectPurchaseResponse $response) 46 | { 47 | $this->form = $response; 48 | } 49 | 50 | public function getFormInputs() 51 | { 52 | if (!isset($this->form)) { 53 | return []; 54 | } 55 | 56 | return $this->form->getRedirectData(); 57 | } 58 | 59 | public function getFormAction() 60 | { 61 | if (!isset($this->form) || empty($this->form->getRedirectUrl())) { 62 | throw new InvalidConfigException('Form action for purchase request is missing'); 63 | } 64 | 65 | return $this->form->getRedirectUrl(); 66 | } 67 | 68 | public function getFormMethod() 69 | { 70 | if (!isset($this->form)) { 71 | return 'POST'; 72 | } 73 | 74 | return $this->form->getMethod(); 75 | } 76 | 77 | public function getPaymentMethodLabel(): ?string 78 | { 79 | if ($this->system !== 'yandexmoney') { 80 | return null; 81 | } 82 | 83 | if ($this->paymentMethod === null) { 84 | return null; 85 | } 86 | 87 | if ($this->paymentMethod === 'AC') { 88 | return Yii::t('merchant', 'via bank card'); 89 | } 90 | 91 | if ($this->paymentMethod === 'PC') { 92 | return Yii::t('merchant', 'via account balance'); 93 | } 94 | 95 | return Yii::t('merchant', 'via phone'); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/transactions/Transaction.php: -------------------------------------------------------------------------------- 1 | id = $id; 35 | $this->merchant = $merchant; 36 | } 37 | 38 | public function getMerchant() 39 | { 40 | return $this->merchant; 41 | } 42 | 43 | /** 44 | * @return bool 45 | */ 46 | public function isCompleted() 47 | { 48 | return $this->success !== null; 49 | } 50 | 51 | public function complete() 52 | { 53 | $this->success = true; 54 | } 55 | 56 | public function cancel($error = null) 57 | { 58 | $this->success = false; 59 | $this->addParameter('error', $error); 60 | } 61 | 62 | public function isConfirmed() 63 | { 64 | return $this->success === true; 65 | } 66 | 67 | /** 68 | * @return bool 69 | */ 70 | public function getSuccess() 71 | { 72 | return $this->success; 73 | } 74 | 75 | /** 76 | * @return string 77 | */ 78 | public function getId() 79 | { 80 | return $this->id; 81 | } 82 | 83 | /** 84 | * @return array 85 | */ 86 | public function getParameters() 87 | { 88 | return $this->parameters; 89 | } 90 | 91 | /** 92 | * @param array $parameters 93 | */ 94 | public function setParameters($parameters) 95 | { 96 | $this->parameters = $parameters; 97 | } 98 | 99 | /** 100 | * Adds parameter $parameter with value $value to the parameters 101 | * 102 | * @param string $parameter 103 | * @param mixed $value 104 | */ 105 | public function addParameter($parameter, $value) 106 | { 107 | if (isset($this->parameters[$parameter])) { 108 | return; 109 | } 110 | 111 | $this->parameters[$parameter] = $value; 112 | } 113 | 114 | /** 115 | * @return array 116 | */ 117 | public function toArray() 118 | { 119 | return [ 120 | 'id' => $this->getId(), 121 | 'merchant' => $this->getMerchant(), 122 | 'parameters' => $this->getParameters(), 123 | 'success' => $this->getSuccess() 124 | ]; 125 | } 126 | 127 | public function getParameter($parameter) 128 | { 129 | return isset($this->parameters[$parameter]) ? $this->parameters[$parameter] : null; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/transactions/TransactionException.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('merchant', 'Account recharging'); 15 | $this->params['breadcrumbs'][] = $this->title; 16 | PaymentIconsAsset::register(Yii::$app->getView()); 17 | 18 | $merchantNames = []; 19 | foreach ($availableMerchants as $merchant) { 20 | $merchantNames[$merchant->system] = $merchant->label; 21 | } 22 | 23 | $primaryCurrency = reset($availableCurrencies); 24 | $primaryCurrencySymbol = $primaryCurrency->getSymbol(); 25 | 26 | ?> 27 | 28 |
29 |
30 |
31 |
32 | 33 | 'currency', 35 | 'value' => $model->currency ?? $primaryCurrency->code, 36 | ]) ?> 37 | getAttributeLabel('amount'), ['for' => 'deposit-amount']) ?> 38 | 39 | 1) : ?> 40 | field($model, 'amount', [ 41 | 'template' => (function () use ($availableCurrencies, $primaryCurrencySymbol) { 42 | foreach ($availableCurrencies as $currency) { 43 | $currencyDropdownOptions[] = 44 | '
  • ' . 45 | Html::a($currency->getSymbol(), 'javascript:void(0);', [ 46 | 'data-value' => $currency->code, 47 | 'data-label' => $currency->getSymbol(), 48 | ]) . 49 | '
  • '; 50 | } 51 | 52 | $currencyDropdownHtml = implode("\n", $currencyDropdownOptions ?? []); 53 | return << 55 |
    56 | 60 | 63 |
    64 | {input} 65 |
    66 | {hint}{error} 67 | HTML 68 | ; 69 | })() 70 | ]) ?> 71 |
    72 | 73 |
    74 | 75 | field($model, 'amount', [ 76 | 'template' => "
    {$primaryCurrencySymbol}{input}
    {hint}{error}", 77 | ]) ?> 78 |
    79 | $primaryCurrency->code, 81 | ]) ?> 82 |
    83 | 84 | 85 | 'btn btn-primary']) ?> 86 | end() ?> 87 |
    88 |
    89 |
    90 | 91 |
    92 |
    93 | context->module->cashewOnly === false) : ?> 94 |
    95 |
    96 |
    97 | 'box-title']) ?> 98 |
    99 |
    100 | implode(',  ', $merchantNames) 102 | ]) ?> 103 |
    104 |
    105 | $label) : ?> 106 | 107 | 108 |
    109 |
    110 |
    111 | 112 |
    113 |
    114 |

    115 |

    116 |
    117 |
    118 |
    119 |
    120 | 121 | 122 | registerJs(<< 131 | -------------------------------------------------------------------------------- /src/views/pay/deposit.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('merchant', 'Select payment method'); 16 | $this->params['breadcrumbs'][] = ['label' => Yii::t('merchant', 'Recharge account'), 'url' => ['deposit']]; 17 | $this->params['breadcrumbs'][] = $this->title; 18 | 19 | ?> 20 | 21 | 22 | 'alert alert-danger text-center', 24 | 'style' => 'width: 50rem; margin: 0 auto;', 25 | ]) ?> 26 | 27 |
    28 |
    29 |
    30 |
    31 |
      32 | 33 |
    • 34 | $request, 36 | 'depositForm' => $depositForm, 37 | ]) ?> 38 |
    • 39 | 40 |
    41 |
    42 |
    43 |
    44 |
    45 | 46 | -------------------------------------------------------------------------------- /src/views/pay/return.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('merchant', 'Payment result'); 11 | 12 | ?> 13 |

    14 | 15 | 16 |

    17 | 18 | Url::to(['@pay/check-return']), 21 | 'data' => [ 22 | 'transactionId' => $transactionId, 23 | ], 24 | ]); 25 | 26 | $this->registerJs(<< 55 | -------------------------------------------------------------------------------- /src/widgets/PayButton.php: -------------------------------------------------------------------------------- 1 | getView()); 52 | $this->registerMerchantCss(); 53 | } 54 | 55 | protected function registerMerchantCss() 56 | { 57 | $pathToCss = dirname(__DIR__) . '/assets/css/selectPayment.css'; 58 | if (is_file($pathToCss)) { 59 | Yii::$app->assetManager->publish($pathToCss); 60 | $file = Yii::$app->assetManager->getPublishedUrl($pathToCss); 61 | $this->view->registerCssFile($file); 62 | } 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function run() 69 | { 70 | return $this->renderButton(); 71 | } 72 | 73 | /** 74 | * Renders the payment button. 75 | * 76 | * @return string 77 | */ 78 | public function renderButton() 79 | { 80 | return $this->render('pay-button', [ 81 | 'widget' => $this, 82 | 'request' => $this->request, 83 | 'depositRequest' => new DepositRequest([ 84 | 'id' => $this->request->id, 85 | 'amount' => $this->depositForm->amount, 86 | 'currency' => $this->depositForm->currency, 87 | 'merchant' => $this->getMerchantName(), 88 | 'finishUrl' => $this->depositForm->finishUrl, 89 | ]) 90 | ]); 91 | } 92 | 93 | /** 94 | * Extracts merchant name from the [[request]]. 95 | * @return string 96 | */ 97 | public function getMerchantName() 98 | { 99 | return $this->request->merchant_name; 100 | } 101 | 102 | /** 103 | * Extracts merchant system from the [[request]]. 104 | * @return string 105 | */ 106 | public function getMerchantSystem() 107 | { 108 | return $this->request->system; 109 | } 110 | 111 | public function getTotalCommission() 112 | { 113 | return $this->request->fee + $this->request->commission_fee; 114 | } 115 | 116 | public function includesVat(): bool 117 | { 118 | return $this->request->vat_rate !== null; 119 | } 120 | 121 | public function getVatRate(): float 122 | { 123 | return $this->request->vat_rate; 124 | } 125 | 126 | public function getVatSum(): float 127 | { 128 | return $this->request->vat_sum; 129 | } 130 | 131 | public function getButtonData() 132 | { 133 | return Json::encode($this->request->getFormInputs()); 134 | } 135 | 136 | /** 137 | * Renders the button comment. Normally triggers [[EVENT_RENDER_COMMENT]] event. 138 | */ 139 | public function renderButtonComment() 140 | { 141 | $this->trigger(self::EVENT_RENDER_COMMENT); 142 | } 143 | 144 | public function formatMoney($sum) 145 | { 146 | $currency = $this->request->currency; 147 | $formatter = new NumberFormatter(Yii::$app->language, NumberFormatter::CURRENCY); 148 | 149 | switch ($currency) { 150 | case 'BTC': 151 | $formatter->setAttribute(NumberFormatter::MAX_SIGNIFICANT_DIGITS, 6); 152 | break; 153 | case 'RUB': 154 | $formatter->setSymbol(NumberFormatter::CURRENCY_SYMBOL, '₽'); 155 | break; 156 | } 157 | 158 | return $formatter->formatCurrency($sum, $currency); 159 | } 160 | 161 | public function isDisabled() 162 | { 163 | return $this->request->disableReason !== null; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/widgets/views/pay-button.php: -------------------------------------------------------------------------------- 1 | 14 | $widget->action]) ?> 15 | 16 | 17 | 18 | 19 | finishUrl) : ?> 20 | 21 | 22 | 23 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | _worker === null) { 29 | $this->_worker = Yii::createObject([ 30 | 'class' => FakeGateway::class, 31 | 'gateway' => $this->gateway, 32 | 'data' => $this->data, 33 | ]); 34 | } 35 | 36 | return $this->_worker; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/unit/FakeTransactionRepository.php: -------------------------------------------------------------------------------- 1 | [ 31 | 'purse' => 'asd', 32 | 'secret' => '123', 33 | ], 34 | 'wmusd' => [ 35 | 'gateway' => 'WebMoney', 36 | 'purse' => 'Z0000000', 37 | 'secret' => '123', 38 | ], 39 | 'fake' => [ 40 | 'class' => 'hiqdev\yii2\merchant\tests\unit\FakeMerchant', 41 | 'purse' => 'SDF', 42 | 'secret' => '000', 43 | ], 44 | ]; 45 | 46 | protected function setUp() 47 | { 48 | $application = new Application([ 49 | 'id' => 'fake', 50 | 'basePath' => dirname(dirname(__DIR__)), 51 | 'modules' => [ 52 | 'merchant' => [ 53 | 'class' => Module::class, 54 | 'username' => 'fake', 55 | 'notifyPage' => '/my/notify/page', 56 | 'returnPage' => '/merchant/pay/return', 57 | 'cancelPage' => '/merchant/pay/cancel', 58 | 'collection' => $this->gateways, 59 | ], 60 | ], 61 | 'container' => [ 62 | 'singletons' => [ 63 | \hiqdev\yii2\merchant\transactions\TransactionRepositoryInterface::class => \hiqdev\yii2\merchant\tests\unit\FakeTransactionRepository::class, 64 | ], 65 | ], 66 | ]); 67 | $this->module = Yii::$app->getModule('merchant'); 68 | } 69 | 70 | protected function tearDown() 71 | { 72 | } 73 | 74 | public function testGetCollection() 75 | { 76 | $this->assertInstanceOf(Collection::class, $this->module->collection); 77 | } 78 | 79 | public function testGetMerchant() 80 | { 81 | $this->assertInstanceOf(FakeMerchant::class, $this->module->collection->fake); 82 | $this->assertInstanceOf(OmnipayMerchant::class, $this->module->collection->wmusd); 83 | $this->assertSame($this->gateways['wmusd']['purse'], $this->module->collection->wmusd->data['purse']); 84 | $this->assertSame($this->gateways['fake']['secret'], $this->module->collection->fake->data['secret']); 85 | } 86 | 87 | public function testGetWorker() 88 | { 89 | $this->assertInstanceOf(FakeGateway::class, $this->module->collection->fake->getWorker()); 90 | $this->assertInstanceOf('Omnipay\Stripe\Gateway', $this->module->collection->Stripe->getWorker()); 91 | $this->assertInstanceOf('Omnipay\WebMoney\Gateway', $this->module->collection->wmusd->getWorker()); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | yii2-merchant 0.1.0 2017-09-28 16:52:32 +0200 e4c0085e667c292263694a3854e41c6f5b5d179c 2 | --------------------------------------------------------------------------------