• Stars
    star
    108
  • Rank 311,659 (Top 7 %)
  • Language
    PHP
  • License
    MIT License
  • Created almost 5 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Librer铆a para usar el servicio web del SAT de Descarga Masiva

phpcfdi/sat-ws-descarga-masiva

Source Code Packagist PHP Version Support Discord Latest Version Software License Build Status Reliability Maintainability Code Coverage Violations Total Downloads

Librer铆a para usar el servicio web del SAT de Descarga Masiva

馃嚭馃嚫 The documentation of this project is in spanish as this is the natural language for intented audience.

馃嚥馃嚱 La documentaci贸n del proyecto est谩 en espa帽ol porque ese es el lenguaje principal de los usuarios. Tambi茅n te esperamos en el canal #phpcfdi de discord

Esta librer铆a contiene un cliente (consumidor) del servicio del SAT de Servicio Web de Descarga Masiva de CFDI y Retenciones.

Instalaci贸n

Utiliza composer, instala de la siguiente forma:

composer require phpcfdi/sat-ws-descarga-masiva

Ejemplos de uso

Todos los objetos de entrada y salida se pueden exportar como JSON para su f谩cil depuraci贸n.

Creaci贸n el servicio

Ejemplo creando el servicio usando una FIEL disponible localmente.

<?php

use PhpCfdi\SatWsDescargaMasiva\RequestBuilder\FielRequestBuilder\Fiel;
use PhpCfdi\SatWsDescargaMasiva\RequestBuilder\FielRequestBuilder\FielRequestBuilder;
use PhpCfdi\SatWsDescargaMasiva\Service;
use PhpCfdi\SatWsDescargaMasiva\WebClient\GuzzleWebClient;

// Creaci贸n de la FIEL, puede leer archivos DER (como los env铆a el SAT) o PEM (convertidos con openssl)
$fiel = Fiel::create(
    file_get_contents('certificado.cer'),
    file_get_contents('llaveprivada.key'),
    '12345678a'
);

// verificar que la FIEL sea v谩lida (no sea CSD y sea vigente acorde a la fecha del sistema)
if (! $fiel->isValid()) {
    return;
}

// creaci贸n del web client basado en Guzzle que implementa WebClientInterface
// para usarlo necesitas instalar guzzlehttp/guzzle, pues no es una dependencia directa
$webClient = new GuzzleWebClient();

// creaci贸n del objeto encargado de crear las solicitudes firmadas usando una FIEL
$requestBuilder = new FielRequestBuilder($fiel);

// Creaci贸n del servicio
$service = new Service($requestBuilder, $webClient);

Cliente para consumir los servicios de CFDI de Retenciones

Existen dos tipos de Comprobantes Fiscales Digitales, los regulares (ingresos, egresos, traslados, n贸minas y pagos), y los CFDI de retenciones e informaci贸n de pagos (retenciones).

Puede utilizar esta librer铆a para consumir los CFDI de Retenciones. Para lograrlo construya el servicio con la especificaci贸n de ServiceEndpoints::retenciones().

Los constructores ServiceEndpoints::cfdi() y ServiceEndpoints::retenciones() agregan autom谩ticamente la propiedad ServiceType al objeto. Esta propiedad ser谩 despu茅s utilizada el servicio para especificar el valor en la consulta antes de consumirla.

use PhpCfdi\SatWsDescargaMasiva\RequestBuilder\RequestBuilderInterface;
use PhpCfdi\SatWsDescargaMasiva\Service;
use PhpCfdi\SatWsDescargaMasiva\Shared\ServiceEndpoints;
use PhpCfdi\SatWsDescargaMasiva\WebClient\GuzzleWebClient;

/**
 * @var GuzzleWebClient $webClient Cliente de Guzzle previamente fabricado
 * @var RequestBuilderInterface $requestBuilder Creador de solicitudes, previamente fabricado
 */
// Creaci贸n del servicio
$service = new Service($requestBuilder, $webClient, null, ServiceEndpoints::retenciones());

Aunque no es recomendado, tambi茅n puedes construir el objeto ServiceEndpoints con direcciones URL del servicio personalizadas utilizando el constructor del objeto en lugar de los m茅todos est谩ticos.

