diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5b608f8 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +# API_KEY= SOLICITAR em https://dev-sicredi.zendesk.com/hc/pt-br/requests/new, após criar APP diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e052100 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,105 @@ +name: "Continuous Integration" + +on: + - pull_request + - push + +env: + COMPOSER_ROOT_VERSION: 1.99 + +jobs: + composer-json-lint: + name: "Lint composer.json" + + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "8.2" + - "8.1" + - "7.4.33" + + steps: + - name: "Checkout" + uses: "actions/checkout@v3" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + tools: composer-normalize + + - name: "Get composer cache directory" + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: "Cache dependencies" + uses: actions/cache@v3 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer- + + - name: "Install dependencies" + run: "composer update --no-interaction --no-progress" + + - name: "Validate composer.json" + run: "composer validate --strict" + + - name: "Normalize composer.json" + run: "composer normalize --dry-run" + + tests: + name: "Tests" + + runs-on: "ubuntu-latest" + + strategy: + matrix: + php-version: + - "7.4" + - "8.0" + - "8.1" + - "8.2" + dependencies: + - "lowest" + - "highest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v3" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + ini-values: zend.assertions=1 + + - name: "Get composer cache directory" + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: "Cache dependencies" + uses: actions/cache@v3 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer- + + - name: "Install lowest dependencies" + if: ${{ matrix.dependencies == 'lowest' }} + run: "composer update --no-interaction --no-progress --prefer-lowest" + + - name: "Install highest dependencies" + if: ${{ matrix.dependencies == 'highest' }} + run: "composer update --no-interaction --no-progress" + + - name: "Run tests with PHPUnit" + timeout-minutes: 3 + run: "XDEBUG_MODE=coverage ./vendor/bin/phpunit tests --coverage-text --colors" + + - name: "Run php-cs-fixer" + timeout-minutes: 3 + run: "composer cs-dry-run" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..709283d --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/.buildpath +/composer.phar +/vendor/ +/private +.env +*~ +*.pdf +/.settings +sicredi-oauth-token.txt +docker-compose.yml +Dockerfile \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5b3fe22 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +CHANGELOG +========= + +Versionamento: +-------------- + +O projeto utiliza o versionamento semântico, no formato MAJOR.MINOR.PATCH + +Versões MAJOR não tem compromisso de compatibilidade com a versão MAJOR anterior + +Versões MINOR podem adicionar funcionalidades e parâmetros, mas mantém a compatibilidade com as versões anteriores da mesma versão MAJOR. + +Versões PATCH apenas corrigem bugs de forma compatível à versão anterior MAJOR.MINOR. + + +Registro das alterações: +------------------------ + +1.0.0 - Suporte à API 3.3 do Banco Sicredi diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d284aa2 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an sicrediface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an sicrediface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is sicrediface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..76470b1 --- /dev/null +++ b/composer.json @@ -0,0 +1,45 @@ +{ + "name" : "crtlmota/banco-sicredi-connector", + "type" : "package", + "version": "1.0.0", + "authors" : [ + { + "name": "Ctrl-Mota", + "email": "lucas.d.mota@gmail.com", + "homepage": "https://github.com/Ctrl-Mota", + "role": "Desenvolvedor" + } + ], + "description" : "Abstração de comunicação rest com a API do Banco Sicredi v3.3, apenas curl", + "homepage" : "https://github.com/Ctrl-Mota/banco-sicredi-connector-php", + "license" : "LGPL-3.0-or-later", + "keywords" : [ + "Banco Sicredi Boletos Cobrança webhook" + ], + "autoload" : { + "psr-4" : { + "crtlmota\\BancoSicrediConnector\\" : "src" + } + }, + "autoload-dev" : { + "psr-4" : { + "crtlmota\\BancoSicrediConnector\\Tests\\" : "tests" + } + }, + "require" : { + "php" : ">=7.4" + }, + "require-dev" : { + "squizlabs/php_codesniffer" : "^3.5", + "phpunit/phpunit" : "^9.1", + "scrutinizer/ocular" : "^1.3", + "phpstan/phpstan" : "^0.12", + "fakerphp/faker": "^1.19", + "vlucas/phpdotenv" : "^5.4" + }, + "scripts" : { + "phpcbf" : "vendor/bin/phpcbf --standard=psr2 src", + "phpcs" : "vendor/bin/phpcs --standard=psr2 src", + "phpstan" : "vendor/bin/phpstan analyse src/ --level 7" + } +} \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..ac05db0 --- /dev/null +++ b/composer.lock @@ -0,0 +1,4012 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "6f2311b445ee7660549689cf381c0770", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", + "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:35:39+00:00" + }, + { + "name": "fakerphp/faker", + "version": "v1.23.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + }, + "time": "2024-01-02T13:46:09+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.2", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862", + "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:16:48+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, + { + "name": "jms/metadata", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/7ca240dcac0c655eb15933ee55736ccd2ea0d7a6", + "reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "require-dev": { + "doctrine/cache": "^1.0", + "doctrine/coding-standard": "^8.0", + "mikey179/vfsstream": "^1.6.7", + "phpunit/phpunit": "^8.5|^9.0", + "psr/container": "^1.0|^2.0", + "symfony/cache": "^3.1|^4.0|^5.0", + "symfony/dependency-injection": "^3.1|^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Metadata\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Class/method/property metadata management in PHP", + "keywords": [ + "annotations", + "metadata", + "xml", + "yaml" + ], + "support": { + "issues": "https://github.com/schmittjoh/metadata/issues", + "source": "https://github.com/schmittjoh/metadata/tree/2.8.0" + }, + "time": "2023-02-15T13:44:18+00:00" + }, + { + "name": "jms/serializer", + "version": "3.30.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/serializer.git", + "reference": "bf1105358123d7c02ee6cad08ea33ab535a09d5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/bf1105358123d7c02ee6cad08ea33ab535a09d5e", + "reference": "bf1105358123d7c02ee6cad08ea33ab535a09d5e", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2.0", + "doctrine/lexer": "^2.0 || ^3.0", + "jms/metadata": "^2.6", + "php": "^7.4 || ^8.0", + "phpstan/phpdoc-parser": "^1.20" + }, + "require-dev": { + "doctrine/annotations": "^1.14 || ^2.0", + "doctrine/coding-standard": "^12.0", + "doctrine/orm": "^2.14 || ^3.0", + "doctrine/persistence": "^2.5.2 || ^3.0", + "doctrine/phpcr-odm": "^1.5.2 || ^2.0", + "ext-pdo_sqlite": "*", + "jackalope/jackalope-doctrine-dbal": "^1.3", + "ocramius/proxy-manager": "^1.0 || ^2.0", + "phpbench/phpbench": "^1.0", + "phpstan/phpstan": "^1.0.2", + "phpunit/phpunit": "^9.0 || ^10.0", + "psr/container": "^1.0 || ^2.0", + "rector/rector": "^0.19.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/form": "^5.4 || ^6.0 || ^7.0", + "symfony/translation": "^5.4 || ^6.0 || ^7.0", + "symfony/uid": "^5.4 || ^6.0 || ^7.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", + "twig/twig": "^1.34 || ^2.4 || ^3.0" + }, + "suggest": { + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", + "symfony/cache": "Required if you like to use cache functionality.", + "symfony/uid": "Required if you'd like to serialize UID objects.", + "symfony/yaml": "Required if you'd like to use the YAML metadata format." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "JMS\\Serializer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.", + "homepage": "http://jmsyst.com/libs/serializer", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "support": { + "issues": "https://github.com/schmittjoh/serializer/issues", + "source": "https://github.com/schmittjoh/serializer/tree/3.30.0" + }, + "funding": [ + { + "url": "https://github.com/goetas", + "type": "github" + } + ], + "time": "2024-02-24T14:12:14+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + }, + "time": "2024-07-01T20:03:41+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.2", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", + "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-11-12T21:59:55+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.29.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "reference": "fcaefacf2d5c417e928405b71b400d4ce10daaf4", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.29.1" + }, + "time": "2024-05-31T08:52:43+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.12.100", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "48236ddf823547081b2b153d1cd2994b784328c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/48236ddf823547081b2b153d1cd2994b784328c3", + "reference": "48236ddf823547081b2b153d1cd2994b784328c3", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.12-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/0.12.100" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-11-01T09:52:08+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.31", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:37:42+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.19", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-04-05T04:35:58+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "scrutinizer/ocular", + "version": "1.9", + "source": { + "type": "git", + "url": "https://github.com/scrutinizer-ci/ocular.git", + "reference": "dda3540f7458b2645cee2a02b24291914769c41c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrutinizer-ci/ocular/zipball/dda3540f7458b2645cee2a02b24291914769c41c", + "reference": "dda3540f7458b2645cee2a02b24291914769c41c", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.3|^7.0", + "jms/serializer": "^1.0.0|^3.0", + "phpoption/phpoption": "~1.0", + "symfony/console": "^2.1.0|~3.0|~4.0|~5.0|^6.0", + "symfony/process": "~2.3|~3.0|~4.0|~5.0|^6.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "phpunit/phpunit": "^9.0.0", + "symfony/filesystem": "~2.0|~3.0|~4.0|~5.0|^6.0" + }, + "bin": [ + "bin/ocular" + ], + "type": "library", + "autoload": { + "psr-4": { + "Scrutinizer\\Ocular\\": "src/Scrutinizer/Ocular" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "support": { + "issues": "https://github.com/scrutinizer-ci/ocular/issues", + "source": "https://github.com/scrutinizer-ci/ocular/tree/1.9" + }, + "time": "2022-02-22T09:49:51+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:33:00+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:35:11+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.10.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", + "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-05-22T21:24:41+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.41", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/6473d441a913cb997123b59ff2dbe3d1cf9e11ba", + "reference": "6473d441a913cb997123b59ff2dbe3d1cf9e11ba", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.41" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T07:48:55+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/80d075412b557d41002320b96a096ca65aa2c98d", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-24T14:02:46+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-19T12:30:46+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.30.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T15:07:36+00:00" + }, + { + "name": "symfony/process", + "version": "v5.4.40", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "deedcb3bb4669cae2148bc920eafd2b16dc7c046" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/deedcb3bb4669cae2148bc920eafd2b16dc7c046", + "reference": "deedcb3bb4669cae2148bc920eafd2b16dc7c046", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.40" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:33:22+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-04-21T15:04:16+00:00" + }, + { + "name": "symfony/string", + "version": "v5.4.41", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/065a9611e0b1fd2197a867e1fb7f2238191b7096", + "reference": "065a9611e0b1fd2197a867e1fb7f2238191b7096", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" + }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.41" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T09:20:55+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.0", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.2", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.2", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2023-11-12T22:43:29+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.4" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/example/ContratarWebhook.php b/example/ContratarWebhook.php new file mode 100644 index 0000000..c76406b --- /dev/null +++ b/example/ContratarWebhook.php @@ -0,0 +1,67 @@ + +load(); +$API_KEY = $_ENV['API_KEY']; + + +$apiUrl = "https://api-parceiro.sicredi.com.br/sb"; +try { + $SANDBOX_USERNAME = '123456789'; + $SANDBOX_PASSWORD = 'teste123'; + $SANDBOX_COOPERATIVA = '6789'; + $SANDBOX_POSTO = '03'; + $SANDEBOX_CODIGO_BENEFICIARIO = '12345'; + + $banco = new SicrediCobranca( + new CredencialsManager( + $SANDBOX_USERNAME, + $SANDBOX_PASSWORD, + $API_KEY, + 'cobranca', + $SANDBOX_COOPERATIVA, + $SANDBOX_POSTO, + $SANDEBOX_CODIGO_BENEFICIARIO, + ), + $apiUrl + ); + $webhook = $banco->createWebhook('https://myapi.com.br/webhook/cobranca'); + /* + Retorno esperado: + { + "cooperativa": "6789", + "posto": "03", + "codBeneficiario": "12345", + "eventos": [ + "LIQUIDACAO" + ], + "url": "https://teste.instituicao.cloud/v1/contratos", + "urlStatus": "ATIVO", + "contratoStatus": "ATIVO", + "nomeResponsavel": "NOME RESPONSAVEL", + "email": "TESTE@EMAIL.COM.BR", + "telefone": "51 999999999" + } + */ + return $webhook; + +} catch (SicrediValidationException | SicrediRequestException $e) { + printf($e->getMessage()); +} diff --git a/example/HandleBoleto.php b/example/HandleBoleto.php new file mode 100644 index 0000000..3642292 --- /dev/null +++ b/example/HandleBoleto.php @@ -0,0 +1,159 @@ + +load(); +$API_KEY = $_ENV['API_KEY']; + + +$apiUrl = "https://api-parceiro.sicredi.com.br/sb"; +try { + $SANDBOX_USERNAME = '123456789'; + $SANDBOX_PASSWORD = 'teste123'; + $SANDBOX_COOPERATIVA = '6789'; + $SANDBOX_POSTO = '03'; + $SANDEBOX_CODIGO_BENEFICIARIO = '12345'; + + $banco = new SicrediCobranca( + new CredencialsManager( + $SANDBOX_USERNAME, + $SANDBOX_PASSWORD, + $API_KEY, + 'cobranca', + $SANDBOX_COOPERATIVA, + $SANDBOX_POSTO, + $SANDEBOX_CODIGO_BENEFICIARIO, + function (string $tokenJson) { //new token callback + if ($tokenFile = fopen('sicredi-oauth-token.txt', 'w')) { + fwrite($tokenFile, $tokenJson); + fclose($tokenFile); + } + }, + function () { //get token callback + $oAuthTokenData = null; + // uso do @ para evitar o warning se o arquivo não existe + if (($tokenFile = @fopen('sicredi-oauth-token.txt', 'r')) !== false) { + // se tiver arquivo com token, carrega ele e retorna + $tokenJson = fread($tokenFile, 8192); + $oAuthTokenData = json_decode($tokenJson, true); + fclose($tokenFile); + return $oAuthTokenData; + } else { + // retorno "falso" força a emissão de novo token + return false; + } + } + ), + $apiUrl + ); + + $fakerB = \Faker\Factory::create(); + $fakerB->addProvider(new \Faker\Provider\pt_BR\Person($fakerB)); + + $fakerP = \Faker\Factory::create(); + $fakerP->addProvider(new \Faker\Provider\pt_BR\Person($fakerP)); + + + + + $beneficiario = (new Beneficiario()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + ->setDocumento($fakerB->cpf(false)) + ->setNome($fakerB->name) + ->setLogradouro($fakerB->streetName) + ->setNumeroEndereco($fakerB->numberBetween(10, 999)) + ->setCidade($fakerB->city) + ->setUf($fakerB->stateAbbr()) + ->setCep($fakerB->numerify("########")); + + $pagador = (new Pagador()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + ->setDocumento($fakerP->cpf(false)) + ->setNome($fakerP->name) + ->setLogradouro($fakerP->streetName) + ->setNumeroEndereco($fakerP->numberBetween(10, 999)) + ->setCidade($fakerP->city) + ->setUf($fakerP->stateAbbr()) + ->setCep($fakerP->numerify("########")); + + $dataVencimento = (new DateTime())->modify("+30 day"); + $boleto = new Boleto(); + $boleto->setPagador($pagador); + $boleto->setBeneficiario($beneficiario); + $boleto->setSeuNumero("TESTE"); + $boleto->setValor(500.00); + $boleto->setDataVencimento($dataVencimento->format("Y-m-d")); + $boleto->setDesconto1((clone $dataVencimento)->modify('-20 days')->format("Y-m-d"), 200.00); + $boleto->setDesconto2((clone $dataVencimento)->modify('-10 days')->format("Y-m-d"), 150.00); + $boleto->setDesconto3((clone $dataVencimento)->modify('-5 days')->format("Y-m-d"), 100.00); + $boleto->setJuros(1); + $boleto->setMulta(12.00); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR MULTA DE ' . $boleto->getMulta() . '%'); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR JUROS DE ' . $boleto->getJuros() . '% AO MÊS'); + + $boletoResponse = $banco->createBoleto($boleto); + + /* + exemplo de body esperado: + { + + IF (tipoCobranca:HIBRIDO) + "txid": "f69d2a0076fb4ea2bddd7babd1200525", + "qrCode": "00020101021226930014br.gov.bcb.pix2571pix-qrcodeh.sicredi.com.br/qr/v2/cobv/6946459e4b6e4c19ab5c9689fe0df30a520400005303986540599.905802BR5921OLIVEIRA MULTI MARCAS6008BRASILIA62070503***6304E5E1", + + IF (tipoCobranca:SPLIT) + "splitBoleto": { + "repasseAutomaticoSplit": "SIM", + "tipoValorRateio": "PERCENTUAL", + "regraRateio": "VALOR_COBRADO", + "destinatarios": + [ + { + "codigoBanco": "237", + "codigoAgencia": "0434", + "numeroContaCorrente": "2323232323", + "numeroCpfCnpj": "02738306004", + "nomeDestinatario": "DECIO OLIVEIRA", + "parcelaRateio": "1", + "valorPercentualRateio": 24.22, + "floatSplit": 20 + } + ] + } + + TODOS OS TIPOS DE COBRANÇA CONTÉM + "linhaDigitavel": "74891125110061420512803153351030188640000009990", + "codigoBarras": "74891886400000099901125100614205120315335103", + "cooperativa": "0512", + "posto": "03", + "nossoNumero": "251006142" + } + + */ + + $findedBoleto = $banco->getBoleto($boletoResponse['nossoNumero']); //'Boleto' + + $findedBoletoPdfTempFilepath = $banco->getBoletoPdf($boletoResponse['linhaDigitavel']); + + $findedBoletoEncodedPdf = $banco->getBoletoEncoded($boletoResponse['linhaDigitavel']); + + $updatedBoleto = $banco->updateVencimento($boletoResponse['nossoNumero'], $dataVencimento->modify("+5 days")->format("Y-m-d")); + + $boletosPagos = $banco->listBoletosPagosByDay($dataVencimento->modify("+5 days")); + + $banco->baixaBoleto($boletoResponse['nossoNumero']); + +} catch (SicrediValidationException | SicrediRequestException $e) { + printf($e->getMessage()); +} diff --git a/src/Cobranca/Beneficiario.php b/src/Cobranca/Beneficiario.php new file mode 100644 index 0000000..2a0de5f --- /dev/null +++ b/src/Cobranca/Beneficiario.php @@ -0,0 +1,5 @@ +beneficiario; + } + /** + * + * @param Beneficiario $beneficiario + */ + public function setBeneficiario(Beneficiario $beneficiario) + { + $this->beneficiario = $beneficiario; + return $this; + } + + /** + * @return ?string + */ + public function getCodigoBeneficiario(): ?string + { + return $this->codigoBeneficiario; + } + /** + * + * @param string $codigoBeneficiario + */ + public function setCodigoBeneficiario($codigoBeneficiario) + { + $this->codigoBeneficiario = $codigoBeneficiario; + return $this; + } + + /** + * + * @return ?Pagador + */ + public function getPagador(): ?Pagador + { + return $this->pagador; + } + + /** + * + * @param Pagador $pagador + */ + public function setPagador(Pagador $pagador) + { + $this->pagador = $pagador; + return $this; + } + + /** + * @return string + */ + public function getEspecieDocumento() + { + return $this->especieDocumento; + } + + /** + * @param string $especieDocumento + * @required + * @options DUPLICATA_MERCANTIL_INDICACAO | DUPLICATA_RURAL | NOTA_PROMISSORIA | NOTA_PROMISSORIA_RURAL | NOTA_SEGUROS | RECIBO | LETRA_CAMBIO | NOTA_DEBITO | DUPLICATA_SERVICO_INDICACAO | OUTROS | BOLETO_PROPOSTA | CARTAO_CREDITO | BOLETO_DEPOSITO + */ + public function setEspecieDocumento(string $especieDocumento) + { + $this->especieDocumento = $especieDocumento; + return $this; + } + + /** + * @return string + */ + public function getTipoCobranca() + { + return $this->tipoCobranca; + } + + /** + * Indica o tipo de cobrança do boleto, podendo ser: NORMAL (Tradicional) ou Híbrido (Com QRCODE PIX) + * @param string $especieDocumento + * @required + * @options NORMAL | HIBRIDO + */ + public function setTipoCobranca(string $tipoCobranca) + { + $this->tipoCobranca = $tipoCobranca; + return $this; + } + + + /** + * @return int + */ + public function getNossoNumero(): ?int + { + return $this->nossoNumero; + } + /** + * Caso o beneficiário não informe, o Sicredi gera automaticamente. + * + * @param int $nossoNumero + */ + public function setNossoNumero(int $nossoNumero) + { + $this->nossoNumero = $nossoNumero; + return $this; + } + + /** + * @return mixed + */ + public function getSeuNumero() + { + return $this->seuNumero; + } + + /** + * Número de controle interno do beneficiário que faz referência ao pagador. + * @param string $seuNumero + */ + public function setSeuNumero(string $seuNumero) + { + $this->seuNumero = $seuNumero; + return $this; + } + + + /** + * @return float + */ + public function getValor() + { + return $this->valor; + } + /** + * precision 14 e scale 2 + * @param float $valor + * + */ + public function setValor(float $valor) + { + $this->valor = $valor; + return $this; + } + /** + * @return string format: Y-m-d + */ + public function getDataVencimento() + { + return $this->dataVencimento; + } + + /** + * @param mixed $dataVencimento + */ + public function setDataVencimento($dataVencimento) + { + $this->dataVencimento = $dataVencimento; + return $this; + } + + /** + * @return int + */ + public function getValidadeAposVencimento(): int + { + return $this->validadeAposVencimento; + } + + /** + * @param int $validadeAposVencimento + */ + public function setValidadeAposVencimento(int $validadeAposVencimento) + { + $this->validadeAposVencimento = $validadeAposVencimento; + return $this; + } + + /** + * @return string + */ + public function getTipoDesconto(): ?string + { + return $this->tipoDesconto; + } + + /** + * Tipo de desconto podendo ser: VALOR ou PERCENTUAL + * @param string $tipoDesconto + * @required + * @options VALOR | PERCENTUAL + */ + public function setTipoDesconto(string $tipoDesconto) + { + $this->tipoDesconto = $tipoDesconto; + return $this; + } + + /** + * + * @return Mensagem[] + */ + public function getMensagens(): array + { + return $this->mensagens; + } + + /** + * + * @param string $mensagem + */ + public function addMensagem(string $mensagem) + { + $this->mensagens[] = $mensagem; + return $this; + } + + /** + * @return float + */ + public function getValorDesconto1(): ?float + { + return $this->valorDesconto1; + } + + public function getValorDesconto2(): ?float + { + return $this->valorDesconto2; + } + + public function getValorDesconto3(): ?float + { + return $this->valorDesconto3; + } + public function getDataDesconto1(): ?string + { + return $this->dataDesconto1; + } + + public function getDataDesconto2(): ?string + { + return $this->dataDesconto2; + } + + public function getDataDesconto3(): ?string + { + return $this->dataDesconto3; + } + + /** + * Desconto 1 podendo ser: VALOR ou PERCENTUAL + * @param string $data YYYY-MM-DD + * @param string $valor precision 14 scale 2 + */ + public function setDesconto1(string $data, float $valor) + { + $this->dataDesconto1 = $data; + $this->valorDesconto1 = $valor; + return $this; + } + /** + * Desconto 2 podendo ser: VALOR ou PERCENTUAL + * @param string $data YYYY-MM-DD + * @param string $valor precision 14 scale 2 + */ + public function setDesconto2(string $data, float $valor) + { + $this->dataDesconto2 = $data; + $this->valorDesconto2 = $valor; + return $this; + } + + /** + * Desconto 3 podendo ser: VALOR ou PERCENTUAL + * @param string $data YYYY-MM-DD + * @param string $valor precision 14 scale 2 + */ + public function setDesconto3(string $data, float $valor) + { + $this->dataDesconto3 = $data; + $this->valorDesconto3 = $valor; + return $this; + } + + /** + * @return float + */ + public function getMulta(): float + { + return $this->multa; + } + + /** + * Percentual de multa a cobrar + * @param float $multa + */ + public function setMulta(float $multa) + { + $this->multa = $multa; + return $this; + } + + + public function getJuros(): ?float + { + return $this->juros; + } + + /** + * Valor de juros a cobrar por dia + * @param float $juros + */ + public function setJuros(float $juros) + { + $this->juros = $juros; + return $this; + } + + /** + * @return string + */ + public function getTipoJuros(): ?string + { + return $this->tipoJuros; + } + /** + * Tipo de Juros, podendo ser: VALOR ou PERCENTUAL + * @param string $tipoJuros + * @required + * @options VALOR | PERCENTUAL + */ + public function setTipoJuros(string $tipoJuros) + { + $this->tipoJuros = $tipoJuros; + return $this; + } + + /** + * @return string + */ + public function getCodigoBarras(): ?string + { + return $this->codigoBarras; + } + + /** + * Código preenchido após a geração do boleto. + * @param mixed $codigoBarras + */ + public function setCodigoBarras($codigoBarras) + { + $this->codigoBarras = $codigoBarras; + return $this; + } + + /** + * @return ?string + */ + public function getLinhaDigitavel(): ?string + { + return $this->linhaDigitavel; + } + + /** + * Preenchido após a geração do boleto. + * @param mixed $linhaDigitavel + */ + public function setLinhaDigitavel($linhaDigitavel) + { + $this->linhaDigitavel = $linhaDigitavel; + return $this; + } + /** + * @param Split $splitBoleto + */ + public function setSplitBoleto(Split $splitBoleto) + { + $this->splitBoleto = $splitBoleto; + return $this; + } + + /** + * @param Split $splitBoleto + */ + public function getSplitBoleto(): ?Split + { + return $this->splitBoleto; + } + +} diff --git a/src/Cobranca/Destinatario.php b/src/Cobranca/Destinatario.php new file mode 100644 index 0000000..1a10f20 --- /dev/null +++ b/src/Cobranca/Destinatario.php @@ -0,0 +1,187 @@ +codigoAgencia; + } + + /** + * Define o código da agência do destinatário. + * + * @param string|null $codigoAgencia Código da agência com 4 dígitos numéricos. + * @return Destinatario + */ + public function setCodigoAgencia(?string $codigoAgencia): Destinatario + { + $this->codigoAgencia = $codigoAgencia; + return $this; + } + + /** + * @return string|null + */ + public function getCodigoBanco(): ?string + { + return $this->codigoBanco; + } + + /** + * Define o código do banco do destinatário. + * + * @param string|null $codigoBanco Código do banco com 3 dígitos numéricos. + * @return Destinatario + */ + public function setCodigoBanco(?string $codigoBanco): Destinatario + { + + $this->codigoBanco = $codigoBanco; + return $this; + } + + /** + * @return int|null + */ + public function getFloatSplit(): ?int + { + return $this->floatSplit; + } + + /** + * Define o Float Split do destinatário. + * + * @param int|null $floatSplit Float Split, podendo ser informado de 0 a 30. + * @return Destinatario + */ + public function setFloatSplit(?int $floatSplit): Destinatario + { + + $this->floatSplit = $floatSplit; + return $this; + } + + /** + * @return string|null + */ + public function getNomeDestinatario(): ?string + { + return $this->nomeDestinatario; + } + + /** + * Define o nome do destinatário. + * + * @param string|null $nomeDestinatario Nome do destinatário, podendo ter de 3 a 40 caracteres. + * @return Destinatario + */ + public function setNomeDestinatario(?string $nomeDestinatario): Destinatario + { + + $this->nomeDestinatario = $nomeDestinatario; + return $this; + } + + /** + * @return string|null + */ + public function getNumeroContaCorrente(): ?string + { + return $this->numeroContaCorrente; + } + + /** + * Define o número da conta corrente do destinatário. + * + * @param string|null $numeroContaCorrente Número da conta corrente, podendo ter de 4 a 13 caracteres numéricos. + * @return Destinatario + */ + public function setNumeroContaCorrente(?string $numeroContaCorrente): Destinatario + { + + $this->numeroContaCorrente = $numeroContaCorrente; + return $this; + } + + /** + * @return string|null + */ + public function getNumeroCpfCnpj(): ?string + { + return $this->numeroCpfCnpj; + } + + /** + * Define o CPF/CNPJ do destinatário. + * + * @param string|null $numeroCpfCnpj CPF/CNPJ do destinatário, podendo ter até 14 caracteres numéricos. + * @return Destinatario + */ + public function setNumeroCpfCnpj(?string $numeroCpfCnpj): Destinatario + { + + $this->numeroCpfCnpj = $numeroCpfCnpj; + return $this; + } + + /** + * @return int|null + */ + public function getParcelaRateio(): ?int + { + return $this->parcelaRateio; + } + + /** + * Define o número da parcela do rateio. + * + * @param int|null $parcelaRateio Número da parcela do rateio, podendo ser informado de 1 a 30. + * @return Destinatario + */ + public function setParcelaRateio(?int $parcelaRateio): Destinatario + { + + $this->parcelaRateio = $parcelaRateio; + return $this; + } + + /** + * @return float|null + */ + public function getValorPercentualRateio(): ?float + { + return $this->valorPercentualRateio; + } + + /** + * Define o valor/percentual do rateio. + * + * @param float|null $valorPercentualRateio Valor/percentual do rateio, podendo ter até 16 dígitos, sendo dois deles para a casa decimal. + * @return Destinatario + */ + public function setValorPercentualRateio(?float $valorPercentualRateio): Destinatario + { + $this->valorPercentualRateio = $valorPercentualRateio; + return $this; + } + +} diff --git a/src/Cobranca/Pagador.php b/src/Cobranca/Pagador.php new file mode 100644 index 0000000..63aa4b2 --- /dev/null +++ b/src/Cobranca/Pagador.php @@ -0,0 +1,7 @@ +tipoPessoa; + } + + /** + * Define o tipo de pessoa do pagador. + * + * @param string|null $tipoPessoa Tipo de pessoa do pagador, podendo ser "PESSOA_JURIDICA" ou "PESSOA_FISICA". + * @required campo requerido + * @return self + */ + public function setTipoPessoa(?string $tipoPessoa): self + { + + $this->tipoPessoa = $tipoPessoa; + return $this; + } + + /** + * @return string|null + */ + public function getDocumento(): ?string + { + return $this->documento; + } + + /** + * Define o CPF ou CNPJ do pagador. + * + * @param string|null $documento CPF ou CNPJ do pagador. + * @required campo requerido + * @return self + */ + public function setDocumento(?string $documento): self + { + + $this->documento = $documento; + return $this; + } + + /** + * @return string|null + */ + public function getNome(): ?string + { + return $this->nome; + } + + /** + * Define o nome do pagador. + * + * @param string|null $nome Nome do pagador. + * @required campo requerido + * @return self + */ + public function setNome(?string $nome): self + { + $this->nome = $nome; + return $this; + } + + /** + * @return string|null + */ + public function getLogradouro(): ?string + { + return $this->logradouro; + } + + /** + * Define o endereço do pagador. + * + * @param string|null $logradouro Endereço do pagador. + * @return self + */ + public function setLogradouro(?string $logradouro): self + { + $this->logradouro = $logradouro; + return $this; + } + + /** + * @return string|null + */ + public function getNumeroEndereco(): ?string + { + return $this->numeroEndereco; + } + + /** + * Define a numeroEndereco do pagador. + * + * @param string|null $numeroEndereco Cidade do pagador. + * @return self + */ + public function setNumeroEndereco(?string $numeroEndereco): self + { + $this->numeroEndereco = $numeroEndereco; + return $this; + } + /** + * @return string|null + */ + public function getCidade(): ?string + { + return $this->cidade; + } + + /** + * Define a cidade do pagador. + * + * @param string|null $cidade Cidade do pagador. + * @return self + */ + public function setCidade(?string $cidade): self + { + $this->cidade = $cidade; + return $this; + } + + /** + * @return string|null + */ + public function getUf(): ?string + { + return $this->uf; + } + + /** + * Define a UF do pagador. + * + * @param string|null $uf @length(2) UF do pagador. + * @return self + */ + public function setUf(?string $uf): self + { + + $this->uf = $uf; + return $this; + } + + /** + * @return string|null + */ + public function getCep(): ?string + { + return $this->cep; + } + + /** + * Define o CEP do pagador. + * + * @param string|null $cep @length(8) CEP do pagador. + * @return self + */ + public function setCep(?string $cep): self + { + $this->cep = $cep; + return $this; + } + + /** + * @return string|null + */ + public function getTelefone(): ?string + { + return $this->telefone; + } + + /** + * Define o telefone do pagador. + * + * @param string|null $telefone Telefone do pagador. + * @return self + */ + public function setTelefone(?string $telefone): self + { + $this->telefone = $telefone; + return $this; + } + + /** + * @return string|null + */ + public function getEmail(): ?string + { + return $this->email; + } + + /** + * Define o email do pagador. + * + * @param string|null $email Email do pagador. + * @return self + */ + public function setEmail(?string $email): self + { + $this->email = filter_var($email, FILTER_VALIDATE_EMAIL); + return $this; + } + +} diff --git a/src/Cobranca/Split.php b/src/Cobranca/Split.php new file mode 100644 index 0000000..4a38ce1 --- /dev/null +++ b/src/Cobranca/Split.php @@ -0,0 +1,104 @@ +repasseAutomaticoSplit; + } + + /** + * Define o repasse automático do Split. + * + * @param string|null $repasseAutomaticoSplit Repasse automático do Split, podendo ser "SIM" ou "NAO". + * @return Split + */ + public function setRepasseAutomaticoSplit(?string $repasseAutomaticoSplit): Split + { + $this->repasseAutomaticoSplit = $repasseAutomaticoSplit; + return $this; + } + + /** + * @return string|null + */ + public function getTipoValorRateio(): ?string + { + return $this->tipoValorRateio; + } + + /** + * Define o tipo de valor do rateio do Split. + * + * @param string|null $tipoValorRateio Tipo de valor do rateio do Split, podendo ser "PERCENTUAL" ou "VALOR". + * @return Split + */ + public function setTipoValorRateio(?string $tipoValorRateio): Split + { + $this->tipoValorRateio = $tipoValorRateio; + return $this; + } + + /** + * @return string|null + */ + public function getRegraRateio(): ?string + { + return $this->regraRateio; + } + + /** + * Define a regra do rateio do Split. + * + * @param string|null $regraRateio Regra do rateio do Split, podendo ser "MENOR_VALOR", "VALOR_COBRADO" ou "VALOR_REGISTRO". + * @return Split + */ + public function setRegraRateio(?string $regraRateio): Split + { + $this->regraRateio = $regraRateio; + return $this; + } + + /** + * @return array|null + */ + public function getDestinatarios(): ?array + { + return $this->destinatarios; + } + + /** + * Define os destinatários do Split. + * Contas destinatárias do Split do boleto. Poderá ser informado de 1 a 30 contas. + * + * @param Destinatario[]|null $destinatarios Array de objetos Destinatario. + * @return Split + */ + public function setDestinatarios(Destinatario $destinatario): Split + { + + $this->destinatarios[] = $destinatario; + return $this; + } + public function jsonSerialize(): array + { + return get_object_vars($this); + } +} diff --git a/src/Cobranca/ValidationTrait.php b/src/Cobranca/ValidationTrait.php new file mode 100644 index 0000000..4d68de9 --- /dev/null +++ b/src/Cobranca/ValidationTrait.php @@ -0,0 +1,266 @@ + 5) { + $erros[] = "O campo 'Informativos' pode ter no máximo 5 itens."; + } else { + foreach ($dados['informativos'] as $informativo) { + if (strlen($informativo) > 80) { + $erros[] = "Cada item do campo 'Informativos' pode ter no máximo 80 caracteres."; + } + } + } + } + } + + // Validação das mensagens + if (isset($dados['mensagens']) && !empty($dados['mensagens'])) { + if (!is_array($dados['mensagens'])) { + $erros[] = "O campo 'Mensagens' deve ser um array."; + } else { + if (count($dados['mensagens']) > 4) { + $erros[] = "O campo 'Mensagens' pode ter no máximo 4 itens."; + } else { + foreach ($dados['mensagens'] as $mensagem) { + if (strlen($mensagem) > 80) { + $erros[] = "Cada item do campo 'Mensagens' pode ter no máximo 80 caracteres."; + } + } + } + } + } + + // Validação do Split (Distribuição de Crédito) + if (isset($dados['regraRateio']) && !empty($dados['regraRateio'])) { + if (!in_array($dados['regraRateio'], ['MENOR_VALOR', 'VALOR_COBRADO', 'VALOR_REGISTRO'])) { + $erros[] = "O campo 'Regra de Rateio' deve ser 'MENOR_VALOR', 'VALOR_COBRADO' ou 'VALOR_REGISTRO'."; + } + if (!isset($dados['repasseAutomaticoSplit']) || empty($dados['repasseAutomaticoSplit'])) { + $erros[] = "O campo 'Repasse Automático do Split' é obrigatório."; + } else { + if (!in_array($dados['repasseAutomaticoSplit'], ['SIM', 'NAO'])) { + $erros[] = "O campo 'Repasse Automático do Split' deve ser 'SIM' ou 'NAO'."; + } + } + if (!isset($dados['tipoValorRateio']) || empty($dados['tipoValorRateio'])) { + $erros[] = "O campo 'Tipo de Valor do Rateio' é obrigatório."; + } else { + if (!in_array($dados['tipoValorRateio'], ['PERCENTUAL', 'VALOR'])) { + $erros[] = "O campo 'Tipo de Valor do Rateio' deve ser 'PERCENTUAL' ou 'VALOR'."; + } + } + if (!isset($dados['destinatarios']) || empty($dados['destinatarios'])) { + $erros[] = "O campo 'Destinatários' é obrigatório."; + } else { + if (!is_array($dados['destinatarios'])) { + $erros[] = "O campo 'Destinatários' deve ser um array."; + } else { + if (count($dados['destinatarios']) > 30) { + $erros[] = "O campo 'Destinatários' pode ter no máximo 30 itens."; + } else { + foreach ($dados['destinatarios'] as $destinatario) { + if (!isset($destinatario['codigoAgencia']) || empty($destinatario['codigoAgencia'])) { + $erros[] = "O campo 'Código da Agência' é obrigatório."; + } + if (!isset($destinatario['codigoBanco']) || empty($destinatario['codigoBanco'])) { + $erros[] = "O campo 'Código do Banco' é obrigatório."; + } + if (!isset($destinatario['floatSplit']) || empty($destinatario['floatSplit'])) { + $erros[] = "O campo 'Float Split' é obrigatório."; + } + if (!isset($destinatario['nomeDestinatario']) || empty($destinatario['nomeDestinatario'])) { + $erros[] = "O campo 'Nome do Destinatário' é obrigatório."; + } + if (!isset($destinatario['numeroContaCorrente']) || empty($destinatario['numeroContaCorrente'])) { + $erros[] = "O campo 'Número da Conta Corrente' é obrigatório."; + } + if (!isset($destinatario['numeroCpfCnpj']) || empty($destinatario['numeroCpfCnpj'])) { + $erros[] = "O campo 'Número do CPF/CNPJ' é obrigatório."; + } + if (!isset($destinatario['parcelaRateio']) || empty($destinatario['parcelaRateio'])) { + $erros[] = "O campo 'Parcela do Rateio' é obrigatório."; + } + if (!isset($destinatario['valorPercentualRateio']) || empty($destinatario['valorPercentualRateio'])) { + $erros[] = "O campo 'Valor/Percentual do Rateio' é obrigatório."; + } + } + } + } + } + } + + + if(!empty($erros)) throw new SicrediValidationException($erros); + + + } +} diff --git a/src/CredencialsManager.php b/src/CredencialsManager.php new file mode 100644 index 0000000..84d6d5c --- /dev/null +++ b/src/CredencialsManager.php @@ -0,0 +1,193 @@ +username = $username; + $this->password = $password; + $this->xApiKey = $xApiKey; + $this->scope = $scope; + $this->cooperativa = $cooperativa; + $this->posto = $posto; + $this->codigoBeneficiario = $codigoBeneficiario; + $this->tokenNewCallback = $tokenNewCallback; + $this->tokenLoadCallback = $tokenLoadCallback; + + } + + + public function getHeaders() { + $authHeaders = [ + 'x-api-key' => $this->xApiKey, + 'context' => $this->context, + + ]; + if($this->hasValidToken()) { + $authHeaders['Authorization'] = 'Bearer ' . $this->accessToken; + $authHeaders['cooperativa'] = $this->cooperativa; + $authHeaders['posto'] = $this->posto; + } + return $authHeaders; + } + + public function getBodyLogin() { + return [ + 'username' => $this->username, + 'password' => $this->password, + 'refresh_token' => $this->refreshToken, + 'grant_type' => $this->grant_type, + 'scope' => $this->scope, + ]; + } + function hasValidToken() : bool { + return !!$this->getAccessToken() && (($this->getTokenTimestamp() + $this->getTokenExpiresIn()) > (time() - 10)); + } + function hasValidRefreshToken() : bool { + return !!$this->getRefreshToken() && ($this->getTokenTimestamp() + $this->getRefreshTokenExpiresIn() > (time() - 10)); + } + + public function getXApiKey() : ?string { + return $this->xApiKey; + } + + public function setXApiKey(?string $xApiKey) { + $this->xApiKey = $xApiKey; + return $this; + } + + public function getCodigoBeneficiario() : ?string { + return $this->codigoBeneficiario; + } + public function getCooperativa() : ?string { + return $this->cooperativa; + } + public function getPosto() : ?string { + return $this->posto; + } + public function getAccessToken() : ?string { + return $this->accessToken; + } + + public function setAccessToken(?string $accessToken) { + $this->accessToken = $accessToken; + return $this; + } + + public function getRefreshToken() : ?string { + return $this->accessToken; + } + + public function setRefreshToken(?string $refreshToken) { + $this->refreshToken = $refreshToken; + return $this; + } + + public function getTokenExpiresIn() : ?int { + return $this->tokenExpiresIn; + } + + public function setTokenExpiresIn(?int $tokenExpiresIn) { + $this->tokenExpiresIn = $tokenExpiresIn; + return $this; + } + + public function getRefreshTokenExpiresIn() : ?int { + return $this->refreshTokenExpiresIn; + } + + public function setRefreshTokenExpiresIn(?int $refreshTokenExpiresIn) { + $this->refreshTokenExpiresIn = $refreshTokenExpiresIn; + return $this; + } + + public function getTokenTimestamp() : ?int { + return $this->tokenTimestamp; + } + + public function setTokenTimestamp(?int $tokenTimestamp) { + $this->tokenTimestamp = $tokenTimestamp; + return $this; + } + + /** + * Define uma função a ser chamada sempre que for necessária a + * utilização do token oAuth permitindo a carga do token a partir + * do cache e a contabilização da utilização tanto com base na + * quantidade quanto com base no tempo. + * + * A função deve retornar um array com os elementos access_token, + * expires_in e timestamp, ou false caso um novo token deva + * ser emitido. + * + * É aconselhável que a função faça uso de alguma implementação de + * cache e semáforos para garantir que a contabilização ocorra de forma + * coerente entre processos. + * + * @param Closure $callback + */ + public function setTokenLoadCallback(?Closure $callback) + { + $this->tokenLoadCallback = $callback; + } + + /** + * Define uma função a ser chamada quando um novo token for emitido, + * permitindo que a aplicação armazene o novo token em um cache + * + * A função irá receber o token formatado como uma string JSON sobre + * a saída do método exportOAuthToken(), que poderá ser usada para + * importar o token posteriormente no parâmetro $oAuthTokenData do + * construtor da classe SicrediCobranca. + * + * É aconselhável que a função faça uso de alguma implementação de + * cache e semáforos para garantir que a o token seja utilizado + * corretamente entre processos concorrentes. + * + * @param Closure $callback + */ + public function setTokenNewCallback(?Closure $callback) + { + $this->tokenNewCallback = $callback; + } + +} diff --git a/src/Exceptions/SicrediRequestException.php b/src/Exceptions/SicrediRequestException.php new file mode 100644 index 0000000..d580ce8 --- /dev/null +++ b/src/Exceptions/SicrediRequestException.php @@ -0,0 +1,8 @@ + $value) { + $headers[] = "$key: $value"; + } + return $headers; + } + /** + * Inicializa a conexão com a API + * + * @param array $headers + */ + protected function intanceRequest($url, array &$headers) + { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($curl, CURLOPT_HEADER, 1); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_URL, $this->apiBaseURL . $url); + + $headers = array_merge( + [ + 'accept' => 'application/json', + 'content-type' => 'application/json', + ], + $this->credencialsManager->getHeaders(), + $headers + ); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->formatHeader($headers)); + + return $curl; + } + + /** + * + * @param string $url + * @param \JsonSerializable $data + * @param array $headers + * @throws SicrediRequestException + * @return \stdClass + */ + public function login( + array $headers = [], + $forcePassword = false + ) { + $url = "/auth/openapi/token"; + + $headers['content-type'] = 'application/x-www-form-urlencoded'; + + $body = $this->credencialsManager->getBodyLogin(); + if ($this->credencialsManager->hasValidRefreshToken()) { + $body['grant_type'] = 'refresh_token'; + } + + $curl = $this->intanceRequest($url, $headers); + // Utils::prettyVarDump($headers); + // Utils::prettyVarDump($body); + + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($body)); + + return $this->handleResponse($curl, $headers); + } + public function get(string $url, array $queryParams = [], array $headers = []) + { + $this->checkOAuthToken(); + + if (!empty($queryParams)) { + $queryString = http_build_query($queryParams); + $url = $url . '?' . $queryString; + } + + $curl = $this->intanceRequest($url, $headers); + + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); + + return $this->handleResponse($curl, $headers); + } + + public function post(string $url, $body, ?array $headers = []) + { + $this->checkOAuthToken(); + + $curl = $this->intanceRequest($url, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); + // Utils::prettyVarDump(json_decode(json_encode($body), true)); + + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body)); + // var_dump(curl_getinfo($curl, CURLOPT_HTTPHEADER)); + + return $this->handleResponse($curl, $headers); + } + + public function patch(string $url, array $body = [], ?array $headers = []) + { + $this->checkOAuthToken(); + + $curl = $this->intanceRequest($url, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH'); + + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body)); + // var_dump(curl_getinfo($curl, CURLOPT_HTTPHEADER)); + + return $this->handleResponse($curl,$headers); + } + public function put(string $url, $body, ?array $headers = []) + { + $this->checkOAuthToken(); + + $curl = $this->intanceRequest($url, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); + // Utils::prettyVarDump(json_decode(json_encode($body), true)); + + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body)); + // var_dump(curl_getinfo($curl, CURLOPT_HTTPHEADER)); + + return $this->handleResponse($curl, $headers); + } + + + + protected function handleResponse($curl, $requestHeaders) + { + $response = curl_exec($curl); + + // Trata possíveis erros na requisição cURL + if (curl_errno($curl)) { + $error_msg = curl_error($curl); + throw new SicrediRequestException("Erro de processamento: " . $error_msg, 500); + } + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + + curl_close($curl); + // Decodifica a resposta JSON + $header = substr($response, 0, $header_size); + $headersResponse = []; + $headerRows = explode("\n", $header); + + foreach ($headerRows as $key => $row) { + $headerParts = explode(":", $row, 2); + if (count($headerParts) < 2) { + continue; + } + + $key = trim($headerParts[0]); + $values = explode(";", trim($headerParts[1])); + if (empty($values)) continue; + // Armazena os cabeçalhos com a mesma chave como um array + $headersResponse[$key] = count($values) > 1 ? $values : $values[0]; + } + + $body = substr($response, $header_size); + if (!empty($body) && $headersResponse['content-type'] === 'application/json') { + $response = json_decode($body, true); + } else { + $response = $body; + } + + // Verifica se houve erro na decodificação do JSON + if (json_last_error() !== JSON_ERROR_NONE) { + throw new SicrediRequestException($body, $statusCode); + } + + if ($statusCode < 200 || $statusCode > 299) { + if (isset($response['message'])) { + $response = $response['message']; + } else if (isset($response['error'])) { + $response = $response['error']; + } elseif ($statusCode === 401) { + $response = "Não foi possível autenticar com as credenciais."; + } + + throw new SicrediRequestException($response, $statusCode); + } + return $response; + } + /** + * Tenta carregar token através de callback, verifica se tem o token oAuth + * disponível, se ele está expirado, requisitando novo token e executando + * o callback se necessário. + * + * @param boolean $emitCallbacks Callbacks serão executados (default true) + */ + protected function checkOAuthToken($emitCallbacks = true) + { + if ($emitCallbacks && $this->credencialsManager->tokenLoadCallback && !$this->credencialsManager->hasValidToken()) { + if (($loadedTokenData = ($this->credencialsManager->tokenLoadCallback)()) !== false) { + $this->credencialsManager->setAccessToken($loadedTokenData["access_token"]); + $this->credencialsManager->setTokenExpiresIn($loadedTokenData["expires_in"]); + $this->credencialsManager->setTokenTimestamp($loadedTokenData["timestamp"]); + $this->credencialsManager->setRefreshToken($loadedTokenData["refresh_token"]); + $this->credencialsManager->setRefreshTokenExpiresIn($loadedTokenData["refresh_expires_in"]); + } else { + $this->credencialsManager->setAccessToken(null); + } + } + + + + if (!$this->credencialsManager->hasValidToken()) { + $response = $this->login(); + + $this->credencialsManager->setAccessToken($response['access_token']); + $this->credencialsManager->setRefreshToken($response['refresh_token']); + $this->credencialsManager->setTokenExpiresIn($response['expires_in']); + $this->credencialsManager->setRefreshTokenExpiresIn($response['refresh_expires_in']); + $this->credencialsManager->setTokenTimestamp(time()); + if ($emitCallbacks && $this->credencialsManager->tokenNewCallback) { + ($this->credencialsManager->tokenNewCallback)(json_encode($this->exportOAuthToken())); + } + } + } + + /** + * return current oAuthToken data + * + * @return [] + */ + public function exportOAuthToken() + { + $this->checkOauthToken(false); + return [ + "access_token" => $this->credencialsManager->getAccessToken(), + "refresh_token" => $this->credencialsManager->getRefreshToken(), + "refresh_expires_in" => $this->credencialsManager->getRefreshTokenExpiresIn(), + "expires_in" => $this->credencialsManager->getTokenExpiresIn(), + "timestamp" => $this->credencialsManager->getTokenTimestamp() + ]; + } +} diff --git a/src/Serializable.php b/src/Serializable.php new file mode 100644 index 0000000..355446c --- /dev/null +++ b/src/Serializable.php @@ -0,0 +1,42 @@ +others[$key] = $value; + return $this; + } + + public function getOthers(): array + { + return $this->others; + } + + /** + * @return array + */ + public function JsonSerialize(): array + { + $data = get_object_vars($this); + + unset($data['others']); + return array_merge($data, $this->getOthers()); + } +} diff --git a/src/SicrediCobranca.php b/src/SicrediCobranca.php new file mode 100644 index 0000000..303548e --- /dev/null +++ b/src/SicrediCobranca.php @@ -0,0 +1,368 @@ +credencialsManager = $credencialsManager; + if ($apiBaseURL) $this->apiBaseURL = $apiBaseURL; + + $this->checkOAuthToken(true); + } + + /** + * Transmite um boleto para o Banco Sicredi + * + * @param Boleto $boleto Boleto a ser transmitido + * @throws SicrediRequestException + * @return array + */ + public function createBoleto(Boleto $boleto, $preValidation = true) + { + $boleto->setCodigoBeneficiario($this->credencialsManager->getCodigoBeneficiario()); + if($preValidation) $boleto->validarBoleto(); + + $response = $this->post("/cobranca/boleto/v1/boletos", $boleto); + + // $boleto->setNossoNumero($response['nossoNumero']); + // $boleto->setCodigoBarras($response['codigoBarras']); + // $boleto->setLinhaDigitavel($response['linhaDigitavel']); + + return $response; + } + + /** + * + * @param string $nossoNumero + * @return \stdClass + */ + public function getBoleto(string $nossoNumero): array + { + // var_dump($nossoNumero); + return $this->get("/cobranca/boleto/v1/boletos", [ + 'nossoNumero' => $nossoNumero, + 'codigoBeneficiario' => $this->credencialsManager->getCodigoBeneficiario() + ]); + } + + /** + * Faz download do PDF do boleto + * + * @param string $nossoNumero + * @param string $savePath Pasta a salvar o arquivo (default para a pasta de upload ou tmp) + * @throws SicrediRequestException + * @return string Caminho completo do arquivo baixado + */ + public function getBoletoPdf(string $linhaDigitavel, string $savePath = null): string + { + if ($savePath == null) { + $savePath = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir(); + } + + $encoded = $this->getBoletoEncoded($linhaDigitavel); + + $filename = tempnam($savePath, "boleto-sicredi-") . ".pdf"; + + if (!file_put_contents($filename, $encoded)) { + throw new SicrediRequestException("Não foi possível decodificar o pdf"); + } + + return $filename; + } + + /** + * + * @param string $linhaDigitavel + * @throws SicrediRequestException + * @return string Conteúdo do PDF codificado + */ + public function getBoletoEncoded(string $linhaDigitavel): string + { + $response = $this->get("/cobranca/boleto/v1/boletos/pdf", [ + "linhaDigitavel" => $linhaDigitavel + ]); + + return $response; + } + /** + * disabled in sandbox mode + * @param string $linhaDigitavel + * @throws SicrediRequestException + * @return void + */ + public function baixaBoleto(string $nossoNumero) + { + return $this->patch("/cobranca/boleto/v1/boletos/" . $nossoNumero . "/baixa", [], [ + "codigoBeneficiario" => $this->credencialsManager->getCodigoBeneficiario() + ]); + } + + /** + * + * @param string $nossoNumero + * @param string $datavencimento formated date (Y-m-d) + * @throws SicrediRequestException + */ + public function updateVencimento(string $nossoNumero, string $datavencimento) + { + + return $this->patch("/cobranca/boleto/v1/boletos/" . $nossoNumero . "/data-vencimento", [ + "dataVencimento" => $datavencimento + ],[ + "codigoBeneficiario" => $this->credencialsManager->getCodigoBeneficiario() + ]); + } + + /** + * Retorna lista de boletos registrados no banco + * @params \DateTimeInterface $dia + */ + public function listBoletosPagosByDay( + \DateTimeInterface $dia, + int $pagina = 1, + ?string $cpfCnpjBeneficiario = null + ): array { + + $url = "/cobranca/boleto/v1/boletos/liquidados/dia"; + $queryParams = []; + if (!$dia) $dia = new \DateTime(); + $queryParams['dia'] = $dia->format('d/m/Y'); + $queryParams['codigoBeneficiario'] = $this->credencialsManager->getCodigoBeneficiario(); + $queryParams['pagina'] = $pagina; + + if ($cpfCnpjBeneficiario) $queryParams['cpfCnpjBeneficiarioFinal'] = $cpfCnpjBeneficiario; + + return $this->get($url, $queryParams); + } + + // /** + // * Retorna o saldo da conta na data informada. Caso não seja informada + // * uma data, retorna o saldo atual. + // * + // * @param \DateTime $dataSaldo + // * @return float + // */ + // public function getSaldo(\DateTime $dataSaldo = null): array + // { + // if (!$dataSaldo) { + // $dataSaldo = new \DateTime(); + // } + + // return $this->get("/banking/v2/saldo?dataSaldo=" . $dataSaldo->format('Y-m-d')); + // } + + // /** + // * Consulta o extrato em um período entre datas específico. Para utilizar esta chamada, + // * suas credenciais junto ao Banco Sicredi precisam ter acesso à permissão "Consulta de extrato + // * e saldo", e você precisa declarar o escopo extrato.read ao criar o CredencialsManager. + // * + // * @param \DateTime dataInicio + // * @param \DateTime dataFim + // * @return \stdClass + // */ + // public function getExtrato(\DateTime $dataInicio, \DateTime $dataFim): array + // { + // $url = "/banking/v2/extrato"; + // $params = []; + // $params['dataInicio'] = $dataInicio->format('Y-m-d'); + // $params['dataFim'] = $dataFim->format('Y-m-d'); + + + // return $this->get($url, $params); + // } + + // /** + // * Consulta o extrato COMPLETO em um período entre datas específico. Para utilizar esta chamada, + // * suas credenciais junto ao Banco sicredi precisam ter acesso à permissão "Consulta de extrato + // * e saldo", e você precisa declarar o escopo extrato.read ao criar o TokenRequest. + // * O extrato completo é paginado (diferente da função extrato) + // * + // * + // * @param \DateTime $dataInicio + // * @param \DateTime $dataFim + // * @param int $pagina Número da página, a primeira página é 0 (zero) + // * @param string $tipoOperacao 'C' para crédito, 'D' para débito + // * @param string $tipoTransacao PIX, CAMBIO, ESTORNO, etc. + // * @return \stdClass + // */ + // public function getExtratoCompleto( + // \DateTime $dataInicio, + // \DateTime $dataFim, + // int $pagina = 0, + // int $tamanhoPagina = 50, + // string $tipoOperacao = '', + // string $tipoTransacao = '' + // ): array { + // $params['dataInicio'] = $dataInicio->format('Y-m-d'); + // $params['dataFim'] = $dataFim->format('Y-m-d'); + // $params['pagina'] = $pagina; + // $params['tamanhoPagina'] = $tamanhoPagina; + // $params['tipoOperacao'] = $tipoOperacao; + // $params['tipoTransacao'] = $tipoTransacao; + + // $url = "/banking/v2/extrato/completo"; + + // return $this->get($url, $params); + // } + + + /** + * Cria o webhook que receberá atualizações automáticos dos boletos (cobranças) + * + * @param $url + * @return array + * @throws SicrediRequestException + * Exemplo de recebimento desse webhook após contratado + * { + * "agencia": "9999", + * "posto": "99", + * "beneficiario": "12345", + * "nossoNumero": "221000144", + * "dataEvento":[2024,3,20,11,40,39,24000000] + * "movimento": "LIQUIDACAO_PIX", + * "valorLiquidacao": "101.01", + * "valorDesconto": "0", + * "valorJuros": "0", + * "valorMulta": "0", + * "valorAbatimento": "0", + * “carteira”: “CARTEIRA SIMPLES” + * "dataPrevisaoPagamento":[2024,3,20] + * "idEventoWebhook": "N000000000000000000000000000000LIQUIDACAO_PIX" + * } + */ + + public function createWebhook($webhookUrl, ?array $eventos = null): array + { + $url = "/cobranca/boleto/v1/webhook/contrato/"; + $allEvents = [ + "LIQUIDACAO", + // "LIQUIDACAO_PIX", + // "LIQUIDACAO_COMPE_H5", + // "LIQUIDACAO_COMPE_H6", + // "LIQUIDACAO_COMPE_H8", + // "LIQUIDACAO_REDE", + // "LIQUIDACAO_CARTORIO", + // "AVISO_PAGAMENTO_COMPE", + // "ESTORNO_LIQUIDACAO_REDE" + ]; + + if ($eventos) $allEvents = $eventos; + + $payload = [ + "cooperativa" => $this->credencialsManager->getCooperativa(), + "posto" => $this->credencialsManager->getPosto(), + "codBeneficiario" => $this->credencialsManager->getCodigoBeneficiario(), + "eventos" => $allEvents, + "url" => $webhookUrl, + "urlStatus" => "ATIVO", + "contratoStatus" => "ATIVO", + ]; + Utils::prettyVarDump($payload); + + //Verifica se a URL do webhook é válida + if (!filter_var($webhookUrl, FILTER_VALIDATE_URL)) { + throw new SicrediValidationException(["URL inválida"]); + } + try { + + return $this->post($url, $payload); + } catch (SicrediRequestException $e) { + if ($e->getCode() == 422 && $e->getMessage() == "Contrato já existente.") { + return $this->getWebhook(); + } + throw $e; + } + } + + /** + * Retorna o webhook cadastrado, se houver + * + * @return array + * @throws SicrediRequestException status 422 quando não encontrado + * + */ + + public function getWebhook(): array + { + $params = [ + "cooperativa" => $this->credencialsManager->getCooperativa(), + "posto" => $this->credencialsManager->getPosto(), + "beneficiario" => $this->credencialsManager->getCodigoBeneficiario() + ]; + + $url = "/cobranca/boleto/v1/webhook/contrato/"; + + return $this->get($url, $params); + } + + /** + * update webhook, se houver + * @throws SicrediRequestException + * @return bool + */ + public function updateUrlWebhook($webhookUrl): bool + { + try { + $existentWebhook = $this->getWebhook(); + + if ($existentWebhook) { + $url = "/cobranca/boleto/v1/webhook/contrato/"; + if($existentWebhook['url'] === $webhookUrl) return true; + $existentWebhook['url'] = $webhookUrl; + $existentWebhook['urlStatus'] = "ATIVO"; + $delete = $this->put($url, $existentWebhook); + // Utils::prettyVarDump($delete); + + return true; + } + return false; + } catch (SicrediRequestException $e) { + if ($e->getCode() == 422 && $e->getMessage() == "Nenhum contrato encontrado") { + return false; + } + throw $e; + } + } + /** + * Deleta o webhook, se houver + * Infelizmente esses endpoint do webwook não seguem um padrão de mercado, achei conveninente reduzir excessões desse processo + * @throws SicrediRequestException + * @return bool + */ + public function deleteWebhook(): bool + { + try { + $existentWebhook = $this->getWebhook(); + + if ($existentWebhook) { + $url = "/cobranca/boleto/v1/webhook/contrato/"; + $existentWebhook['contratoStatus'] = "INATIVO"; + $existentWebhook['status'] = "INATIVO"; + $delete = $this->put($url, $existentWebhook); + // Utils::prettyVarDump($delete); + + return true; + } + return false; + } catch (SicrediRequestException $e) { + if ($e->getCode() == 422 && $e->getMessage() == "Nenhum contrato encontrado") { + return false; + } + throw $e; + } + } + + +} diff --git a/src/Utils.php b/src/Utils.php new file mode 100644 index 0000000..b1c36f1 --- /dev/null +++ b/src/Utils.php @@ -0,0 +1,40 @@ +\s*\n\s*)/', '/\]\=\>\s*/', '/array\(\d+\)/', '/\n/'], + ["[\n ", " => ", "Array", "\n"], + $output + ); + + // Enviar a saída formatada para o terminal + echo "\033[1;32m" . $output . "\033[0m"; // Verde para texto + } + + /** + * Assert if value complies with size restriction + * + * @param string $value + * @param int $size + * @param bool $exact + * @return string | false + */ + public static function assertSize(string $fieldName, string $value, int $size, bool $exact = false) + { + if ($exact && mb_strlen($value, "8bit") != $size) { + return sprintf("%s '%s' deveria ter %s %s carácter(es)",$fieldName, $value, 'exatamente', $size); + } elseif (!$exact && mb_strlen($value, "8bit") > $size) { + return sprintf("%s '%s' deveria ter %s %s carácter(es)",$fieldName, $value, 'no máximo', $size); + } + return false; + } +} \ No newline at end of file diff --git a/tests/BoletoTest.php b/tests/BoletoTest.php new file mode 100644 index 0000000..191560c --- /dev/null +++ b/tests/BoletoTest.php @@ -0,0 +1,17 @@ +assertInstanceOf(Boleto::class, $boleto); + + $boleto->setPagador(new Pagador()); + } + +} diff --git a/tests/PagadorTest.php b/tests/PagadorTest.php new file mode 100644 index 0000000..d962c22 --- /dev/null +++ b/tests/PagadorTest.php @@ -0,0 +1,13 @@ +assertInstanceOf(Pagador::class, $pagador); + } +} diff --git a/tests/SicrediCobrancaTest.php b/tests/SicrediCobrancaTest.php new file mode 100644 index 0000000..ea93426 --- /dev/null +++ b/tests/SicrediCobrancaTest.php @@ -0,0 +1,357 @@ +load(); + $API_KEY = $_ENV['API_KEY']; + // AVISO: + // estes testes não fazem sentido se não forem alterados + // com dados possíveis de boletos e de correntista + + $apiUrl = "https://api-parceiro.sicredi.com.br/sb"; + + try { + $cred = new CredencialsManager( + self::SANDBOX_USERNAME, + self::SANDBOX_PASSWORD, + $API_KEY, + 'cobranca', + self::SANDBOX_COOPERATIVA, + self::SANDBOX_POSTO, + self::SANDBOX_CODIGO_BENEFICIARIO, + function (string $tokenJson) { //new token callback + if ($tokenFile = fopen('sicredi-oauth-token.txt', 'w')) { + fwrite($tokenFile, $tokenJson); + fclose($tokenFile); + } + }, + function () { //get token callback + $oAuthTokenData = null; + // uso do @ para evitar o warning se o arquivo não existe + if (($tokenFile = @fopen('sicredi-oauth-token.txt', 'r')) !== false) { + // se tiver arquivo com token, carrega ele e retorna + $tokenJson = fread($tokenFile, 8192); + $oAuthTokenData = json_decode($tokenJson, true); + fclose($tokenFile); + return $oAuthTokenData; + } else { + // retorno "falso" força a emissão de novo token + return false; + } + } + ); + + $banco = new SicrediCobranca( + $cred, + $apiUrl + ); + + $this->assertInstanceOf(SicrediCobranca::class, $banco); + + // $this->assertEquals($banco->getApiBaseURL(), $apiUrl); + + $fakerB = \Faker\Factory::create(); + $fakerB->addProvider(new \Faker\Provider\pt_BR\Person($fakerB)); + + $fakerP = \Faker\Factory::create(); + $fakerP->addProvider(new \Faker\Provider\pt_BR\Person($fakerP)); + $beneficiario = (new Beneficiario()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + ->setDocumento($fakerB->cpf(false)) + ->setNome($fakerB->name) + ->setLogradouro($fakerB->streetName) + ->setNumeroEndereco($fakerB->numberBetween(10, 999)) + ->setCidade($fakerB->city) + ->setUf($fakerB->stateAbbr()) + ->setCep($fakerB->numerify("########")); + + $pagador = (new Pagador()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + ->setDocumento($fakerP->cpf(false)) + ->setNome($fakerP->name) + ->setLogradouro($fakerP->streetName) + ->setNumeroEndereco($fakerP->numberBetween(10, 999)) + ->setCidade($fakerP->city) + ->setUf($fakerP->stateAbbr()) + ->setCep($fakerP->numerify("########")); + + $dataVencimento = (new DateTime())->modify("+30 days"); + $boleto = new Boleto(); + $boleto->setPagador($pagador); + $boleto->setBeneficiario($beneficiario); + $boleto->setSeuNumero("TESTE"); + $boleto->setValor(500.00); + $boleto->setDataVencimento($dataVencimento->format("Y-m-d")); + $boleto->setDesconto1((clone $dataVencimento)->modify('-20 days')->format("Y-m-d"), 200.00); + $boleto->setDesconto2((clone $dataVencimento)->modify('-10 days')->format("Y-m-d"), 150.00); + $boleto->setDesconto3((clone $dataVencimento)->modify('-5 days')->format("Y-m-d"), 100.00); + $boleto->setJuros(1); + $boleto->setMulta(12.00); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR MULTA DE ' . $boleto->getMulta() . '%'); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR JUROS DE ' . $boleto->getJuros() . '% AO MÊS'); + + $boletoResponse = $banco->createBoleto($boleto); + $this->assertIsArray($boletoResponse); + $this->assertIsString($boletoResponse['nossoNumero']); + $this->assertIsString($boletoResponse['codigoBarras']); + $this->assertIsString($boletoResponse['linhaDigitavel']); + + $findedBoleto = $banco->getBoleto($boletoResponse['nossoNumero']); + $this->assertIsArray($findedBoleto, 'busca de Boleto'); + + $findedBoletoPdf = $banco->getBoletoPdf($boletoResponse['linhaDigitavel']); + $this->assertIsString($findedBoletoPdf, 'temp path pdf do boleto resgatado com sucesso'); + + $findedBoletoEncodedPdf = $banco->getBoletoEncoded($boletoResponse['linhaDigitavel']); + $this->assertIsString($findedBoletoEncodedPdf, 'binario pdf do boleto resgatado com sucesso'); + + $updatedBoleto = $banco->updateVencimento($boletoResponse['nossoNumero'], $dataVencimento->modify("+5 days")->format("Y-m-d")); + $this->assertIsArray($updatedBoleto, 'Boleto atualizado com sucesso'); + + $boletosPagos = $banco->listBoletosPagosByDay($dataVencimento->modify("+5 days")); + $this->assertArrayHasKey('items', $boletosPagos); + $this->assertIsArray($boletosPagos['items']); + //não habilitado para sandbox + // $banco->baixaBoleto($boletoResponse['nossoNumero']); + + } catch (SicrediValidationException | SicrediRequestException | \Exception $e) { + $this->fail($e->getMessage()); + } + } + + /** + * @test + * @return void + * @throws SicrediValidationException + * @throws SicrediRequestException + */ + public function test_fail_validation_on_create_boleto() + { + $dotenv = \Dotenv\Dotenv::createImmutable(__DIR__ . '/..'); + $dotenv->load(); + $API_KEY = $_ENV['API_KEY']; + $apiUrl = "https://api-parceiro.sicredi.com.br/sb"; + $banco = new SicrediCobranca( + new CredencialsManager( + self::SANDBOX_USERNAME, + self::SANDBOX_PASSWORD, + $API_KEY, + 'cobranca', + self::SANDBOX_COOPERATIVA, + self::SANDBOX_POSTO, + self::SANDBOX_CODIGO_BENEFICIARIO, + function (string $tokenJson) { //new token callback + if ($tokenFile = fopen('sicredi-oauth-token.txt', 'w')) { + fwrite($tokenFile, $tokenJson); + fclose($tokenFile); + } + }, + function () { //get token callback + $oAuthTokenData = null; + // uso do @ para evitar o warning se o arquivo não existe + if (($tokenFile = @fopen('sicredi-oauth-token.txt', 'r')) !== false) { + // se tiver arquivo com token, carrega ele e retorna + $tokenJson = fread($tokenFile, 8192); + $oAuthTokenData = json_decode($tokenJson, true); + fclose($tokenFile); + return $oAuthTokenData; + } else { + // retorno "falso" força a emissão de novo token + return false; + } + } + ), + $apiUrl + ); + + + // $this->assertEquals($banco->getApiBaseURL(), $apiUrl); + + $fakerB = \Faker\Factory::create(); + $fakerB->addProvider(new \Faker\Provider\pt_BR\Person($fakerB)); + + $fakerP = \Faker\Factory::create(); + $fakerP->addProvider(new \Faker\Provider\pt_BR\Person($fakerP)); + try { + $beneficiario = (new Beneficiario()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + // ->setDocumento($fakerB->cpf(false)) + ->setNome($fakerB->name) + ->setLogradouro($fakerB->streetName) + ->setNumeroEndereco($fakerB->numberBetween(10, 999)) + ->setCidade($fakerB->city) + ->setUf($fakerB->stateAbbr()) + ->setCep($fakerB->numerify("########")); + + $pagador = (new Pagador()) + ->setTipoPessoa(Pessoa::TIPO_PESSOA_FISICA) + // ->setDocumento($fakerP->cpf(false)) + ->setNome($fakerP->name) + ->setLogradouro($fakerP->streetName) + ->setNumeroEndereco($fakerP->numberBetween(10, 999)) + ->setCidade($fakerP->city) + ->setUf($fakerP->stateAbbr()) + ->setCep($fakerP->numerify("########")); + + $dataVencimento = (new DateTime())->modify("+30 day"); + $boleto = new Boleto(); + $boleto->setPagador($pagador); + $boleto->setBeneficiario($beneficiario); + $boleto->setSeuNumero("TESTE"); + $boleto->setValor(500.00); + $boleto->setDataVencimento($dataVencimento->format("Y-m-d")); + $boleto->setDesconto1((clone $dataVencimento)->modify('-20 days')->format("Y-m-d"), 200.00); + $boleto->setDesconto2((clone $dataVencimento)->modify('-10 days')->format("Y-m-d"), 150.00); + $boleto->setDesconto3((clone $dataVencimento)->modify('-5 days')->format("Y-m-d"), 100.00); + $boleto->setJuros(1); + $boleto->setMulta(12.00); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR MULTA DE ' . $boleto->getMulta() . '%'); + $boleto->addMensagem('APÓS O VENCIMENTO, COBRAR JUROS DE ' . $boleto->getJuros() . '% AO MÊS'); + + $banco->createBoleto($boleto); + } catch (SicrediValidationException $e) { + $this->assertIsString($e->getMessage()); + } catch (SicrediRequestException $e) { + $this->fail($e->getMessage()); + } + } + /** + * @test + * @return void + * @throws SicrediValidationException + * @throws SicrediRequestException + */ + public function test_fail_request_on_login() + { + + $apiUrl = "https://api-parceiro.sicredi.com.br/sb"; + try { + $banco = new SicrediCobranca( + new CredencialsManager( + self::SANDBOX_USERNAME, + self::SANDBOX_PASSWORD, + 'errorapikey', + 'cobranca', + self::SANDBOX_COOPERATIVA, + self::SANDBOX_POSTO, + self::SANDBOX_CODIGO_BENEFICIARIO, + ), + $apiUrl + ); + } catch (SicrediValidationException $e) { + } catch (SicrediRequestException $e) { + $this->assertIsString($e->getMessage()); + } + } + // Desabilitado para testes com sandbox pois a sicredi só permite criação de webhook em produção + // /** + // * @test + // * @return void + // * @throws + // * @throws SicrediValidationException + // * @throws SicrediRequestException + // * Habilitado somente em produção + // * @skip + // */ + // public function test_contract_webwook() + // { + // $dotenv = \Dotenv\Dotenv::createImmutable(__DIR__ . '/..'); + // $dotenv->load(); + // $API_KEY = $_ENV['API_KEY']; + // // AVISO: + // // estes testes não fazem sentido se não forem alterados + // // com dados possíveis de boletos e de correntista + // $apiUrl = "https://api-parceiro.sicredi.com.br/sb"; + // try { + // $banco = new SicrediCobranca( + // new CredencialsManager( + // self::SANDBOX_USERNAME, + // self::SANDBOX_PASSWORD, + // $API_KEY, + // 'cobranca', + // self::SANDBOX_COOPERATIVA, + // self::SANDBOX_POSTO, + // self::SANDBOX_CODIGO_BENEFICIARIO, + // ), + // $apiUrl + // ); + + // $this->assertInstanceOf(SicrediCobranca::class, $banco); + + // $webhook = $banco->createWebhook('https://myapi.com.br/webhook/cobranca'); + // $this->assertIsArray($webhook); + + // } catch (SicrediValidationException | SicrediRequestException $e) { + // $this->fail($e->getMessage()); + // } + // } + // /** + // * @test + // * @return void + // * @throws SicrediValidationException + // * @throws SicrediRequestException + // * Habilitado somente em produção + // * @skip + // */ + // public function test_disabled_webwook() + // { + // $dotenv = \Dotenv\Dotenv::createImmutable(__DIR__ . '/..'); + // $dotenv->load(); + // $API_KEY = $_ENV['API_KEY']; + // // AVISO: + // // estes testes não fazem sentido se não forem alterados + // // com dados possíveis de boletos e de correntista + // $apiUrl = "https://api-parceiro.sicredi.com.br/"; + // try { + // $banco = new SicrediCobranca( + // new CredencialsManager( + // self::SANDBOX_USERNAME, + // self::SANDBOX_PASSWORD, + // $API_KEY, + // 'cobranca', + // self::SANDBOX_COOPERATIVA, + // self::SANDBOX_POSTO, + // self::SANDBOX_CODIGO_BENEFICIARIO, + // ), + // $apiUrl + // ); + + // $this->assertInstanceOf(SicrediCobranca::class, $banco); + + // $webhook = $banco->deleteWebhook(); + // $this->assertIsBool($webhook); + // $this->assertEquals(true, $webhook); + + // } catch (SicrediValidationException | SicrediRequestException $e) { + // $this->fail($e->getMessage()); + // } + // } + +}