├── .github
└── workflows
│ ├── ci.yml
│ └── docs.yml
├── .gitignore
├── .scrutinizer.yml
├── COPYING
├── README.md
├── composer.json
├── composer.lock
├── docs
├── dev
│ ├── index.rst
│ └── unit-test.rst
├── getting-started
│ ├── example.rst
│ ├── index.rst
│ ├── install.rst
│ ├── legal.rst
│ └── setup.rst
└── index.rst
├── php-cs-fixer.php
├── phpdoc.xml
├── phpstan.neon
├── phpunit.xml
├── src
├── ApiClient.php
├── ApiException.php
└── HttpCurlClient.php
└── tests
├── bootstrap.php
├── dte_facturacion
├── AbstractDteFacturacion.php
├── BuscarDteTempTest.php
├── DescargarPdfDteTempTest.php
├── EliminarDteTempTest.php
├── EmitirDteTempTest.php
├── GenerarDteRealTest.php
└── ListarDtesTempTest.php
├── lce_contabilidad
└── AsientoContableTest.php
├── pagos_cobros_masivos
├── AbstractPagosCobrosMasivos.php
├── BuscarCobroDteTempTest.php
├── CrearCobroMasivoProgramadoTest.php
├── EmitirCobroMasivoProgramadoTest.php
├── ListarCobrosDteTempTest.php
├── ListarCobrosMasivosProgramadosTest.php
├── ObtenerCobroDocumentoEmitidoTest.php
└── PagarCobroDteTempTest.php
└── test.env-dist
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master # Ejecuta pruebas al hacer push en la rama 'master'
7 | env:
8 | env_var: ${{ vars.ENV_CONTEXT_VAR }}
9 |
10 | jobs:
11 | test:
12 | runs-on: ubuntu-latest
13 |
14 | strategy:
15 | matrix:
16 | php-version: ['8.3'] # Puedes cambiar las versiones según necesites
17 |
18 | steps:
19 | - name: Check out repository code
20 | uses: actions/checkout@v3
21 |
22 | - name: Setup PHP ${{ matrix.php-version }}
23 | uses: shivammathur/setup-php@v2
24 | with:
25 | php-version: ${{ matrix.php-version }} # Configura la versión de PHP desde la matriz
26 | extensions: curl, mbstring, intl, xdebug
27 | tools: composer
28 |
29 | - name: Install Composer dependencies
30 | run: composer install --no-progress --no-suggest
31 |
32 | - name: Run PHP tests dte temp
33 | env:
34 | LIBREDTE_HASH: ${{ secrets.LIBREDTE_HASH }}
35 | LIBREDTE_RUT: ${{ vars.LIBREDTE_RUT }}
36 | run: |
37 | composer tests-readonly
38 |
39 | - name: Upload PHPUnit result report
40 | if: failure()
41 | uses: actions/upload-artifact@v4
42 | with:
43 | name: tests-testdox-php_${{ matrix.php-version }}.txt
44 | path: var/tests-testdox.txt
45 |
46 | - name: Upload Coverage Report
47 | uses: actions/upload-artifact@v4
48 | with:
49 | name: tests-coverage-php_${{ matrix.php-version }}.txt
50 | path: var/tests-coverage.txt
51 |
52 | - name: Display PHP version
53 | run: php -v
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Docs
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 |
9 | jobs:
10 | docs:
11 | name: Docs
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - name: Check out repository
16 | uses: actions/checkout@v4
17 |
18 | - name: Set up PHP
19 | uses: shivammathur/setup-php@v2
20 | with:
21 | php-version: '8.3'
22 |
23 | - name: Download phpDocumentor
24 | run: |
25 | mkdir -p tools
26 | wget https://phpdoc.org/phpDocumentor.phar -O tools/phpdocumentor
27 |
28 | - name: Generate Documentation
29 | run: php tools/phpdocumentor run --config=phpdoc.xml
30 |
31 | - name: Create CNAME file
32 | run: echo "api-client-php.docs.libredte.cl" > build/docs/CNAME
33 |
34 | - name: Deploy to GitHub Pages
35 | if: success()
36 | uses: peaceiris/actions-gh-pages@v4
37 | with:
38 | github_token: ${{ secrets.GITHUB_TOKEN }}
39 | publish_dir: ./build/docs
40 | publish_branch: gh-pages
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | tests/test.env
3 | tests/archivos/dte_facturacion/*
4 |
5 | var/
6 | tools/
7 | build/
8 |
9 | prueba-ejemplo.php
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | checks:
2 | php: true
3 |
4 | build:
5 | nodes:
6 | analysis:
7 | tests:
8 | override:
9 | - php-scrutinizer-run
10 | - command: composer tests-readonly
11 | coverage:
12 | file: var/tests-coverage.xml
13 | format: clover
14 | environment:
15 | php:
16 | version: 8.3.13
17 | pecl_extensions:
18 | - xdebug
19 | dependencies:
20 | before:
21 | - composer install --no-progress --prefer-dist
22 |
23 | tools:
24 | php_code_sniffer:
25 | enabled: true
26 | config:
27 | standard: PSR12
28 |
29 | filter:
30 | paths:
31 | - src/*
32 | excluded_paths:
33 | - resources/*
34 | - tests/*
35 | - tools/*
36 | - var/*
37 | - vendor/*
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | LibreDTE: Cliente de API en PHP
2 | ===============================
3 |
4 | [](https://github.com/libredte/libredte-api-client-php/actions/workflows/ci.yml?query=branch%3Amaster)
5 | [](https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/)
6 | [](https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/)
7 | [](https://packagist.org/packages/libredte/libredte-api-client)
8 | [](https://app.fossa.com/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php?ref=badge_shield&issueType=license)
9 | [](https://app.fossa.com/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php?ref=badge_shield&issueType=security)
10 | [](https://packagist.org/packages/libredte/libredte-api-client)
11 | [](https://packagist.org/packages/libredte/libredte-api-client)
12 |
13 | Cliente para realizar la integración con los servicios web de [LibreDTE](https://www.libredte.cl) desde PHP.
14 |
15 | Revisa la [documentación](https://api-client-php.docs.libredte.cl/guide/index.html) de la biblioteca para más información, sus características y detalles de su uso.
16 |
17 | Licencia
18 | --------
19 |
20 | Este programa es software libre: usted puede redistribuirlo y/o modificarlo
21 | bajo los términos de la GNU Lesser General Public License (LGPL) publicada
22 | por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
23 | o (a su elección) cualquier versión posterior de la misma.
24 |
25 | Este programa se distribuye con la esperanza de que sea útil, pero SIN
26 | GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
27 | PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
28 | Public License (LGPL) para obtener una información más detallada.
29 |
30 | Debería haber recibido una copia de la GNU Lesser General Public License
31 | (LGPL) junto a este programa. En caso contrario, consulte
32 | [GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl.html).
33 |
34 | Enlaces
35 | -------
36 |
37 | - [Sitio web LibreDTE](https://www.libredte.cl).
38 | - [Código fuente en GitHub](https://github.com/LibreDTE/libredte-api-client-php).
39 | - [Paquete en Packagist](https://packagist.org/packages/libredte/libredte-api-client).
40 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "libredte/libredte-api-client",
3 | "description": "Cliente para realizar la integración con los servicios web de LibreDTE desde PHP.",
4 | "type": "library",
5 | "keywords": ["api", "dte", "sii", "facturación electrónica", "chile"],
6 | "homepage": "https://www.libredte.cl",
7 | "license": "LGPL-3.0+",
8 | "authors": [
9 | {
10 | "name": "LibreDTE",
11 | "homepage": "https://www.libredte.cl"
12 | }
13 | ],
14 | "support": {
15 | "issues": "https://github.com/LibreDTE/libredte-api-client-php/issues",
16 | "source": "https://github.com/LibreDTE/libredte-api-client-php"
17 | },
18 | "config": {
19 | "platform": {
20 | "php": "8.2"
21 | }
22 | },
23 | "require": {
24 | "php": "^8.2 || ^8.3",
25 | "ext-curl": "*"
26 | },
27 | "require-dev": {
28 | "friendsofphp/php-cs-fixer": "^3.63",
29 | "phpstan/phpstan": "^1.12",
30 | "phpunit/phpunit": "^11.3",
31 | "vlucas/phpdotenv": "^5.6"
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "libredte\\api_client\\": "src/",
36 | "libredte\\dte_facturacion\\": "tests/dte_facturacion/",
37 | "libredte\\pagos_cobros_masivos\\": "tests/pagos_cobros_masivos/"
38 | }
39 | },
40 | "scripts": {
41 | "docs": "php tools/phpdocumentor run --config=phpdoc.xml",
42 | "tests": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration=phpunit.xml",
43 | "tests-dte": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration=phpunit.xml --testsuite dte-facturacion",
44 | "tests-contab": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration=phpunit.xml --testsuite lce-contabilidad",
45 | "tests-cobros": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration=phpunit.xml --testsuite pagos-cobros-mas",
46 | "tests-readonly": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration=phpunit.xml --filter 'testBuscarDteTemp|testDescargarPdfDteTemp|testEmitirDteTemp|testEliminarDteTemp|testListarDteTemp|testListarCobrosDteTemp|testBuscarCobroDteTemp'",
47 | "phpcs-fix": "php-cs-fixer fix -v --config=php-cs-fixer.php .",
48 | "phpcs-fix-dry-run": "php-cs-fixer fix -v --dry-run --diff --config=php-cs-fixer.php .",
49 | "phpstan": "phpstan analyse --configuration=phpstan.neon --memory-limit=1G",
50 | "phpstan-export": "phpstan analyse --configuration=phpstan.neon --level 9 --generate-baseline"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/docs/dev/index.rst:
--------------------------------------------------------------------------------
1 | Desarrollo
2 | ==========
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | unit-test
--------------------------------------------------------------------------------
/docs/dev/unit-test.rst:
--------------------------------------------------------------------------------
1 | Pruebas unitarias
2 | =================
3 |
4 | .. important::
5 | Al ejecutar pruebas, deberás tener configuradas las variables de entorno necesarias en el archivo test.env. Favor de duplicar test.env-dist, cambiar su nombre a test.env y rellenar las variables necesarias.
6 |
7 | Antes de empezar, debes configurar las siguientes variables de entorno:
8 |
9 | .. code-block:: shell
10 | LIBREDTE_URL="https://libredte.cl"
11 | LIBREDTE_HASH="hash-libredte"
12 | LIBREDTE_RUT="66666666-6"
13 |
14 | Para ejecutar las pruebas unitarias se necesita tener instaladas las dependencias de composer, y para hacer todas las pruebas, ejecutar lo siguiente:
15 |
16 | .. code-block:: shell
17 | ./vendor/bin/phpunit
18 |
19 | También es posible ejecutar una prueba específica indicando el test. Ejemplo:
20 |
21 | .. code-block:: shell
22 | ./vendor/bin/phpunit --filter testEmitirDteTemp --no-coverage
23 |
--------------------------------------------------------------------------------
/docs/getting-started/example.rst:
--------------------------------------------------------------------------------
1 | Ejemplo
2 | =======
3 |
4 | Ejemplo de Generar un DTE temporal
5 | -------------------------------
6 |
7 | Antes de probar, integrar y/o utilizar el cliente de API, necesitas haber definido previamente las variables de entorno.
8 |
9 | .. seealso::
10 | Para más información sobre este paso, referirse al la guía en Configuración.
11 |
12 | El siguiente es un ejemplo básico de cómo emitir un DTE usando el cliente de API de LibreDTE:
13 |
14 | .. code-block:: php
15 | [
31 | 'IdDoc' => [
32 | 'TipoDTE' => 33,
33 | ],
34 | 'Emisor' => [
35 | 'RUTEmisor' => $emisor_rut,
36 | ],
37 | 'Receptor' => [
38 | 'RUTRecep' => '60803000-K',
39 | 'RznSocRecep' => 'Servicio de Impuestos Internos (SII)',
40 | 'GiroRecep' => 'Administración Pública',
41 | 'Contacto' => '+56 2 3252 5575',
42 | 'CorreoRecep' => 'facturacionmipyme@sii.cl',
43 | 'DirRecep' => 'Teatinos 120',
44 | 'CmnaRecep' => 'Santiago',
45 | ],
46 | ],
47 | 'Detalle' => [
48 | [
49 | //'IndExe' => 1, // para items exentos
50 | 'NmbItem' => 'Asesoría de LibreDTE',
51 | 'QtyItem' => 1,
52 | 'PrcItem' => 1000,
53 | ],
54 | ],
55 | 'Referencia' => [
56 | [
57 | 'TpoDocRef' => 801,
58 | 'FolioRef' => 'OC123',
59 | 'FchRef' => '2015-10-01',
60 | ]
61 | ],
62 | ];
63 |
64 | # Recurso a consumir.
65 | $resource = '/dte/documentos/emitir';
66 |
67 | # Se efectua la solicitud HTTP y se guarda la respuesta.
68 | $response = $client->post($resource, $datos);
69 |
70 | # Código del response
71 | echo "Status: ".$response['status']['code']."\n";
72 |
73 | # Despliegue del body.
74 | if ($response['status']['code'] != 200) {
75 | echo $response['body']."\n"; # Si falla, el body contendrá el mensaje de error.
76 | } else {
77 | echo "\nDTEs Temporales: \n";
78 | echo "\n",'FACTURAR DTE TEMP: ',json_encode($response['body']),"\n";
79 | }
80 |
81 | .. seealso::
82 | Para saber más sobre los parámetros posibles y el cómo consumir las API, referirse a la `documentación de LibreDTE. `_
83 |
--------------------------------------------------------------------------------
/docs/getting-started/index.rst:
--------------------------------------------------------------------------------
1 | Empezando
2 | =========
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | legal
8 | install
9 | setup
10 | example
--------------------------------------------------------------------------------
/docs/getting-started/install.rst:
--------------------------------------------------------------------------------
1 | Instalación
2 | ===========
3 |
4 | Desde Composer:
5 |
6 | Para obtener el cliente de la API, debe tener composer instalado, y ejecutar el siguiente comando en consola para instalar el cliente de API en PHP:
7 |
8 | .. code-block:: shell
9 | composer require libredte/libredte-api-client
10 |
11 | Desde GitHub:
12 |
13 | Si estás utilizando la versión de GitHub, deberás instalar los paquetes necesarios para su funcionamiento. Para ello debes ejecutar lo siguiente en su lugar desde la carpeta del proyecto:
14 |
15 | .. code-block:: shell
16 | composer install
17 |
18 | .. important::
19 | Si el segundo paso no funciona, remueve composer.lock y vuelve a ejecutar composer install.
20 |
21 | Requerimientos
22 | --------------
23 |
24 | - PHP 7.3 o superior.
25 |
26 | - Extensiones de PHP:
27 | - curl.
28 | - ext-curl.
29 | - guzzlehttp.
30 | - phpdotenv.
31 | - phpdocumentor.
--------------------------------------------------------------------------------
/docs/getting-started/legal.rst:
--------------------------------------------------------------------------------
1 | Términos y Condiciones de Uso
2 | =============================
3 |
4 | Este programa es software libre: usted puede redistribuirlo y/o modificarlo
5 | bajo los términos de la GNU Lesser General Public License (LGPL) publicada
6 | por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
7 | o (a su elección) cualquier versión posterior de la misma.
8 |
9 | Este programa se distribuye con la esperanza de que sea útil, pero SIN
10 | GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
11 | PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
12 | Public License (LGPL) para obtener una información más detallada.
13 |
14 | Debería haber recibido una copia de la GNU Lesser General Public License
15 | (LGPL) junto a este programa. En caso contrario, consulte
16 | `GNU Lesser General Public License `_.
17 |
18 | .. important::
19 |
20 | Para utilizar el cliente de API de LibreDTE, necesitará una cuenta de LibreDTE. Al usar dicha cuenta, es obligatorio leer y aceptar por completo los `términos y condiciones de uso `_.
21 |
--------------------------------------------------------------------------------
/docs/getting-started/setup.rst:
--------------------------------------------------------------------------------
1 | Configuración
2 | =============
3 |
4 | Para utilizar el cliente de API de LibreDTE, se debe tener un token de usuario, generado y obtenido desde la cuenta de LibreDTE.
5 |
6 | .. important::
7 | El archivo test.env sólo sirve para usar con los test. Por lo que se deberán definir las variables de entorno por los siguientes dos métodos: Directo por consola (temporal), o definirlas directamente en el entorno (persistente).
8 |
9 | En Linux o MacOS:
10 | -----------------
11 |
12 | El token se almacena en una variable de entorno. Para almacenar en una variable de entorno, se debe escribir lo siguiente en consola.
13 |
14 |
15 | .. code-block:: shell
16 | export LIBREDTE_URL="https://libredte.cl"
17 | export LIBREDTE_HASH="aqui-tu-hash-de-libredte"
18 | export LIBREDTE_RUT="66666666-6"
19 |
20 | - ``LIBREDTE_HASH`` es una cadena de varios caracteres. Almacena ese token en un lugar seguro y no lo compartas con nadie.
21 | - ``LIBREDTE_RUT`` contiene tu RUT asociado a la cuenta de LibreDTE, con Dígito Verificador.
22 |
23 | Introducir en consola las variables de entorno almacena temporalmente las variables, y alternativamente, se puede modificar el archivo de configuración de shell en Linux (que se explicará a continuación), y añadir al final del archivo los comandos previamente introducidos. Añadir variables de entorno de esta forma es más persistente y no se repite su definición.
24 |
25 | - Si se usa Linux, se deben añadir al archivo ``~/.bashrc`` los comandos previamente definidos.
26 | - Si se usa MacOS, se deben añadir al archivo ``~/.zshrc``.
27 |
28 | El paso siguiente sólo se hace para usuarios de MacOS. Por último, ejecutar el comando en cuestión para efectuar los cambios.
29 |
30 | .. code-block:: shell
31 | source ~/.zshrc
32 |
33 | En Windows:
34 | -----------
35 |
36 | Para almacenar en una variable de entorno en Windows, hay varias alternativas. La primera es utilizando cmd, y para almacenarlas utilizando cmd, ejecuta en el buscador de Windows "cmd", y ejecuta los siguientes comandos:
37 |
38 | .. code-block:: shell
39 | setx LIBREDTE_URL "https://libredte.cl"
40 | setx LIBREDTE_HASH "aqui-tu-hash-de-libredte"
41 | setx LIBREDTE_RUT "66666666-6"
42 |
43 | También se pueden definir utilizando Windows PowerShell, de una manera similar. Ejecuta en el buscador de Windows "PowerShell", y ejecuta los siguientes comandos:
44 |
45 | .. code-block:: shell
46 | $Env:LIBREDTE_URL="https://libredte.cl"
47 | $Env:LIBREDTE_HASH="aqui-tu-hash-de-libredte"
48 | $Env:LIBREDTE_RUT="66666666-6"
49 |
50 |
51 | Como alternativa para almacenar las variables de manera persistente, debes seguir los siguientes pasos:
52 |
53 | 1. Abre el Panel de Control > Sistema > Configuración avanzada del sistema.
54 | 2. En la pestaña Opciones avanzadas, selecciona Variables de entorno.
55 | 3. Añade o modifica las variables en la sección de "Variables de usuario" o "Variables del sistema".
56 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | Docs: libredte-api-client-php
2 | ==============
3 |
4 | .. image:: https://github.com/libredte/libredte-api-client-php/actions/workflows/ci.yml/badge.svg?branch=master&event=push
5 | :target: https://github.com/libredte/libredte-api-client-php/actions/workflows/ci.yml?query=branch%3Amaster
6 |
7 | .. image:: https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/badges/quality-score.png?b=master
8 | :target: https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/
9 |
10 | .. image:: https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/badges/coverage.png?b=master
11 | :target: https://scrutinizer-ci.com/g/libredte/libredte-api-client-php/
12 |
13 | .. image:: https://poser.pugx.org/libredte/libredte-api-client/license
14 | :target: https://packagist.org/packages/libredte/libredte-api-client
15 |
16 | .. image:: https://app.fossa.com/api/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php.svg?type=shield&issueType=license
17 | :target: https://app.fossa.com/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php?ref=badge_shield&issueType=license
18 |
19 | .. image:: https://app.fossa.com/api/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php.svg?type=shield&issueType=security
20 | :target: https://app.fossa.com/projects/git%2Bgithub.com%2FLibreDTE%2Flibredte-api-client-php?ref=badge_shield&issueType=security
21 |
22 | .. image:: https://poser.pugx.org/libredte/libredte-api-client/downloads
23 | :target: https://packagist.org/packages/libredte/libredte-api-client
24 |
25 | .. image:: https://poser.pugx.org/libredte/libredte-api-client/d/monthly
26 | :target: https://packagist.org/packages/libredte/libredte-api-client
27 |
28 | Bienvenido a la documentación del cliente de API de LibreDTE.
29 |
30 | .. toctree::
31 | :titlesonly:
32 |
33 | getting-started/index
34 | features/index
35 | dev/index
36 |
37 | LibreDTE es un proyecto que tiene como objetivo emitir y manejar los Documentos Tributarios Electrónicos con mucha más facilidad.
38 |
39 | Aquí podrás encontrar la biblioteca escrita en lenguaje PHP para llamar a las APIs de LibreDTE. Este cliente normalmente requiere una cuenta en el SII para poder manejar las DTE que necesites gestionar o emitir.
40 |
41 | Enlaces
42 | -------
43 |
44 | - `Sitio web LibreDTE `_
45 | - `Código fuente en GitHub `_
46 | - `Paquete en Packagist `_
47 | - `Documentación `_
--------------------------------------------------------------------------------
/php-cs-fixer.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | /**
25 | * Archivo de configuración para PHP CS Fixer.
26 | */
27 |
28 | use PhpCsFixer\Config;
29 | use PhpCsFixer\Finder;
30 |
31 | $dir = __DIR__;
32 |
33 | $finder = Finder::create()
34 | ->in($dir)
35 | ->name('*.php')
36 | ->exclude('vendor');
37 |
38 | return (new Config())
39 | // Permitir reglas riesgosas que cambian la lógica del código.
40 | ->setRiskyAllowed(true)
41 | // Basado en PSR-12, la última recomendación de estilo.
42 | ->setRules([
43 | '@PSR12' => true,
44 | // Añadir "declare(strict_types=1);" a los archivos.
45 | // Esto los añade así true,
48 | // Indentar con espacios.
49 | 'indentation_type' => true,
50 | // Ordenar los "use" alfabéticamente.
51 | 'ordered_imports' => [
52 | 'sort_algorithm' => 'alpha',
53 | ],
54 | // Eliminar imports no usados.
55 | 'no_unused_imports' => true,
56 | // Un import por declaración.
57 | 'single_import_per_statement' => true,
58 | // Convertir arreglos a la sintaxis corta "[]".
59 | 'array_syntax' => [
60 | 'syntax' => 'short',
61 | ],
62 | // Añadir comas finales en arreglos de varias líneas.
63 | 'trailing_comma_in_multiline' => true,
64 | // Separar constantes y propiedades.
65 | 'class_attributes_separation' => [
66 | 'elements' => [
67 | 'const' => 'one',
68 | 'property' => 'one',
69 | 'method' => 'one',
70 | ],
71 | ],
72 | // Reemplazar strpos con un return de bool.
73 | // Ejemplo usar: str_contains().
74 | 'modernize_strpos' => true,
75 | // Convertir funciones anónimas a funciones flecha.
76 | 'use_arrow_functions' => true,
77 | // Usar constructores de PHPUnit en lugar de métodos de fábrica.
78 | 'php_unit_construct' => true,
79 | // Usar aserciones más estrictas en PHPUnit.
80 | // Ejemplo: usar assertSame() en vez de assertEquals().
81 | 'php_unit_strict' => true,
82 | ])
83 | ->setLineEnding("\n")
84 | ->setCacheFile($dir . '/var/cache/php-cs-fixer.cache')
85 | ->setFinder($finder)
86 | ;
87 |
--------------------------------------------------------------------------------
/phpdoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 | LibreDTE API Client
9 |
10 |
11 | var/cache/phpdocumentor
12 |
13 |
14 | latest
15 |
16 | libredte-api-client
17 |
18 | src
19 |
20 |
21 | php
22 |
23 | false
24 |
25 | TODO
26 | FIXME
27 | WARNING
28 | NOTE
29 |
30 |
31 |
32 |
33 | docs
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | # Nivel de revisión, desde básico (1) a muy completo (9).
3 | level: 5
4 | # Directorios de código fuente que se revisarán.
5 | paths:
6 | - src
7 | - tests
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 | src
28 |
29 |
30 |
31 |
32 | tests/dte_facturacion
33 |
34 |
35 | tests/lce_contabilidad
36 |
37 |
38 | tests/pagos_cobros_masivos
39 |
40 |
41 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/ApiClient.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | namespace libredte\api_client;
25 |
26 | /**
27 | * Clase ApiClient para la integración con la API de LibreDTE.
28 | *
29 | * Proporciona funcionalidades para realizar peticiones HTTP a la API de
30 | * LibreDTE, incluyendo métodos para realizar solicitudes GET y POST.
31 | */
32 | class ApiClient
33 | {
34 | /**
35 | * La URL base de la API de LibreDTE.
36 | *
37 | * @var string
38 | */
39 | private $api_url = 'https://libredte.cl';
40 |
41 | /**
42 | * El prefijo para las rutas de la API.
43 | *
44 | * @var string
45 | */
46 | private $api_prefix = '/api';
47 |
48 | /**
49 | * Valores por defecto de la cabecera que se pasarán a cURL.
50 | *
51 | * @var array
52 | */
53 | private $headers = [
54 | 'User-Agent' => 'LibreDTE: Cliente de API en PHP.',
55 | 'Content-Type' => 'application/json',
56 | 'Accept' => 'application/json',
57 | ];
58 |
59 | /**
60 | * Objeto para manejar las conexiones HTTP mediante cURL.
61 | *
62 | * @var HttpCurlClient
63 | */
64 | private $client;
65 |
66 | /**
67 | * Constructor de la clase ApiClient.
68 | *
69 | * Inicializa el cliente con las credenciales y la URL de la API. Si no se
70 | * proporcionan, se intentará obtener desde las variables de entorno.
71 | *
72 | * @param string|null $hash Hash de autenticación del usuario en LibreDTE.
73 | * @param string|null $url URL base de la API de LibreDTE.
74 | * @throws ApiException si el hash de autenticación no está presente.
75 | */
76 | public function __construct(string $hash = null, string $url = null)
77 | {
78 | $hash = $hash ?: $this->env('LIBREDTE_HASH');
79 | if (!$hash) {
80 | throw new ApiException(message: 'LIBREDTE_HASH missing');
81 | }
82 | $this->headers['Authorization'] = 'Basic ' . base64_encode(
83 | $hash . ':X'
84 | );
85 | $this->api_url = $url ?: $this->env('LIBREDTE_URL') ?: $this->api_url;
86 | $this->client = new HttpCurlClient();
87 | }
88 |
89 | /**
90 | * Establece una cabecera para las solicitudes HTTP.
91 | *
92 | * Permite definir un valor para una cabecera específica que se incluirá en
93 | * todas las solicitudes HTTP realizadas por la instancia del cliente.
94 | *
95 | * @param string $name Nombre de la cabecera.
96 | * @param mixed $value Valor de la cabecera.
97 | * @return void
98 | */
99 | public function setHeader(string $name, mixed $value): void
100 | {
101 | $this->headers[$name] = $value;
102 | }
103 |
104 | /**
105 | * Configura las opciones de SSL para las conexiones HTTP.
106 | *
107 | * Este método permite activar o desactivar la verificación del certificado
108 | * SSL del servidor.
109 | *
110 | * @param boolean $sslcheck Activar o desactivar la verificación del
111 | * certificado SSL.
112 | * @return void
113 | */
114 | public function setSSL($sslcheck = true): void
115 | {
116 | $this->client->setSSL($sslcheck);
117 | }
118 |
119 | /**
120 | * Realiza una solicitud POST a la API de LibreDTE.
121 | *
122 | * Envia datos a un recurso específico de la API utilizando el método POST.
123 | *
124 | * @param string $resource El recurso de la API a solicitar.
125 | * @param mixed|null $data Los datos a enviar en la solicitud POST.
126 | * @param array $headers Encabezados adicionales para la solicitud.
127 | * @return array Respuesta de la API.
128 | */
129 | public function post(string $resource, mixed $data = null, array $headers = []): array|bool
130 | {
131 | $headers = array_merge($this->headers, $headers);
132 | return $this->client->query(
133 | method: 'POST',
134 | url: $this->api_url . $this->api_prefix . $resource,
135 | data: $data,
136 | headers: $headers
137 | );
138 | }
139 |
140 | /**
141 | * Realiza una solicitud GET a la API de LibreDTE.
142 | *
143 | * Recupera datos de un recurso específico de la API utilizando el método
144 | * GET.
145 | *
146 | * @param string $resource El recurso de la API a solicitar.
147 | * @param mixed|null $data Los datos a enviar en la solicitud GET.
148 | * @param array $headers Encabezados adicionales para la solicitud.
149 | * @return array Respuesta de la API.
150 | */
151 | public function get(string $resource, mixed $data = null, array $headers = []): array|bool
152 | {
153 | $headers = array_merge($this->headers, $headers);
154 | return $this->client->query(
155 | method: 'GET',
156 | url: $this->api_url . $this->api_prefix . $resource,
157 | data: $data,
158 | headers: $headers
159 | );
160 | }
161 |
162 | /**
163 | * Obtiene el valor de una variable de entorno.
164 | *
165 | * Este método es utilizado internamente para obtener configuraciones
166 | * como el hash de autenticación o la URL base de la API.
167 | *
168 | * @param string $name Nombre de la variable de entorno.
169 | * @return mixed|null Valor de la variable de entorno o null si no está
170 | * definida.
171 | */
172 | private function env($name): mixed
173 | {
174 | return function_exists('env') ? env($name) : getenv($name);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/ApiException.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | namespace libredte\api_client;
25 |
26 | /**
27 | * Clase ApiException para la gestión de excepciones en el cliente de la API
28 | * de LibreDTE.
29 | *
30 | * Esta clase extiende la clase Exception estándar de PHP y se utiliza para
31 | * manejar errores específicos que pueden ocurrir durante las interacciones
32 | * con la API de LibreDTE.
33 | * Las instancias de ApiException pueden incluir información adicional
34 | * relevante para los errores de la API.
35 | */
36 | class ApiException extends \Exception
37 | {
38 | // Aquí van los métodos y propiedades de la clase
39 | }
40 |
--------------------------------------------------------------------------------
/src/HttpCurlClient.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | namespace libredte\api_client;
25 |
26 | /**
27 | * Clase HttpCurlClient para realizar consultas HTTP utilizando cURL.
28 | *
29 | * Esta clase proporciona una interfaz para realizar peticiones HTTP, como GET
30 | * y POST, utilizando cURL. Ofrece configuración de SSL y manejo de errores de
31 | * cURL.
32 | */
33 | class HttpCurlClient
34 | {
35 | /**
36 | * Indica si se debe validar el certificado SSL del servidor.
37 | *
38 | * @var boolean
39 | */
40 | private $sslcheck = true;
41 |
42 | /**
43 | * Historial de errores de las consultas HTTP mediante cURL.
44 | *
45 | * @var array
46 | */
47 | private $errors = [];
48 |
49 | /**
50 | * Devuelve los errores ocurridos en las peticiones HTTP.
51 | *
52 | * Este método devuelve un array con los errores generados por cURL en las
53 | * peticiones HTTP realizadas.
54 | *
55 | * @return array Lista de errores de cURL.
56 | */
57 | public function getErrors(): array
58 | {
59 | return $this->errors;
60 | }
61 |
62 | /**
63 | * Devuelve el último error ocurrido en una petición HTTP.
64 | *
65 | * Este método devuelve el último error generado por cURL en una petición
66 | * HTTP.
67 | *
68 | * @return string Descripción del último error de cURL.
69 | */
70 | public function getLastError(): string
71 | {
72 | return $this->errors[count($this->errors) - 1];
73 | }
74 |
75 | /**
76 | * Configura las opciones de SSL para las peticiones HTTP.
77 | *
78 | * Este método permite activar o desactivar la verificación del certificado
79 | * SSL del servidor.
80 | *
81 | * @param boolean $sslcheck Activar o desactivar la verificación del
82 | * certificado SSL.
83 | */
84 | public function setSSL(bool $sslcheck = true): void
85 | {
86 | $this->sslcheck = $sslcheck;
87 | }
88 |
89 | /**
90 | * Realiza una solicitud HTTP a una URL.
91 | *
92 | * Este método ejecuta una petición HTTP utilizando cURL y devuelve la
93 | * respuesta.
94 | * Soporta varios métodos HTTP como GET, POST, PUT, DELETE, etc.
95 | *
96 | * @param string $method Método HTTP a utilizar.
97 | * @param string $url URL a la que se realiza la petición.
98 | * @param mixed $data Datos a enviar en la petición.
99 | * @param array $headers Cabeceras HTTP a enviar.
100 | * @return array|false Respuesta HTTP o false en caso de error.
101 | */
102 | public function query(
103 | string $method,
104 | string $url,
105 | mixed $data = [],
106 | array $headers = []
107 | ): array|bool {
108 | // preparar datos
109 | if ($data && $method != 'GET') {
110 | if (isset($data['@files'])) {
111 | $files = $data['@files'];
112 | unset($data['@files']);
113 | $data = ['@data' => json_encode($data)];
114 | foreach ($files as $key => $file) {
115 | $data[$key] = $file;
116 | }
117 | } else {
118 | $data = json_encode($data);
119 | $headers['Content-Length'] = strlen($data);
120 | }
121 | }
122 | // inicializar curl
123 | $curl = curl_init();
124 | // asignar método y datos dependiendo de si es GET u otro método
125 | if ($method == 'GET') {
126 | if (is_array($data)) {
127 | $data = http_build_query($data);
128 | }
129 | if ($data) {
130 | $url = sprintf("%s?%s", $url, $data);
131 | }
132 | } else {
133 | curl_setopt($curl, CURLOPT_POST, 1);
134 | curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
135 | if ($data) {
136 | curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
137 | }
138 | }
139 | // asignar cabecera
140 | foreach ($headers as $key => &$value) {
141 | $value = $key.': '.$value;
142 | }
143 | // asignar cabecera
144 | curl_setopt($curl, CURLOPT_HTTPHEADER, array_values($headers));
145 | // realizar consulta a curl recuperando cabecera y cuerpo
146 | curl_setopt($curl, CURLOPT_URL, $url);
147 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
148 | curl_setopt($curl, CURLOPT_HEADER, 1);
149 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->sslcheck);
150 | $response = curl_exec($curl);
151 | if (!$response) {
152 | $this->errors[] = curl_error($curl);
153 | return false;
154 | }
155 | $headers_size = curl_getinfo(handle: $curl, option: CURLINFO_HEADER_SIZE);
156 | // cerrar conexión de curl
157 | curl_close($curl);
158 | // entregar respuesta de la solicitud
159 | $response_headers = $this->parseResponseHeaders(
160 | substr(
161 | string: $response,
162 | offset: 0,
163 | length: $headers_size
164 | )
165 | );
166 | $body = substr($response, $headers_size);
167 | $json = json_decode(json: $body, associative: true);
168 | return [
169 | 'status' => $this->parseResponseStatus($response_headers[0]),
170 | 'header' => $response_headers,
171 | 'body' => $json !== null ? $json : $body,
172 | ];
173 | }
174 |
175 | /**
176 | * Método que procesa y convierte la cabecera en texto plano a un arreglo
177 | * asociativo.
178 | *
179 | * Convierte las cabeceras HTTP dadas en texto plano a un arreglo
180 | * asociativo. Si una cabecera aparece más de una vez, su valor será un
181 | * arreglo con todos sus valores.
182 | *
183 | * @param string $headers_txt Cabeceras HTTP en formato de texto plano.
184 | * @return array Arreglo asociativo con las cabeceras procesadas.
185 | */
186 | private function parseResponseHeaders(string $headers_txt): array
187 | {
188 | $headers = [];
189 | $lineas = explode("\n", $headers_txt);
190 | foreach ($lineas as &$linea) {
191 | $linea = trim($linea);
192 | if (!isset($linea[0])) {
193 | continue;
194 | }
195 | if (strpos($linea, ':')) {
196 | list($key, $value) = explode(
197 | separator: ':',
198 | string: $linea,
199 | limit: 2
200 | );
201 | } else {
202 | $key = 0;
203 | $value = $linea;
204 | }
205 | $key = trim(strval($key));
206 | $value = trim($value);
207 | if (!isset($headers[$key])) {
208 | $headers[$key] = $value;
209 | } elseif (!is_array($headers[$key])) {
210 | $aux = $headers[$key];
211 | $headers[$key] = [$aux, $value];
212 | } else {
213 | $headers[$key][] = $value;
214 | }
215 | }
216 | return $headers;
217 | }
218 |
219 | /**
220 | * Método que procesa la línea de estado de la respuesta HTTP y extrae
221 | * información útil.
222 | *
223 | * Extrae el protocolo, el código de estado y el mensaje del estado de la
224 | * línea de respuesta HTTP.
225 | * Útil para entender y manejar la respuesta HTTP.
226 | *
227 | * @param array|string $response_line Línea de respuesta HTTP.
228 | * @return array Arreglo con información del estado, incluyendo protocolo,
229 | * código y mensaje.
230 | */
231 | private function parseResponseStatus(array|string $response_line): array
232 | {
233 | if (is_array($response_line)) {
234 | $response_line = $response_line[count($response_line) - 1];
235 | }
236 | $parts = explode(separator: ' ', string: $response_line, limit: 3);
237 | return [
238 | 'protocol' => $parts[0],
239 | 'code' => $parts[1],
240 | 'message' => !empty($parts[2]) ? $parts[2] : null,
241 | ];
242 | }
243 | }
244 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | // asignar zona horaria de PHP
25 | date_default_timezone_set('America/Santiago');
26 |
27 | // dependencias de composer
28 | require_once __DIR__ . '/../vendor/autoload.php';
29 |
30 | // cargar variables de entorno (según si test.env existe o no).
31 | if (file_exists(__DIR__ . '/test.env')) {
32 | $dotenv = \Dotenv\Dotenv::createMutable(__DIR__, 'test.env');
33 | try {
34 | $dotenv->load();
35 | } catch (\Dotenv\Exception\InvalidPathException $e) {
36 | die($e->getMessage());
37 | } catch (\Dotenv\Exception\InvalidFileException $e) {
38 | die($e->getMessage());
39 | }
40 | }
41 |
42 | /**
43 | * Función que carga una variable de entorno o su valor por defecto
44 | * @param string varname Variable que se desea consultar
45 | * @param mixed|null default Valor por defecto de la variable
46 | */
47 | function env(string $varname, mixed $default = null)
48 | {
49 | if (isset($_ENV[$varname])) {
50 | return $_ENV[$varname];
51 | }
52 | $value = getenv($varname);
53 | if ($value !== false) {
54 | return $value;
55 | }
56 | return $default;
57 | }
58 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/AbstractDteFacturacion.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | namespace libredte\dte_facturacion;
25 |
26 | use libredte\api_client\ApiClient;
27 | use libredte\api_client\ApiException;
28 | use PHPUnit\Framework\TestCase;
29 |
30 | abstract class AbstractDteFacturacion extends TestCase
31 | {
32 | /**
33 | * Variable para desplegar resultados.
34 | *
35 | * @var bool
36 | */
37 | protected static $verbose;
38 |
39 | /**
40 | * Variable instancia del API Client.
41 | *
42 | * @var ApiClient
43 | */
44 | protected static $client;
45 |
46 | /**
47 | * RUT del emisor a utilizar.
48 | *
49 | * @var int
50 | */
51 | protected static $emisor_rut;
52 |
53 | /**
54 | * Datos para producir el DTE temporal.
55 | *
56 | * @var array
57 | */
58 | private static $datos = [
59 | 'Encabezado' => [
60 | 'IdDoc' => [
61 | 'TipoDTE' => 33,
62 | ],
63 | 'Emisor' => [
64 | 'RUTEmisor' => null, // se reemplaza al preparar la clase
65 | ],
66 | 'Receptor' => [
67 | 'RUTRecep' => '60803000-K',
68 | 'RznSocRecep' => 'Servicio de Impuestos Internos (SII)',
69 | 'GiroRecep' => 'Administración Pública',
70 | 'Contacto' => '+56 2 3252 5575',
71 | 'CorreoRecep' => 'facturacionmipyme@sii.cl',
72 | 'DirRecep' => 'Teatinos 120',
73 | 'CmnaRecep' => 'Santiago',
74 | ],
75 | ],
76 | 'Detalle' => [
77 | [
78 | //'IndExe' => 1, // para items exentos
79 | 'NmbItem' => 'Asesoría de LibreDTE',
80 | 'QtyItem' => 1,
81 | 'PrcItem' => 1000,
82 | ],
83 | ],
84 | 'Referencia' => [
85 | [
86 | 'TpoDocRef' => 801,
87 | 'FolioRef' => 'OC123',
88 | 'FchRef' => '2015-10-01',
89 | ],
90 | ],
91 | ];
92 |
93 | /**
94 | * Inicialización de variables y clases pre ejecución de tests.
95 | *
96 | * @return void
97 | */
98 | public static function setUpBeforeClass(): void
99 | {
100 | self::$verbose = (bool)env(varname: 'TEST_VERBOSE', default: 'false');
101 | self::$emisor_rut = (
102 | explode(
103 | '-',
104 | (string)env('LIBREDTE_RUT')
105 | )[0]
106 | );
107 | self::$datos['Encabezado']['Emisor']['RUTEmisor'] = env(
108 | 'LIBREDTE_RUT'
109 | );
110 | self::$client = new ApiClient();
111 | }
112 |
113 | /**
114 | * Método para listar DTEs temporales.
115 | *
116 | * @throws \libredte\api_client\ApiException
117 | *
118 | * @return array Listado de DTEs temporales entre 2015 y hoy.
119 | */
120 | protected function listarDteTemp(): array
121 | {
122 | // Se crea el filtro a utilizar, en este caso fechas de búsqueda.
123 | $filtros = [
124 | 'fecha_desde' => date(
125 | format: 'Y-m-d',
126 | timestamp: strtotime('-30 days')
127 | ),
128 | 'fecha_hasta' => date('Y-m-d'),
129 | ];
130 | // Se genera el recurso a consumir.
131 | $resource = sprintf(
132 | '/dte/dte_tmps/buscar/%d',
133 | self::$emisor_rut
134 | );
135 | // Se envía la solicitud http y se guarda su respuesta.
136 | $response = self::$client->post(resource: $resource, data: $filtros);
137 |
138 | // Si el código http no es '200', arroja error ApiException.
139 | if ($response['status']['code'] !== '200') {
140 | throw new ApiException(
141 | message: $response['body'],
142 | code: (int)$response['status']['code']
143 | );
144 | }
145 |
146 | // Retorna la respuesta http.
147 | return $response;
148 | }
149 |
150 | /**
151 | * Método para emitir un DTE temporal.
152 | *
153 | * @throws \libredte\api_client\ApiException
154 | *
155 | * @return array DTE temporal generado.
156 | */
157 | protected function emitirDteTemp(): array
158 | {
159 | // Se envía la solicitud http y se guarda su respuesta.
160 | $response = self::$client->post(
161 | resource: '/dte/documentos/emitir',
162 | data: self::$datos
163 | );
164 |
165 | // Si el código http no es '200', arroja error ApiException.
166 | if ($response['status']['code'] !== '200') {
167 | throw new ApiException(
168 | message: $response['body'],
169 | code: (int)$response['status']['code']
170 | );
171 | }
172 |
173 | // Retorna la respuesta http.
174 | return $response;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/BuscarDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas que permite buscar un DTE temporal.
34 | */
35 | class BuscarDteTempTest extends AbstractDteFacturacion
36 | {
37 | /**
38 | * Método de test que prueba el servicio para buscar un DTE temporal.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testBuscarDteTemp(): void
45 | {
46 | try {
47 | // Se emite un DTE temporal para ejecutar esta prueba.
48 | $dte_temp = $this->emitirDteTemp();
49 |
50 | // Se genera el recurso para buscar el DTE temporal generado.
51 | $resource = sprintf(
52 | "/dte/dte_tmps/info/%d/%d/%s/%d",
53 | $dte_temp['body']['receptor'],
54 | $dte_temp['body']['dte'],
55 | $dte_temp['body']['codigo'],
56 | self::$emisor_rut
57 | );
58 |
59 | // Se envía la solicitud http y se guarda su respuesta.
60 | $response = self::$client->get($resource);
61 | // Si el código http no es '200', arroja error ApiException.
62 | if ($response['status']['code'] !== '200') {
63 | throw new ApiException(
64 | message: $response['body'],
65 | code: (int)$response['status']['code']
66 | );
67 | }
68 | // Se obtiene el body de la lista.
69 | $documento = $response['body'];
70 |
71 | // Se compara el código con '200' Si no es 200, la prueba falla.
72 | $this->assertSame('200', $response['status']['code']);
73 | // Se despliega en consola los resultados si verbose es true.
74 | if (self::$verbose) {
75 | echo "\n",'testBuscarDteTemp() DTE: ',json_encode(
76 | $documento
77 | ),"\n";
78 | }
79 | } catch (ApiException $e) {
80 | // Si falla, desplegará el mensaje y error en el siguiente formato:
81 | // [ApiException codigo-http] mensaje]
82 | $this->fail(sprintf(
83 | '[ApiException %d] %s',
84 | $e->getCode(),
85 | $e->getMessage()
86 | ));
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/DescargarPdfDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas para descargar un PDF de un DTE temporal.
34 | */
35 | class DescargarPdfDteTempTest extends AbstractDteFacturacion
36 | {
37 | /**
38 | * Método de test que prueba el servicio de obtener un PDF de un DTE
39 | * temporal.
40 | *
41 | * @throws \libredte\api_client\ApiException
42 | *
43 | * @return void
44 | */
45 | public function testDescargarPdfDteTemp(): void
46 | {
47 | try {
48 | // Se emite un DTE temporal para ejecutar esta prueba.
49 | $emitir = $this->emitirDteTemp();
50 | $documento = $emitir['body'];
51 |
52 | // Se genera el recurso a consumir.
53 | $resource = sprintf(
54 | '/dte/dte_tmps/pdf/%d/%d/%s/%d',
55 | $documento['receptor'],
56 | $documento['dte'],
57 | $documento['codigo'],
58 | self::$emisor_rut,
59 | );
60 | // Se envía la solicitud http y se guarda su respuesta.
61 | $response = self::$client->get($resource);
62 |
63 | // Si el código http no es '200', arroja error ApiException.
64 | if ($response['status']['code'] !== '200') {
65 | throw new ApiException(
66 | message: $response['body'],
67 | code: (int)$response['status']['code']
68 | );
69 | }
70 | // Se compara el código con '200' Si no es 200, la prueba falla.
71 | $this->assertSame('200', $response['status']['code']);
72 |
73 | // Ruta base para el directorio actual (archivo ejecutándose en
74 | // "tests/dte_facturacion")
75 | $currentDir = __DIR__;
76 |
77 | // Nueva ruta relativa para guardar el archivo PDF en "tests/archivos"
78 | $targetDir = dirname($currentDir) .
79 | '/archivos/dte_facturacion';
80 |
81 | // Define el nombre del archivo PDF en el nuevo directorio
82 | $filename = $targetDir . '/' . sprintf(
83 | 'LIBREDTE_%d_%d-%s.pdf',
84 | self::$emisor_rut,
85 | $documento['dte'],
86 | $documento['codigo']
87 | );
88 |
89 | // Verifica si el directorio existe, si no, créalo
90 | if (!is_dir($targetDir)) {
91 | mkdir(directory: $targetDir, permissions: 0777, recursive: true);
92 | }
93 |
94 | // Se genera el archivo PDF.
95 | file_put_contents($filename, $response['body']);
96 |
97 | // Se despliega en consola los resultados si verbose es true.
98 | if (self::$verbose) {
99 | echo "\n",'testDescargarPdfTemp() PDF: ',$filename,"\n";
100 | }
101 | } catch (ApiException $e) {
102 | // Si falla, desplegará el mensaje y error en el siguiente formato:
103 | // [ApiException codigo-http] mensaje]
104 | $this->fail(sprintf(
105 | '[ApiException %d] %s',
106 | $e->getCode(),
107 | $e->getMessage()
108 | ));
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/EliminarDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de test para eliminar un DTE temporal.
34 | */
35 | class EliminarDteTempTest extends AbstractDteFacturacion
36 | {
37 | /**
38 | * Método de test que prueba el servicio de eliminar un DTE temporal.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testEliminarDteTemp(): void
45 | {
46 | // Se emite un DTE temporal para ejecutar esta prueba.
47 | $dte_temp = $this->emitirDteTemp();
48 |
49 | // Se genera el recurso a consumir.
50 | $resource = sprintf(
51 | '/dte/dte_tmps/eliminar/%d/%d/%s/%d',
52 | $dte_temp['body']['receptor'],
53 | $dte_temp['body']['dte'],
54 | $dte_temp['body']['codigo'],
55 | self::$emisor_rut
56 | );
57 | try {
58 | // Se envía la solicitud http y se guarda su respuesta.
59 | $response = self::$client->get($resource);
60 | // Si el código http no es '200', arroja error ApiException.
61 | if ($response['status']['code'] !== '200') {
62 | throw new ApiException(
63 | message: $response['body'],
64 | code: (int)$response['status']['code']
65 | );
66 | }
67 | // Se compara el código con '200' Si no es 200, la prueba falla.
68 | $this->assertSame('200', $response['status']['code']);
69 | // Se despliega en consola los resultados si verbose es true.
70 | if (self::$verbose) {
71 | echo "\n",'testEliminarDteTemp() eliminar_dte ',json_encode(
72 | $response['body']
73 | ),"\n";
74 | }
75 | } catch (ApiException $e) {
76 | // Si falla, desplegará el mensaje y error en el siguiente formato:
77 | // [ApiException codigo-http] mensaje]
78 | $this->fail(sprintf(
79 | '[ApiException %d] %s',
80 | $e->getCode(),
81 | $e->getMessage()
82 | ));
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/EmitirDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de tests que permite emitir un DTE Temporal. Require de método obtenido desde Dtes.php.
34 | */
35 | class EmitirDteTempTest extends AbstractDteFacturacion
36 | {
37 | /**
38 | * Método de test que prueba el servicio emitir un DTE temporal
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testEmitirDteTemp(): void
45 | {
46 | try {
47 | // Se emite un DTE temporal para ejecutar esta prueba.
48 | $dte_temp = $this->emitirDteTemp();
49 |
50 | // Se compara el código con '200' Si no es 200, la prueba falla.
51 | $this->assertSame('200', $dte_temp['status']['code']);
52 | // Se despliega en consola los resultados si verbose es true.
53 | if (self::$verbose) {
54 | echo "\n",'testEmitirDteTemp() Emitir: ',json_encode(
55 | $dte_temp['body']
56 | ),"\n";
57 | }
58 | } catch (ApiException $e) {
59 | // Si falla, desplegará el mensaje y error en el siguiente formato:
60 | // [ApiException codigo-http] mensaje]
61 | $this->fail(sprintf(
62 | '[ApiException %d] %s',
63 | $e->getCode(),
64 | $e->getMessage()
65 | ));
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/GenerarDteRealTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | class GenerarDteRealTest extends AbstractDteFacturacion
33 | {
34 | /**
35 | * Método de test que permite generar un DTE real a partir de
36 | * un DTE temporal.
37 | *
38 | * @throws \libredte\api_client\ApiException
39 | *
40 | * @return void
41 | */
42 | public function testGenerarDteReal(): void
43 | {
44 | try {
45 | // Se emite un DTE temporal para ejecutar esta prueba.
46 | $dte_temp = $this->emitirDteTemp();
47 |
48 | // Se llena una lista con la información que se va a pasar
49 | // a la petición http.
50 | $data = [
51 | 'emisor' => self::$emisor_rut,
52 | 'receptor' => $dte_temp['body']['receptor'],
53 | 'dte' => $dte_temp['body']['dte'],
54 | 'codigo' => $dte_temp['body']['codigo'],
55 | ];
56 | // Se envía la solicitud http y se guarda su respuesta.
57 | $response = self::$client->post(
58 | '/dte/documentos/generar',
59 | $data
60 | );
61 | // Si el código http no es '200', arroja error ApiException.
62 | if ($response['status']['code'] !== '200') {
63 | throw new ApiException(
64 | message: $response['body'],
65 | code: (int)$response['status']['code']
66 | );
67 | }
68 | // Se compara el código con '200' Si no es 200, la prueba falla.
69 | $this->assertSame('200', $response['status']['code']);
70 | // Se despliega en consola los resultados si verbose es true.
71 | if (self::$verbose) {
72 | echo "\n",'testGenerarDteReal() Generar: ',json_encode(
73 | $response['body']
74 | ),"\n";
75 | }
76 | } catch (ApiException $e) {
77 | // Si falla, desplegará el mensaje y error en el siguiente formato:
78 | // [ApiException codigo-http] mensaje]
79 | $this->fail(sprintf(
80 | '[ApiException %d] %s',
81 | $e->getCode(),
82 | $e->getMessage()
83 | ));
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/dte_facturacion/ListarDtesTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\dte_facturacion\AbstractDteFacturacion;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas que permite buscar un DTE temporal.
34 | */
35 | class ListarDtesTempTest extends AbstractDteFacturacion
36 | {
37 | /**
38 | * Método de test para listar todos los DTEs temporales.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testListarDtesTemp(): void
45 | {
46 | try {
47 | // Se listan los DTEs temporales.
48 | $lista_dtes = $this->listarDteTemp();
49 |
50 | // La prueba tendrá éxito si la búsqueda funciona.
51 | $this->assertTrue(true);
52 | // Se despliega en consola los resultados si verbose es true.
53 | if (self::$verbose) {
54 | echo "\n",'testListarDteTemps() Lista DTEs: ',json_encode(
55 | $lista_dtes['body']
56 | ),"\n";
57 | }
58 | } catch (ApiException $e) {
59 | // Si falla, desplegará el mensaje y error en el siguiente formato:
60 | // [ApiException codigo-http] mensaje]
61 | $this->fail(sprintf(
62 | '[ApiException %d] %s',
63 | $e->getCode(),
64 | $e->getMessage()
65 | ));
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tests/lce_contabilidad/AsientoContableTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use PHPUnit\Framework\Attributes\CoversClass;
28 | use PHPUnit\Framework\TestCase;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas para probar los servicios relacionados con los
34 | * asientos contables.
35 | */
36 | class AsientoContableTest extends TestCase
37 | {
38 | /**
39 | * Variable para desplegar resultados.
40 | *
41 | * @var bool
42 | */
43 | protected static $verbose;
44 |
45 | /**
46 | * Variable de instanciación de API Client.
47 | *
48 | * @var ApiClient
49 | */
50 | protected static $client;
51 |
52 | /**
53 | * RUT del emisor sin DV a utilizar.
54 | *
55 | * @var int
56 | */
57 | protected static $emisor_rut;
58 |
59 | /**
60 | * Función para inicializar variables y clases pre ejecución de tests.
61 | *
62 | * @return void
63 | */
64 | public static function setUpBeforeClass(): void
65 | {
66 | self::$verbose = env(varname: 'TEST_VERBOSE', default: false);
67 | self::$emisor_rut = (int)(
68 | explode(
69 | '-',
70 | (string)env('LIBREDTE_RUT')
71 | )[0]
72 | );
73 | self::$client = new ApiClient();
74 | }
75 |
76 | /**
77 | * Método privado para obtener datos de un asiento contable.
78 | *
79 | * Este es un ejemplo de una venta, puede ser cualquier tipo de
80 | * asiento contable las cuentas contables usadas deben existir
81 | * previamente, se asignan en las variable de entorno si no son los
82 | * códigos acá propuestos
83 | *
84 | * @return array Datos del asiento contable.
85 | */
86 | private function _datosAsiento(): array
87 | {
88 | // Inicialización de variables de entorno.
89 | $cuenta_caja = env('TEST_LCE_CUENTA_CAJA', 1101001);
90 | $cuenta_ventas = env('TEST_LCE_CUENTA_VENTAS', 4101001);
91 | $cuenta_iva_debito = env('TEST_LCE_CUENTA_IVA_DEBITO', 2105101);
92 |
93 | // Retorna un array con los datos de un asiento contable.
94 | return [
95 | 'fecha' => date('Y-m-d'),
96 | 'glosa' => 'Venta T33F123',
97 | 'detalle' => [
98 | 'debe' => [
99 | // cuenta: caja
100 | $cuenta_caja => 119,
101 | ],
102 | 'haber' => [
103 | // cuenta: ventas
104 | $cuenta_ventas => 100,
105 | // cuenta: iva débito
106 | $cuenta_iva_debito => 19,
107 | ],
108 | ],
109 | 'operacion' => 'I',
110 | // esto es opcional, pero se recomienda ya que el SII lo puede pedir
111 | // además que permite usar un informe que indica qué documentos no
112 | // tienen asientos contables asociados (para cuadraturas)
113 | 'documentos' => ['emitidos' => [['dte' => 33, 'folio' => 123]]],
114 | ];
115 | }
116 |
117 | /**
118 | * Método de test para crear un asiento contable.
119 | *
120 | * @throws \libredte\api_client\ApiException
121 | *
122 | * @return void
123 | */
124 | public function testLceCrearAsiento(): void
125 | {
126 | // Recurso a consumir.
127 | $resource = sprintf(
128 | '/lce/lce_asientos/crear/%d',
129 | self::$emisor_rut
130 | );
131 | // Creación de datos de un asiento contable
132 | $datos = $this->_datosAsiento();
133 | try {
134 | // Se envía la solicitud http y se guarda su respuesta.
135 | $response = self::$client->post($resource, $datos);
136 | // Si el código http no es '200', arroja error ApiException.
137 | if ($response['status']['code'] != '200') {
138 | throw new ApiException(
139 | $response['body'],
140 | (int)$response['status']['code']
141 | );
142 | }
143 | // Se compara el código con '200' Si no es 200, la prueba falla.
144 | $this->assertSame('200', $response['status']['code']);
145 | // Se despliega en consola los resultados si verbose es true.
146 | if (self::$verbose) {
147 | echo "\n",
148 | 'test_lce_crear_asiento() asiento ',
149 | $response['body']['asiento'],
150 | "\n";
151 | echo "\n",
152 | 'test_lce_crear_asiento() creado ',
153 | $response['body']['creado'],
154 | "\n";
155 | }
156 | } catch (ApiException $e) {
157 | // Si falla, desplegará el mensaje y error en el siguiente formato:
158 | // [ApiException codigo-http] mensaje]
159 | $this->fail(sprintf(
160 | '[ApiException %d] %s',
161 | $e->getCode(),
162 | $e->getMessage()
163 | ));
164 | }
165 | }
166 |
167 | /**
168 | * Método privado para buscar y listar asientos contables.
169 | *
170 | * @throws \libredte\api_client\ApiException
171 | *
172 | * @return array Listado de asientos contables.
173 | */
174 | private function _buscar(): array
175 | {
176 | // Filtros para buscar asientos contables.
177 | $filtros = [
178 | 'fecha_desde' => date(
179 | format: 'Y-m-d',
180 | timestamp: strtotime('-30 days')
181 | ),
182 | 'fecha_hasta' => date('Y-m-d'),
183 | ];
184 | // Recurso a consumir.
185 | $resource = sprintf(
186 | '/lce/lce_asientos/buscar/%d',
187 | self::$emisor_rut
188 | );
189 | // Se envía la solicitud http y se guarda su respuesta.
190 | $response = self::$client->post(resource: $resource, data: $filtros);
191 | // Si el código http no es '200', arroja error ApiException.
192 | if ($response['status']['code'] != '200') {
193 | throw new ApiException(
194 | message: $response['body'],
195 | code: (int)$response['status']['code']
196 | );
197 | }
198 | return $response['body'];
199 | }
200 |
201 | /**
202 | * Método de test para probarla búsqueda y listado de asientos contables.
203 | *
204 | * @return void
205 | */
206 | public function testLceBuscarAsiento(): void
207 | {
208 | try {
209 | // Búsqueda de asiento contable.
210 | $asientos = $this->_buscar();
211 | // assertTrue si la búsqueda fue exitosa.
212 | $this->assertTrue(true);
213 | // Se despliega en consola los resultados si verbose es true.
214 | if (self::$verbose) {
215 | echo "\n",'test_lce_buscar_asientos() n_asientos ',count(
216 | $asientos
217 | ),"\n";
218 | }
219 | } catch (ApiException $e) {
220 | // Si falla, desplegará el mensaje y error en el siguiente formato:
221 | // [ApiException codigo-http] mensaje]
222 | $this->fail(sprintf(
223 | '[ApiException %d] %s',
224 | $e->getCode(),
225 | $e->getMessage()
226 | ));
227 | }
228 | }
229 |
230 | /**
231 | * Método de test para editar un asiento contable.
232 | *
233 | * En la edición de un asiento todos los campos son opcionales, se debe
234 | * mandar a lo menos uno. Acá por simpleza se toman los mismos datos
235 | * originales ya que de esta forma el asiento que se encuentre (que no
236 | * necesariamente es el creado) se editará y "tendrá sentido" al ser igual
237 | * al creado.
238 | *
239 | * @throws \libredte\api_client\ApiException
240 | *
241 | * @return void
242 | */
243 | public function testLceEditarAsiento(): void
244 | {
245 | $datos = $this->_datosAsiento();
246 | $datos['glosa'] = 'VENTA CON FACTURA EDITADA';
247 | try {
248 | // Búsqueda de asiento contable.
249 | $asientos = $this->_buscar();
250 | // Recurso a consumir.
251 | $url = sprintf(
252 | '/lce/lce_asientos/editar/%d/%d/%d',
253 | $asientos[0]['periodo'],
254 | $asientos[0]['asiento'],
255 | self::$emisor_rut
256 | );
257 | // Se envía la solicitud http y se guarda su respuesta.
258 | $response = self::$client->post(resource: $url, data: $datos);
259 | // Si el código http no es '200', arroja error ApiException.
260 | if ($response['status']['code'] != '200') {
261 | throw new ApiException(
262 | message: $response['body'],
263 | code: (int)$response['status']['code']
264 | );
265 | }
266 | // Se compara el código con '200' Si no es 200, la prueba falla.
267 | $this->assertSame('200', $response['status']['code']);
268 | // Se despliega en consola los resultados si verbose es true.
269 | if (self::$verbose) {
270 | echo "\n",
271 | 'test_lce_editar_asiento() asiento ',
272 | $response['body']['asiento'],
273 | "\n";
274 | echo "\n",
275 | 'test_lce_editar_asiento() creado ',
276 | $response['body']['creado'],
277 | "\n";
278 | echo "\n",
279 | 'test_lce_editar_asiento() modificado ',
280 | $response['body']['modificado'],
281 | "\n";
282 | }
283 | } catch (ApiException $e) {
284 | // Si falla, desplegará el mensaje y error en el siguiente formato:
285 | // [ApiException codigo-http] mensaje]
286 | $this->fail(sprintf(
287 | '[ApiException %d] %s',
288 | $e->getCode(),
289 | $e->getMessage()
290 | ));
291 | }
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/AbstractPagosCobrosMasivos.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | namespace libredte\pagos_cobros_masivos;
25 |
26 | use libredte\api_client\ApiClient;
27 | use libredte\api_client\ApiException;
28 | use PHPUnit\Framework\TestCase;
29 |
30 | abstract class AbstractPagosCobrosMasivos extends TestCase
31 | {
32 | /**
33 | * Variable para desplegar resultados.
34 | *
35 | * @var bool
36 | */
37 | protected static $verbose;
38 |
39 | /**
40 | * Variable de instanciación del API Client.
41 | *
42 | * @var ApiClient
43 | */
44 | protected static $client;
45 |
46 | /**
47 | * RUT del emisor sin DV
48 | *
49 | * @var int
50 | */
51 | protected static $emisor_rut;
52 |
53 | /**
54 | * Función para inicializar variables y clases pre ejecución de tests.
55 | *
56 | * @return void
57 | */
58 | public static function setUpBeforeClass(): void
59 | {
60 | self::$verbose = env(varname: 'TEST_VERBOSE', default: false);
61 | self::$emisor_rut = (int)(
62 | explode(
63 | '-',
64 | (string)env('LIBREDTE_RUT')
65 | )[0]
66 | );
67 | self::$client = new ApiClient();
68 | }
69 |
70 | /**
71 | * Método para buscar un cobro.
72 | *
73 | * @throws \libredte\api_client\ApiException
74 | *
75 | * @return array Arreglo que contiene el resultado de los cobros entre
76 | * 2015 y hoy.
77 | */
78 | protected function listarCobros(): array
79 | {
80 | // Se crea la lista con filtros para aplicar a la búsqueda.
81 | $filtros = [
82 | 'fecha_desde' => date(
83 | format: 'Y-m-d',
84 | timestamp: strtotime('-30 days')
85 | ),
86 | 'fecha_hasta' => date('Y-m-d'),
87 | 'pagado' => false,
88 | ];
89 | // Se genera el recurso a consumir.
90 | $resource = sprintf(
91 | '/pagos/cobros/buscar/%d',
92 | self::$emisor_rut
93 | );
94 | // Se envía la solicitud http y se guarda su respuesta.
95 | $response = self::$client->post(resource: $resource, data: $filtros);
96 |
97 | // Si el código http no es '200', arroja error ApiException.
98 | if ($response['status']['code'] != '200') {
99 | throw new ApiException(
100 | $response['body'],
101 | (int)$response['status']['code']
102 | );
103 | }
104 | // Si el body de la respuesta es vacío o nulo, arroja error
105 | // ApiException.
106 | if (empty($response['body'])) {
107 | throw new ApiException(
108 | message: 'No se encontraron cobros para la búsqueda realizada.',
109 | code: 404
110 | );
111 | }
112 | return $response;
113 | }
114 |
115 | /**
116 | * Método para emitir un DTE temporal.
117 | *
118 | * @throws \libredte\api_client\ApiException
119 | *
120 | * @return array DTE temporal generado.
121 | */
122 | private function emitirDteTemp(): array
123 | {
124 | // Datos del DTE temporal a emitir.
125 | $datos = [
126 | 'Encabezado' => [
127 | 'IdDoc' => [
128 | 'TipoDTE' => 33,
129 | ],
130 | 'Emisor' => [
131 | 'RUTEmisor' => self::$emisor_rut,
132 | ],
133 | 'Receptor' => [
134 | 'RUTRecep' => '60803000-K',
135 | 'RznSocRecep' => 'Servicio de Impuestos Internos (SII)',
136 | 'GiroRecep' => 'Administración Pública',
137 | 'Contacto' => '+56 2 3252 5575',
138 | 'CorreoRecep' => 'facturacionmipyme@sii.cl',
139 | 'DirRecep' => 'Teatinos 120',
140 | 'CmnaRecep' => 'Santiago',
141 | ],
142 | ],
143 | 'Detalle' => [
144 | [
145 | //'IndExe' => 1, // para items exentos
146 | 'NmbItem' => 'Asesoría de LibreDTE',
147 | 'QtyItem' => 1,
148 | 'PrcItem' => 1000,
149 | ],
150 | ],
151 | 'Referencia' => [
152 | [
153 | 'TpoDocRef' => 801,
154 | 'FolioRef' => 'OC123',
155 | 'FchRef' => '2015-10-01',
156 | ],
157 | ],
158 | ];
159 |
160 | // Se envía la solicitud http y se guarda su respuesta.
161 | $response = self::$client->post(
162 | resource: '/dte/documentos/emitir',
163 | data: $datos
164 | );
165 |
166 | // Si el código http no es '200', arroja error ApiException.
167 | if ($response['status']['code'] !== '200') {
168 | throw new ApiException(
169 | message: $response['body'],
170 | code: (int)$response['status']['code']
171 | );
172 | }
173 |
174 | return $response;
175 | }
176 |
177 | /**
178 | * Método de test para obtener un cobro a partir de un DTE temporal.
179 | *
180 | * @throws \libredte\api_client\ApiException
181 | *
182 | * @return array Cobro asociado a un DTE temporal recién emitido.
183 | */
184 | protected function obtenerCobroDteTemp(): array
185 | {
186 | // Se emite un documento temporal para obtener su cobro
187 | $documento = $this->emitirDteTemp();
188 |
189 | // Se genera el recurso a consumir.
190 | $resource = sprintf(
191 | '/dte/dte_tmps/cobro/%d/%d/%s/%d',
192 | $documento['body']['receptor'],
193 | $documento['body']['dte'],
194 | $documento['body']['codigo'],
195 | self::$emisor_rut
196 | );
197 | // Se envía la solicitud http y se guarda su respuesta.
198 | $response = self::$client->get($resource);
199 | // Si el código http no es '200', arroja error ApiException.
200 | if ($response['status']['code'] != '200') {
201 | throw new ApiException(
202 | message: $response['body'],
203 | code: (int)$response['status']['code']
204 | );
205 | }
206 |
207 | return $response;
208 | }
209 |
210 | /**
211 | * Método privado para buscar un DTE emitido.
212 | *
213 | * @throws \libredte\api_client\ApiException
214 | *
215 | * @return array Arreglo con los DTEs emitidos.
216 | */
217 | protected function listarDteEmitidos(): array
218 | {
219 | // Filtros para la petición http.
220 | $filtros = [
221 | 'fecha_desde' => date(
222 | format: 'Y-m-d',
223 | timestamp: strtotime('-30 days')
224 | ),
225 | 'fecha_hasta' => date('Y-m-d'),
226 | ];
227 | // Recurso a consumir.
228 | $resource = sprintf(
229 | '/dte/dte_emitidos/buscar/%d',
230 | self::$emisor_rut
231 | );
232 | // Se envía la solicitud http y se guarda su respuesta.
233 | $response = self::$client->post(resource: $resource, data: $filtros);
234 | // Si el código http no es '200', arroja error ApiException.
235 | if ($response['status']['code'] != '200') {
236 | throw new ApiException(
237 | message: $response['body'],
238 | code: (int)$response['status']['code']
239 | );
240 | }
241 | return $response;
242 | }
243 |
244 | /**
245 | * Método privado para listar cobros masivos programados.
246 | *
247 | * @throws \libredte\api_client\ApiException
248 | *
249 | * @return array Arreglo con los cobros masivos programados.
250 | */
251 | protected function listarCobrosMasivosProgramados(): array
252 | {
253 | // Filtros para la petición http.
254 | $filtros = [
255 | 'siguiente_desde' => date(
256 | format: 'Y-m-d',
257 | timestamp: strtotime('-30 days')
258 | ),
259 | 'siguiente_hasta' => date('Y-m-d'),
260 | 'activo' => true,
261 | ];
262 | // Recurso a consumir.
263 | $resource = sprintf(
264 | '/pagos/cobro_masivo_programados/buscar/%d',
265 | self::$emisor_rut
266 | );
267 | // Se envía la solicitud http y se guarda su respuesta.
268 | $response = self::$client->post(resource: $resource, data: $filtros);
269 | // Si el código http no es '200', arroja error ApiException.
270 | if ($response['status']['code'] != '200') {
271 | throw new ApiException(
272 | message: $response['body'],
273 | code: (int)$response['status']['code']
274 | );
275 | }
276 | // Si el body de la respuesta es vacío o nulo, arroja error ApiException.
277 | if (empty($response['body'])) {
278 | throw new ApiException(
279 | message: 'No se encontraron cobros masivos programados para la búsqueda realizada.',
280 | code: 404
281 | );
282 | }
283 | return $response;
284 | }
285 | }
286 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/BuscarCobroDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas para buscar un cobro asociado a un DTE temporal.
34 | */
35 | class BuscarCobroDteTempTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Método de test para buscar un cobro específico.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testBuscarCobroDteTemp(): void
45 | {
46 | try {
47 | // Se obtiene la lista de cobros.
48 | $cobro = $this->obtenerCobroDteTemp();
49 | // Se crea el recurso a consumir.
50 | $resource = sprintf(
51 | '/pagos/cobros/info/%s/%d',
52 | $cobro['body']['codigo'],
53 | self::$emisor_rut
54 | );
55 | // Se envía la solicitud http y se guarda su respuesta.
56 | $response = self::$client->get($resource);
57 | // Si el código http no es '200', arroja error ApiException.
58 | if ($response['status']['code'] !== '200') {
59 | throw new ApiException(
60 | message: $response['body'],
61 | code: (int)$response['status']['code']
62 | );
63 | }
64 | // Se compara el código con '200' Si no es 200, la prueba falla.
65 | $this->assertSame('200', $response['status']['code']);
66 | // Se despliega en consola los resultados si verbose es true.
67 | if (self::$verbose) {
68 | echo "\n",'testBuscarCobroAsociado() Cobro: ',json_encode(
69 | $response['body']
70 | ),"\n";
71 | }
72 | } catch (ApiException $e) {
73 | // Si falla, desplegará el mensaje y error en el siguiente formato:
74 | // [ApiException codigo-http] mensaje]
75 | $this->fail(sprintf(
76 | '[ApiException %d] %s',
77 | $e->getCode(),
78 | $e->getMessage()
79 | ));
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/CrearCobroMasivoProgramadoTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase para ejecutar tests a los servicios de cobros masivos.
34 | */
35 | class CrearCobroMasivoProgramadoTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Prueba unitaria que muestra los pasos para:
39 | * - Guardar cambios en un cobro masivo programado a un receptor
40 | *
41 | * Esto permite aplicar un descuento o modificar la cantidad en el listado
42 | * de items. Por ejemplo, sirve para actualizar la cantidad de algo que se
43 | * está cobrando (ej: consumo de GB en una cuenta de hosting).
44 | *
45 | * Se puede editar todo el cobro, o sea los campos:
46 | * - dte: código del DTE, ej: 33 (factura electrónica afecta)
47 | * - dte_real: =1 emite DTE real, =0 emite cotización
48 | * - siguiente: fecha siguiente cobro AAAA-MM-DD
49 | * - activo: 1 o 0
50 | * - observacion: texto
51 | * - items: arreglo de item con campos:
52 | * - descripcion: string (máx 1000 chars)
53 | * - cantidad: real
54 | * - descuento: real
55 | * - descuento_tipo (% o $)
56 | * - referencias: arreglo de referencias con campos:
57 | * - documento
58 | * - folio
59 | * - fecha
60 | * - descripcion
61 | *
62 | * IMPORTANTE: para eliminar un item marcarlo con cantidad = 0.
63 | * No es posible eliminar vía servicios web items obligatorios.
64 | *
65 | * @throws \libredte\api_client\ApiException
66 | *
67 | * @return void
68 | */
69 | public function testCrearCobroMasivoProgramado(): void
70 | {
71 | try {
72 | // Búsqueda de cobros masivos.
73 | $cobros = $this->listarCobrosMasivosProgramados();
74 | // Recurso a consumir.
75 | $resource = '/pagos/cobro_masivo_programados/guardar';
76 | // Datos del cobro masivo.
77 | $datos = [
78 | // datos obligatorios
79 | 'emisor' => self::$emisor_rut,
80 | 'cobro_masivo_codigo' => $cobros['body'][0]['masivo_codigo'],
81 | 'receptor' => explode('-', $cobros['body'][0]['rut'])[0],
82 | // datos que varían, acá se guarda una referencia
83 | // pero podría ser modificados los items o la fecha de siguiente cobro
84 | 'referencias' => [
85 | [
86 | 'documento' => 801,
87 | 'folio' => 123,
88 | 'fecha' => date('Y-m-d'), // =false se elimina la referencia
89 | 'descripcion' => 'REF A OC',
90 | ],
91 | ],
92 | ];
93 | // Se envía la solicitud http y se guarda su respuesta.
94 | $response = self::$client->post(
95 | $resource,
96 | $datos
97 | );
98 | // Si el código http no es '200', arroja error ApiException.
99 | if ($response['status']['code'] != '200') {
100 | throw new ApiException(
101 | message: $response['body'],
102 | code: (int)$response['status']['code']
103 | );
104 | }
105 | // Se compara el código con '200' Si no es 200, la prueba falla.
106 | $this->assertSame('200', $response['status']['code']);
107 | // Se despliega en consola los resultados si verbose es true.
108 | if (self::$verbose) {
109 | echo "\n",
110 | 'testCrearCobroMasivoProgramado() Cobro: ',
111 | json_encode(
112 | $response['body']
113 | ),"\n";
114 | }
115 | } catch (ApiException $e) {
116 | // Si falla, desplegará el mensaje y error en el siguiente formato:
117 | // [ApiException codigo-http] mensaje]
118 | $this->fail(sprintf(
119 | '[ApiException %d] %s',
120 | $e->getCode(),
121 | $e->getMessage()
122 | ));
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/EmitirCobroMasivoProgramadoTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase para ejecutar tests a los servicios de cobros masivos.
34 | */
35 | class EmitirCobroMasivoProgramadoTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Prueba unitaria que muestra los pasos para:
39 | * - Emitir un cobro masivo, emitiendo y enviando por correo, cada uno de
40 | * los documentos generados (si así está configurado)
41 | *
42 | * @throws \libredte\api_client\ApiException
43 | *
44 | * @return void
45 | */
46 | public function testEmitirCobroMasivoProgramado(): void
47 | {
48 | try {
49 | // Búsqueda de cobros masivos programados.
50 | $cobros = $this->listarCobrosMasivosProgramados();
51 | // Recurso a consumir.
52 | $resource = sprintf(
53 | '/pagos/cobro_masivo_programados/emitir/%s/%d/%d',
54 | $cobros['body'][0]['masivo_codigo'],
55 | explode('-', $cobros['body'][0]['rut'])[0],
56 | self::$emisor_rut
57 | );
58 | // Se envía la solicitud http y se guarda su respuesta.
59 | $response = self::$client->get($resource);
60 | // Si el código http no es '200', arroja error ApiException.
61 | if ($response['status']['code'] != '200') {
62 | throw new ApiException(
63 | message: $response['body'],
64 | code: (int)$response['status']['code']
65 | );
66 | }
67 | // Se compara el código con '200' Si no es 200, la prueba falla.
68 | $this->assertSame('200', $response['status']['code']);
69 | // Se despliega en consola los resultados si verbose es true.
70 | if (self::$verbose) {
71 | echo "\n",
72 | 'testEmitirCobroMasivoProgramado() Cobro: ',
73 | json_encode(
74 | $response['body']
75 | ),"\n";
76 | }
77 | } catch (ApiException $e) {
78 | // Si falla, desplegará el mensaje y error en el siguiente formato:
79 | // [ApiException codigo-http] mensaje]
80 | $this->fail(sprintf(
81 | '[ApiException %d] %s',
82 | $e->getCode(),
83 | $e->getMessage()
84 | ));
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/ListarCobrosDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas para ejecutar tests de listado de cobros.
34 | */
35 | class ListarCobrosDteTempTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Método de test para listar los cobros existentes.
39 | *
40 | * @return void
41 | */
42 | public function testListarCobrosDteTemp(): void
43 | {
44 | try {
45 | // Se obtiene un listado de cobros.
46 | $cobros = $this->listarCobros();
47 | // La prueba tendrá éxito si la búsqueda funciona.
48 | $this->assertTrue(true);
49 | // Se despliega en consola los resultados si verbose es true.
50 | if (self::$verbose) {
51 | echo "\n",
52 | 'testListarCobrosDteTemp() Cobro: ',
53 | json_encode(
54 | $cobros['body']
55 | ),"\n";
56 | }
57 | } catch (ApiException $e) {
58 | // Si falla, desplegará el mensaje y error en el siguiente formato:
59 | // [ApiException codigo-http] mensaje]
60 | $this->fail(sprintf(
61 | '[ApiException %d] %s',
62 | $e->getCode(),
63 | $e->getMessage()
64 | ));
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/ListarCobrosMasivosProgramadosTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebas para listar cobros masivos programados.
34 | */
35 | class ListarCobrosMasivosProgramadosTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Método de test para listar cobros masivos programados.
39 | *
40 | * @return void
41 | */
42 | public function testListarCobrosMasivosProgramados(): void
43 | {
44 | try {
45 | // Se listan cobros masivos programados.
46 | $cobros = $this->listarCobrosMasivosProgramados();
47 | // La prueba tendrá éxito si la búsqueda funciona.
48 | $this->assertTrue(true);
49 | // Se despliega en consola los resultados si verbose es true.
50 | if (self::$verbose) {
51 | echo "\n",
52 | 'testListarCobroMasivoProgramado() Cobro Masivo: ',
53 | json_encode(
54 | $cobros['body']
55 | ),"\n";
56 | }
57 | } catch (ApiException $e) {
58 | // Si falla, desplegará el mensaje y error en el siguiente formato:
59 | // [ApiException codigo-http] mensaje]
60 | $this->fail(sprintf(
61 | '[ApiException %d] %s',
62 | $e->getCode(),
63 | $e->getMessage()
64 | ));
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/ObtenerCobroDocumentoEmitidoTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de test para generar un cobro de un documento emitido (real).
34 | */
35 | class ObtenerCobroDocumentoEmitidoTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Método de test para obtener un cobro asociado a un DTE emitido.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testObtenerCobroDteEmitido(): void
45 | {
46 | try {
47 | // Búsqueda de DTE emitido.
48 | $documentos = $this->listarDteEmitidos();
49 | // Recurso a consumir.
50 | $resource = sprintf(
51 | '/dte/dte_emitidos/cobro/%d/%d/%d',
52 | $documentos['body'][0]['dte'],
53 | $documentos['body'][0]['folio'],
54 | self::$emisor_rut
55 | );
56 | // Se envía la solicitud http y se guarda su respuesta.
57 | // Se obtiene el cobro asociado con el recurso previo.
58 | $response = self::$client->get($resource);
59 | // Si el código http no es '200', arroja error ApiException.
60 | if ($response['status']['code'] != '200') {
61 | throw new ApiException(
62 | message: $response['body'],
63 | code: (int)$response['status']['code']
64 | );
65 | }
66 | // Se compara el código con '200' Si no es 200, la prueba falla.
67 | $this->assertSame('200', $response['status']['code']);
68 | // Se despliega en consola los resultados si verbose es true.
69 | if (self::$verbose) {
70 | echo "\n",
71 | 'testObtenerCobroDteEmitido() Cobro: ',
72 | json_encode(
73 | $response['body']
74 | ),"\n";
75 | }
76 | } catch (ApiException $e) {
77 | // Si falla, desplegará el mensaje y error en el siguiente formato:
78 | // [ApiException codigo-http] mensaje]
79 | $this->fail(sprintf(
80 | '[ApiException %d] %s',
81 | $e->getCode(),
82 | $e->getMessage()
83 | ));
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/pagos_cobros_masivos/PagarCobroDteTempTest.php:
--------------------------------------------------------------------------------
1 |
8 | *
9 | * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10 | * bajo los términos de la GNU Lesser General Public License (LGPL) publicada
11 | * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12 | * o (a su elección) cualquier versión posterior de la misma.
13 | *
14 | * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15 | * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16 | * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la GNU Lesser General
17 | * Public License (LGPL) para obtener una información más detallada.
18 | *
19 | * Debería haber recibido una copia de la GNU Lesser General Public License
20 | * (LGPL) junto a este programa. En caso contrario, consulte
21 | * .
22 | */
23 |
24 | use libredte\api_client\ApiClient;
25 | use libredte\api_client\ApiException;
26 | use libredte\api_client\HttpCurlClient;
27 | use libredte\pagos_cobros_masivos\AbstractPagosCobrosMasivos;
28 | use PHPUnit\Framework\Attributes\CoversClass;
29 |
30 | #[CoversClass(ApiClient::class)]
31 | #[CoversClass(HttpCurlClient::class)]
32 | /**
33 | * Clase de pruebbas para pagar el cobro de un DTE temporal.
34 | */
35 | class PagarCobroDteTempTest extends AbstractPagosCobrosMasivos
36 | {
37 | /**
38 | * Método de test que permite pagar un cobro de un DTE temporal.
39 | *
40 | * @throws \libredte\api_client\ApiException
41 | *
42 | * @return void
43 | */
44 | public function testPagarCobroDteTemp(): void
45 | {
46 | try {
47 | // Se obtiene una lista de cobros.
48 | $cobro = $this->obtenerCobroDteTemp();
49 |
50 | // Se crea el recurso a consumir.
51 | $resource = sprintf(
52 | '/pagos/cobros/pagar/%s/%d',
53 | $cobro['body']['codigo'],
54 | self::$emisor_rut
55 | );
56 | // Se crea el array con los datos a enviar,
57 | $data = [
58 | 'medio' => 'efectivo',
59 | 'fecha' => (string)date('Y-m-d'),
60 | ];
61 |
62 | // Se envía la solicitud http y se guarda su respuesta.
63 | $response = self::$client->post(
64 | resource: $resource,
65 | data: $data
66 | );
67 |
68 | // Si el código http no es '200', arroja error ApiException.
69 | if ($response['status']['code'] !== '200') {
70 | throw new ApiException(
71 | message: $response['body'],
72 | code: (int)$response['status']['code']
73 | );
74 | }
75 |
76 | $this->assertSame('200', $response['status']['code']);
77 |
78 | // Se despliega en consola los resultados si verbose es true.
79 | if (self::$verbose) {
80 | echo "\n",
81 | 'testPagarCobroDteTemp() Cobro: ',
82 | json_encode(
83 | $response['body']
84 | ),"\n";
85 | }
86 | } catch (ApiException $e) {
87 | // Si falla, desplegará el mensaje y error en el siguiente formato:
88 | // [ApiException codigo-http] mensaje]
89 | $this->fail(sprintf(
90 | '[ApiException %d] %s',
91 | $e->getCode(),
92 | $e->getMessage()
93 | ));
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/tests/test.env-dist:
--------------------------------------------------------------------------------
1 | #
2 | # Variables de entorno para la ejecución de los tests
3 | #
4 |
5 | # Autenticación en LibreDTE
6 | LIBREDTE_URL="https://libredte.cl"
7 | LIBREDTE_HASH=""
8 |
9 | # Contribuyente con el que se trabajará
10 | LIBREDTE_RUT=""
11 |
12 | # Correo electrónico para las pruebas de envío
13 | TEST_EMAIL=""
14 |
--------------------------------------------------------------------------------