Realizar una consulta

Una vez creado el servicio, se puede presentar la consulta, si se pudo presentar devolver谩 el identificador de la solicitud, y con este identificador se podr谩 continuar al servicio de verificaci贸n.

<?php

use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\DateTimePeriod;

// Crear la consulta
$request = QueryParameters::create(
    DateTimePeriod::createFromValues('2019-01-13 00:00:00', '2019-01-13 23:59:59'),
);

// presentar la consulta
$query = $service->query($request);

// verificar que el proceso de consulta fue correcto
if (! $query->getStatus()->isAccepted()) {
    echo "Fallo al presentar la consulta: {$query->getStatus()->getMessage()}";
    return;
}

// el identificador de la consulta est谩 en $query->getRequestId()
echo "Se gener贸 la solicitud {$query->getRequestId()}", PHP_EOL;

Par谩metros de la consulta

Periodo (DateTimePeriod)

Fecha y hora de inicio y fin de la consulta. Si no se especifica crea un periodo del segundo exacto de la creaci贸n del objeto.

Tipo de descarga (DownloadType)

Especifica si la solicitud es de documentos emitidos DownloadType::issued() o recibidos DownloadType::received(). Si no se especifica utiliza el valor de emitidos.

Tipo de solicitud (RequestType)

Especifica si la solicitud es de Metadatos RequestType::metadata() o archivos XML RequestType::xml(). Si no se especifica utiliza el valor de Metadatos.

Tipo de comprobante (DocumentType)

Filtra la solicitud por tipo de comprobante. Si no se especifica utiliza no utiliza el filtro.

  • Cualquiera: DocumentType::undefined() (predeterminado).
  • Ingreso: DocumentType::ingreso().
  • Egreso: DocumentType::egreso().
  • Traslado: DocumentType::traslado().
  • N贸mina: DocumentType::nomina().
  • Pago: DocumentType::pago().

Tipo de complemento (ComplementoCfdi o ComplementoRetenciones)

Filtra la solicitud por la existencia de un tipo de complemento dentro del comprobante. Si no se especifica utiliza ComplementoUndefined::undefined() que excluye el filtro.

Hay dos tipos de objetos que satisfacen este par谩metro, depende del tipo de comprobante que se est谩 solicitando. Si se trata de comprobantes de CFDI Regulares entonces se usa la clase ComplementoCfdi. Si se trata de CFDI de retenciones e informaci贸n de pagos entonces se usa la clase ComplementoRetenciones.

Estos objetos se pueden crear nombrados (ComplementoCfdi::leyendasFiscales10()), por constructor (new ComplementoCfdi('leyendasfisc')), o bien, por el m茅todo est谩tico create (ComplementoCfdi::create('leyendasfisc')).

Adem谩s, se puede acceder al nombre del complemento utilizando el m茅todo label(), por ejemplo, echo ComplementoCfdi::leyendasFiscales10()->label(); // Leyendas Fiscales 1.0.

A su vez, este objeto ofrece un m茅todo est谩tico getLabels(): array para obtener un arreglo con los datos, en donde la llave es el identificador del complemento y el valor es el nombre del complemento.

Estado del comprobante (DocumentStatus)

Filtra la solicitud por el estado de comprobante: Vigente (DocumentStatus::active()) y Cancelado (DocumentStatus::cancelled()). Si no se especifica utiliza DocumentStatus::undefined() que excluye el filtro.

UUID (Uuid)

Filtra la solicitud por UUID. Para crear el objeto del filtro hay que usar Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'). Si no se especifica utiliza Uuid::empty() que excluye el filtro.

Filtrado a cuenta de terceros (RfcOnBehalf)

Filtra la solicitud por el RFC utilizado a cuenta de terceros. Para crear el objeto del filtro hay que usar RfcOnBehalf::create('XXX01010199A'). Si no se especifica utiliza RfcOnBehalf::empty() que excluye el filtro.

Filtrado por RFC contraparte (RfcMatch/RfcMatches)

