├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── CREDITS ├── LICENSE.md ├── README.md ├── composer.json ├── composer.lock ├── examples ├── .bog.example ├── .cartu.example └── .tbcpay.example ├── phpcs.xml ├── phpunit.xml.dist ├── src ├── Contracts │ ├── Logger.php │ └── Options.php ├── Logger.php ├── Options.php ├── Payment.php └── Provider │ ├── AbstractProvider.php │ ├── AbstractXMLResponse.php │ ├── Card │ ├── Bog │ │ ├── Provider.php │ │ └── XMLResponse.php │ └── Cartu │ │ ├── Provider.php │ │ └── XMLResponse.php │ └── Pay │ └── Tbcpay │ ├── Provider.php │ └── XMLResponse.php └── tests ├── Bootstrap.php └── Unit ├── LoggerTest.php ├── OptionsTest.php ├── PaymentTest.php └── TestCase.php /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE & System Related Files # 2 | .buildpath 3 | .project 4 | .settings 5 | .DS_Store 6 | .idea 7 | .phpintel 8 | composer.phar 9 | 10 | # Local System Files (i.e. cache, logs, etc.) # 11 | /cache 12 | /build/logs 13 | /build/coverage 14 | /tmp 15 | 16 | # Test Related Files # 17 | /phpunit.xml 18 | 19 | # Composer 20 | vendor/ 21 | 22 | .fuse_hidden* 23 | 24 | # phpDocumentor Logs # 25 | phpdoc-* 26 | 27 | # OSX # 28 | ._* 29 | .Spotlight-V100 30 | .Trashes 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - 7.0 9 | - 7.1 10 | - hhvm 11 | 12 | sudo: false 13 | 14 | before_install: 15 | - composer self-update 16 | 17 | install: 18 | - travis_retry composer update --no-interaction --prefer-source 19 | 20 | script: 21 | - ./vendor/bin/phpcs --standard=phpcs.xml -snp --encoding=utf-8 src/ --report-width=150 22 | - ./vendor/bin/phpunit 23 | 24 | matrix: 25 | allow_failures: 26 | - php: 5.3 27 | - php: 5.4 28 | fast_finish: true 29 | 30 | 31 | notifications: 32 | on_success: never 33 | on_failure: always -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ------------- 3 | 4 | Before you contribute code to this project, please make sure it conforms to the PSR-2 coding standard 5 | and that the project unit tests still pass. The easiest way to contribute is to work on a checkout of the repository, 6 | or your own fork. If you do this, you can run the following commands to check if everything is ready to submit: 7 | 8 | cd php-geopayment 9 | composer update 10 | ./vendor/bin/phpcs --standard=phpcs.xml -sp --encoding=utf-8 src/ --report-width=150 11 | 12 | Which should give you no errors, indicating that there are no coding standard errors. And then: 13 | 14 | ./vendor/bin/phpunit 15 | 16 | Which should give you no failures or errors. You can ignore any skipped tests as these are for external tools. 17 | 18 | Pushing 19 | ------- 20 | 21 | Development is based on the git flow branching model (see http://nvie.com/posts/a-successful-git-branching-model/ ) 22 | If you fix a bug please push in hotfix branch. 23 | If you develop a new feature please create a new branch. 24 | 25 | Version 26 | ------- 27 | Version number: 0.#version.#hotfix 28 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | This is at least a partial credits-file of people that have 2 | contributed to the current project. It is sorted by name and 3 | formatted to allow easy grepping and beautification by 4 | scripts. The fields are: name (N), email (E), web-address 5 | (W) and description (D). 6 | Thanks, 7 | 8 | Avtandil Kikabidze 9 | ---------- 10 | 11 | N: Avtandil Kikabidze aka LONGMAN 12 | E: akalongman@gmail.com 13 | W: http://longman.me 14 | D: Project owner, Maintainer 15 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The [MIT License](http://opensource.org/licenses/mit-license.php) 2 | 3 | Copyright (c) 2015 [Avtandil Kikabidze aka LONGMAN](https://github.com/akalongman) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GeoPayment 2 | 3 | [![Build Status](https://travis-ci.org/akalongman/php-geopayment.svg?branch=master)](https://travis-ci.org/akalongman/php-geopayment) 4 | [![Latest Stable Version](https://img.shields.io/packagist/v/Longman/geopayment.svg)](https://packagist.org/packages/longman/geopayment) 5 | [![Total Downloads](https://img.shields.io/packagist/dt/Longman/geopayment.svg)](https://packagist.org/packages/longman/geopayment) 6 | [![Downloads Month](https://img.shields.io/packagist/dm/Longman/geopayment.svg)](https://packagist.org/packages/longman/geopayment) 7 | [![License](https://img.shields.io/packagist/l/Longman/geopayment.svg)](LICENSE.md) 8 | 9 | Georgian bank/terminal payment integration library 10 | 11 | ## Table of Contents 12 | - [Installation](#installation) 13 | - [Composer](#composer) 14 | - [Usage](#usage) 15 | - [Card Payments](#card-payments) (Visa/MasterCard/AmEX) 16 | - [BOG](#bog) (Bank of Georgia) 17 | - [Step 1: Redirecting on payment page](#bog-step-1-redirecting-on-payment-page) 18 | - [Step 2: Bank checks payment availability](#bog-step-2-bank-checks-payment-availability) 19 | - [Step 3: Bank registers payment](#bog-step-3-bank-registers-payment) 20 | - [Cartu](#cartu) (Cartu Bank) 21 | - [Step 1: Redirecting on payment page](#cartu-step-1-redirecting-on-payment-page) 22 | - [Step 2: Bank registers payment](#cartu-step-2-bank-registers-payment) 23 | - [Terminal Payments](#terminal-payments) 24 | - [TBC Pay](#tbc-pay) 25 | - [Step 1: Check payment](#tbc-pay-step-1-check-payment) 26 | - [Step 2: Register Payment](#tbc-pay-step-2-register-payment) 27 | - [Recommended Response codes](#tbc-pay-recommended-response-codes) 28 | - [Liberty Pay](#liberty-pay) 29 | - [Step 1: Check payment](#liberty-pay-step-1-check-payment) 30 | - [Step 2: Register Payment](#liberty-liberty-step-2-register-payment) 31 | - [Recommended Response codes](#liberty-pay-recommended-response-codes) 32 | 33 | - [TODO](#todo) 34 | - [Troubleshooting](#troubleshooting) 35 | - [Contributing](#contributing) 36 | - [License](#license) 37 | - [Credits](#credits) 38 | 39 | 40 | ## Installation 41 | 42 | ### Composer 43 | 44 | Install this package through [Composer](https://getcomposer.org/). 45 | 46 | Edit your project's `composer.json` file to require `longman/geopayment` 47 | 48 | Create *composer.json* file: 49 | ```js 50 | { 51 | "name": "yourproject/yourproject", 52 | "type": "project", 53 | "require": { 54 | "longman/geopayment": "*" 55 | } 56 | } 57 | ``` 58 | And run composer update 59 | 60 | **Or** run a command in your command line: 61 | 62 | ``` 63 | composer require longman/geopayment 64 | ``` 65 | 66 | *** 67 | 68 | [(Back to top)](#table-of-contents) 69 | 70 | 71 | ## Usage 72 | 73 | ```php 74 | 'value1', 82 | 'option2' => 'value2', 83 | 'option3' => 'value3', 84 | . . . 85 | ]; 86 | 87 | // or create .configfile file and specify file path in options 88 | $options = [ 89 | 'config_path' => '/path/to/folder/.configfile', 90 | ]; 91 | 92 | // Create payment instance 93 | $payment = new Payment('{provider}', '{type}', $options); 94 | 95 | // do more job depending on bank documentation 96 | 97 | ``` 98 | 99 | **Important:** If your .config file is under server document_root, you must deny access to that file via http. 100 | 101 | Apache 102 | 103 | Add in your .htaccess file: 104 | ``` 105 | 106 | Order allow,deny 107 | Deny from all 108 | Satisfy all 109 | 110 | ``` 111 | 112 | Nginx 113 | 114 | In server section: 115 | ``` 116 | location ~ /\. { 117 | deny all; 118 | access_log off; 119 | log_not_found off; 120 | } 121 | ``` 122 | 123 | ### Card Payments 124 | 125 | #### Bog 126 | 127 | BOG config example you can find here [.bog.example](examples/.bog.example) 128 | 129 | ##### Bog Step 1: Redirecting on payment page 130 | 131 | ```php 132 | '/path/to/config/.bog', 139 | ]; 140 | 141 | // Create payment instance 142 | $payment = new Payment('bog', Payment::TYPE_CARD, $options); 143 | 144 | // Set mode 'redirect' 145 | $payment->setMode('redirect'); 146 | 147 | // Set success url 148 | $payment->setSuccessUrl('your_success_url'); 149 | 150 | // Set fail url 151 | $payment->setFailUrl('your_fail_url'); 152 | 153 | // Set order id or any payment identificator in your db 154 | $payment->addParam('order_id', 'your_order_id'); 155 | 156 | // You can add more params if needed 157 | $payment->addParam('param1', 'value1'); 158 | $payment->addParam('param2', 'value2'); 159 | 160 | // And simple redirect 161 | $payment->redirect(); 162 | 163 | // Or get payment initialization url if needed and after redirect 164 | $url = $payment->getPaymentUrl(); 165 | . . . 166 | $payment->redirect($url); 167 | ``` 168 | 169 | ##### Bog Step 2: Bank checks payment availability 170 | 171 | ```php 172 | '/path/to/config/.bog', 179 | ]; 180 | 181 | $payment = new Payment('bog', Payment::TYPE_CARD, $options); 182 | 183 | // Set mode 'check' 184 | $payment->setMode('check'); 185 | 186 | // Check IP (if needed) 187 | $payment->checkIpAllowed(); 188 | 189 | // Check HTTP authorization 190 | $payment->checkHttpAuth(); 191 | 192 | // Check signature validation (depends on documentation) 193 | $payment->checkSignature(); 194 | 195 | // Here you must check order_id or any other parameters which before redirecting set via $payment->addParam 196 | $order_id = $payment->getParam('o.order_id'); 197 | if (!$order_id) { 198 | $payment->sendErrorResponse('order_id is empty!'); 199 | } 200 | 201 | // check if order exists 202 | $order = get_order_from_yout_db($order_id); 203 | if (empty($order)) { 204 | $payment->sendErrorResponse('order with id "'.$order_id.'" not found!'); 205 | } 206 | 207 | // check if order already completed 208 | if ($order->isCompleted()) { 209 | $payment->sendErrorResponse('Purchase for order "'.$order_id.'" already completed!'); 210 | } 211 | . . . 212 | 213 | // Build parameters for response 214 | $params = []; 215 | $params['amount'] = 'Order price (In minor units)'; 216 | $params['short_desc'] = 'Payment short description'; 217 | $params['long_desc'] = 'Payment long description'; 218 | 219 | $payment->sendSuccessResponse($params); 220 | 221 | ``` 222 | 223 | 224 | ##### Bog Step 3: Bank registers payment 225 | 226 | ```php 227 | '/path/to/config/.bog', 234 | ]; 235 | 236 | $payment = new Payment('bog', Payment::TYPE_CARD, $options); 237 | 238 | // Set mode 'reg' 239 | $payment->setMode('reg'); 240 | 241 | // Check IP (if needed) 242 | $payment->checkIpAllowed(); 243 | 244 | // Check HTTP authorization 245 | $payment->checkHttpAuth(); 246 | 247 | // Check signature validation (depends on documentation) 248 | $payment->checkSignature(); 249 | 250 | // Here you must check order_id or any other parameters which before redirecting set via $payment->addParam 251 | $order_id = $payment->getParam('o.order_id'); 252 | if (!$order_id) { 253 | $payment->sendErrorResponse('order_id is empty!'); 254 | } 255 | 256 | // check if order exists 257 | $order = get_order_from_yout_db($order_id); 258 | if (empty($order)) { 259 | $payment->sendErrorResponse('order with id "'.$order_id.'" not found!'); 260 | } 261 | 262 | // check if order already completed 263 | if ($order->isCompleted()) { 264 | $payment->sendErrorResponse('Purchase for order "'.$order_id.'" already completed!'); 265 | } 266 | 267 | // Get and check payment result code 268 | $result_code = $payment->getParam('result_code'); 269 | if (empty($result_code)) { 270 | $payment->sendErrorResponse('result_code is empty!'); 271 | } 272 | 273 | // Register payment with result code (1 - success, 2 - failed) 274 | . . . 275 | 276 | // Send response 277 | $payment->sendSuccessResponse(); 278 | 279 | ``` 280 | 281 | *** 282 | 283 | [(Back to top)](#table-of-contents) 284 | 285 | 286 | 287 | #### Cartu 288 | 289 | Cartu config example you can find here [.cartu.example](examples/.cartu.example) 290 | 291 | ##### Cartu Step 1: Redirecting on payment page 292 | 293 | ```php 294 | '/path/to/config/.cartu', 301 | ]; 302 | 303 | // Create payment instance 304 | $payment = new Payment('cartu', Payment::TYPE_CARD, $options); 305 | 306 | // Set mode 'redirect' 307 | $payment->setMode('redirect'); 308 | 309 | // generate order id 310 | $order_id = '1111111'; 311 | 312 | // prepare parameters for redirect 313 | $purchase_desc = $order_id.'!!!'; 314 | $purchase_amt = '20.25'; 315 | 316 | $payment->addParam('PurchaseDesc', $purchase_desc); 317 | $payment->addParam('PurchaseAmt', $purchase_amt); 318 | 319 | // And simple redirect 320 | $payment->redirect(); 321 | 322 | // Or get payment initialization url if needed and after redirect 323 | $url = $payment->getPaymentUrl(); 324 | . . . 325 | $payment->redirect($url); 326 | ``` 327 | 328 | ##### Cartu Step 2: Bank registers payment 329 | 330 | ```php 331 | '/path/to/config/.cartu', 338 | ]; 339 | 340 | $payment = new Payment('cartu', Payment::TYPE_CARD, $options); 341 | 342 | $payment->setMode('response'); 343 | 344 | // Check IP (if needed) 345 | $payment->checkIpAllowed(); 346 | 347 | // get bank parameters 348 | $TransactionId = $payment->getTransactionId(); 349 | $PaymentId = $payment->getPaymentId(); 350 | $PaymentDate = $payment->getPaymentDate(); 351 | $Amount = $payment->getAmount(); 352 | $CardType = $payment->getCardType(); 353 | $Reason = $payment->getReason(); 354 | $Status = $payment->getStatus(); 355 | 356 | switch($Status) { 357 | case 'C': // check 358 | // check order availability by TransactionId 359 | 360 | $payment->sendSuccessResponse($params); 361 | break; 362 | 363 | case 'Y': // success 364 | // update order status by TransactionId 365 | 366 | $payment->sendSuccessResponse($params); 367 | break; 368 | 369 | case 'N': // failed 370 | // set order status to failed 371 | 372 | $payment->sendErrorResponse('Transaction failed'); 373 | break; 374 | 375 | case 'U': // unfinished 376 | 377 | $payment->sendErrorResponse('Unfinished request'); 378 | 379 | break; 380 | 381 | default: 382 | // throw error 383 | $payment->sendErrorResponse('Status unspecified'); 384 | 385 | break; 386 | } 387 | 388 | 389 | ``` 390 | 391 | *** 392 | 393 | [(Back to top)](#table-of-contents) 394 | 395 | 396 | 397 | ### Terminal Payments 398 | 399 | 400 | #### TBC Pay 401 | 402 | TBC Pay config example you can find here [.tbcpay.example](examples/.tbcpay.example) 403 | 404 | ##### TBC Pay Step 1: Check payment 405 | 406 | ```php 407 | '/path/to/config/.tbcpay', 414 | ]; 415 | 416 | // Create payment instance 417 | $payment = new Payment('tbcpay', Payment::TYPE_PAY, $options); 418 | 419 | // Set mode 'check' 420 | $payment->setMode('check'); 421 | 422 | // Check IP (if needed) 423 | $payment->checkIpAllowed(); 424 | 425 | // Check HTTP authorization 426 | $payment->checkHttpAuth(); 427 | 428 | // Get account identifier from request 429 | $account = $payment->getParam('account'); 430 | if (empty($account)) { 431 | // Pass response code and message 432 | $payment->sendErrorResponse(4, 'Invalid Account Number Format'); 433 | } 434 | 435 | // Check account id in db and show error if needed 436 | . . . 437 | 438 | // Generate some extra data for response. You can add more parameters if needed 439 | $extra = []; 440 | $extra['customer'] = 'John Doe'; 441 | $extra['debt'] = '500.00'; 442 | 443 | $payment->sendSuccessResponse($extra); 444 | 445 | ``` 446 | 447 | ##### TBC Pay Step 2: Register Payment 448 | 449 | ```php 450 | '/path/to/config/.tbcpay', 457 | ]; 458 | 459 | // Create payment instance 460 | $payment = new Payment('tbcpay', Payment::TYPE_PAY, $options); 461 | 462 | // Set mode 'reg' 463 | $payment->setMode('reg'); 464 | 465 | // Check IP (if needed) 466 | $payment->checkIpAllowed(); 467 | 468 | // Check HTTP authorization 469 | $payment->checkHttpAuth(); 470 | 471 | // Get account identifier from request 472 | $account = $payment->getParam('account'); 473 | if (empty($account)) { 474 | $payment->sendErrorResponse(4, 'Invalid Account Number Format'); 475 | } 476 | 477 | // Check account id in db and show error if needed 478 | . . . 479 | 480 | // Get transaction id 481 | $txn_id = $payment->getParam('txn_id'); 482 | if (empty($txn_id)) { 483 | $payment->sendErrorResponse(300, 'txn_id is not defined'); 484 | } 485 | 486 | // Check transaction id in db and show error if needed 487 | . . . 488 | 489 | // Get payd amount 490 | $sum = $payment->getParam('sum'); 491 | if (empty($sum)) { 492 | $payment->sendErrorResponse(300, 'sum is not defined'); 493 | } 494 | 495 | $payment->sendSuccessResponse(); 496 | 497 | 498 | ``` 499 | 500 | ##### TBC Pay: Recommended Response codes 501 | 502 | | Code | Message | 503 | |:----:|:-------:| 504 | | 0 | Success | 505 | | 1 | Server timeout | 506 | | 4 | Invalid account format | 507 | | 5 | Account not found | 508 | | 7 | Payment is restricted | 509 | | 215 | Duplicate transaction | 510 | | 275 | Invalid amount | 511 | | 300 | Internal server error | 512 | 513 | 514 | *** 515 | 516 | [(Back to top)](#table-of-contents) 517 | 518 | 519 | #### Liberty Pay 520 | 521 | ##### Liberty Pay Step 1: Check payment 522 | 523 | TBD 524 | 525 | ##### Liberty Pay Step 2: Register Payment 526 | 527 | TBD 528 | 529 | ##### Liberty Pay: Recommended Response codes 530 | 531 | | Code | Message | 532 | |:----:|:-------:| 533 | | 0 | Success | 534 | | 1 | Server timeout | 535 | | 4 | Invalid account format | 536 | | 5 | Account not found | 537 | | 7 | Payment is restricted | 538 | | 215 | Duplicate transaction | 539 | | 275 | Invalid amount | 540 | | 300 | Internal server error | 541 | 542 | 543 | *** 544 | 545 | [(Back to top)](#table-of-contents) 546 | 547 | 548 | 549 | 550 | ## TODO 551 | 552 | Add more providers and write more tests 553 | 554 | ## Troubleshooting 555 | 556 | If you like living on the edge, please report any bugs you find on the 557 | [PHP GeoPayment issues](https://github.com/akalongman/php-geopayment/issues) page. 558 | 559 | ## Contributing 560 | 561 | Pull requests are welcome. 562 | See [CONTRIBUTING.md](CONTRIBUTING.md) for information. 563 | 564 | ## License 565 | 566 | Please see the [LICENSE](LICENSE.md) included in this repository for a full copy of the MIT license, 567 | which this project is licensed under. 568 | 569 | ## Credits 570 | 571 | - [Avtandil Kikabidze aka LONGMAN](https://github.com/akalongman) 572 | 573 | Full credit list in [CREDITS](CREDITS) -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "longman/geopayment", 3 | "type": "library", 4 | "description": "PHP library for working with Georgian payment providers and banks", 5 | "keywords": ["payment", "pay", "georgia", "bog", "tbc", "cartu", "merchant", "visa", "ecommerce", "tbcpay", "libertypay", "terminal"], 6 | "license": "MIT", 7 | "homepage": "https://github.com/akalongman/php-geopayment", 8 | "support": { 9 | "issues": "https://github.com/akalongman/php-geopayment/issues", 10 | "source": "https://github.com/akalongman/php-geopayment" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Avtandil Kikabidze aka LONGMAN", 15 | "email": "akalongman@gmail.com", 16 | "homepage": "http://longman.me", 17 | "role": "Maintainer, Developer" 18 | } 19 | ], 20 | "require": { 21 | "php": ">=5.3.0", 22 | "monolog/monolog": "~1.17", 23 | "symfony/var-dumper": "~3.0|~4.0", 24 | "vlucas/phpdotenv": "~2.2", 25 | "symfony/http-foundation": "~3.0|~4.0", 26 | "nesbot/carbon": "~1.21", 27 | "longman/ip-tools": "~1.1" 28 | }, 29 | "require-dev": { 30 | "mockery/mockery": "0.9.*", 31 | "phpunit/phpunit": "~4.0", 32 | "phpspec/phpspec": "2.4.*", 33 | "squizlabs/php_codesniffer": "2.5.*" 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Longman\\GeoPayment\\": "src/" 38 | } 39 | }, 40 | "autoload-dev": { 41 | "psr-4": { 42 | "Tests\\": "tests/" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b939be7921dcc59575fafce6e9321693", 8 | "packages": [ 9 | { 10 | "name": "longman/ip-tools", 11 | "version": "1.2.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/akalongman/php-ip-tools.git", 15 | "reference": "6c050dfbf91811d14b9b3aa31fb7116eac0f0a18" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/akalongman/php-ip-tools/zipball/6c050dfbf91811d14b9b3aa31fb7116eac0f0a18", 20 | "reference": "6c050dfbf91811d14b9b3aa31fb7116eac0f0a18", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-bcmath": "*", 25 | "php": ">=5.5" 26 | }, 27 | "require-dev": { 28 | "phpspec/phpspec": "~2.1", 29 | "phpunit/phpunit": "~4.1", 30 | "squizlabs/php_codesniffer": "~2.3" 31 | }, 32 | "type": "library", 33 | "autoload": { 34 | "psr-4": { 35 | "Longman\\IPTools\\": "src/" 36 | } 37 | }, 38 | "notification-url": "https://packagist.org/downloads/", 39 | "license": [ 40 | "MIT" 41 | ], 42 | "authors": [ 43 | { 44 | "name": "Avtandil Kikabidze aka LONGMAN", 45 | "email": "akalongman@gmail.com", 46 | "homepage": "https://longman.me", 47 | "role": "Developer" 48 | } 49 | ], 50 | "description": "PHP IP Tools for manipulation with IPv4 and IPv6", 51 | "homepage": "https://github.com/akalongman/php-ip-tools", 52 | "keywords": [ 53 | "IP", 54 | "Match", 55 | "compare", 56 | "ipv4", 57 | "ipv6", 58 | "mask", 59 | "subnet", 60 | "tools", 61 | "utilities" 62 | ], 63 | "time": "2016-10-23T20:08:46+00:00" 64 | }, 65 | { 66 | "name": "monolog/monolog", 67 | "version": "1.23.0", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/Seldaek/monolog.git", 71 | "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4", 76 | "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": ">=5.3.0", 81 | "psr/log": "~1.0" 82 | }, 83 | "provide": { 84 | "psr/log-implementation": "1.0.0" 85 | }, 86 | "require-dev": { 87 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 88 | "doctrine/couchdb": "~1.0@dev", 89 | "graylog2/gelf-php": "~1.0", 90 | "jakub-onderka/php-parallel-lint": "0.9", 91 | "php-amqplib/php-amqplib": "~2.4", 92 | "php-console/php-console": "^3.1.3", 93 | "phpunit/phpunit": "~4.5", 94 | "phpunit/phpunit-mock-objects": "2.3.0", 95 | "ruflin/elastica": ">=0.90 <3.0", 96 | "sentry/sentry": "^0.13", 97 | "swiftmailer/swiftmailer": "^5.3|^6.0" 98 | }, 99 | "suggest": { 100 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 101 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 102 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 103 | "ext-mongo": "Allow sending log messages to a MongoDB server", 104 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 105 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 106 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 107 | "php-console/php-console": "Allow sending log messages to Google Chrome", 108 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 109 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 110 | "sentry/sentry": "Allow sending log messages to a Sentry server" 111 | }, 112 | "type": "library", 113 | "extra": { 114 | "branch-alias": { 115 | "dev-master": "2.0.x-dev" 116 | } 117 | }, 118 | "autoload": { 119 | "psr-4": { 120 | "Monolog\\": "src/Monolog" 121 | } 122 | }, 123 | "notification-url": "https://packagist.org/downloads/", 124 | "license": [ 125 | "MIT" 126 | ], 127 | "authors": [ 128 | { 129 | "name": "Jordi Boggiano", 130 | "email": "j.boggiano@seld.be", 131 | "homepage": "http://seld.be" 132 | } 133 | ], 134 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 135 | "homepage": "http://github.com/Seldaek/monolog", 136 | "keywords": [ 137 | "log", 138 | "logging", 139 | "psr-3" 140 | ], 141 | "time": "2017-06-19T01:22:40+00:00" 142 | }, 143 | { 144 | "name": "nesbot/carbon", 145 | "version": "1.34.0", 146 | "source": { 147 | "type": "git", 148 | "url": "https://github.com/briannesbitt/Carbon.git", 149 | "reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33" 150 | }, 151 | "dist": { 152 | "type": "zip", 153 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33", 154 | "reference": "1dbd3cb01c5645f3e7deda7aa46ef780d95fcc33", 155 | "shasum": "" 156 | }, 157 | "require": { 158 | "php": ">=5.3.9", 159 | "symfony/translation": "~2.6 || ~3.0 || ~4.0" 160 | }, 161 | "require-dev": { 162 | "friendsofphp/php-cs-fixer": "~2", 163 | "phpunit/phpunit": "^4.8.35 || ^5.7" 164 | }, 165 | "type": "library", 166 | "extra": { 167 | "laravel": { 168 | "providers": [ 169 | "Carbon\\Laravel\\ServiceProvider" 170 | ] 171 | } 172 | }, 173 | "autoload": { 174 | "psr-4": { 175 | "": "src/" 176 | } 177 | }, 178 | "notification-url": "https://packagist.org/downloads/", 179 | "license": [ 180 | "MIT" 181 | ], 182 | "authors": [ 183 | { 184 | "name": "Brian Nesbitt", 185 | "email": "brian@nesbot.com", 186 | "homepage": "http://nesbot.com" 187 | } 188 | ], 189 | "description": "A simple API extension for DateTime.", 190 | "homepage": "http://carbon.nesbot.com", 191 | "keywords": [ 192 | "date", 193 | "datetime", 194 | "time" 195 | ], 196 | "time": "2018-09-20T19:36:25+00:00" 197 | }, 198 | { 199 | "name": "psr/log", 200 | "version": "1.0.2", 201 | "source": { 202 | "type": "git", 203 | "url": "https://github.com/php-fig/log.git", 204 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 205 | }, 206 | "dist": { 207 | "type": "zip", 208 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 209 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 210 | "shasum": "" 211 | }, 212 | "require": { 213 | "php": ">=5.3.0" 214 | }, 215 | "type": "library", 216 | "extra": { 217 | "branch-alias": { 218 | "dev-master": "1.0.x-dev" 219 | } 220 | }, 221 | "autoload": { 222 | "psr-4": { 223 | "Psr\\Log\\": "Psr/Log/" 224 | } 225 | }, 226 | "notification-url": "https://packagist.org/downloads/", 227 | "license": [ 228 | "MIT" 229 | ], 230 | "authors": [ 231 | { 232 | "name": "PHP-FIG", 233 | "homepage": "http://www.php-fig.org/" 234 | } 235 | ], 236 | "description": "Common interface for logging libraries", 237 | "homepage": "https://github.com/php-fig/log", 238 | "keywords": [ 239 | "log", 240 | "psr", 241 | "psr-3" 242 | ], 243 | "time": "2016-10-10T12:19:37+00:00" 244 | }, 245 | { 246 | "name": "symfony/http-foundation", 247 | "version": "v4.1.6", 248 | "source": { 249 | "type": "git", 250 | "url": "https://github.com/symfony/http-foundation.git", 251 | "reference": "d528136617ff24f530e70df9605acc1b788b08d4" 252 | }, 253 | "dist": { 254 | "type": "zip", 255 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d528136617ff24f530e70df9605acc1b788b08d4", 256 | "reference": "d528136617ff24f530e70df9605acc1b788b08d4", 257 | "shasum": "" 258 | }, 259 | "require": { 260 | "php": "^7.1.3", 261 | "symfony/polyfill-mbstring": "~1.1" 262 | }, 263 | "require-dev": { 264 | "predis/predis": "~1.0", 265 | "symfony/expression-language": "~3.4|~4.0" 266 | }, 267 | "type": "library", 268 | "extra": { 269 | "branch-alias": { 270 | "dev-master": "4.1-dev" 271 | } 272 | }, 273 | "autoload": { 274 | "psr-4": { 275 | "Symfony\\Component\\HttpFoundation\\": "" 276 | }, 277 | "exclude-from-classmap": [ 278 | "/Tests/" 279 | ] 280 | }, 281 | "notification-url": "https://packagist.org/downloads/", 282 | "license": [ 283 | "MIT" 284 | ], 285 | "authors": [ 286 | { 287 | "name": "Fabien Potencier", 288 | "email": "fabien@symfony.com" 289 | }, 290 | { 291 | "name": "Symfony Community", 292 | "homepage": "https://symfony.com/contributors" 293 | } 294 | ], 295 | "description": "Symfony HttpFoundation Component", 296 | "homepage": "https://symfony.com", 297 | "time": "2018-10-03T08:48:45+00:00" 298 | }, 299 | { 300 | "name": "symfony/polyfill-mbstring", 301 | "version": "v1.9.0", 302 | "source": { 303 | "type": "git", 304 | "url": "https://github.com/symfony/polyfill-mbstring.git", 305 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" 306 | }, 307 | "dist": { 308 | "type": "zip", 309 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", 310 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", 311 | "shasum": "" 312 | }, 313 | "require": { 314 | "php": ">=5.3.3" 315 | }, 316 | "suggest": { 317 | "ext-mbstring": "For best performance" 318 | }, 319 | "type": "library", 320 | "extra": { 321 | "branch-alias": { 322 | "dev-master": "1.9-dev" 323 | } 324 | }, 325 | "autoload": { 326 | "psr-4": { 327 | "Symfony\\Polyfill\\Mbstring\\": "" 328 | }, 329 | "files": [ 330 | "bootstrap.php" 331 | ] 332 | }, 333 | "notification-url": "https://packagist.org/downloads/", 334 | "license": [ 335 | "MIT" 336 | ], 337 | "authors": [ 338 | { 339 | "name": "Nicolas Grekas", 340 | "email": "p@tchwork.com" 341 | }, 342 | { 343 | "name": "Symfony Community", 344 | "homepage": "https://symfony.com/contributors" 345 | } 346 | ], 347 | "description": "Symfony polyfill for the Mbstring extension", 348 | "homepage": "https://symfony.com", 349 | "keywords": [ 350 | "compatibility", 351 | "mbstring", 352 | "polyfill", 353 | "portable", 354 | "shim" 355 | ], 356 | "time": "2018-08-06T14:22:27+00:00" 357 | }, 358 | { 359 | "name": "symfony/polyfill-php72", 360 | "version": "v1.9.0", 361 | "source": { 362 | "type": "git", 363 | "url": "https://github.com/symfony/polyfill-php72.git", 364 | "reference": "95c50420b0baed23852452a7f0c7b527303ed5ae" 365 | }, 366 | "dist": { 367 | "type": "zip", 368 | "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/95c50420b0baed23852452a7f0c7b527303ed5ae", 369 | "reference": "95c50420b0baed23852452a7f0c7b527303ed5ae", 370 | "shasum": "" 371 | }, 372 | "require": { 373 | "php": ">=5.3.3" 374 | }, 375 | "type": "library", 376 | "extra": { 377 | "branch-alias": { 378 | "dev-master": "1.9-dev" 379 | } 380 | }, 381 | "autoload": { 382 | "psr-4": { 383 | "Symfony\\Polyfill\\Php72\\": "" 384 | }, 385 | "files": [ 386 | "bootstrap.php" 387 | ] 388 | }, 389 | "notification-url": "https://packagist.org/downloads/", 390 | "license": [ 391 | "MIT" 392 | ], 393 | "authors": [ 394 | { 395 | "name": "Nicolas Grekas", 396 | "email": "p@tchwork.com" 397 | }, 398 | { 399 | "name": "Symfony Community", 400 | "homepage": "https://symfony.com/contributors" 401 | } 402 | ], 403 | "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", 404 | "homepage": "https://symfony.com", 405 | "keywords": [ 406 | "compatibility", 407 | "polyfill", 408 | "portable", 409 | "shim" 410 | ], 411 | "time": "2018-08-06T14:22:27+00:00" 412 | }, 413 | { 414 | "name": "symfony/translation", 415 | "version": "v4.1.6", 416 | "source": { 417 | "type": "git", 418 | "url": "https://github.com/symfony/translation.git", 419 | "reference": "9f0b61e339160a466ebcde167a6c5521c810e304" 420 | }, 421 | "dist": { 422 | "type": "zip", 423 | "url": "https://api.github.com/repos/symfony/translation/zipball/9f0b61e339160a466ebcde167a6c5521c810e304", 424 | "reference": "9f0b61e339160a466ebcde167a6c5521c810e304", 425 | "shasum": "" 426 | }, 427 | "require": { 428 | "php": "^7.1.3", 429 | "symfony/polyfill-mbstring": "~1.0" 430 | }, 431 | "conflict": { 432 | "symfony/config": "<3.4", 433 | "symfony/dependency-injection": "<3.4", 434 | "symfony/yaml": "<3.4" 435 | }, 436 | "require-dev": { 437 | "psr/log": "~1.0", 438 | "symfony/config": "~3.4|~4.0", 439 | "symfony/console": "~3.4|~4.0", 440 | "symfony/dependency-injection": "~3.4|~4.0", 441 | "symfony/finder": "~2.8|~3.0|~4.0", 442 | "symfony/intl": "~3.4|~4.0", 443 | "symfony/yaml": "~3.4|~4.0" 444 | }, 445 | "suggest": { 446 | "psr/log-implementation": "To use logging capability in translator", 447 | "symfony/config": "", 448 | "symfony/yaml": "" 449 | }, 450 | "type": "library", 451 | "extra": { 452 | "branch-alias": { 453 | "dev-master": "4.1-dev" 454 | } 455 | }, 456 | "autoload": { 457 | "psr-4": { 458 | "Symfony\\Component\\Translation\\": "" 459 | }, 460 | "exclude-from-classmap": [ 461 | "/Tests/" 462 | ] 463 | }, 464 | "notification-url": "https://packagist.org/downloads/", 465 | "license": [ 466 | "MIT" 467 | ], 468 | "authors": [ 469 | { 470 | "name": "Fabien Potencier", 471 | "email": "fabien@symfony.com" 472 | }, 473 | { 474 | "name": "Symfony Community", 475 | "homepage": "https://symfony.com/contributors" 476 | } 477 | ], 478 | "description": "Symfony Translation Component", 479 | "homepage": "https://symfony.com", 480 | "time": "2018-10-02T16:36:10+00:00" 481 | }, 482 | { 483 | "name": "symfony/var-dumper", 484 | "version": "v4.1.6", 485 | "source": { 486 | "type": "git", 487 | "url": "https://github.com/symfony/var-dumper.git", 488 | "reference": "60319b45653580b0cdacca499344577d87732f16" 489 | }, 490 | "dist": { 491 | "type": "zip", 492 | "url": "https://api.github.com/repos/symfony/var-dumper/zipball/60319b45653580b0cdacca499344577d87732f16", 493 | "reference": "60319b45653580b0cdacca499344577d87732f16", 494 | "shasum": "" 495 | }, 496 | "require": { 497 | "php": "^7.1.3", 498 | "symfony/polyfill-mbstring": "~1.0", 499 | "symfony/polyfill-php72": "~1.5" 500 | }, 501 | "conflict": { 502 | "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", 503 | "symfony/console": "<3.4" 504 | }, 505 | "require-dev": { 506 | "ext-iconv": "*", 507 | "symfony/process": "~3.4|~4.0", 508 | "twig/twig": "~1.34|~2.4" 509 | }, 510 | "suggest": { 511 | "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", 512 | "ext-intl": "To show region name in time zone dump", 513 | "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" 514 | }, 515 | "bin": [ 516 | "Resources/bin/var-dump-server" 517 | ], 518 | "type": "library", 519 | "extra": { 520 | "branch-alias": { 521 | "dev-master": "4.1-dev" 522 | } 523 | }, 524 | "autoload": { 525 | "files": [ 526 | "Resources/functions/dump.php" 527 | ], 528 | "psr-4": { 529 | "Symfony\\Component\\VarDumper\\": "" 530 | }, 531 | "exclude-from-classmap": [ 532 | "/Tests/" 533 | ] 534 | }, 535 | "notification-url": "https://packagist.org/downloads/", 536 | "license": [ 537 | "MIT" 538 | ], 539 | "authors": [ 540 | { 541 | "name": "Nicolas Grekas", 542 | "email": "p@tchwork.com" 543 | }, 544 | { 545 | "name": "Symfony Community", 546 | "homepage": "https://symfony.com/contributors" 547 | } 548 | ], 549 | "description": "Symfony mechanism for exploring and dumping PHP variables", 550 | "homepage": "https://symfony.com", 551 | "keywords": [ 552 | "debug", 553 | "dump" 554 | ], 555 | "time": "2018-10-02T16:36:10+00:00" 556 | }, 557 | { 558 | "name": "vlucas/phpdotenv", 559 | "version": "v2.5.1", 560 | "source": { 561 | "type": "git", 562 | "url": "https://github.com/vlucas/phpdotenv.git", 563 | "reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e" 564 | }, 565 | "dist": { 566 | "type": "zip", 567 | "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e", 568 | "reference": "8abb4f9aa89ddea9d52112c65bbe8d0125e2fa8e", 569 | "shasum": "" 570 | }, 571 | "require": { 572 | "php": ">=5.3.9" 573 | }, 574 | "require-dev": { 575 | "phpunit/phpunit": "^4.8.35 || ^5.0" 576 | }, 577 | "type": "library", 578 | "extra": { 579 | "branch-alias": { 580 | "dev-master": "2.5-dev" 581 | } 582 | }, 583 | "autoload": { 584 | "psr-4": { 585 | "Dotenv\\": "src/" 586 | } 587 | }, 588 | "notification-url": "https://packagist.org/downloads/", 589 | "license": [ 590 | "BSD-3-Clause" 591 | ], 592 | "authors": [ 593 | { 594 | "name": "Vance Lucas", 595 | "email": "vance@vancelucas.com", 596 | "homepage": "http://www.vancelucas.com" 597 | } 598 | ], 599 | "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", 600 | "keywords": [ 601 | "dotenv", 602 | "env", 603 | "environment" 604 | ], 605 | "time": "2018-07-29T20:33:41+00:00" 606 | } 607 | ], 608 | "packages-dev": [ 609 | { 610 | "name": "doctrine/instantiator", 611 | "version": "1.1.0", 612 | "source": { 613 | "type": "git", 614 | "url": "https://github.com/doctrine/instantiator.git", 615 | "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" 616 | }, 617 | "dist": { 618 | "type": "zip", 619 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", 620 | "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", 621 | "shasum": "" 622 | }, 623 | "require": { 624 | "php": "^7.1" 625 | }, 626 | "require-dev": { 627 | "athletic/athletic": "~0.1.8", 628 | "ext-pdo": "*", 629 | "ext-phar": "*", 630 | "phpunit/phpunit": "^6.2.3", 631 | "squizlabs/php_codesniffer": "^3.0.2" 632 | }, 633 | "type": "library", 634 | "extra": { 635 | "branch-alias": { 636 | "dev-master": "1.2.x-dev" 637 | } 638 | }, 639 | "autoload": { 640 | "psr-4": { 641 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 642 | } 643 | }, 644 | "notification-url": "https://packagist.org/downloads/", 645 | "license": [ 646 | "MIT" 647 | ], 648 | "authors": [ 649 | { 650 | "name": "Marco Pivetta", 651 | "email": "ocramius@gmail.com", 652 | "homepage": "http://ocramius.github.com/" 653 | } 654 | ], 655 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 656 | "homepage": "https://github.com/doctrine/instantiator", 657 | "keywords": [ 658 | "constructor", 659 | "instantiate" 660 | ], 661 | "time": "2017-07-22T11:58:36+00:00" 662 | }, 663 | { 664 | "name": "hamcrest/hamcrest-php", 665 | "version": "v1.2.2", 666 | "source": { 667 | "type": "git", 668 | "url": "https://github.com/hamcrest/hamcrest-php.git", 669 | "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" 670 | }, 671 | "dist": { 672 | "type": "zip", 673 | "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", 674 | "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", 675 | "shasum": "" 676 | }, 677 | "require": { 678 | "php": ">=5.3.2" 679 | }, 680 | "replace": { 681 | "cordoval/hamcrest-php": "*", 682 | "davedevelopment/hamcrest-php": "*", 683 | "kodova/hamcrest-php": "*" 684 | }, 685 | "require-dev": { 686 | "phpunit/php-file-iterator": "1.3.3", 687 | "satooshi/php-coveralls": "dev-master" 688 | }, 689 | "type": "library", 690 | "autoload": { 691 | "classmap": [ 692 | "hamcrest" 693 | ], 694 | "files": [ 695 | "hamcrest/Hamcrest.php" 696 | ] 697 | }, 698 | "notification-url": "https://packagist.org/downloads/", 699 | "license": [ 700 | "BSD" 701 | ], 702 | "description": "This is the PHP port of Hamcrest Matchers", 703 | "keywords": [ 704 | "test" 705 | ], 706 | "time": "2015-05-11T14:41:42+00:00" 707 | }, 708 | { 709 | "name": "mockery/mockery", 710 | "version": "0.9.9", 711 | "source": { 712 | "type": "git", 713 | "url": "https://github.com/mockery/mockery.git", 714 | "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" 715 | }, 716 | "dist": { 717 | "type": "zip", 718 | "url": "https://api.github.com/repos/mockery/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", 719 | "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", 720 | "shasum": "" 721 | }, 722 | "require": { 723 | "hamcrest/hamcrest-php": "~1.1", 724 | "lib-pcre": ">=7.0", 725 | "php": ">=5.3.2" 726 | }, 727 | "require-dev": { 728 | "phpunit/phpunit": "~4.0" 729 | }, 730 | "type": "library", 731 | "extra": { 732 | "branch-alias": { 733 | "dev-master": "0.9.x-dev" 734 | } 735 | }, 736 | "autoload": { 737 | "psr-0": { 738 | "Mockery": "library/" 739 | } 740 | }, 741 | "notification-url": "https://packagist.org/downloads/", 742 | "license": [ 743 | "BSD-3-Clause" 744 | ], 745 | "authors": [ 746 | { 747 | "name": "Pádraic Brady", 748 | "email": "padraic.brady@gmail.com", 749 | "homepage": "http://blog.astrumfutura.com" 750 | }, 751 | { 752 | "name": "Dave Marshall", 753 | "email": "dave.marshall@atstsolutions.co.uk", 754 | "homepage": "http://davedevelopment.co.uk" 755 | } 756 | ], 757 | "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", 758 | "homepage": "http://github.com/padraic/mockery", 759 | "keywords": [ 760 | "BDD", 761 | "TDD", 762 | "library", 763 | "mock", 764 | "mock objects", 765 | "mockery", 766 | "stub", 767 | "test", 768 | "test double", 769 | "testing" 770 | ], 771 | "time": "2017-02-28T12:52:32+00:00" 772 | }, 773 | { 774 | "name": "phpdocumentor/reflection-common", 775 | "version": "1.0.1", 776 | "source": { 777 | "type": "git", 778 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 779 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 780 | }, 781 | "dist": { 782 | "type": "zip", 783 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 784 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 785 | "shasum": "" 786 | }, 787 | "require": { 788 | "php": ">=5.5" 789 | }, 790 | "require-dev": { 791 | "phpunit/phpunit": "^4.6" 792 | }, 793 | "type": "library", 794 | "extra": { 795 | "branch-alias": { 796 | "dev-master": "1.0.x-dev" 797 | } 798 | }, 799 | "autoload": { 800 | "psr-4": { 801 | "phpDocumentor\\Reflection\\": [ 802 | "src" 803 | ] 804 | } 805 | }, 806 | "notification-url": "https://packagist.org/downloads/", 807 | "license": [ 808 | "MIT" 809 | ], 810 | "authors": [ 811 | { 812 | "name": "Jaap van Otterdijk", 813 | "email": "opensource@ijaap.nl" 814 | } 815 | ], 816 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 817 | "homepage": "http://www.phpdoc.org", 818 | "keywords": [ 819 | "FQSEN", 820 | "phpDocumentor", 821 | "phpdoc", 822 | "reflection", 823 | "static analysis" 824 | ], 825 | "time": "2017-09-11T18:02:19+00:00" 826 | }, 827 | { 828 | "name": "phpdocumentor/reflection-docblock", 829 | "version": "4.3.0", 830 | "source": { 831 | "type": "git", 832 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 833 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08" 834 | }, 835 | "dist": { 836 | "type": "zip", 837 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", 838 | "reference": "94fd0001232e47129dd3504189fa1c7225010d08", 839 | "shasum": "" 840 | }, 841 | "require": { 842 | "php": "^7.0", 843 | "phpdocumentor/reflection-common": "^1.0.0", 844 | "phpdocumentor/type-resolver": "^0.4.0", 845 | "webmozart/assert": "^1.0" 846 | }, 847 | "require-dev": { 848 | "doctrine/instantiator": "~1.0.5", 849 | "mockery/mockery": "^1.0", 850 | "phpunit/phpunit": "^6.4" 851 | }, 852 | "type": "library", 853 | "extra": { 854 | "branch-alias": { 855 | "dev-master": "4.x-dev" 856 | } 857 | }, 858 | "autoload": { 859 | "psr-4": { 860 | "phpDocumentor\\Reflection\\": [ 861 | "src/" 862 | ] 863 | } 864 | }, 865 | "notification-url": "https://packagist.org/downloads/", 866 | "license": [ 867 | "MIT" 868 | ], 869 | "authors": [ 870 | { 871 | "name": "Mike van Riel", 872 | "email": "me@mikevanriel.com" 873 | } 874 | ], 875 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 876 | "time": "2017-11-30T07:14:17+00:00" 877 | }, 878 | { 879 | "name": "phpdocumentor/type-resolver", 880 | "version": "0.4.0", 881 | "source": { 882 | "type": "git", 883 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 884 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 885 | }, 886 | "dist": { 887 | "type": "zip", 888 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 889 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 890 | "shasum": "" 891 | }, 892 | "require": { 893 | "php": "^5.5 || ^7.0", 894 | "phpdocumentor/reflection-common": "^1.0" 895 | }, 896 | "require-dev": { 897 | "mockery/mockery": "^0.9.4", 898 | "phpunit/phpunit": "^5.2||^4.8.24" 899 | }, 900 | "type": "library", 901 | "extra": { 902 | "branch-alias": { 903 | "dev-master": "1.0.x-dev" 904 | } 905 | }, 906 | "autoload": { 907 | "psr-4": { 908 | "phpDocumentor\\Reflection\\": [ 909 | "src/" 910 | ] 911 | } 912 | }, 913 | "notification-url": "https://packagist.org/downloads/", 914 | "license": [ 915 | "MIT" 916 | ], 917 | "authors": [ 918 | { 919 | "name": "Mike van Riel", 920 | "email": "me@mikevanriel.com" 921 | } 922 | ], 923 | "time": "2017-07-14T14:27:02+00:00" 924 | }, 925 | { 926 | "name": "phpspec/php-diff", 927 | "version": "v1.0.2", 928 | "source": { 929 | "type": "git", 930 | "url": "https://github.com/phpspec/php-diff.git", 931 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" 932 | }, 933 | "dist": { 934 | "type": "zip", 935 | "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", 936 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", 937 | "shasum": "" 938 | }, 939 | "type": "library", 940 | "autoload": { 941 | "psr-0": { 942 | "Diff": "lib/" 943 | } 944 | }, 945 | "notification-url": "https://packagist.org/downloads/", 946 | "license": [ 947 | "BSD-3-Clause" 948 | ], 949 | "authors": [ 950 | { 951 | "name": "Chris Boulton", 952 | "homepage": "http://github.com/chrisboulton" 953 | } 954 | ], 955 | "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", 956 | "time": "2013-11-01T13:02:21+00:00" 957 | }, 958 | { 959 | "name": "phpspec/phpspec", 960 | "version": "2.4.1", 961 | "source": { 962 | "type": "git", 963 | "url": "https://github.com/phpspec/phpspec.git", 964 | "reference": "5528ce1e93a1efa090c9404aba3395c329b4e6ed" 965 | }, 966 | "dist": { 967 | "type": "zip", 968 | "url": "https://api.github.com/repos/phpspec/phpspec/zipball/5528ce1e93a1efa090c9404aba3395c329b4e6ed", 969 | "reference": "5528ce1e93a1efa090c9404aba3395c329b4e6ed", 970 | "shasum": "" 971 | }, 972 | "require": { 973 | "doctrine/instantiator": "^1.0.1", 974 | "ext-tokenizer": "*", 975 | "php": ">=5.3.3", 976 | "phpspec/php-diff": "~1.0.0", 977 | "phpspec/prophecy": "~1.4", 978 | "sebastian/exporter": "~1.0", 979 | "symfony/console": "~2.3|~3.0", 980 | "symfony/event-dispatcher": "~2.1|~3.0", 981 | "symfony/finder": "~2.1|~3.0", 982 | "symfony/process": "^2.6|~3.0", 983 | "symfony/yaml": "~2.1|~3.0" 984 | }, 985 | "require-dev": { 986 | "behat/behat": "^3.0.11", 987 | "bossa/phpspec2-expect": "~1.0", 988 | "phpunit/phpunit": "~4.4", 989 | "symfony/filesystem": "~2.1|~3.0" 990 | }, 991 | "suggest": { 992 | "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" 993 | }, 994 | "bin": [ 995 | "bin/phpspec" 996 | ], 997 | "type": "library", 998 | "extra": { 999 | "branch-alias": { 1000 | "dev-master": "2.2.x-dev" 1001 | } 1002 | }, 1003 | "autoload": { 1004 | "psr-0": { 1005 | "PhpSpec": "src/" 1006 | } 1007 | }, 1008 | "notification-url": "https://packagist.org/downloads/", 1009 | "license": [ 1010 | "MIT" 1011 | ], 1012 | "authors": [ 1013 | { 1014 | "name": "Konstantin Kudryashov", 1015 | "email": "ever.zet@gmail.com", 1016 | "homepage": "http://everzet.com" 1017 | }, 1018 | { 1019 | "name": "Marcello Duarte", 1020 | "homepage": "http://marcelloduarte.net/" 1021 | } 1022 | ], 1023 | "description": "Specification-oriented BDD framework for PHP 5.3+", 1024 | "homepage": "http://phpspec.net/", 1025 | "keywords": [ 1026 | "BDD", 1027 | "SpecBDD", 1028 | "TDD", 1029 | "spec", 1030 | "specification", 1031 | "testing", 1032 | "tests" 1033 | ], 1034 | "time": "2016-01-01T10:17:54+00:00" 1035 | }, 1036 | { 1037 | "name": "phpspec/prophecy", 1038 | "version": "1.8.0", 1039 | "source": { 1040 | "type": "git", 1041 | "url": "https://github.com/phpspec/prophecy.git", 1042 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" 1043 | }, 1044 | "dist": { 1045 | "type": "zip", 1046 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 1047 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 1048 | "shasum": "" 1049 | }, 1050 | "require": { 1051 | "doctrine/instantiator": "^1.0.2", 1052 | "php": "^5.3|^7.0", 1053 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 1054 | "sebastian/comparator": "^1.1|^2.0|^3.0", 1055 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 1056 | }, 1057 | "require-dev": { 1058 | "phpspec/phpspec": "^2.5|^3.2", 1059 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 1060 | }, 1061 | "type": "library", 1062 | "extra": { 1063 | "branch-alias": { 1064 | "dev-master": "1.8.x-dev" 1065 | } 1066 | }, 1067 | "autoload": { 1068 | "psr-0": { 1069 | "Prophecy\\": "src/" 1070 | } 1071 | }, 1072 | "notification-url": "https://packagist.org/downloads/", 1073 | "license": [ 1074 | "MIT" 1075 | ], 1076 | "authors": [ 1077 | { 1078 | "name": "Konstantin Kudryashov", 1079 | "email": "ever.zet@gmail.com", 1080 | "homepage": "http://everzet.com" 1081 | }, 1082 | { 1083 | "name": "Marcello Duarte", 1084 | "email": "marcello.duarte@gmail.com" 1085 | } 1086 | ], 1087 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1088 | "homepage": "https://github.com/phpspec/prophecy", 1089 | "keywords": [ 1090 | "Double", 1091 | "Dummy", 1092 | "fake", 1093 | "mock", 1094 | "spy", 1095 | "stub" 1096 | ], 1097 | "time": "2018-08-05T17:53:17+00:00" 1098 | }, 1099 | { 1100 | "name": "phpunit/php-code-coverage", 1101 | "version": "2.2.4", 1102 | "source": { 1103 | "type": "git", 1104 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1105 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 1106 | }, 1107 | "dist": { 1108 | "type": "zip", 1109 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1110 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 1111 | "shasum": "" 1112 | }, 1113 | "require": { 1114 | "php": ">=5.3.3", 1115 | "phpunit/php-file-iterator": "~1.3", 1116 | "phpunit/php-text-template": "~1.2", 1117 | "phpunit/php-token-stream": "~1.3", 1118 | "sebastian/environment": "^1.3.2", 1119 | "sebastian/version": "~1.0" 1120 | }, 1121 | "require-dev": { 1122 | "ext-xdebug": ">=2.1.4", 1123 | "phpunit/phpunit": "~4" 1124 | }, 1125 | "suggest": { 1126 | "ext-dom": "*", 1127 | "ext-xdebug": ">=2.2.1", 1128 | "ext-xmlwriter": "*" 1129 | }, 1130 | "type": "library", 1131 | "extra": { 1132 | "branch-alias": { 1133 | "dev-master": "2.2.x-dev" 1134 | } 1135 | }, 1136 | "autoload": { 1137 | "classmap": [ 1138 | "src/" 1139 | ] 1140 | }, 1141 | "notification-url": "https://packagist.org/downloads/", 1142 | "license": [ 1143 | "BSD-3-Clause" 1144 | ], 1145 | "authors": [ 1146 | { 1147 | "name": "Sebastian Bergmann", 1148 | "email": "sb@sebastian-bergmann.de", 1149 | "role": "lead" 1150 | } 1151 | ], 1152 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1153 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1154 | "keywords": [ 1155 | "coverage", 1156 | "testing", 1157 | "xunit" 1158 | ], 1159 | "time": "2015-10-06T15:47:00+00:00" 1160 | }, 1161 | { 1162 | "name": "phpunit/php-file-iterator", 1163 | "version": "1.4.5", 1164 | "source": { 1165 | "type": "git", 1166 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1167 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 1168 | }, 1169 | "dist": { 1170 | "type": "zip", 1171 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 1172 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 1173 | "shasum": "" 1174 | }, 1175 | "require": { 1176 | "php": ">=5.3.3" 1177 | }, 1178 | "type": "library", 1179 | "extra": { 1180 | "branch-alias": { 1181 | "dev-master": "1.4.x-dev" 1182 | } 1183 | }, 1184 | "autoload": { 1185 | "classmap": [ 1186 | "src/" 1187 | ] 1188 | }, 1189 | "notification-url": "https://packagist.org/downloads/", 1190 | "license": [ 1191 | "BSD-3-Clause" 1192 | ], 1193 | "authors": [ 1194 | { 1195 | "name": "Sebastian Bergmann", 1196 | "email": "sb@sebastian-bergmann.de", 1197 | "role": "lead" 1198 | } 1199 | ], 1200 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1201 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1202 | "keywords": [ 1203 | "filesystem", 1204 | "iterator" 1205 | ], 1206 | "time": "2017-11-27T13:52:08+00:00" 1207 | }, 1208 | { 1209 | "name": "phpunit/php-text-template", 1210 | "version": "1.2.1", 1211 | "source": { 1212 | "type": "git", 1213 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1214 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1215 | }, 1216 | "dist": { 1217 | "type": "zip", 1218 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1219 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1220 | "shasum": "" 1221 | }, 1222 | "require": { 1223 | "php": ">=5.3.3" 1224 | }, 1225 | "type": "library", 1226 | "autoload": { 1227 | "classmap": [ 1228 | "src/" 1229 | ] 1230 | }, 1231 | "notification-url": "https://packagist.org/downloads/", 1232 | "license": [ 1233 | "BSD-3-Clause" 1234 | ], 1235 | "authors": [ 1236 | { 1237 | "name": "Sebastian Bergmann", 1238 | "email": "sebastian@phpunit.de", 1239 | "role": "lead" 1240 | } 1241 | ], 1242 | "description": "Simple template engine.", 1243 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1244 | "keywords": [ 1245 | "template" 1246 | ], 1247 | "time": "2015-06-21T13:50:34+00:00" 1248 | }, 1249 | { 1250 | "name": "phpunit/php-timer", 1251 | "version": "1.0.9", 1252 | "source": { 1253 | "type": "git", 1254 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1255 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 1256 | }, 1257 | "dist": { 1258 | "type": "zip", 1259 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1260 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1261 | "shasum": "" 1262 | }, 1263 | "require": { 1264 | "php": "^5.3.3 || ^7.0" 1265 | }, 1266 | "require-dev": { 1267 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1268 | }, 1269 | "type": "library", 1270 | "extra": { 1271 | "branch-alias": { 1272 | "dev-master": "1.0-dev" 1273 | } 1274 | }, 1275 | "autoload": { 1276 | "classmap": [ 1277 | "src/" 1278 | ] 1279 | }, 1280 | "notification-url": "https://packagist.org/downloads/", 1281 | "license": [ 1282 | "BSD-3-Clause" 1283 | ], 1284 | "authors": [ 1285 | { 1286 | "name": "Sebastian Bergmann", 1287 | "email": "sb@sebastian-bergmann.de", 1288 | "role": "lead" 1289 | } 1290 | ], 1291 | "description": "Utility class for timing", 1292 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1293 | "keywords": [ 1294 | "timer" 1295 | ], 1296 | "time": "2017-02-26T11:10:40+00:00" 1297 | }, 1298 | { 1299 | "name": "phpunit/php-token-stream", 1300 | "version": "1.4.12", 1301 | "source": { 1302 | "type": "git", 1303 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1304 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 1305 | }, 1306 | "dist": { 1307 | "type": "zip", 1308 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 1309 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 1310 | "shasum": "" 1311 | }, 1312 | "require": { 1313 | "ext-tokenizer": "*", 1314 | "php": ">=5.3.3" 1315 | }, 1316 | "require-dev": { 1317 | "phpunit/phpunit": "~4.2" 1318 | }, 1319 | "type": "library", 1320 | "extra": { 1321 | "branch-alias": { 1322 | "dev-master": "1.4-dev" 1323 | } 1324 | }, 1325 | "autoload": { 1326 | "classmap": [ 1327 | "src/" 1328 | ] 1329 | }, 1330 | "notification-url": "https://packagist.org/downloads/", 1331 | "license": [ 1332 | "BSD-3-Clause" 1333 | ], 1334 | "authors": [ 1335 | { 1336 | "name": "Sebastian Bergmann", 1337 | "email": "sebastian@phpunit.de" 1338 | } 1339 | ], 1340 | "description": "Wrapper around PHP's tokenizer extension.", 1341 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1342 | "keywords": [ 1343 | "tokenizer" 1344 | ], 1345 | "time": "2017-12-04T08:55:13+00:00" 1346 | }, 1347 | { 1348 | "name": "phpunit/phpunit", 1349 | "version": "4.8.36", 1350 | "source": { 1351 | "type": "git", 1352 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1353 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" 1354 | }, 1355 | "dist": { 1356 | "type": "zip", 1357 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", 1358 | "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", 1359 | "shasum": "" 1360 | }, 1361 | "require": { 1362 | "ext-dom": "*", 1363 | "ext-json": "*", 1364 | "ext-pcre": "*", 1365 | "ext-reflection": "*", 1366 | "ext-spl": "*", 1367 | "php": ">=5.3.3", 1368 | "phpspec/prophecy": "^1.3.1", 1369 | "phpunit/php-code-coverage": "~2.1", 1370 | "phpunit/php-file-iterator": "~1.4", 1371 | "phpunit/php-text-template": "~1.2", 1372 | "phpunit/php-timer": "^1.0.6", 1373 | "phpunit/phpunit-mock-objects": "~2.3", 1374 | "sebastian/comparator": "~1.2.2", 1375 | "sebastian/diff": "~1.2", 1376 | "sebastian/environment": "~1.3", 1377 | "sebastian/exporter": "~1.2", 1378 | "sebastian/global-state": "~1.0", 1379 | "sebastian/version": "~1.0", 1380 | "symfony/yaml": "~2.1|~3.0" 1381 | }, 1382 | "suggest": { 1383 | "phpunit/php-invoker": "~1.1" 1384 | }, 1385 | "bin": [ 1386 | "phpunit" 1387 | ], 1388 | "type": "library", 1389 | "extra": { 1390 | "branch-alias": { 1391 | "dev-master": "4.8.x-dev" 1392 | } 1393 | }, 1394 | "autoload": { 1395 | "classmap": [ 1396 | "src/" 1397 | ] 1398 | }, 1399 | "notification-url": "https://packagist.org/downloads/", 1400 | "license": [ 1401 | "BSD-3-Clause" 1402 | ], 1403 | "authors": [ 1404 | { 1405 | "name": "Sebastian Bergmann", 1406 | "email": "sebastian@phpunit.de", 1407 | "role": "lead" 1408 | } 1409 | ], 1410 | "description": "The PHP Unit Testing framework.", 1411 | "homepage": "https://phpunit.de/", 1412 | "keywords": [ 1413 | "phpunit", 1414 | "testing", 1415 | "xunit" 1416 | ], 1417 | "time": "2017-06-21T08:07:12+00:00" 1418 | }, 1419 | { 1420 | "name": "phpunit/phpunit-mock-objects", 1421 | "version": "2.3.8", 1422 | "source": { 1423 | "type": "git", 1424 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1425 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 1426 | }, 1427 | "dist": { 1428 | "type": "zip", 1429 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1430 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 1431 | "shasum": "" 1432 | }, 1433 | "require": { 1434 | "doctrine/instantiator": "^1.0.2", 1435 | "php": ">=5.3.3", 1436 | "phpunit/php-text-template": "~1.2", 1437 | "sebastian/exporter": "~1.2" 1438 | }, 1439 | "require-dev": { 1440 | "phpunit/phpunit": "~4.4" 1441 | }, 1442 | "suggest": { 1443 | "ext-soap": "*" 1444 | }, 1445 | "type": "library", 1446 | "extra": { 1447 | "branch-alias": { 1448 | "dev-master": "2.3.x-dev" 1449 | } 1450 | }, 1451 | "autoload": { 1452 | "classmap": [ 1453 | "src/" 1454 | ] 1455 | }, 1456 | "notification-url": "https://packagist.org/downloads/", 1457 | "license": [ 1458 | "BSD-3-Clause" 1459 | ], 1460 | "authors": [ 1461 | { 1462 | "name": "Sebastian Bergmann", 1463 | "email": "sb@sebastian-bergmann.de", 1464 | "role": "lead" 1465 | } 1466 | ], 1467 | "description": "Mock Object library for PHPUnit", 1468 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1469 | "keywords": [ 1470 | "mock", 1471 | "xunit" 1472 | ], 1473 | "time": "2015-10-02T06:51:40+00:00" 1474 | }, 1475 | { 1476 | "name": "sebastian/comparator", 1477 | "version": "1.2.4", 1478 | "source": { 1479 | "type": "git", 1480 | "url": "https://github.com/sebastianbergmann/comparator.git", 1481 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 1482 | }, 1483 | "dist": { 1484 | "type": "zip", 1485 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1486 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1487 | "shasum": "" 1488 | }, 1489 | "require": { 1490 | "php": ">=5.3.3", 1491 | "sebastian/diff": "~1.2", 1492 | "sebastian/exporter": "~1.2 || ~2.0" 1493 | }, 1494 | "require-dev": { 1495 | "phpunit/phpunit": "~4.4" 1496 | }, 1497 | "type": "library", 1498 | "extra": { 1499 | "branch-alias": { 1500 | "dev-master": "1.2.x-dev" 1501 | } 1502 | }, 1503 | "autoload": { 1504 | "classmap": [ 1505 | "src/" 1506 | ] 1507 | }, 1508 | "notification-url": "https://packagist.org/downloads/", 1509 | "license": [ 1510 | "BSD-3-Clause" 1511 | ], 1512 | "authors": [ 1513 | { 1514 | "name": "Jeff Welch", 1515 | "email": "whatthejeff@gmail.com" 1516 | }, 1517 | { 1518 | "name": "Volker Dusch", 1519 | "email": "github@wallbash.com" 1520 | }, 1521 | { 1522 | "name": "Bernhard Schussek", 1523 | "email": "bschussek@2bepublished.at" 1524 | }, 1525 | { 1526 | "name": "Sebastian Bergmann", 1527 | "email": "sebastian@phpunit.de" 1528 | } 1529 | ], 1530 | "description": "Provides the functionality to compare PHP values for equality", 1531 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1532 | "keywords": [ 1533 | "comparator", 1534 | "compare", 1535 | "equality" 1536 | ], 1537 | "time": "2017-01-29T09:50:25+00:00" 1538 | }, 1539 | { 1540 | "name": "sebastian/diff", 1541 | "version": "1.4.3", 1542 | "source": { 1543 | "type": "git", 1544 | "url": "https://github.com/sebastianbergmann/diff.git", 1545 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 1546 | }, 1547 | "dist": { 1548 | "type": "zip", 1549 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1550 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 1551 | "shasum": "" 1552 | }, 1553 | "require": { 1554 | "php": "^5.3.3 || ^7.0" 1555 | }, 1556 | "require-dev": { 1557 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1558 | }, 1559 | "type": "library", 1560 | "extra": { 1561 | "branch-alias": { 1562 | "dev-master": "1.4-dev" 1563 | } 1564 | }, 1565 | "autoload": { 1566 | "classmap": [ 1567 | "src/" 1568 | ] 1569 | }, 1570 | "notification-url": "https://packagist.org/downloads/", 1571 | "license": [ 1572 | "BSD-3-Clause" 1573 | ], 1574 | "authors": [ 1575 | { 1576 | "name": "Kore Nordmann", 1577 | "email": "mail@kore-nordmann.de" 1578 | }, 1579 | { 1580 | "name": "Sebastian Bergmann", 1581 | "email": "sebastian@phpunit.de" 1582 | } 1583 | ], 1584 | "description": "Diff implementation", 1585 | "homepage": "https://github.com/sebastianbergmann/diff", 1586 | "keywords": [ 1587 | "diff" 1588 | ], 1589 | "time": "2017-05-22T07:24:03+00:00" 1590 | }, 1591 | { 1592 | "name": "sebastian/environment", 1593 | "version": "1.3.8", 1594 | "source": { 1595 | "type": "git", 1596 | "url": "https://github.com/sebastianbergmann/environment.git", 1597 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" 1598 | }, 1599 | "dist": { 1600 | "type": "zip", 1601 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", 1602 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", 1603 | "shasum": "" 1604 | }, 1605 | "require": { 1606 | "php": "^5.3.3 || ^7.0" 1607 | }, 1608 | "require-dev": { 1609 | "phpunit/phpunit": "^4.8 || ^5.0" 1610 | }, 1611 | "type": "library", 1612 | "extra": { 1613 | "branch-alias": { 1614 | "dev-master": "1.3.x-dev" 1615 | } 1616 | }, 1617 | "autoload": { 1618 | "classmap": [ 1619 | "src/" 1620 | ] 1621 | }, 1622 | "notification-url": "https://packagist.org/downloads/", 1623 | "license": [ 1624 | "BSD-3-Clause" 1625 | ], 1626 | "authors": [ 1627 | { 1628 | "name": "Sebastian Bergmann", 1629 | "email": "sebastian@phpunit.de" 1630 | } 1631 | ], 1632 | "description": "Provides functionality to handle HHVM/PHP environments", 1633 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1634 | "keywords": [ 1635 | "Xdebug", 1636 | "environment", 1637 | "hhvm" 1638 | ], 1639 | "time": "2016-08-18T05:49:44+00:00" 1640 | }, 1641 | { 1642 | "name": "sebastian/exporter", 1643 | "version": "1.2.2", 1644 | "source": { 1645 | "type": "git", 1646 | "url": "https://github.com/sebastianbergmann/exporter.git", 1647 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 1648 | }, 1649 | "dist": { 1650 | "type": "zip", 1651 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 1652 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 1653 | "shasum": "" 1654 | }, 1655 | "require": { 1656 | "php": ">=5.3.3", 1657 | "sebastian/recursion-context": "~1.0" 1658 | }, 1659 | "require-dev": { 1660 | "ext-mbstring": "*", 1661 | "phpunit/phpunit": "~4.4" 1662 | }, 1663 | "type": "library", 1664 | "extra": { 1665 | "branch-alias": { 1666 | "dev-master": "1.3.x-dev" 1667 | } 1668 | }, 1669 | "autoload": { 1670 | "classmap": [ 1671 | "src/" 1672 | ] 1673 | }, 1674 | "notification-url": "https://packagist.org/downloads/", 1675 | "license": [ 1676 | "BSD-3-Clause" 1677 | ], 1678 | "authors": [ 1679 | { 1680 | "name": "Jeff Welch", 1681 | "email": "whatthejeff@gmail.com" 1682 | }, 1683 | { 1684 | "name": "Volker Dusch", 1685 | "email": "github@wallbash.com" 1686 | }, 1687 | { 1688 | "name": "Bernhard Schussek", 1689 | "email": "bschussek@2bepublished.at" 1690 | }, 1691 | { 1692 | "name": "Sebastian Bergmann", 1693 | "email": "sebastian@phpunit.de" 1694 | }, 1695 | { 1696 | "name": "Adam Harvey", 1697 | "email": "aharvey@php.net" 1698 | } 1699 | ], 1700 | "description": "Provides the functionality to export PHP variables for visualization", 1701 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1702 | "keywords": [ 1703 | "export", 1704 | "exporter" 1705 | ], 1706 | "time": "2016-06-17T09:04:28+00:00" 1707 | }, 1708 | { 1709 | "name": "sebastian/global-state", 1710 | "version": "1.1.1", 1711 | "source": { 1712 | "type": "git", 1713 | "url": "https://github.com/sebastianbergmann/global-state.git", 1714 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1715 | }, 1716 | "dist": { 1717 | "type": "zip", 1718 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1719 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1720 | "shasum": "" 1721 | }, 1722 | "require": { 1723 | "php": ">=5.3.3" 1724 | }, 1725 | "require-dev": { 1726 | "phpunit/phpunit": "~4.2" 1727 | }, 1728 | "suggest": { 1729 | "ext-uopz": "*" 1730 | }, 1731 | "type": "library", 1732 | "extra": { 1733 | "branch-alias": { 1734 | "dev-master": "1.0-dev" 1735 | } 1736 | }, 1737 | "autoload": { 1738 | "classmap": [ 1739 | "src/" 1740 | ] 1741 | }, 1742 | "notification-url": "https://packagist.org/downloads/", 1743 | "license": [ 1744 | "BSD-3-Clause" 1745 | ], 1746 | "authors": [ 1747 | { 1748 | "name": "Sebastian Bergmann", 1749 | "email": "sebastian@phpunit.de" 1750 | } 1751 | ], 1752 | "description": "Snapshotting of global state", 1753 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1754 | "keywords": [ 1755 | "global state" 1756 | ], 1757 | "time": "2015-10-12T03:26:01+00:00" 1758 | }, 1759 | { 1760 | "name": "sebastian/recursion-context", 1761 | "version": "1.0.5", 1762 | "source": { 1763 | "type": "git", 1764 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1765 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 1766 | }, 1767 | "dist": { 1768 | "type": "zip", 1769 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1770 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 1771 | "shasum": "" 1772 | }, 1773 | "require": { 1774 | "php": ">=5.3.3" 1775 | }, 1776 | "require-dev": { 1777 | "phpunit/phpunit": "~4.4" 1778 | }, 1779 | "type": "library", 1780 | "extra": { 1781 | "branch-alias": { 1782 | "dev-master": "1.0.x-dev" 1783 | } 1784 | }, 1785 | "autoload": { 1786 | "classmap": [ 1787 | "src/" 1788 | ] 1789 | }, 1790 | "notification-url": "https://packagist.org/downloads/", 1791 | "license": [ 1792 | "BSD-3-Clause" 1793 | ], 1794 | "authors": [ 1795 | { 1796 | "name": "Jeff Welch", 1797 | "email": "whatthejeff@gmail.com" 1798 | }, 1799 | { 1800 | "name": "Sebastian Bergmann", 1801 | "email": "sebastian@phpunit.de" 1802 | }, 1803 | { 1804 | "name": "Adam Harvey", 1805 | "email": "aharvey@php.net" 1806 | } 1807 | ], 1808 | "description": "Provides functionality to recursively process PHP variables", 1809 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1810 | "time": "2016-10-03T07:41:43+00:00" 1811 | }, 1812 | { 1813 | "name": "sebastian/version", 1814 | "version": "1.0.6", 1815 | "source": { 1816 | "type": "git", 1817 | "url": "https://github.com/sebastianbergmann/version.git", 1818 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1819 | }, 1820 | "dist": { 1821 | "type": "zip", 1822 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1823 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1824 | "shasum": "" 1825 | }, 1826 | "type": "library", 1827 | "autoload": { 1828 | "classmap": [ 1829 | "src/" 1830 | ] 1831 | }, 1832 | "notification-url": "https://packagist.org/downloads/", 1833 | "license": [ 1834 | "BSD-3-Clause" 1835 | ], 1836 | "authors": [ 1837 | { 1838 | "name": "Sebastian Bergmann", 1839 | "email": "sebastian@phpunit.de", 1840 | "role": "lead" 1841 | } 1842 | ], 1843 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1844 | "homepage": "https://github.com/sebastianbergmann/version", 1845 | "time": "2015-06-21T13:59:46+00:00" 1846 | }, 1847 | { 1848 | "name": "squizlabs/php_codesniffer", 1849 | "version": "2.5.1", 1850 | "source": { 1851 | "type": "git", 1852 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1853 | "reference": "6731851d6aaf1d0d6c58feff1065227b7fda3ba8" 1854 | }, 1855 | "dist": { 1856 | "type": "zip", 1857 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6731851d6aaf1d0d6c58feff1065227b7fda3ba8", 1858 | "reference": "6731851d6aaf1d0d6c58feff1065227b7fda3ba8", 1859 | "shasum": "" 1860 | }, 1861 | "require": { 1862 | "ext-tokenizer": "*", 1863 | "ext-xmlwriter": "*", 1864 | "php": ">=5.1.2" 1865 | }, 1866 | "require-dev": { 1867 | "phpunit/phpunit": "~4.0" 1868 | }, 1869 | "bin": [ 1870 | "scripts/phpcs", 1871 | "scripts/phpcbf" 1872 | ], 1873 | "type": "library", 1874 | "extra": { 1875 | "branch-alias": { 1876 | "dev-master": "2.x-dev" 1877 | } 1878 | }, 1879 | "autoload": { 1880 | "classmap": [ 1881 | "CodeSniffer.php", 1882 | "CodeSniffer/CLI.php", 1883 | "CodeSniffer/Exception.php", 1884 | "CodeSniffer/File.php", 1885 | "CodeSniffer/Fixer.php", 1886 | "CodeSniffer/Report.php", 1887 | "CodeSniffer/Reporting.php", 1888 | "CodeSniffer/Sniff.php", 1889 | "CodeSniffer/Tokens.php", 1890 | "CodeSniffer/Reports/", 1891 | "CodeSniffer/Tokenizers/", 1892 | "CodeSniffer/DocGenerators/", 1893 | "CodeSniffer/Standards/AbstractPatternSniff.php", 1894 | "CodeSniffer/Standards/AbstractScopeSniff.php", 1895 | "CodeSniffer/Standards/AbstractVariableSniff.php", 1896 | "CodeSniffer/Standards/IncorrectPatternException.php", 1897 | "CodeSniffer/Standards/Generic/Sniffs/", 1898 | "CodeSniffer/Standards/MySource/Sniffs/", 1899 | "CodeSniffer/Standards/PEAR/Sniffs/", 1900 | "CodeSniffer/Standards/PSR1/Sniffs/", 1901 | "CodeSniffer/Standards/PSR2/Sniffs/", 1902 | "CodeSniffer/Standards/Squiz/Sniffs/", 1903 | "CodeSniffer/Standards/Zend/Sniffs/" 1904 | ] 1905 | }, 1906 | "notification-url": "https://packagist.org/downloads/", 1907 | "license": [ 1908 | "BSD-3-Clause" 1909 | ], 1910 | "authors": [ 1911 | { 1912 | "name": "Greg Sherwood", 1913 | "role": "lead" 1914 | } 1915 | ], 1916 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 1917 | "homepage": "http://www.squizlabs.com/php-codesniffer", 1918 | "keywords": [ 1919 | "phpcs", 1920 | "standards" 1921 | ], 1922 | "time": "2016-01-19T23:39:10+00:00" 1923 | }, 1924 | { 1925 | "name": "symfony/console", 1926 | "version": "v3.4.17", 1927 | "source": { 1928 | "type": "git", 1929 | "url": "https://github.com/symfony/console.git", 1930 | "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b" 1931 | }, 1932 | "dist": { 1933 | "type": "zip", 1934 | "url": "https://api.github.com/repos/symfony/console/zipball/3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", 1935 | "reference": "3b2b415d4c48fbefca7dc742aa0a0171bfae4e0b", 1936 | "shasum": "" 1937 | }, 1938 | "require": { 1939 | "php": "^5.5.9|>=7.0.8", 1940 | "symfony/debug": "~2.8|~3.0|~4.0", 1941 | "symfony/polyfill-mbstring": "~1.0" 1942 | }, 1943 | "conflict": { 1944 | "symfony/dependency-injection": "<3.4", 1945 | "symfony/process": "<3.3" 1946 | }, 1947 | "require-dev": { 1948 | "psr/log": "~1.0", 1949 | "symfony/config": "~3.3|~4.0", 1950 | "symfony/dependency-injection": "~3.4|~4.0", 1951 | "symfony/event-dispatcher": "~2.8|~3.0|~4.0", 1952 | "symfony/lock": "~3.4|~4.0", 1953 | "symfony/process": "~3.3|~4.0" 1954 | }, 1955 | "suggest": { 1956 | "psr/log-implementation": "For using the console logger", 1957 | "symfony/event-dispatcher": "", 1958 | "symfony/lock": "", 1959 | "symfony/process": "" 1960 | }, 1961 | "type": "library", 1962 | "extra": { 1963 | "branch-alias": { 1964 | "dev-master": "3.4-dev" 1965 | } 1966 | }, 1967 | "autoload": { 1968 | "psr-4": { 1969 | "Symfony\\Component\\Console\\": "" 1970 | }, 1971 | "exclude-from-classmap": [ 1972 | "/Tests/" 1973 | ] 1974 | }, 1975 | "notification-url": "https://packagist.org/downloads/", 1976 | "license": [ 1977 | "MIT" 1978 | ], 1979 | "authors": [ 1980 | { 1981 | "name": "Fabien Potencier", 1982 | "email": "fabien@symfony.com" 1983 | }, 1984 | { 1985 | "name": "Symfony Community", 1986 | "homepage": "https://symfony.com/contributors" 1987 | } 1988 | ], 1989 | "description": "Symfony Console Component", 1990 | "homepage": "https://symfony.com", 1991 | "time": "2018-10-02T16:33:53+00:00" 1992 | }, 1993 | { 1994 | "name": "symfony/debug", 1995 | "version": "v4.1.6", 1996 | "source": { 1997 | "type": "git", 1998 | "url": "https://github.com/symfony/debug.git", 1999 | "reference": "e3f76ce6198f81994e019bb2b4e533e9de1b9b90" 2000 | }, 2001 | "dist": { 2002 | "type": "zip", 2003 | "url": "https://api.github.com/repos/symfony/debug/zipball/e3f76ce6198f81994e019bb2b4e533e9de1b9b90", 2004 | "reference": "e3f76ce6198f81994e019bb2b4e533e9de1b9b90", 2005 | "shasum": "" 2006 | }, 2007 | "require": { 2008 | "php": "^7.1.3", 2009 | "psr/log": "~1.0" 2010 | }, 2011 | "conflict": { 2012 | "symfony/http-kernel": "<3.4" 2013 | }, 2014 | "require-dev": { 2015 | "symfony/http-kernel": "~3.4|~4.0" 2016 | }, 2017 | "type": "library", 2018 | "extra": { 2019 | "branch-alias": { 2020 | "dev-master": "4.1-dev" 2021 | } 2022 | }, 2023 | "autoload": { 2024 | "psr-4": { 2025 | "Symfony\\Component\\Debug\\": "" 2026 | }, 2027 | "exclude-from-classmap": [ 2028 | "/Tests/" 2029 | ] 2030 | }, 2031 | "notification-url": "https://packagist.org/downloads/", 2032 | "license": [ 2033 | "MIT" 2034 | ], 2035 | "authors": [ 2036 | { 2037 | "name": "Fabien Potencier", 2038 | "email": "fabien@symfony.com" 2039 | }, 2040 | { 2041 | "name": "Symfony Community", 2042 | "homepage": "https://symfony.com/contributors" 2043 | } 2044 | ], 2045 | "description": "Symfony Debug Component", 2046 | "homepage": "https://symfony.com", 2047 | "time": "2018-10-02T16:36:10+00:00" 2048 | }, 2049 | { 2050 | "name": "symfony/event-dispatcher", 2051 | "version": "v3.4.17", 2052 | "source": { 2053 | "type": "git", 2054 | "url": "https://github.com/symfony/event-dispatcher.git", 2055 | "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb" 2056 | }, 2057 | "dist": { 2058 | "type": "zip", 2059 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", 2060 | "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", 2061 | "shasum": "" 2062 | }, 2063 | "require": { 2064 | "php": "^5.5.9|>=7.0.8" 2065 | }, 2066 | "conflict": { 2067 | "symfony/dependency-injection": "<3.3" 2068 | }, 2069 | "require-dev": { 2070 | "psr/log": "~1.0", 2071 | "symfony/config": "~2.8|~3.0|~4.0", 2072 | "symfony/dependency-injection": "~3.3|~4.0", 2073 | "symfony/expression-language": "~2.8|~3.0|~4.0", 2074 | "symfony/stopwatch": "~2.8|~3.0|~4.0" 2075 | }, 2076 | "suggest": { 2077 | "symfony/dependency-injection": "", 2078 | "symfony/http-kernel": "" 2079 | }, 2080 | "type": "library", 2081 | "extra": { 2082 | "branch-alias": { 2083 | "dev-master": "3.4-dev" 2084 | } 2085 | }, 2086 | "autoload": { 2087 | "psr-4": { 2088 | "Symfony\\Component\\EventDispatcher\\": "" 2089 | }, 2090 | "exclude-from-classmap": [ 2091 | "/Tests/" 2092 | ] 2093 | }, 2094 | "notification-url": "https://packagist.org/downloads/", 2095 | "license": [ 2096 | "MIT" 2097 | ], 2098 | "authors": [ 2099 | { 2100 | "name": "Fabien Potencier", 2101 | "email": "fabien@symfony.com" 2102 | }, 2103 | { 2104 | "name": "Symfony Community", 2105 | "homepage": "https://symfony.com/contributors" 2106 | } 2107 | ], 2108 | "description": "Symfony EventDispatcher Component", 2109 | "homepage": "https://symfony.com", 2110 | "time": "2018-07-26T09:06:28+00:00" 2111 | }, 2112 | { 2113 | "name": "symfony/finder", 2114 | "version": "v3.4.17", 2115 | "source": { 2116 | "type": "git", 2117 | "url": "https://github.com/symfony/finder.git", 2118 | "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d" 2119 | }, 2120 | "dist": { 2121 | "type": "zip", 2122 | "url": "https://api.github.com/repos/symfony/finder/zipball/54ba444dddc5bd5708a34bd095ea67c6eb54644d", 2123 | "reference": "54ba444dddc5bd5708a34bd095ea67c6eb54644d", 2124 | "shasum": "" 2125 | }, 2126 | "require": { 2127 | "php": "^5.5.9|>=7.0.8" 2128 | }, 2129 | "type": "library", 2130 | "extra": { 2131 | "branch-alias": { 2132 | "dev-master": "3.4-dev" 2133 | } 2134 | }, 2135 | "autoload": { 2136 | "psr-4": { 2137 | "Symfony\\Component\\Finder\\": "" 2138 | }, 2139 | "exclude-from-classmap": [ 2140 | "/Tests/" 2141 | ] 2142 | }, 2143 | "notification-url": "https://packagist.org/downloads/", 2144 | "license": [ 2145 | "MIT" 2146 | ], 2147 | "authors": [ 2148 | { 2149 | "name": "Fabien Potencier", 2150 | "email": "fabien@symfony.com" 2151 | }, 2152 | { 2153 | "name": "Symfony Community", 2154 | "homepage": "https://symfony.com/contributors" 2155 | } 2156 | ], 2157 | "description": "Symfony Finder Component", 2158 | "homepage": "https://symfony.com", 2159 | "time": "2018-10-03T08:46:40+00:00" 2160 | }, 2161 | { 2162 | "name": "symfony/polyfill-ctype", 2163 | "version": "v1.9.0", 2164 | "source": { 2165 | "type": "git", 2166 | "url": "https://github.com/symfony/polyfill-ctype.git", 2167 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" 2168 | }, 2169 | "dist": { 2170 | "type": "zip", 2171 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", 2172 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", 2173 | "shasum": "" 2174 | }, 2175 | "require": { 2176 | "php": ">=5.3.3" 2177 | }, 2178 | "suggest": { 2179 | "ext-ctype": "For best performance" 2180 | }, 2181 | "type": "library", 2182 | "extra": { 2183 | "branch-alias": { 2184 | "dev-master": "1.9-dev" 2185 | } 2186 | }, 2187 | "autoload": { 2188 | "psr-4": { 2189 | "Symfony\\Polyfill\\Ctype\\": "" 2190 | }, 2191 | "files": [ 2192 | "bootstrap.php" 2193 | ] 2194 | }, 2195 | "notification-url": "https://packagist.org/downloads/", 2196 | "license": [ 2197 | "MIT" 2198 | ], 2199 | "authors": [ 2200 | { 2201 | "name": "Symfony Community", 2202 | "homepage": "https://symfony.com/contributors" 2203 | }, 2204 | { 2205 | "name": "Gert de Pagter", 2206 | "email": "BackEndTea@gmail.com" 2207 | } 2208 | ], 2209 | "description": "Symfony polyfill for ctype functions", 2210 | "homepage": "https://symfony.com", 2211 | "keywords": [ 2212 | "compatibility", 2213 | "ctype", 2214 | "polyfill", 2215 | "portable" 2216 | ], 2217 | "time": "2018-08-06T14:22:27+00:00" 2218 | }, 2219 | { 2220 | "name": "symfony/process", 2221 | "version": "v3.4.17", 2222 | "source": { 2223 | "type": "git", 2224 | "url": "https://github.com/symfony/process.git", 2225 | "reference": "1dc2977afa7d70f90f3fefbcd84152813558910e" 2226 | }, 2227 | "dist": { 2228 | "type": "zip", 2229 | "url": "https://api.github.com/repos/symfony/process/zipball/1dc2977afa7d70f90f3fefbcd84152813558910e", 2230 | "reference": "1dc2977afa7d70f90f3fefbcd84152813558910e", 2231 | "shasum": "" 2232 | }, 2233 | "require": { 2234 | "php": "^5.5.9|>=7.0.8" 2235 | }, 2236 | "type": "library", 2237 | "extra": { 2238 | "branch-alias": { 2239 | "dev-master": "3.4-dev" 2240 | } 2241 | }, 2242 | "autoload": { 2243 | "psr-4": { 2244 | "Symfony\\Component\\Process\\": "" 2245 | }, 2246 | "exclude-from-classmap": [ 2247 | "/Tests/" 2248 | ] 2249 | }, 2250 | "notification-url": "https://packagist.org/downloads/", 2251 | "license": [ 2252 | "MIT" 2253 | ], 2254 | "authors": [ 2255 | { 2256 | "name": "Fabien Potencier", 2257 | "email": "fabien@symfony.com" 2258 | }, 2259 | { 2260 | "name": "Symfony Community", 2261 | "homepage": "https://symfony.com/contributors" 2262 | } 2263 | ], 2264 | "description": "Symfony Process Component", 2265 | "homepage": "https://symfony.com", 2266 | "time": "2018-10-02T12:28:39+00:00" 2267 | }, 2268 | { 2269 | "name": "symfony/yaml", 2270 | "version": "v3.4.17", 2271 | "source": { 2272 | "type": "git", 2273 | "url": "https://github.com/symfony/yaml.git", 2274 | "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f" 2275 | }, 2276 | "dist": { 2277 | "type": "zip", 2278 | "url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f", 2279 | "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f", 2280 | "shasum": "" 2281 | }, 2282 | "require": { 2283 | "php": "^5.5.9|>=7.0.8", 2284 | "symfony/polyfill-ctype": "~1.8" 2285 | }, 2286 | "conflict": { 2287 | "symfony/console": "<3.4" 2288 | }, 2289 | "require-dev": { 2290 | "symfony/console": "~3.4|~4.0" 2291 | }, 2292 | "suggest": { 2293 | "symfony/console": "For validating YAML files using the lint command" 2294 | }, 2295 | "type": "library", 2296 | "extra": { 2297 | "branch-alias": { 2298 | "dev-master": "3.4-dev" 2299 | } 2300 | }, 2301 | "autoload": { 2302 | "psr-4": { 2303 | "Symfony\\Component\\Yaml\\": "" 2304 | }, 2305 | "exclude-from-classmap": [ 2306 | "/Tests/" 2307 | ] 2308 | }, 2309 | "notification-url": "https://packagist.org/downloads/", 2310 | "license": [ 2311 | "MIT" 2312 | ], 2313 | "authors": [ 2314 | { 2315 | "name": "Fabien Potencier", 2316 | "email": "fabien@symfony.com" 2317 | }, 2318 | { 2319 | "name": "Symfony Community", 2320 | "homepage": "https://symfony.com/contributors" 2321 | } 2322 | ], 2323 | "description": "Symfony Yaml Component", 2324 | "homepage": "https://symfony.com", 2325 | "time": "2018-10-02T16:33:53+00:00" 2326 | }, 2327 | { 2328 | "name": "webmozart/assert", 2329 | "version": "1.3.0", 2330 | "source": { 2331 | "type": "git", 2332 | "url": "https://github.com/webmozart/assert.git", 2333 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a" 2334 | }, 2335 | "dist": { 2336 | "type": "zip", 2337 | "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", 2338 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a", 2339 | "shasum": "" 2340 | }, 2341 | "require": { 2342 | "php": "^5.3.3 || ^7.0" 2343 | }, 2344 | "require-dev": { 2345 | "phpunit/phpunit": "^4.6", 2346 | "sebastian/version": "^1.0.1" 2347 | }, 2348 | "type": "library", 2349 | "extra": { 2350 | "branch-alias": { 2351 | "dev-master": "1.3-dev" 2352 | } 2353 | }, 2354 | "autoload": { 2355 | "psr-4": { 2356 | "Webmozart\\Assert\\": "src/" 2357 | } 2358 | }, 2359 | "notification-url": "https://packagist.org/downloads/", 2360 | "license": [ 2361 | "MIT" 2362 | ], 2363 | "authors": [ 2364 | { 2365 | "name": "Bernhard Schussek", 2366 | "email": "bschussek@gmail.com" 2367 | } 2368 | ], 2369 | "description": "Assertions to validate method input/output with nice error messages.", 2370 | "keywords": [ 2371 | "assert", 2372 | "check", 2373 | "validate" 2374 | ], 2375 | "time": "2018-01-29T19:49:41+00:00" 2376 | } 2377 | ], 2378 | "aliases": [], 2379 | "minimum-stability": "stable", 2380 | "stability-flags": [], 2381 | "prefer-stable": false, 2382 | "prefer-lowest": false, 2383 | "platform": { 2384 | "php": ">=5.3.0" 2385 | }, 2386 | "platform-dev": [] 2387 | } 2388 | -------------------------------------------------------------------------------- /examples/.bog.example: -------------------------------------------------------------------------------- 1 | merchant_id='' # Merchant ID in format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 2 | account_id='' # Account ID in format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 3 | page_id='' # Page ID in format XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 4 | http_auth_user='' # Username for HTTP Authorization 5 | http_auth_pass='' # Password for HTTP Authorization 6 | shop_name='' # Shop Name 7 | payment_url='https://sb3d.georgiancard.ge/payment/start.wsm' # Payment init url 8 | lang='ka' # ka, en 9 | currency='981' # 981 - GEL, 840 - USD, 978 - EUR 10 | cert_path='/path/to/certificate' # Path to certificate for checking signature 11 | log_path='/path/to/logs' # Path to logs folder 12 | allowed_ips='127.0.0.1,192.168.1.*' # Comma separated of allowed IP list. (possible specify ip ranges too) 13 | -------------------------------------------------------------------------------- /examples/.cartu.example: -------------------------------------------------------------------------------- 1 | CountryCode='268' # 268 - Georgia 2 | CurrencyCode='981' # 981 - GEL, 840 - USD, 978 - EUR 3 | MerchantName='' # Merchant name and url in format: shop_name!www.shopurl.ge 4 | MerchantURL='' # URL for redirect after payment 5 | MerchantCity='Tbilisi' # Merchant city 6 | MerchantID='' # Merchant ID in format 0000000XXXXXXXX-00000001 7 | xDDDSProxy.Language='01' # 01 - GEO, 02 - ENG, 03 - RUS, 04 - DEU, 05 - TUR 8 | payment_url='https://e-commerce.cartubank.ge/servlet/Process3DSServlet/3dsproxy_init.jsp' # Payment init url 9 | cert_path='/path/to/certificate' # Path to certificate for checking signature 10 | log_path='/path/to/logs' # Path to logs folder 11 | allowed_ips='127.0.0.1,192.168.1.*' # Comma separated of allowed IP list. (possible specify ip ranges too) 12 | -------------------------------------------------------------------------------- /examples/.tbcpay.example: -------------------------------------------------------------------------------- 1 | http_auth_user='' # Username for HTTP Authorization 2 | http_auth_pass='' # Password for HTTP Authorization 3 | log_path='/path/to/logs' # Path to logs folder 4 | allowed_ips='127.0.0.1,192.168.1.*' # Comma separated of allowed IP list. (possible specify ip ranges too) 5 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PHP Code Sniffer 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | warning 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | warning 41 | 42 | 43 | warning 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Please review this TODO comment: %s 63 | warning 64 | 65 | 66 | Please review this FIXME comment: %s 67 | warning 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 102 | 103 | 104 | 105 | 106 | warning 107 | 108 | 109 | 110 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | ./tests/ 29 | 30 | 31 | 32 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/Contracts/Logger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Contracts; 12 | 13 | interface Logger 14 | { 15 | /** 16 | * Log an alert message to the logs. 17 | * 18 | * @param string $message 19 | * @param array $context 20 | * @return void 21 | */ 22 | public function alert($message, array $context = []); 23 | 24 | /** 25 | * Log a critical message to the logs. 26 | * 27 | * @param string $message 28 | * @param array $context 29 | * @return void 30 | */ 31 | public function critical($message, array $context = []); 32 | 33 | /** 34 | * Log an error message to the logs. 35 | * 36 | * @param string $message 37 | * @param array $context 38 | * @return void 39 | */ 40 | public function error($message, array $context = []); 41 | 42 | /** 43 | * Log a warning message to the logs. 44 | * 45 | * @param string $message 46 | * @param array $context 47 | * @return void 48 | */ 49 | public function warning($message, array $context = []); 50 | 51 | /** 52 | * Log a notice to the logs. 53 | * 54 | * @param string $message 55 | * @param array $context 56 | * @return void 57 | */ 58 | public function notice($message, array $context = []); 59 | 60 | /** 61 | * Log an informational message to the logs. 62 | * 63 | * @param string $message 64 | * @param array $context 65 | * @return void 66 | */ 67 | public function info($message, array $context = []); 68 | 69 | /** 70 | * Log a debug message to the logs. 71 | * 72 | * @param string $message 73 | * @param array $context 74 | * @return void 75 | */ 76 | public function debug($message, array $context = []); 77 | 78 | /** 79 | * Log a message to the logs. 80 | * 81 | * @param string $level 82 | * @param string $message 83 | * @param array $context 84 | * @return void 85 | */ 86 | public function log($level, $message, array $context = []); 87 | 88 | /** 89 | * Register a file log handler. 90 | * 91 | * @param string $path 92 | * @param string $level 93 | * @return void 94 | */ 95 | public function useFiles($path, $level = 'debug'); 96 | 97 | /** 98 | * Register a daily file log handler. 99 | * 100 | * @param string $path 101 | * @param int $days 102 | * @param string $level 103 | * @return void 104 | */ 105 | public function useDailyFiles($path, $days = 0, $level = 'debug'); 106 | } 107 | -------------------------------------------------------------------------------- /src/Contracts/Options.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Contracts; 12 | 13 | interface Options 14 | { 15 | 16 | /** 17 | * Constructor 18 | * 19 | * @param array $data Options 20 | * 21 | * @return void 22 | */ 23 | public function __construct($data = []); 24 | 25 | /** 26 | * Get option 27 | * 28 | * @param string $name Option name 29 | * @param mixed $default Default value 30 | * 31 | * @return mixed 32 | */ 33 | public function get($name, $default = null); 34 | 35 | /** 36 | * Set option 37 | * 38 | * @param string $name Option name 39 | * @param array $value Option value 40 | * 41 | * @return void 42 | */ 43 | public function set($name, $value); 44 | } 45 | -------------------------------------------------------------------------------- /src/Logger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment; 12 | 13 | use InvalidArgumentException; 14 | use Longman\GeoPayment\Contracts\Logger as LoggerContract; 15 | use Monolog\Handler\SyslogHandler; 16 | use Monolog\Handler\StreamHandler; 17 | use Monolog\Logger as MonologLogger; 18 | use Monolog\Formatter\LineFormatter; 19 | use Monolog\Handler\ErrorLogHandler; 20 | use Monolog\Handler\RotatingFileHandler; 21 | use Psr\Log\LoggerInterface as PsrLoggerInterface; 22 | 23 | /** 24 | * Logger class. 25 | * 26 | */ 27 | class Logger implements LoggerContract, PsrLoggerInterface 28 | { 29 | /** 30 | * The Monolog logger instance. 31 | * 32 | * @var \Monolog\Logger 33 | */ 34 | protected $monolog; 35 | 36 | /** 37 | * The Log levels. 38 | * 39 | * @var array 40 | */ 41 | protected $levels = [ 42 | 'debug' => MonologLogger::DEBUG, 43 | 'info' => MonologLogger::INFO, 44 | 'notice' => MonologLogger::NOTICE, 45 | 'warning' => MonologLogger::WARNING, 46 | 'error' => MonologLogger::ERROR, 47 | 'critical' => MonologLogger::CRITICAL, 48 | 'alert' => MonologLogger::ALERT, 49 | 'emergency' => MonologLogger::EMERGENCY, 50 | ]; 51 | 52 | /** 53 | * Create a new log writer instance. 54 | * 55 | * @param \Monolog\Logger $monolog 56 | * @return void 57 | */ 58 | public function __construct(MonologLogger $monolog) 59 | { 60 | $this->monolog = $monolog; 61 | } 62 | 63 | /** 64 | * Log an emergency message to the logs. 65 | * 66 | * @param string $message 67 | * @param array $context 68 | * @return void 69 | */ 70 | public function emergency($message, array $context = []) 71 | { 72 | return $this->writeLog(__FUNCTION__, $message, $context); 73 | } 74 | 75 | /** 76 | * Log an alert message to the logs. 77 | * 78 | * @param string $message 79 | * @param array $context 80 | * @return void 81 | */ 82 | public function alert($message, array $context = []) 83 | { 84 | return $this->writeLog(__FUNCTION__, $message, $context); 85 | } 86 | 87 | /** 88 | * Log a critical message to the logs. 89 | * 90 | * @param string $message 91 | * @param array $context 92 | * @return void 93 | */ 94 | public function critical($message, array $context = []) 95 | { 96 | return $this->writeLog(__FUNCTION__, $message, $context); 97 | } 98 | 99 | /** 100 | * Log an error message to the logs. 101 | * 102 | * @param string $message 103 | * @param array $context 104 | * @return void 105 | */ 106 | public function error($message, array $context = []) 107 | { 108 | return $this->writeLog(__FUNCTION__, $message, $context); 109 | } 110 | 111 | /** 112 | * Log a warning message to the logs. 113 | * 114 | * @param string $message 115 | * @param array $context 116 | * @return void 117 | */ 118 | public function warning($message, array $context = []) 119 | { 120 | return $this->writeLog(__FUNCTION__, $message, $context); 121 | } 122 | 123 | /** 124 | * Log a notice to the logs. 125 | * 126 | * @param string $message 127 | * @param array $context 128 | * @return void 129 | */ 130 | public function notice($message, array $context = []) 131 | { 132 | return $this->writeLog(__FUNCTION__, $message, $context); 133 | } 134 | 135 | /** 136 | * Log an informational message to the logs. 137 | * 138 | * @param string $message 139 | * @param array $context 140 | * @return void 141 | */ 142 | public function info($message, array $context = []) 143 | { 144 | return $this->writeLog(__FUNCTION__, $message, $context); 145 | } 146 | 147 | /** 148 | * Log a debug message to the logs. 149 | * 150 | * @param string $message 151 | * @param array $context 152 | * @return void 153 | */ 154 | public function debug($message, array $context = []) 155 | { 156 | return $this->writeLog(__FUNCTION__, $message, $context); 157 | } 158 | 159 | /** 160 | * Log a message to the logs. 161 | * 162 | * @param string $level 163 | * @param string $message 164 | * @param array $context 165 | * @return void 166 | */ 167 | public function log($level, $message, array $context = []) 168 | { 169 | return $this->writeLog($level, $message, $context); 170 | } 171 | 172 | /** 173 | * Dynamically pass log calls into the writer. 174 | * 175 | * @param string $level 176 | * @param string $message 177 | * @param array $context 178 | * @return void 179 | */ 180 | public function write($level, $message, array $context = []) 181 | { 182 | return $this->writeLog($level, $message, $context); 183 | } 184 | 185 | /** 186 | * Write a message to Monolog. 187 | * 188 | * @param string $level 189 | * @param string $message 190 | * @param array $context 191 | * @return void 192 | */ 193 | protected function writeLog($level, $message, $context) 194 | { 195 | $this->monolog->{$level}($message, $context); 196 | } 197 | 198 | /** 199 | * Register a file log handler. 200 | * 201 | * @param string $path 202 | * @param string $level 203 | * @return void 204 | */ 205 | public function useFiles($path, $level = 'debug') 206 | { 207 | $this->monolog->pushHandler($handler = new StreamHandler($path, $this->parseLevel($level))); 208 | 209 | $handler->setFormatter($this->getDefaultFormatter()); 210 | } 211 | 212 | /** 213 | * Register a daily file log handler. 214 | * 215 | * @param string $path 216 | * @param int $days 217 | * @param string $level 218 | * @return void 219 | */ 220 | public function useDailyFiles($path, $days = 0, $level = 'debug') 221 | { 222 | $this->monolog->pushHandler( 223 | $handler = new RotatingFileHandler($path, $days, $this->parseLevel($level)) 224 | ); 225 | 226 | $handler->setFormatter($this->getDefaultFormatter()); 227 | } 228 | 229 | /** 230 | * Register a Syslog handler. 231 | * 232 | * @param string $name 233 | * @param string $level 234 | * @return \Psr\Log\LoggerInterface 235 | */ 236 | public function useSyslog($name = 'laravel', $level = 'debug') 237 | { 238 | return $this->monolog->pushHandler(new SyslogHandler($name, LOG_USER, $level)); 239 | } 240 | 241 | /** 242 | * Register an error_log handler. 243 | * 244 | * @param string $level 245 | * @param int $messageType 246 | * @return void 247 | */ 248 | public function useErrorLog($level = 'debug', $messageType = ErrorLogHandler::OPERATING_SYSTEM) 249 | { 250 | $this->monolog->pushHandler( 251 | $handler = new ErrorLogHandler($messageType, $this->parseLevel($level)) 252 | ); 253 | 254 | $handler->setFormatter($this->getDefaultFormatter()); 255 | } 256 | 257 | /** 258 | * Parse the string level into a Monolog constant. 259 | * 260 | * @param string $level 261 | * @return int 262 | * 263 | * @throws \InvalidArgumentException 264 | */ 265 | protected function parseLevel($level) 266 | { 267 | if (isset($this->levels[$level])) { 268 | return $this->levels[$level]; 269 | } 270 | 271 | throw new InvalidArgumentException('Invalid log level.'); 272 | } 273 | 274 | /** 275 | * Get the underlying Monolog instance. 276 | * 277 | * @return \Monolog\Logger 278 | */ 279 | public function getMonolog() 280 | { 281 | return $this->monolog; 282 | } 283 | 284 | /** 285 | * Get a defaut Monolog formatter instance. 286 | * 287 | * @return \Monolog\Formatter\LineFormatter 288 | */ 289 | protected function getDefaultFormatter() 290 | { 291 | return new LineFormatter("[%datetime%] [%ip%] %channel%.%level_name%: %message% %context% %extra%\n", null, false, true); 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /src/Options.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment; 12 | 13 | use Longman\GeoPayment\Contracts\Options as OptionsContract; 14 | 15 | /** 16 | * Class for holding options data 17 | * 18 | */ 19 | class Options implements OptionsContract 20 | { 21 | 22 | /** 23 | * @var array 24 | */ 25 | protected $data; 26 | 27 | /** 28 | * Constructor 29 | * 30 | * @param array $data Options 31 | * 32 | * @return void 33 | */ 34 | public function __construct($data = []) 35 | { 36 | $this->data = $data; 37 | } 38 | 39 | /** 40 | * Get option 41 | * 42 | * @param string $name Option name 43 | * @param mixed $default Default value 44 | * 45 | * @return mixed 46 | */ 47 | public function get($name, $default = null) 48 | { 49 | if (isset($this->data[$name])) { 50 | return $this->data[$name]; 51 | } 52 | 53 | if (isset($_ENV[$name])) { 54 | return $_ENV[$name]; 55 | } 56 | 57 | return $default; 58 | } 59 | 60 | /** 61 | * Set option 62 | * 63 | * @param string $name Option name 64 | * @param array $value Option value 65 | * 66 | * @return void 67 | */ 68 | public function set($name, $value) 69 | { 70 | $this->data[$name] = $value; 71 | return $this; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Payment.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment; 12 | 13 | use Dotenv\Dotenv; 14 | use InvalidArgumentException; 15 | use Longman\GeoPayment\Contracts\Options as OptionsContract; 16 | use Longman\GeoPayment\Contracts\Logger as LoggerContract; 17 | use Longman\GeoPayment\Provider\AbstractProvider; 18 | use RuntimeException; 19 | use Symfony\Component\HttpFoundation\Request; 20 | use Monolog\Logger as MonologLogger; 21 | 22 | /** 23 | * Universal payment class. 24 | * 25 | */ 26 | class Payment 27 | { 28 | 29 | /** 30 | * @var \Longman\GeoPayment\Provider\Pay\AbstractProvider 31 | */ 32 | protected $provider; 33 | 34 | /** 35 | * Payment type 36 | * 37 | * @var string 38 | */ 39 | protected $type = 'card'; 40 | 41 | /** 42 | * @var \Longman\GeoPayment\Logger 43 | */ 44 | protected $logger; 45 | 46 | /** 47 | * @var \Longman\GeoPayment\Options 48 | */ 49 | protected $options; 50 | 51 | /** 52 | * @var \Symfony\Component\HttpFoundation\Request 53 | */ 54 | protected $request; 55 | 56 | /** 57 | * @var bool 58 | */ 59 | protected $debug; 60 | 61 | /** 62 | * @var string 63 | */ 64 | const TYPE_CARD = 'Card'; 65 | 66 | /** 67 | * @var string 68 | */ 69 | const TYPE_PAY = 'Pay'; 70 | 71 | 72 | /** 73 | * Constructor 74 | * 75 | * @param string $provider Provider name 76 | * @param array $options Options 77 | * 78 | * @return void 79 | */ 80 | public function __construct($provider = null, $type = self::TYPE_CARD, array $options = []) 81 | { 82 | $this->type = $type; 83 | 84 | $this->createOptionsInstance($options); 85 | 86 | $this->createRequestInstance(); 87 | 88 | if ($config_path = $this->options->get('config_path')) { 89 | $this->setConfigFile($config_path); 90 | } 91 | 92 | if ($log_path = $this->options->get('log_path')) { 93 | $this->createLoggerInstance($log_path, $provider); 94 | } 95 | 96 | if ($provider) { 97 | $this->createProviderInstance($provider); 98 | } 99 | 100 | } 101 | 102 | /** 103 | * Create Request instance 104 | * 105 | * @return \Longman\GeoPayment\Payment 106 | */ 107 | protected function createRequestInstance() 108 | { 109 | $this->setRequestInstance(Request::createFromGlobals()); 110 | return $this; 111 | } 112 | 113 | /** 114 | * Set Request instance 115 | * 116 | * @param \Symfony\Component\HttpFoundation\Request $request Request instance 117 | * 118 | * @return \Longman\GeoPayment\Payment 119 | */ 120 | public function setRequestInstance(Request $request) 121 | { 122 | $this->request = $request; 123 | return $this; 124 | } 125 | 126 | 127 | /** 128 | * Create Options instance 129 | * 130 | * @param array $options Options array 131 | * 132 | * @return \Longman\GeoPayment\Payment 133 | */ 134 | protected function createOptionsInstance(array $options) 135 | { 136 | $this->setOptionsInstance(new Options($options)); 137 | return $this; 138 | } 139 | 140 | /** 141 | * Set Options instance 142 | * 143 | * @param \Longman\GeoPayment\Contracts\Options $options Options instance 144 | * 145 | * @return \Longman\GeoPayment\Payment 146 | */ 147 | public function setOptionsInstance(OptionsContract $options) 148 | { 149 | $this->options = $options; 150 | return $this; 151 | } 152 | 153 | /** 154 | * Configure logger object 155 | * 156 | * @param string $path Path to log folder 157 | * @param string $provider Provider name 158 | * 159 | * @return \Longman\GeoPayment\Payment 160 | */ 161 | protected function createLoggerInstance($path, $provider = null) 162 | { 163 | if (!$provider) { 164 | $provider = 'default'; 165 | } 166 | 167 | $log_path = $path . '/' . $provider . '.log'; 168 | $log_level = $this->options->get('log_level', 'debug'); 169 | 170 | $logger = new Logger(new MonologLogger($log_level)); 171 | 172 | $logger->getMonolog()->pushProcessor(function ($record) { 173 | $record['ip'] = $this->request->server->get('REMOTE_ADDR'); 174 | $record['extra']['GET'] = $this->request->query->all(); 175 | $record['extra']['POST'] = $this->request->request->all(); 176 | return $record; 177 | }); 178 | 179 | $logger->useDailyFiles($log_path, 0); 180 | 181 | $this->setLoggerInstance($logger); 182 | 183 | return $this; 184 | } 185 | 186 | /** 187 | * Set Logger instance 188 | * 189 | * @param \Longman\GeoPayment\Contracts\Logger $logger Logger instance 190 | * 191 | * @return \Longman\GeoPayment\Payment 192 | */ 193 | public function setLoggerInstance(LoggerContract $logger) 194 | { 195 | $this->logger = $logger; 196 | return $this; 197 | } 198 | 199 | 200 | /** 201 | * Parse config dotfile 202 | * 203 | * @param string $path Config file path 204 | * 205 | * @return \Longman\GeoPayment\Payment 206 | */ 207 | public function setConfigFile($path) 208 | { 209 | if (!is_file($path)) { 210 | throw new InvalidArgumentException('Config path "' . $path . '" is not a file'); 211 | } 212 | 213 | $folder = dirname($path); 214 | $file = pathinfo($path, PATHINFO_BASENAME); 215 | $dotenv = new Dotenv($folder, $file); 216 | $dotenv->load(); 217 | return $this; 218 | } 219 | 220 | /** 221 | * Create provider instance 222 | * 223 | * @param string $provider Provider name 224 | * 225 | * @return \Longman\GeoPayment\Payment 226 | * 227 | * @throws \InvalidArgumentException When the provider not found 228 | */ 229 | protected function createProviderInstance($provider) 230 | { 231 | $class = '\Longman\GeoPayment\Provider\\'.ucfirst($this->type).'\\' . ucfirst($provider) . '\Provider'; 232 | if (!class_exists($class)) { 233 | throw new InvalidArgumentException('Provider "' . $provider . '" not found!'); 234 | } 235 | 236 | $this->setProviderInstance(new $class($this->options, $this->request, $this->logger)); 237 | 238 | return $this; 239 | } 240 | 241 | /** 242 | * Set provider instance 243 | * 244 | * @param \Longman\GeoPayment\Provider\Pay\AbstractProvider $provider Provider instance 245 | * 246 | * @return \Longman\GeoPayment\Payment 247 | */ 248 | public function setProviderInstance(AbstractProvider $provider) 249 | { 250 | $this->provider = $provider; 251 | return $this; 252 | } 253 | 254 | 255 | /** 256 | * Get Option value 257 | * 258 | * @param string $name Option name 259 | * @param mixed $default Default value 260 | * 261 | * @return mixed 262 | */ 263 | public function getOption($name = null, $default = null) 264 | { 265 | return $this->options->get($name, $default); 266 | } 267 | 268 | 269 | /** 270 | * Get Options object 271 | * 272 | * @return mixed|\Longman\GeoPayment\Options 273 | */ 274 | public function getOptions() 275 | { 276 | return $this->options; 277 | } 278 | 279 | /** 280 | * Get request instance 281 | * 282 | * @return \Symfony\Component\HttpFoundation\Request 283 | */ 284 | public function getRequest() 285 | { 286 | return $this->request; 287 | } 288 | 289 | /** 290 | * Get provider instance 291 | * 292 | * @return \Longman\GeoPayment\Provider\Pay\AbstractProvider 293 | */ 294 | public function getProvider() 295 | { 296 | return $this->provider; 297 | } 298 | 299 | /** 300 | * Pass function calls to provider instance 301 | * 302 | * @return mixed 303 | * 304 | * @throws \RuntimeException When the provider can not call method 305 | */ 306 | public function __call($method, $args) 307 | { 308 | if (!$this->provider instanceof AbstractProvider) { 309 | throw new RuntimeException('Provider not initialized'); 310 | } 311 | 312 | if (!is_callable([$this->provider, $method])) { 313 | throw new RuntimeException('Provider "' . $this->provider->getName() . '" does not have callable method "' . $method . '"'); 314 | } 315 | 316 | return call_user_func_array([$this->provider, $method], $args); 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /src/Provider/AbstractProvider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Provider; 12 | 13 | use Longman\GeoPayment\Logger; 14 | use Longman\GeoPayment\Options; 15 | use Symfony\Component\HttpFoundation\RedirectResponse; 16 | use Symfony\Component\HttpFoundation\Request; 17 | use Symfony\Component\HttpFoundation\Response; 18 | use UnexpectedValueException; 19 | 20 | /** 21 | * Abstract Provider class 22 | * 23 | */ 24 | abstract class AbstractProvider 25 | { 26 | 27 | /** 28 | * Provider name 29 | * 30 | * @var string 31 | */ 32 | protected $name; 33 | 34 | /** 35 | * Mode (depends on bank) 36 | * 37 | * @var string 38 | */ 39 | protected $mode; 40 | 41 | /** 42 | * @var \Longman\GeoPayment\Logger 43 | */ 44 | protected $logger; 45 | 46 | /** 47 | * @var \Longman\GeoPayment\Options 48 | */ 49 | protected $options; 50 | 51 | /** 52 | * @var \Symfony\Component\HttpFoundation\Request 53 | */ 54 | protected $request; 55 | 56 | /** 57 | * Custom parameters 58 | * 59 | * @var array 60 | */ 61 | protected $params = []; 62 | 63 | /** 64 | * Constructor 65 | * 66 | * @param \Longman\GeoPayment\Options $options Options object 67 | * @param \Symfony\Component\HttpFoundation\Request $request Request object 68 | * @param \Longman\GeoPayment\Logger $logger Logger object 69 | * 70 | * @return void 71 | */ 72 | public function __construct(Options $options, Request $request, Logger $logger) 73 | { 74 | $this->options = $options; 75 | $this->request = $request; 76 | $this->logger = $logger; 77 | } 78 | 79 | /** 80 | * Get provider name 81 | * 82 | * @return string 83 | */ 84 | public function getName() 85 | { 86 | return $this->name; 87 | } 88 | 89 | /** 90 | * Add custom parameter to url 91 | * 92 | * @param string $name Parameter name 93 | * @param mixed $value Parameter value 94 | * 95 | * @return \Longman\GeoPayment\Provider\Pay\AbstractProvider 96 | */ 97 | public function addParam($name, $value) 98 | { 99 | $this->params[$name] = $value; 100 | return $this; 101 | } 102 | 103 | /** 104 | * Get parameter from params, otherwise get request field 105 | * 106 | * @param string $name Parameter name 107 | * @param mixed $default Parameter default value 108 | * 109 | * @return mixed 110 | */ 111 | public function getParam($name, $default = null) 112 | { 113 | if (isset($this->params[$name])) { 114 | return $this->params[$name]; 115 | } 116 | $name = str_replace('.', '_', $name); 117 | return $this->request->get($name, $default); 118 | } 119 | 120 | /** 121 | * Redirect to url 122 | * 123 | * @param string $url Url to redirect 124 | * 125 | * @return void 126 | */ 127 | public function redirect($url = null) 128 | { 129 | if (is_null($url)) { 130 | $url = $this->getPaymentUrl(); 131 | } 132 | 133 | RedirectResponse::create($url)->send(); 134 | 135 | exit(); 136 | } 137 | 138 | /** 139 | * Set mode 140 | * 141 | * @param string $mode 142 | * 143 | * @return \Longman\GeoPayment\Provider\Pay\AbstractProvider 144 | */ 145 | public function setMode($mode) 146 | { 147 | $this->mode = $mode; 148 | return $this; 149 | } 150 | 151 | /** 152 | * Get mode 153 | * 154 | * @return string 155 | */ 156 | public function getMode() 157 | { 158 | return $this->mode; 159 | } 160 | 161 | /** 162 | * Check HTTP Authorization 163 | * 164 | * @return void 165 | */ 166 | public function checkHttpAuth() 167 | { 168 | if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) { 169 | header('WWW-Authenticate: Basic realm="' . $this->options->get('shop_name', 'Online Shop') . '"'); 170 | header('HTTP/1.0 401 Unauthorized'); 171 | $this->logger->warning('HTTP Authorization cancelled'); 172 | echo 'Access denied'; 173 | exit; 174 | } else { 175 | if ($_SERVER['PHP_AUTH_USER'] != $this->options->get('http_auth_user') 176 | || $_SERVER['PHP_AUTH_PW'] != $this->options->get('http_auth_pass') 177 | ) { 178 | $this->logger->warning('HTTP Authorization error: wrong username or password'); 179 | header('HTTP/1.0 401 Unauthorized'); 180 | echo 'Access denied'; 181 | exit; 182 | } 183 | } 184 | } 185 | 186 | 187 | /** 188 | * Check if IP Address Allowed 189 | * 190 | * @return void 191 | */ 192 | public function checkIpAllowed() 193 | { 194 | $ip_list = $this->options->get('allowed_ips'); 195 | if ($ip_list) { 196 | $client_ip = $this->request->getClientIp(); 197 | $status = Ip::match($client_ip, explode(',', $ip_list)); 198 | if (!$status) { 199 | $this->logger->warning('IP Not Allowed'); 200 | $response = Response::create('Access denied for IP: '.$client_ip, 403); 201 | $response->send(); 202 | exit(); 203 | } 204 | } 205 | } 206 | 207 | /** 208 | * Parse XML string 209 | * 210 | * @param string $xml 211 | * 212 | * @return \SimpleXMLElement 213 | * 214 | * @throws \UnexpectedValueException 215 | */ 216 | protected function parseXml($xml) 217 | { 218 | libxml_use_internal_errors(true); 219 | $object = simplexml_load_string($xml); 220 | $errors = libxml_get_errors(); 221 | libxml_clear_errors(); 222 | if ($errors) { 223 | $err = []; 224 | foreach ($errors as $err_obj) { 225 | $err[] = $err_obj->message; 226 | } 227 | $err_str = implode(', ', $err); 228 | 229 | $this->logger->error('XML parsing error. ' . $err_str); 230 | throw new UnexpectedValueException('XML string is invalid. libXML Errors: ' . $err_str); 231 | } 232 | 233 | return $object; 234 | } 235 | 236 | /** 237 | * Perform amount to minor (eg. cents) 238 | * 239 | * @param float $amount Amount in major units (eg. dollars) 240 | * 241 | * @return int 242 | */ 243 | public function amtToMinor($amount) 244 | { 245 | if ($amount == 0) { 246 | return 0; 247 | } 248 | $amount = str_replace([',', ' '], ['.', ''], trim($amount)); 249 | $amount *= 100; 250 | 251 | return intval($amount); 252 | } 253 | 254 | 255 | /** 256 | * Perform amount to major (dollars) 257 | * 258 | * @param int $amount Amount in minor units (eg. cents) 259 | * 260 | * @return float 261 | */ 262 | public function amtToMajor($amount) 263 | { 264 | if ($amount == 0) { 265 | return $this->format($amount); 266 | } 267 | $amount = $amount / 100; 268 | return $this->format($amount); 269 | } 270 | 271 | 272 | 273 | /** 274 | * Format amount 275 | * 276 | * @param mixed $amount Amount 277 | * @param int $decimals Sets the number of decimal points. 278 | * 279 | * @return float 280 | */ 281 | public function format($amount = 0, $decimals = 2) 282 | { 283 | $amount = str_replace([',', ' '], ['.', ''], trim($amount)); 284 | $amount = (float) $amount; 285 | $amount = ($amount * 100) / 100; 286 | $amount = number_format($amount, $decimals, '.', ''); 287 | return (float) $amount; 288 | } 289 | 290 | /** 291 | * Get request url 292 | * 293 | * @return string 294 | */ 295 | protected function getRequestUrl() 296 | { 297 | return $this->request->getUri(); 298 | } 299 | 300 | /** 301 | * Encode url string 302 | * 303 | * @param string $str 304 | * 305 | * @return string Encoded string 306 | */ 307 | protected function encode($str) 308 | { 309 | return rawurlencode($str); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /src/Provider/AbstractXMLResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Longman\GeoPayment\Provider; 11 | 12 | use Symfony\Component\HttpFoundation\Response; 13 | 14 | /** 15 | * Abstract XML response class 16 | * 17 | */ 18 | abstract class AbstractXMLResponse 19 | { 20 | 21 | /** 22 | * Response mode (Depends on bank) 23 | * 24 | * @var string 25 | */ 26 | protected $mode; 27 | 28 | /** 29 | * Response body 30 | * 31 | * @var string 32 | */ 33 | protected $content; 34 | 35 | /** 36 | * Response object 37 | * 38 | * @var \Symfony\Component\HttpFoundation\Response 39 | */ 40 | protected $response; 41 | 42 | /** 43 | * Constructor 44 | * 45 | * @param string $mode Response mode 46 | * 47 | * @return void 48 | */ 49 | public function __construct($mode) 50 | { 51 | $this->mode = $mode; 52 | $this->response = new Response('', Response::HTTP_OK, ['content-type' => 'text/xml']); 53 | } 54 | 55 | /** 56 | * Get response body 57 | * 58 | * @return string 59 | */ 60 | public function getContent() 61 | { 62 | return $this->content; 63 | } 64 | 65 | /** 66 | * Get response object 67 | * 68 | * @return \Symfony\Component\HttpFoundation\Response 69 | */ 70 | public function getResponse() 71 | { 72 | return $this->response; 73 | } 74 | 75 | /** 76 | * Send response to browser 77 | * 78 | * @return void 79 | */ 80 | public function send() 81 | { 82 | $this->response->setContent($this->content); 83 | 84 | $this->response->send(); 85 | 86 | exit; 87 | } 88 | 89 | /** 90 | * Prepare response body 91 | * 92 | * @return string Response body 93 | */ 94 | protected function prepare($string) 95 | { 96 | $string = preg_replace('##', '', $string); 97 | return $string; 98 | } 99 | 100 | /** 101 | * Clean string 102 | * 103 | * @return string 104 | */ 105 | protected function clean($var, $substr = null) 106 | { 107 | $var = htmlspecialchars($var); 108 | if ($substr) { 109 | $var = mb_substr($var, 0, $substr, 'UTF-8'); 110 | } 111 | 112 | return $var; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Provider/Card/Bog/Provider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Provider\Card\Bog; 12 | 13 | use Longman\GeoPayment\Options; 14 | use Longman\GeoPayment\Provider\AbstractProvider; 15 | use Longman\GeoPayment\Provider\Card\Bog\XMLResponse; 16 | use InvalidArgumentException; 17 | 18 | class Provider extends AbstractProvider 19 | { 20 | protected $name = 'bog'; 21 | 22 | protected $mode = 'redirect'; 23 | 24 | const DEF_PAYMENT_URL = 'https://sb3d.georgiancard.ge/payment/start.wsm'; 25 | const DEF_CURRENCY = '981'; 26 | const DEF_LANG = 'ka'; 27 | 28 | public function setSuccessUrl($url) 29 | { 30 | $this->options->set('back_url_s', $url); 31 | return $this; 32 | } 33 | 34 | public function setFailUrl($url) 35 | { 36 | $this->options->set('back_url_f', $url); 37 | return $this; 38 | } 39 | 40 | public function checkSignature() 41 | { 42 | $signature = $this->request->get('signature'); 43 | if (!$signature) { 44 | $this->sendErrorResponse('Signature is missing!'); 45 | } 46 | 47 | $request_url = $url = $this->getRequestUrl(); 48 | 49 | $url = preg_replace('#&signature=.*$#', '', $url); 50 | $url = rawurldecode($url); 51 | 52 | $cert_file = $this->options->get('cert_path'); 53 | $cert = file_get_contents($cert_file); 54 | $key = openssl_pkey_get_public($cert); 55 | //dump(openssl_pkey_get_details($key)); 56 | 57 | $signature = base64_decode($signature); 58 | $valid = openssl_verify($url, $signature, $key, OPENSSL_ALGO_SHA1); 59 | 60 | if ($valid !== 1) { 61 | $this->sendErrorResponse('Signature is invalid!'); 62 | } 63 | 64 | //$this->logger->info('url: '.$url); 65 | 66 | return $this; 67 | } 68 | 69 | public function getPaymentUrl() 70 | { 71 | $gateway = $this->options->get('payment_url', self::DEF_PAYMENT_URL); 72 | 73 | $gateway .= '?lang=' . $this->encode($this->options->get('lang', self::DEF_LANG)); 74 | 75 | $gateway .= '&page_id=' . $this->encode($this->options->get('page_id')); 76 | $gateway .= '&merch_id=' . $this->encode($this->options->get('merchant_id')); 77 | 78 | $gateway .= '&back_url_s=' . $this->encode($this->options->get('back_url_s')); 79 | $gateway .= '&back_url_f=' . $this->encode($this->options->get('back_url_f')); 80 | 81 | foreach ($this->params as $key => $value) { 82 | $gateway .= '&o.' . $key . '=' . $this->encode($value); 83 | } 84 | 85 | return $gateway; 86 | } 87 | 88 | public function sendSuccessResponse($data = []) 89 | { 90 | $response = new XMLResponse($this->mode); 91 | 92 | if ($this->mode == 'check') { 93 | $data['account_id'] = $this->options->get('account_id'); 94 | $data['currency'] = $this->options->get('currency', self::DEF_CURRENCY); 95 | 96 | if (empty($data['amount'])) { 97 | $this->logger->debug('amount not defined', ['data' => $data]); 98 | throw new InvalidArgumentException('amount not defined'); 99 | } 100 | 101 | if (empty($data['short_desc'])) { 102 | $this->logger->debug('short_desc not defined', ['data' => $data]); 103 | throw new InvalidArgumentException('short_desc not defined'); 104 | } 105 | 106 | if (empty($data['long_desc'])) { 107 | $this->logger->debug('long_desc not defined', ['data' => $data]); 108 | throw new InvalidArgumentException('long_desc not defined'); 109 | } 110 | } 111 | 112 | $this->logger->debug('sendSuccessResponse: ' . $this->mode, ['data' => $data]); 113 | 114 | $response->success($data)->send(); 115 | } 116 | 117 | public function sendErrorResponse($error = 'Unable to accept this payment') 118 | { 119 | $this->logger->debug('sendErrorResponse: ' . $error); 120 | $response = new XMLResponse($this->mode); 121 | $response->error(2, $error)->send(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Provider/Card/Bog/XMLResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Longman\GeoPayment\Provider\Card\Bog; 11 | 12 | use Longman\GeoPayment\Provider\AbstractXMLResponse; 13 | 14 | class XMLResponse extends AbstractXMLResponse 15 | { 16 | 17 | public function error($code = 2, $desc = 'Unable to accept this payment') 18 | { 19 | if ($this->mode == 'check') { 20 | $this->content = $this->getCheckErrorBody($code, $desc); 21 | } elseif ($this->mode == 'reg') { 22 | $this->content = $this->getRegErrorBody($code, $desc); 23 | } 24 | return $this; 25 | } 26 | 27 | public function success($data = []) 28 | { 29 | if ($this->mode == 'check') { 30 | $this->content = $this->getCheckSuccessBody($data); 31 | } elseif ($this->mode == 'reg') { 32 | $this->content = $this->getRegSuccessBody($data); 33 | } 34 | return $this; 35 | } 36 | 37 | protected function getCheckSuccessBody($data) 38 | { 39 | $trx_id = $this->clean($data['trx_id'], 50); 40 | $short_desc = $this->clean($data['short_desc'], 30); 41 | $long_desc = $this->clean($data['long_desc'], 125); 42 | $account_id = $this->clean($data['account_id'], 32); 43 | $amount = intval($data['amount']); 44 | $currency = $this->clean($data['currency']); 45 | 46 | $content = << 48 | 49 | 1 50 | OK 51 | 52 | 53 | {$trx_id} 54 | 55 | 56 | {$short_desc} 57 | 58 | {$long_desc} 59 | 60 | 61 | 62 | 63 | {$account_id} 64 | 65 | {$amount} 66 | 67 | {$currency} 68 | 69 | 2 70 | 71 | 72 | 73 | XML; 74 | 75 | return $content; 76 | } 77 | 78 | protected function getCheckErrorBody($code, $desc = 'Unable to accept this payment') 79 | { 80 | $desc = $this->clean($desc, 125); 81 | 82 | $content = << 84 | 85 | 2 86 | {$desc} 87 | 88 | 89 | XML; 90 | return $content; 91 | } 92 | 93 | protected function getRegSuccessBody($data) 94 | { 95 | $content = << 97 | 98 | 1 99 | OK 100 | 101 | 102 | XML; 103 | 104 | return $content; 105 | } 106 | 107 | protected function getRegErrorBody($code, $desc = 'Unable to accept this payment') 108 | { 109 | $desc = $this->clean($desc, 125); 110 | 111 | $content = << 113 | 114 | 2 115 | {$desc} 116 | 117 | 118 | XML; 119 | return $content; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Provider/Card/Cartu/Provider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Provider\Card\Cartu; 12 | 13 | use Carbon\Carbon; 14 | use Longman\GeoPayment\Options; 15 | use Longman\GeoPayment\Provider\AbstractProvider; 16 | use Longman\GeoPayment\Provider\Card\Cartu\XMLResponse; 17 | use Symfony\Component\HttpFoundation\Request; 18 | use InvalidArgumentException; 19 | 20 | class Provider extends AbstractProvider 21 | { 22 | protected $name = 'cartu'; 23 | 24 | protected $mode = 'redirect'; // redirect, response 25 | 26 | protected $xml_request = ''; 27 | 28 | const DEF_PAYMENT_URL = 'https://e-commerce.cartubank.ge/servlet/Process3DSServlet/3dsproxy_init.jsp'; 29 | const DEF_CURRENCY = '840'; 30 | const DEF_LANG = '01'; 31 | 32 | public function setMode($mode) 33 | { 34 | parent::setMode($mode); 35 | 36 | if ($mode == 'response') { 37 | $ConfirmRequest = $this->request->get('ConfirmRequest'); 38 | if ($ConfirmRequest) { 39 | $this->xml_request = $this->parseXml($ConfirmRequest); 40 | } 41 | } 42 | return $this; 43 | } 44 | 45 | public function getTransactionId() 46 | { 47 | return (string) $this->xml_request->TransactionId; 48 | } 49 | 50 | public function getPaymentId() 51 | { 52 | return (string) $this->xml_request->PaymentId; 53 | } 54 | 55 | public function getPaymentDate() 56 | { 57 | $date = (string) $this->xml_request->PaymentDate; 58 | $date = Carbon::createFromFormat('d.m.Y H:i:s', $date); 59 | return $date; 60 | } 61 | 62 | public function getAmount() 63 | { 64 | return (string) $this->xml_request->Amount; 65 | } 66 | 67 | public function getCardType() 68 | { 69 | return (string) $this->xml_request->CardType; 70 | } 71 | 72 | public function getReason() 73 | { 74 | return (string) $this->xml_request->Reason; 75 | } 76 | 77 | public function getStatus() 78 | { 79 | return (string) $this->xml_request->Status; 80 | } 81 | 82 | public function checkSignature() 83 | { 84 | $signature = $this->request->get('signature'); 85 | if (!$signature) { 86 | $this->sendErrorResponse('Signature is missing!'); 87 | } 88 | 89 | $ConfirmRequest = $this->request->get('ConfirmRequest'); 90 | 91 | $request_url = $url = $this->getRequestUrl(); 92 | 93 | $url = preg_replace('#&signature=.*$#', '', $url); 94 | $url = rawurldecode($url); 95 | 96 | $cert_file = $this->options->get('cert_path'); 97 | $cert = file_get_contents($cert_file); 98 | $key = openssl_pkey_get_public($cert); 99 | //dump(openssl_pkey_get_details($key)); 100 | 101 | $signature = base64_decode($signature); 102 | $valid = openssl_verify($url, $signature, $key, OPENSSL_ALGO_SHA1); 103 | 104 | if ($valid !== 1) { 105 | $this->sendErrorResponse('Signature is invalid!'); 106 | } 107 | 108 | //$this->logger->info('url: '.$url); 109 | 110 | return $this; 111 | } 112 | 113 | public function getPaymentUrl() 114 | { 115 | $gateway = $this->options->get('payment_url', self::DEF_PAYMENT_URL); 116 | 117 | $gateway .= '?CountryCode=' . $this->encode($this->options->get('CountryCode', self::DEF_LANG)); 118 | 119 | $gateway .= '&CurrencyCode=' . $this->encode($this->options->get('CurrencyCode', self::DEF_CURRENCY)); 120 | 121 | $gateway .= '&MerchantName=' . $this->encode($this->options->get('MerchantName')); 122 | $gateway .= '&MerchantURL=' . $this->encode($this->options->get('MerchantURL')); 123 | $gateway .= '&MerchantCity=' . $this->encode($this->options->get('MerchantCity')); 124 | $gateway .= '&MerchantID=' . $this->encode($this->options->get('MerchantID')); 125 | $gateway .= '&xDDDSProxy.Language=' . $this->encode($this->options->get('xDDDSProxy.Language')); 126 | 127 | foreach ($this->params as $key => $value) { 128 | $gateway .= '&' . $key . '=' . $this->encode($value); 129 | } 130 | 131 | return $gateway; 132 | } 133 | 134 | public function sendSuccessResponse($data = []) 135 | { 136 | $response = new XMLResponse($this->mode); 137 | 138 | if (empty($data['TransactionId'])) { 139 | $this->logger->debug('TransactionId not defined', ['data' => $data]); 140 | throw new InvalidArgumentException('TransactionId not defined'); 141 | } 142 | 143 | if (empty($data['PaymentId'])) { 144 | $this->logger->debug('PaymentId not defined', ['data' => $data]); 145 | throw new InvalidArgumentException('PaymentId not defined'); 146 | } 147 | 148 | $this->logger->debug('sendSuccessResponse: ' . $this->mode, ['data' => $data]); 149 | 150 | $response->success($data)->send(); 151 | } 152 | 153 | public function sendErrorResponse($data = []) 154 | { 155 | $this->logger->debug('sendErrorResponse: ' . $this->mode, ['data' => $data]); 156 | $response = new XMLResponse($this->mode); 157 | $response->error($data)->send(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/Provider/Card/Cartu/XMLResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Longman\GeoPayment\Provider\Card\Cartu; 11 | 12 | use Longman\GeoPayment\Provider\AbstractXMLResponse; 13 | 14 | class XMLResponse extends AbstractXMLResponse 15 | { 16 | 17 | public function error($data) 18 | { 19 | $this->content = $this->getCheckErrorBody($code, $desc); 20 | return $this; 21 | } 22 | 23 | public function success($data = []) 24 | { 25 | $this->content = $this->getCheckSuccessBody($data); 26 | return $this; 27 | } 28 | 29 | protected function getCheckSuccessBody($data) 30 | { 31 | $TransactionId = $this->clean($data['TransactionId'], 32); 32 | $PaymentId = $this->clean($data['PaymentId'], 12); 33 | 34 | $content = << 36 | {$TransactionId} 37 | {$PaymentId} 38 | ACCEPTED 39 | 40 | XML; 41 | return $content; 42 | } 43 | 44 | protected function getCheckErrorBody($data) 45 | { 46 | $TransactionId = $this->clean($data['TransactionId'], 32); 47 | $PaymentId = $this->clean($data['PaymentId'], 12); 48 | 49 | $content = << 51 | {$TransactionId} 52 | {$PaymentId} 53 | DECLINED 54 | 55 | XML; 56 | 57 | return $content; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Provider/Pay/Tbcpay/Provider.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace Longman\GeoPayment\Provider\Pay\Tbcpay; 12 | 13 | use Longman\GeoPayment\Options; 14 | use Longman\GeoPayment\Provider\AbstractProvider; 15 | use Longman\GeoPayment\Provider\Pay\Tbcpay\XMLResponse; 16 | use InvalidArgumentException; 17 | 18 | class Provider extends AbstractProvider 19 | { 20 | protected $name = 'tbcpay'; 21 | 22 | protected $mode = 'check'; 23 | 24 | 25 | public function sendSuccessResponse($data = []) 26 | { 27 | $response = new XMLResponse($this->mode); 28 | 29 | if ($this->mode == 'check') { 30 | if (empty($data)) { 31 | $this->logger->debug('extra data not defined', ['data' => $data]); 32 | throw new InvalidArgumentException('extra data not defined'); 33 | } 34 | } 35 | 36 | $this->logger->debug('sendSuccessResponse: ' . $this->mode, ['data' => $data]); 37 | 38 | $response->success($data)->send(); 39 | } 40 | 41 | public function sendErrorResponse($code = 1, $error = 'Unable to accept this payment') 42 | { 43 | $this->logger->debug('sendErrorResponse: "' . $error .'" with code: '.$code); 44 | $response = new XMLResponse($this->mode); 45 | $response->error($code, $error)->send(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Provider/Pay/Tbcpay/XMLResponse.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Longman\GeoPayment\Provider\Pay\Tbcpay; 11 | 12 | use Longman\GeoPayment\Provider\AbstractXMLResponse; 13 | 14 | class XMLResponse extends AbstractXMLResponse 15 | { 16 | 17 | public function error($code = 2, $desc = 'Unable to accept this payment') 18 | { 19 | $this->content = $this->getErrorBody($code, $desc); 20 | return $this; 21 | } 22 | 23 | public function success($data = []) 24 | { 25 | $this->content = $this->getSuccessBody($data); 26 | return $this; 27 | } 28 | 29 | protected function getSuccessBody(array $data = []) 30 | { 31 | $extra_str = ''; 32 | foreach ($data as $k => $v) { 33 | $extra_str .= ''.$this->clean($v).''.PHP_EOL; 34 | } 35 | 36 | if ($extra_str) { 37 | $content = << 39 | 40 | 0 41 | 42 | {$extra_str} 43 | 44 | OK 45 | 46 | XML; 47 | } else { 48 | $content = << 50 | 51 | 0 52 | OK 53 | 54 | XML; 55 | } 56 | 57 | return $content; 58 | } 59 | 60 | protected function getErrorBody($code, $desc = 'Unable to accept this payment') 61 | { 62 | $desc = $this->clean($desc, 125); 63 | 64 | $content = << 66 | 67 | {$code} 68 | {$desc} 69 | 70 | XML; 71 | return $content; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tests/Bootstrap.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | /* 12 | * Set error reporting to the level to which Mockery code must comply. 13 | */ 14 | error_reporting(-1); 15 | 16 | /* 17 | * Set UTC timezone. 18 | */ 19 | date_default_timezone_set('UTC'); 20 | 21 | 22 | 23 | $root = realpath(dirname(dirname(__FILE__))); 24 | /** 25 | * Check that --dev composer installation was done 26 | */ 27 | if (!file_exists($root . '/vendor/autoload.php')) { 28 | throw new Exception( 29 | 'Please run "php composer.phar install --dev" in root directory ' 30 | . 'to setup unit test dependencies before running the tests' 31 | ); 32 | } 33 | 34 | // Include the Composer autoloader 35 | $loader = require __DIR__ . '/../vendor/autoload.php'; 36 | 37 | /* 38 | * Unset global variables that are no longer needed. 39 | */ 40 | unset($root, $loader); 41 | -------------------------------------------------------------------------------- /tests/Unit/LoggerTest.php: -------------------------------------------------------------------------------- 1 | shouldReceive('pushHandler')->once()->with(m::type('Monolog\Handler\StreamHandler')); 19 | $writer->useFiles(__DIR__); 20 | } 21 | 22 | public function testRotatingFileHandlerCanBeAdded() 23 | { 24 | $writer = new Logger($monolog = m::mock('Monolog\Logger')); 25 | $monolog->shouldReceive('pushHandler')->once()->with(m::type('Monolog\Handler\RotatingFileHandler')); 26 | $writer->useDailyFiles(__DIR__, 5); 27 | } 28 | 29 | public function testErrorLogHandlerCanBeAdded() 30 | { 31 | $writer = new Logger($monolog = m::mock('Monolog\Logger')); 32 | $monolog->shouldReceive('pushHandler')->once()->with(m::type('Monolog\Handler\ErrorLogHandler')); 33 | $writer->useErrorLog(); 34 | } 35 | 36 | public function testMethodsPassErrorAdditionsToMonolog() 37 | { 38 | $writer = new Logger($monolog = m::mock('Monolog\Logger')); 39 | $monolog->shouldReceive('error')->once()->with('foo', []); 40 | $writer->error('foo'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Unit/OptionsTest.php: -------------------------------------------------------------------------------- 1 | 'value1']); 14 | $this->assertEquals('value1', $options->get('param1')); 15 | } 16 | 17 | public function testGetParamDefault() 18 | { 19 | $options = new Options([]); 20 | $this->assertEquals('value1', $options->get('param1', 'value1')); 21 | } 22 | 23 | public function testGetParamFromEnv() 24 | { 25 | $options = new Options([]); 26 | $_ENV['param1'] = 'value1'; 27 | $this->assertEquals('value1', $options->get('param1')); 28 | } 29 | 30 | public function testSetParam() 31 | { 32 | $options = new Options([]); 33 | $options->set('param1', 'value1'); 34 | $this->assertEquals('value1', $options->get('param1')); 35 | } 36 | 37 | public function testSetMixedParam() 38 | { 39 | $options = new Options([]); 40 | $object = new \stdClass; 41 | $object->param1 = 'value1'; 42 | $options->set('object', $object); 43 | $this->assertEquals($object, $options->get('object')); 44 | } 45 | 46 | public function testDottedParamName() 47 | { 48 | $options = new Options(['param.1' => 'value.1']); 49 | $this->assertEquals('value.1', $options->get('param.1')); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Unit/PaymentTest.php: -------------------------------------------------------------------------------- 1 | ')) { 29 | $this->markTestSkipped( 30 | 'Skipping test that can run only on a PHP 7.' 31 | ); 32 | } 33 | 34 | $this->setExpectedException('\TypeError'); 35 | $payment = new Payment(null, 'type', 'aaa'); 36 | } 37 | 38 | /** 39 | * @expectedException \InvalidArgumentException 40 | */ 41 | public function testSetWrongConfigFile() 42 | { 43 | $payment = new Payment(); 44 | $payment->setConfigFile('/test/path/.file'); 45 | } 46 | 47 | 48 | public function testSetValidConfigFile() 49 | { 50 | $payment = new Payment(); 51 | $payment->setConfigFile(__DIR__.'/../../examples/.bog.example'); 52 | $currency = $payment->getOption('currency'); 53 | $this->assertNotNull($currency); 54 | } 55 | 56 | 57 | public function testSetAndGetParameter() 58 | { 59 | $payment = new Payment(); 60 | 61 | $options = new Options(['param1' => 'value1']); 62 | $request = Request::createFromGlobals(); 63 | $logger = new Logger($monolog = m::mock('Monolog\Logger')); 64 | 65 | $provider = $this->getMockForAbstractClass('Longman\GeoPayment\Provider\AbstractProvider', [$options, $request, $logger]); 66 | 67 | $provider->addParam('test1', 'value1'); 68 | 69 | $this->assertEquals('value1', $provider->getParam('test1')); 70 | } 71 | 72 | 73 | public function testSetAndGetMode() 74 | { 75 | $payment = new Payment(); 76 | 77 | $options = new Options([]); 78 | $request = Request::createFromGlobals(); 79 | $logger = new Logger($monolog = m::mock('Monolog\Logger')); 80 | 81 | $provider = $this->getMockForAbstractClass('Longman\GeoPayment\Provider\AbstractProvider', [$options, $request, $logger]); 82 | 83 | $provider->setMode('test'); 84 | 85 | $this->assertEquals('test', $provider->getMode()); 86 | } 87 | 88 | public function testAmtToMinor() 89 | { 90 | $payment = new Payment(); 91 | 92 | $options = new Options([]); 93 | $request = Request::createFromGlobals(); 94 | $logger = new Logger($monolog = m::mock('Monolog\Logger')); 95 | 96 | $provider = $this->getMockForAbstractClass('Longman\GeoPayment\Provider\AbstractProvider', [$options, $request, $logger]); 97 | 98 | $this->assertSame(10000, $provider->amtToMinor(100)); 99 | $this->assertSame(150000, $provider->amtToMinor(1500)); 100 | } 101 | 102 | 103 | public function testAmtToMajor() 104 | { 105 | $payment = new Payment(); 106 | 107 | $options = new Options([]); 108 | $request = Request::createFromGlobals(); 109 | $logger = new Logger($monolog = m::mock('Monolog\Logger')); 110 | 111 | $provider = $this->getMockForAbstractClass('Longman\GeoPayment\Provider\AbstractProvider', [$options, $request, $logger]); 112 | 113 | $this->assertSame(100.00, $provider->amtToMajor(10000)); 114 | $this->assertSame(1500.00, $provider->amtToMajor(150000)); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tests/Unit/TestCase.php: -------------------------------------------------------------------------------- 1 | markTestSkipped( 13 | 'Skipping test that can run only on a 64-bit build of PHP.' 14 | ); 15 | } 16 | } 17 | 18 | protected function callMethod($obj, $name, array $args) 19 | { 20 | $class = new ReflectionClass($obj); 21 | $method = $class->getMethod($name); 22 | $method->setAccessible(true); 23 | return $method->invokeArgs($obj, $args); 24 | } 25 | } 26 | --------------------------------------------------------------------------------