phpcfdi / sat-estado-cfdi
Consulta el estado de un cfdi en el webservice del SAT
Installs: 38 999
Dependents: 2
Suggesters: 0
Security: 0
Stars: 20
Watchers: 5
Forks: 9
Open Issues: 0
Requires
- php: >=8.2
Requires (Dev)
- ext-curl: *
- ext-dom: *
- ext-soap: *
- guzzlehttp/guzzle: ^7.8
- guzzlehttp/psr7: ^2.6
- phpcfdi/cfdi-expresiones: ^3.0
- phpunit/phpunit: ^11.0.3
- psr/http-client: ^1.0|^2.0
- psr/http-factory: ^1.0|^2.0
- psr/http-message: ^1.0|^2.0
Suggests
- ext-dom: Extensi贸n para poder usar el cliente HTTP PSR
- ext-soap: Extensi贸n para poder usar el cliente SOAP
- phpcfdi/cfdi-expresiones: Genera expresiones de CFDI 4.0, CFDI 3.3, CFDI 3.2, RET 1.0 y RET 2.0
- psr/http-client: Requerimiento del cliente HTTP PSR
- psr/http-factory: Requerimiento del cliente HTTP PSR
- psr/http-message: Requerimiento del cliente HTTP PSR
README
Consulta el estado de un CFDI en el webservice del SAT
馃嚭馃嚫 This library contains helpers to consume the Servicio de Consulta de CFDI from SAT. The documentation of this project is in spanish as this is the natural language for intended audience.
馃嚥馃嚱 Esta librer铆a se utiliza para consumir el Servicio de Consulta de CFDI del SAT. La documentaci贸n del proyecto est谩 en espa帽ol porque ese es el lenguaje de los usuarios que la utilizar谩n.
Esta librer铆a solo permite verificar el estado de un CFDI Regular y no de CFDI de Retenciones e informaci贸n de pagos. Para estos 煤ltimos, use la librer铆a phpcfdi/sat-estado-retenciones.
Servicio de Consulta de CFDI del SAT:
- Servicio productivo: https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc
- Servicio de pruebas: https://pruebacfdiconsultaqr.cloudapp.net/ConsultaCFDIService.svc
- SAT: https://www.sat.gob.mx/consultas/20585/conoce-los-servicios-especializados-de-validacion
- Documentaci贸n del Servicio de Consulta de CFDIVersi贸n 1.4 (noviembre 2022): https://www.sat.gob.mx/cs/Satellite?blobcol=urldata&blobkey=id&blobtable=MungoBlobs&blobwhere=1461175223997&ssbinary=true
Cambios recientes en el servicio:
- Por motivo del cambio en el proceso de cancelaci贸n, en 2018 agregaron nuevos estados.
- Por una raz贸n desconocida e inexplicable, el WSDL no estuvo disponible de 2018 a 2020. Esta librer铆a usa una estrategia en donde no depende del WSDL para consumir el servicio.
- A finales de 2020 agregaron el campo de respuesta
VerificacionEFOS
.
Instalaci贸n
Usa composer
composer require phpcfdi/sat-estado-cfdi
Ejemplo b谩sico de uso
Los pasos b谩sicos son:
- Tener un cliente que implemente
ConsumerClientInterface
. - Crear un consumidor del servicio
Consumer
- Realizar la solicitud con una expresi贸n definida.
- Usar el resultado
<?php use PhpCfdi\SatEstadoCfdi\Consumer; use PhpCfdi\SatEstadoCfdi\Contracts\ConsumerClientInterface; /** @var ConsumerClientInterface $client */ $consumer = new Consumer($client); $cfdiStatus = $consumer->execute('...expression'); if ($cfdiStatus->cancellable->isNotCancellable()) { echo 'CFDI no es cancelable'; }
Clientes de consumo ConsumerClientInterface
Esta librer铆a incluye dos diferentes clientes de consumo: SoapConsumerClient
y HttpConsumerClient
.
Adem谩s, puedes usar tu propio cliente de consumo implementando la interface ConsumerClientInterface
.
Cliente SOAP SoapConsumerClient
El cliente SoapConsumerClient
permite hacer el consumo usando la estrategia SOAP.
Requerimientos:
ext-soap
: Extensi贸n SOAP de PHP.
Ejemplo:
<?php use PhpCfdi\SatEstadoCfdi\Clients\Soap\SoapConsumerClient; use PhpCfdi\SatEstadoCfdi\Consumer; function createConsumerUsingSoap(): Consumer { $client = new SoapConsumerClient(); return new Consumer($client); }
Cliente HTTP PSR HttpConsumerClient
El cliente HttpConsumerClient
permite hacer el consumo usando la estrategia HTTP con base en los est谩ndares PSR.
Est谩ndares utilizados:
- PSR-18: HTTP Client: Interfaces para clientes HTTP (el que hace la llamada POST). https://www.php-fig.org/psr/psr-18/
- PSR-17: HTTP Factories: Interfaces de f谩bricas de HTTP Request y Response (para PSR-7). https://www.php-fig.org/psr/psr-17/
Las librer铆as de Guzzle
guzzlehttp/guzzle
, y
guzzlehttp/psr7
proveen los est谩ndares necesarios.
O puedes ver en Packagist los que te agraden:
- PSR-18: https://packagist.org/providers/psr/http-client-implementation
- PSR-17: https://packagist.org/providers/psr/http-factory-implementation
Requerimientos:
ext-dom
: Extensi贸n DOM de PHP.psr/http-client: ^1.0
: Est谩ndar PSR-18 (Cliente HTTP).psr/http-factory: ^1.0
: Est谩ndar PSR-17 (F谩bricas de mensajes HTTP).- Algunas librer铆as que implementen PSR-18 y PSR-17, por ejemplo:
- Guzzle:
guzzlehttp/guzzle
yguzzlehttp/psr7
. - Symfony:
symfony/http-client
ynyholm/psr7
olaminas/laminas-diactoros
.
- Guzzle:
Ejemplo:
<?php use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerClient; use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerFactory; use PhpCfdi\SatEstadoCfdi\Consumer; function createConsumerUsingGuzzle(): Consumer { // Implements PSR-18 \Psr\Http\Client\ClientInterface $guzzleClient = new \GuzzleHttp\Client(); // Implements PSR-17 \Psr\Http\Message\RequestFactoryInterface and PSR-17 \Psr\Http\Message\StreamFactoryInterface $guzzleFactory = new \GuzzleHttp\Psr7\HttpFactory(); $factory = new HttpConsumerFactory($guzzleClient, $guzzleFactory, $guzzleFactory); $client = new HttpConsumerClient($factory); return new Consumer($client); }
El siguiente es un ejemplo usando symfony/http-client
y nyholm/psr7
:
use PhpCfdi\SatEstadoCfdi\Consumer; use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerClient; use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerFactory; function createConsumerUsingSymfonyNyholm(): Consumer { $httpClient = new \Symfony\Component\HttpClient\Psr18Client(); $messageFactory = new \Nyholm\Psr7\Factory\Psr17Factory(); $factory = new HttpConsumerFactory($httpClient, $messageFactory, $messageFactory); $client = new HttpConsumerClient($factory); return new Consumer($client); }
Para Laravel puedes usar alg煤n paquete adicional como wimski/laravel-psr-http
,
que gracias al uso del propio framework y php-http/discovery
, facilita la creaci贸n de los objetos,
ya sea que los fabrique directamente usando el contenedor, o bien los inyecte como dependencias.
<?php use PhpCfdi\SatEstadoCfdi\Consumer; use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerClient; use PhpCfdi\SatEstadoCfdi\Clients\Http\HttpConsumerFactory; function createConsumerUsingLaravel(): Consumer { $httpClient = app(\Psr\Http\Client\ClientInterface::class); $requestFactory = app(Psr\Http\Message\RequestFactoryInterface::class); $streamFactory = app(Psr\Http\Message\StreamFactoryInterface::class); $factory = new HttpConsumerFactory($httpClient, $requestFactory, $streamFactory); $client = new HttpConsumerClient($factory); return new Consumer($client); }
Tambi茅n te recomiendo hacer tu propio Service Provider o configurar el Service Container
y solo requerir la clase Consumer
como cualquier otra dependencia y permitir que sea inyectada.
Expresiones (input)
El consumidor requiere una expresi贸n para poder consultar. La expresi贸n es el texto que viene en el c贸digo QR de la representaci贸n impresa de un CFDI.
Las expresiones son diferentes para CFDI 3.2, CFDI 3.3, CFDI 4.0, RET 1.0 y RET 2.0. Tienen reglas espec铆ficas de formato y de la informaci贸n que debe contener.
Si no cuentas con la expresi贸n, te recomiendo usar la librer铆a
phpcfdi/cfdi-expresiones
que puedes instalar
usando composer require phpcfdi/cfdi-expresiones
.
<?php use PhpCfdi\CfdiExpresiones\DiscoverExtractor; use PhpCfdi\SatEstadoCfdi\Consumer; // lectura del contenido del CFDI $document = new DOMDocument(); $document->load('archivo-cfdi.xml'); // creaci贸n de la expresi贸n $expressionExtractor = new DiscoverExtractor(); $expression = $expressionExtractor->extract($document); // realizar la consulta con la expresi贸n obtenida /** @var Consumer $consumer */ $cfdiStatus = $consumer->execute($expression); // usar el estado if ($cfdiStatus->document->isActive()) { echo 'El CFDI se encuentra vigente'; }
Estados (salida)
Despu茅s de consumir el servicio, se responder谩 con un objeto CfdiStatus
que agrupa de los cuatro estados.
Los estados son enumeradores, puedes compararlos r谩pidamente usando m茅todos de ayuda is*
,
por ejemplo: $response->document->isCancelled()
.
Posibles estados:
-
CodigoEstatus
:query: QueryStatus
.Found
: Si el estado inicia conS -
.NotFound
: en cualquier otro caso.
-
Estado
:document: DocumentStatus
.Active
: Si el estado report贸Vigente
.Cancelled
: Si el estado report贸Cancelado
.NotFound
: en cualquier otro caso.
-
EsCancelable
:cancellable: CancellableStatus
.CancellableByDirectCall
: Si el estado report贸Cancelable sin aceptaci贸n
.CancellableByApproval
: Si el estado report贸Cancelable con aceptaci贸n
.NotCancellable
: en cualquier otro caso.
-
EstatusCancelacion
:cancellation: CancellationStatus
.CancelledByDirectCall
: Si el estado report贸Cancelado sin aceptaci贸n
.CancelledByApproval
: Si el estado report贸Cancelado con aceptaci贸n
.CancelledByExpiration
: Si el estado report贸Plazo vencido
.Pending
: Si el estado report贸En proceso
.Disapproved
: Si el estado report贸Solicitud rechazada
.Undefined
: en cualquier otro caso.
-
ValidacionEFOS
:efos: EfosStatus
.Included
: Si el estado no report贸200
o201
.Excluded
: Si el estado report贸200
o201
.
Estados mutuamente excluyentes
Cuando tienes un CFDI en estado Cancelable con aceptaci贸n y mandas a hacer la cancelaci贸n entonces su estado de cancelaci贸n cambiar铆a a En proceso.
El receptor puede aceptar la cancelaci贸n (Cancelado con aceptaci贸n) o rechazarla (Solicitud rechazada).
Si es la primera vez que se hace la solicitud, el receptor tiene 72 horas para aceptarla o rechazarla, si no lo hace entonces autom谩ticamente ser谩 cancelada (Plazo vencido).
Podr铆as volver a enviar la solicitud de cancelaci贸n por segunda vez aun cuando la solicitud fue previamente rechazada.
En ese caso, el receptor puede aceptar o rechazar la cancelaci贸n, pero ya no aplicar谩 un lapso de 72 horas. Por lo anterior entonces podr铆as tener el CFDI en estado de cancelaci贸n en proceso indefinidamente. Incluso, que la cancelaci贸n suceda meses despu茅s de lo esperado.
Compatibilidad
Esta librer铆a se mantendr谩 compatible con al menos la versi贸n con soporte activo de PHP m谩s reciente.
Tambi茅n utilizamos Versionado Sem谩ntico 2.0.0 por lo que puedes usar esta librer铆a sin temor a romper tu aplicaci贸n.
Contribuciones
Las contribuciones con bienvenidas. Por favor lee CONTRIBUTING para m谩s detalles y recuerda revisar el archivo de tareas pendientes TODO y el archivo CHANGELOG.
Copyright and License
The phpcfdi/sat-estado-cfdi
library is copyright 漏 PhpCfdi
and licensed for use under the MIT License (MIT). Please see LICENSE for more information.