Filtra la solicitud por el RFC en contraparte, es decir, que si la consulta es de emitidos entonces filtrar谩 donde el RFC especificado sea el receptor, si la consulta es de recibidos entonces filtrar谩 donde el RFC especificado sea el emisor.

Para crear el objeto del filtro hay que usar RfcMatch::create('XXX01010199A'). Si no se especifica utiliza una lista vac铆a RfcMatches::create() que excluye el filtro.

$rfcMatch = RfcMatch::create('XXX01010199A');
$parameters = $parameters->withRfcMatch();
var_dump($rfcMatch === $parameters->getRfcMatch()); // bool(true)

El servicio del SAT permite especificar hasta 5 RFC Receptores, al menos as铆 lo establecen en su documentaci贸n. Sin embargo, al tratarse de receptores, solo se puede utilizar en una consulta de documentos emitidos. En el caso de una consulta de documentos recibidos, solo se utilizar谩 el primero de la lista.

Por lo regular utilizar谩 solamente los m茅todos QueryParameter::getRfcMatch(): RfcMatch y QueryParameter::withRfcMatch(RfcMatch $rfcMatch).

Sin embargo, si fuera necesario especificar el listado de RFC, se puede realizar de la siguiente manera:

$parameters = $parameters->withRfcMatches(
    RfcMatches::create(
        RfcMatch::create('AAA010101000'),
        RfcMatch::create('AAA010101001'),
        RfcMatch::create('AAA010101002')
    )
);

O bien, utilizar una lista de RFC como cadenas de texto:

$parameters = $parameters->withRfcMatches(
    RfcMatches::createFromValues('AAA010101000', 'AAA010101001', 'AAA010101002')
);
Acerca de RfcMatches

Este objeto mantiene una lista de RfcMatches, pero con caracter铆sticas especiales:

  • Los objetos RfcMatch vac铆os o repetidos son ignorados, solo se mantienen valores no vac铆os 煤nicos.
  • El m茅todo RfcMatch::getFirst() devuelve siempre el primer elemento, si no existe entonces devuelve uno vac铆o.
  • La clase RfcMatch es iterable, se puede hacer foreach() sobre los elementos.
  • La clase RfcMatch es contable, se puede hacer count() sobre los elementos.

Tipo de servicio (ServiceType)

Esta es una propiedad que bien se podr铆a considerar interna y no necesitas especificarla en la consulta. Por defecto est谩 no definida y con el valor null. Se puede conocer si la propiedad ha sido definida con la propiedad hasServiceType(): bool y cambiar con withServiceType(ServiceType): self.

No se recomienda definir esta propiedad y dejar que el servicio establezca el valor correcto seg煤n a donde est茅 apuntando el servicio.

Cuando se ejecuta una consulta, el servicio (Service) autom谩ticamente define esta propiedad si es que no est谩 definida estableci茅ndole el mismo valor que est谩 definido en el objeto ServiceEndpoints. Si esta propiedad ya estaba definida, y su valor no es el mismo que el definido en el objeto ServiceEndpoints entonces se genera una LogicException.

Ejemplo de especificaci贸n de par谩metros

En el siguiente ejemplo, se crea una consulta sin par谩metros y posteriormente se van modificando. Los m茅todos no cambian la propiedad del objeto (no son set*), lo que hacen es crear una nueva instancia de la consulta con los nuevos valores (son with*).

Puede que los cambios del ejemplo no sean l贸gicos, es solo para ilustrar c贸mo se establecen los valores:

  • Un periodo espec铆fico de 2019-01-13 00:00:00 a 2019-01-13 23:59:59 (inclusive).
  • Sobre los documentos recibidos.
  • Solicitando los archivos XML.
  • Filtrando por documentos de tipo ingreso.
  • Filtrando por los que tengan el complemento de leyendas fiscales.
  • Filtrando por 煤nicamente documentos vigentes (excluye cancelados).
  • Filtrando por el RFC a cuenta de terceros XXX01010199A.
  • Filtrando por el RFC contraparte MAG041126GT8. Como se solicitan recibidos, entonces son los emidos por ese RFC.
  • Filtrando por el UUID 96623061-61fe-49de-b298-c7156476aa8b.
<?php

use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\ComplementoCfdi;
use PhpCfdi\SatWsDescargaMasiva\Shared\DateTimePeriod;
use PhpCfdi\SatWsDescargaMasiva\Shared\DocumentStatus;
use PhpCfdi\SatWsDescargaMasiva\Shared\DocumentType;
use PhpCfdi\SatWsDescargaMasiva\Shared\DownloadType;
use PhpCfdi\SatWsDescargaMasiva\Shared\RequestType;
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcMatch;
use PhpCfdi\SatWsDescargaMasiva\Shared\RfcOnBehalf;
use PhpCfdi\SatWsDescargaMasiva\Shared\Uuid;

$query = QueryParameters::create()
    ->withPeriod(DateTimePeriod::createFromValues('2019-01-13 00:00:00', '2019-01-13 23:59:59'))
    ->withDownloadType(DownloadType::received())
    ->withRequestType(RequestType::xml())
    ->withDocumentType(DocumentType::ingreso())
    ->withComplement(ComplementoCfdi::leyendasFiscales10())
    ->withDocumentStatus(DocumentStatus::active())
    ->withRfcOnBehalf(RfcOnBehalf::create('XXX01010199A'))
    ->withRfcMatch(RfcMatch::create('MAG041126GT8'))
    ->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
;

Ejemplo de consulta por UUID

En este caso se especifica solamente el UUID a consultar, en el ejemplo es 96623061-61fe-49de-b298-c7156476aa8b.

Nota: Todos los dem谩s argumentos de la consulta son ignorados.

<?php

use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\Shared\Uuid;

$query = QueryParameters::create()
    ->withUuid(Uuid::create('96623061-61fe-49de-b298-c7156476aa8b'))
;

Verificar una consulta

La verificaci贸n depende de que la consulta haya sido aceptada.

<?php

use PhpCfdi\SatWsDescargaMasiva\Service;

/**
 * @var Service $service Objeto de ayuda de consumo de servicio, previamente fabricado
 * @var string $requestId Identificador generado al presentar la consulta, previamente fabricado
 */

// consultar el servicio de verificaci贸n
$verify = $service->verify($requestId);

// revisar que el proceso de verificaci贸n fue correcto
if (! $verify->getStatus()->isAccepted()) {
    echo "Fallo al verificar la consulta {$requestId}: {$verify->getStatus()->getMessage()}";
    return;
}

// revisar que la consulta no haya sido rechazada
if (! $verify->getCodeRequest()->isAccepted()) {
    echo "La solicitud {$requestId} fue rechazada: {$verify->getCodeRequest()->getMessage()}", PHP_EOL;
    return;
}

// revisar el progreso de la generaci贸n de los paquetes
$statusRequest = $verify->getStatusRequest();
if ($statusRequest->isExpired() || $statusRequest->isFailure() || $statusRequest->isRejected()) {
    echo "La solicitud {$requestId} no se puede completar", PHP_EOL;
    return;
}
if ($statusRequest->isInProgress() || $statusRequest->isAccepted()) {
    echo "La solicitud {$requestId} se est谩 procesando", PHP_EOL;
    return;
}
if ($statusRequest->isFinished()) {
    echo "La solicitud {$requestId} est谩 lista", PHP_EOL;
}

echo "Se encontraron {$verify->countPackages()} paquetes", PHP_EOL;
foreach ($verify->getPackagesIds() as $packageId) {
    echo " > {$packageId}", PHP_EOL;
}

Descargar los paquetes de la consulta

La descarga de los paquetes depende de que la consulta haya sido correctamente verificada.

Una consulta genera un identificador de la solicitud, la verificaci贸n retorna uno o varios identificadores de paquetes. Necesitas descargar todos y cada uno de los paquetes para tener la informaci贸n completa de la consulta.

<?php

use PhpCfdi\SatWsDescargaMasiva\Service;

/**
 * @var Service $service Objeto de ayuda de consumo de servicio, previamente fabricado
 * @var string[] $packagesIds Listado de identificadores de paquetes generado en la verificaci贸n, previamente fabricado
 */

// consultar el servicio de verificaci贸n
foreach($packagesIds as $packageId) {
    $download = $service->download($packageId);
    if (! $download->getStatus()->isAccepted()) {
        echo "El paquete {$packageId} no se ha podido descargar: {$download->getStatus()->getMessage()}", PHP_EOL;
        continue;
    }
    $zipfile = "$packageId.zip";
    file_put_contents($zipfile, $download->getPackageContent());
    echo "El paquete {$packageId} se ha almacenado", PHP_EOL;
}

Lectura de paquetes

Los paquetes de Metadata y CFDI se pueden leer con las clases MetadataPackageReader y CfdiPackageReader respectivamente. Para fabricar los objetos, se pueden usar sus m茅todos createFromFile para crearlo a partir de un archivo existente o createFromContents para crearlo a partir del contenido del archivo en memoria.

Cada paquete puede contener uno o m谩s archivos internos. Cada paquete se lee individualmente.

Lectura de paquetes de tipo Metadata

<?php
use PhpCfdi\SatWsDescargaMasiva\PackageReader\Exceptions\OpenZipFileException;
use PhpCfdi\SatWsDescargaMasiva\PackageReader\MetadataPackageReader;

/**
 * @var string $zipfile Contiene la ruta al archivo de paquete de Metadata
 */

// abrir el archivo de Metadata
try {
    $metadataReader = MetadataPackageReader::createFromFile($zipfile);
} catch (OpenZipFileException $exception) {
    echo $exception->getMessage(), PHP_EOL;
    return;
}

// leer todos los registros de metadata dentro de todos los archivos del archivo ZIP
foreach ($metadataReader->metadata() as $uuid => $metadata) {
    echo $metadata->uuid, ': ', $metadata->fechaEmision, PHP_EOL;
}

Lectura de paquetes de tipo CFDI

<?php
use PhpCfdi\SatWsDescargaMasiva\PackageReader\Exceptions\OpenZipFileException;
use PhpCfdi\SatWsDescargaMasiva\PackageReader\CfdiPackageReader;

/**
 * @var string $zipfile Contiene la ruta al archivo de paquete de archivos ZIP
 */
try {
    $cfdiReader = CfdiPackageReader::createFromFile($zipfile);
} catch (OpenZipFileException $exception) {
    echo $exception->getMessage(), PHP_EOL;
    return;
}

// leer todos los CFDI dentro del archivo ZIP con el UUID como llave
foreach ($cfdiReader->cfdis() as $uuid => $content) {
    file_put_contents("cfdis/$uuid.xml", $content);
}

Informaci贸n t茅cnica

Acerca de la interfaz RequestBuilderInterface

El Servicio Web del SAT de Descarga Masiva requiere comunicaci贸n SOAP especial, con autenticaci贸n y mensajes firmados. Generar estos mensajes requiere de gran detalle porque si el mensaje contiene errores ser谩 inmediatamente rechazado.

La firma de estos mensajes es con la FIEL, as铆 que se puede utilizar la clase FielRequestBuilder que junto con la clase Fiel y la librer铆a phpcfdi/credentials hacen la combinaci贸n adecuada para firmar los mensajes.

Sin embargo, existen escenarios distribuidos donde lo mejor ser铆a contar con la creaci贸n de estos mensajes firmados en un lugar externo, de esta forma la FIEL (la llave privada y contrase帽a) no se necesita exponer al exterior. Para estos (u otros) escenarios, es posible crear una implementaci贸n de RequestBuilderInterface que contenga la l贸gica adecuada y entregue los mensajes firmados necesarios para la comunicaci贸n.

Acerca de la interfaz WebClientInterface

Para hacer esta librer铆a compatible con diferentes formas de comunicaci贸n se utiliza una interfaz de cliente HTTP. T煤 puedes crear tu implementaci贸n para poderla utilizar.

Si lo prefieres -como en el ejemplo de uso- podr铆as instalar Guzzle composer require guzzlehttp/guzzle y usar la clase GuzzleWebClient.

Recomendaci贸n de f谩brica del servicio

Te recomendamos configurar el framework de tu aplicaci贸n (Dependency Injection Container) o crear una clase que fabrique los objetos Service, RequestBuilder y WebClient, usando tus propias configuraciones de Fiel en caso de que tengas disponible el certificado, llave privada y contrase帽a.

Manejo de excepciones

Al trabajar con el lector de paquetes (PackageReader) o con la comunicaci贸n HTTP con el servidor web set SAT (WebClient), la librer铆a puede lanzar excepciones que puedes atrapar y analizar, ya sea en el momento de implementaci贸n o para personalizar los mensajes de error.

Acerca del Servicio Web de Descarga Masiva de CFDI y Retenciones

El servicio se compone de 4 partes:

  1. Autenticaci贸n: Esto se hace con tu FIEL y la librer铆a oculta la l贸gica de obtener y usar el Token.
  2. Solicitud: Presentar una solicitud incluyendo la fecha de inicio, fecha de fin, tipo de solicitud emitidas/recibidas y tipo de informaci贸n solicitada (cfdi o metadata).
  3. Verificaci贸n: pregunta al SAT si ya tiene disponible la solicitud.
  4. Descargar los paquetes emitidos por la solicitud.

Una forma burda de entenderlo es: imagina que el servicio del SAT se compone de tres ventanillas con tres personas diferentes atendiendo cada una de estas ventanillas.

  • En la primera vas y presentas una solicitud de informaci贸n. Te firman de recibido, pero eso no significa que tu informaci贸n est茅 lista, solo que han recibido tu solicitud.

  • En la segunda ventanilla preguntas por tu n煤mero de solicitud y te responden que a煤n no tienen lista la solicitud, regresas despu茅s y te dicen que a煤n no est谩 lista, hasta que finalmente te dicen que ya est谩 completada, y te piden pasar a otra ventanilla por las cajas con tu informaci贸n.

  • En la 煤ltima ventanilla llegas y pides cada una de las cajas, una a la vez, te las entregan y te las llevas. Si perdiste tu caja y regresaste varios d铆as despu茅s y pides la caja, puede que ya no est茅 disponible. Si le pides muchas veces una caja puede que te digan que dejes de estar pidiendo la misma caja y haces enojar al funcionario del SAT y no te la da m谩s.

  • Todo esto sucede con un m谩ximo de seguridad, cada vez que hablas con un funcionario te pide que le ense帽es tu permiso y si no lo tienes o ya est谩 vencido (duran apenas unos minutos) te mandan con la persona de seguridad para que le demuestres que eres t煤 y te extienda un nuevo permiso.

Informaci贸n oficial

Notas importantes del web service:

  • Podr谩s recuperar hasta 200 mil registros por petici贸n y hasta 1,000,000 en metadata.
  • No existe limitante en cuanto al n煤mero de solicitudes siempre que no se descargue en m谩s de dos ocasiones un XML.

Notas de uso

  • No se aplica la restricci贸n de la documentaci贸n oficial: que no se descargue en m谩s de dos ocasiones un XML.

Se ha encontrado que la regla relacionada con las descargas de tipo CFDI no se aplica en la forma como est谩 redactada. Sin embargo, se ha encontrado que la regla que s铆 aplica es: no solicitar en m谩s de 2 ocasiones el mismo periodo. Cuando esto ocurre, el proceso de solicitud devuelve el mensaje "5002: Se han agotado las solicitudes de por vida".

Recuerda que, si se cambia la fecha inicial o final en al menos un segundo ya se trata de otro periodo, por lo que si te encuentras en este problema podr铆as solucionarlo de esta forma.

En consultas del tipo Metadata no se aplica la limitante mencionada anteriormente, por ello es recomendable hacer las pruebas de implementaci贸n con este tipo de consulta.

  • Tiempo de respuesta entre la presentaci贸n de la consulta y su verificaci贸n exitosa.

No se ha podido encontrar una constante para suponer el tiempo que puede tardar una consulta en regresar un estado de verificaci贸n exitosa y que los paquetes est茅n listos para descargarse.

En nuestra experiencia, entre m谩s grande el periodo y m谩s consultas se presenten m谩s lenta es la respuesta, y puede ser desde minutos a horas. Por lo general es raro que excedan 24 horas. Sin embargo, varios usuarios han experimentado casos raros (posiblemente por problemas en el SAT) en donde las solicitudes han llegado a tardar hasta 72 horas para ser completadas.

Problemas conocidos

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.

Actualizaciones

Contribuciones

Las contribuciones son 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-ws-descarga-masiva library is copyright 漏 PhpCfdi and licensed for use under the MIT License (MIT). Please see LICENSE for more information.

More Repositories

1

cfdi-sat-scraper

PHP library to make web scraping to the SAT cfdi download page
PHP
54
star
2

credentials

Library to use eFirma (fiel) and CSD (sellos) from SAT
PHP
51
star
3

resources-sat-catalogs

Cat谩logos CFDI del SAT
36
star
4

cfditopdf

Create a generic PDF file from a CFDI 3.3 & 4.0 (CLI included)
PHP
34
star
5

cfdi-to-json

Herramienta para convertir archivos CFDI a JSON
PHP
25
star
6

sat-catalogos

Cat谩logos de SAT para CFDI 3.3, CFDI 4.0 y N贸mina 1.2 (spanish)
PHP
22
star
7

rfc

PHP library to deal with Mexican RFC
PHP
20
star
8

sat-catalogos-populate

Herramienta para crear y actualizar los cat谩logos de SAT/CFDI en una base de datos SQLite3
PHP
19
star
9

sat-estado-cfdi

Consulta el estado de un cfdi en el webservice del SAT
PHP
17
star
10

finkok

Librer铆a para conectar con la API de servicios de FINKOK
PHP
16
star
11

api-descarga-masiva

Aplicaci贸n API para consumir el Servicio Web de Descarga Masiva del SAT.
PHP
12
star
12

csf-scraper

Obtiene los datos fiscales actuales de una persona moral o f铆sica dado su RFC y CIFID
PHP
12
star
13

cfdi-cleaner

Herramienta para limpiar Comprobantes Fiscales Digitales 3.2, 3.3 y 4.0
PHP
12
star
14

resources-sat-xml

Recursos de archivos XSD y XSLT que el SAT en M茅xico ofrece para trabajar con CFDI.
XSLT
12
star
15

rfclinc

Listado de RFC Inscritos No Cancelados (php library and application)
PHP
10
star
16

ceutils

PHP library for Mexican SAT Electronic Accounting 1.3
PHP
8
star
17

image-captcha-resolver

Conectores para resolver captchas de im谩genes
PHP
7
star
18

sat-ns-registry

Registro de namespaces del SAT de facturaci贸n electr贸nica
PHP
7
star
19

xml-cancelacion

Genera documentos de cancelaci贸n de CFDI firmados (XMLSEC)
PHP
7
star
20

app-descarga-masiva

Quasar application for api-descarga-masiva
JavaScript
6
star
21

sat-estado-cfdi-soap

Consulta el estado de un CFDI en el webservice del SAT usando SOAP (sin WSDL)
PHP
6
star
22

www.phpcfdi.com

static website of https://www.phpcfdi.com
PHP
5
star
23

Timbrado

Conectarse a diferentes PAC para timbrar, obtener y cancelar CFDI
PHP
5
star
24

sat-estado-retenciones

Consulta el estado de un CFDI de Retenciones haciendo scrap del sitio del SAT
PHP
5
star
25

sat-estado-cfdi-http-psr

Consulta el estado de un CFDI en el webservice del SAT usando HTTP (PSR-17 y PSR-18)
PHP
4
star
26

cfdi-expresiones

Genera expresiones de CFDI 4.0, CFDI 3.3, CFDI 3.2, RET 1.0 y RET 2.0
PHP
3
star
27

resources-sat-efos

Recurso que contiene las listas del SAT de Empresas Facturadoras de Operaciones Simuladas (EFOS) de acuerdo a Art 69 y 69B
PHP
2
star
28

resources-sat-xml-generator

Programa PHP para generar los recursos desde los archivos XSD y XSLT del SAT para CFDI
PHP
2
star
29

resources-sat-efos-generator

Generador de las listas del SAT de Empresas Facturadoras de Operaciones Simuladas (EFOS) de acuerdo a Art 69 y 69B
1
star