Loading repository data…
Loading repository data…
TecnoFact / repository
SDK para integracion de servicio de timbrado en lenguaje de PHP.
SDK oficial de PHP para la integración con el servicio de Timbrado CFDI 4.0 de TecnoFact. Facilita la emisión, cancelación y consulta de facturas electrónicas cumpliendo con los requisitos del SAT mexicano.
json, openssl, curlcomposer require tecnofact/sdk-tecnofact
# Clonar el repositorio
git clone https://github.com/TecnoFact/SDK-Tecnofact-php.git
cd SDK-Tecnofact-php
# Construir imagen Docker
docker-compose build
# Iniciar entorno de desarrollo
docker-compose up sdk
# Construir imagen
docker-compose build
# Iniciar entorno interactivo
docker-compose up sdk
# Ejecutar tests
docker-compose run --rm sdk vendor/bin/phpunit
# Ejecutar PHPStan (análisis estático)
docker-compose run --rm sdk vendor/bin/phpstan analyse
# Ejecutar linter (estilo de código)
docker-compose run --rm sdk vendor/bin/php-cs-fixer fix --diff
# Ejecutar análisis completo (CI)
docker-compose run --rm sdk vendor/bin/phpstan analyse && docker-compose run --rm sdk vendor/bin/phpunit
Si prefieres usar Make:
make docker-build # Construir imagen
make docker-up # Iniciar entorno
make docker-test # Ejecutar tests
make docker-analyze # Ejecutar PHPStan
make docker-lint # Verificar estilo
make docker-ci # CI completo
<?php
require_once 'vendor/autoload.php';
use TecnoFact\Sdk\Config\Config;
use TecnoFact\Sdk\Enums\Environment;
// Configuración con valores por defecto
$config = new Config(
apiKey: 'tu-api-key',
apiSecret: 'tu-api-secret'
);
// Configuración completa
$config = new Config(
apiKey: 'tu-api-key',
apiSecret: 'tu-api-secret',
environment: Environment::SANDBOX, // o ENVIRONMENT_PRODUCTION
timeout: 30, // segundos
retries: 3 // reintentos automáticos
);
<?php
use TecnoFact\Sdk\Config\Config;
// Lee automáticamente de $_ENV o $_SERVER
$config = Config::fromEnvironment();
Variables requeridas:
TECN_FACT_API_KEY - Tu API KeyTECN_FACT_API_SECRET - Tu API SecretTECN_FACT_ENVIRONMENT - sandbox o production (opcional)# .env
TECN_FACT_API_KEY=tu-api-key
TECN_FACT_API_SECRET=tu-api-secret
TECN_FACT_ENVIRONMENT=sandbox
src/
├── Config/
│ └── Config.php # Configuración inmutable del SDK
├── Contracts/
│ └── HttpClientInterface.php # Interfaz para el cliente HTTP
├── Enums/
│ ├── Environment.php # Entornos (Sandbox/Production)
│ └── TipoComprobante.php # Tipos de CFDI
├── Exceptions/
│ ├── TecnoFactException.php # Excepción base
│ ├── AuthenticationException.php # Error de autenticación
│ ├── ValidationException.php # Error de validación
│ ├── TimbradoException.php # Error de timbrado
│ ├── CancelacionException.php # Error de cancelación
│ ├── NotFoundException.php # Recurso no encontrado
│ ├── RateLimitException.php # Límite de peticiones
│ └── ServerException.php # Error del servidor
├── Http/
│ └── HttpClient.php # Cliente HTTP con Guzzle
└── Models/
├── Emisor.php # Datos del emisor
├── Receptor.php # Datos del receptor
├── Concepto.php # Conceptos de factura
├── Cfdi4Request.php # Solicitud CFDI 4.0
├── CfdiRelacionados.php # CFDIs relacionados
├── Impuestos.php # Impuestos globales
├── ImpuestosConcepto.php # Impuestos por concepto
├── Traslado.php # Traslado de impuestos
├── TrasladoGlobal.php # Traslado global
├── Retencion.php # Retención de impuestos
├── RetencionGlobal.php # Retención global
├── CuentaPredial.php # Cuenta predial
├── InformacionAduanera.php # Información aduanera
└── Parte.php # Partes/componentes
<?php
require_once 'vendor/autoload.php';
use TecnoFact\Sdk\Config\Config;
use TecnoFact\Sdk\Enums\Environment;
$config = new Config(
apiKey: 'TU_API_KEY',
apiSecret: 'TU_API_SECRET',
environment: Environment::SANDBOX,
timeout: 30,
retries: 3
);
echo "Entorno: " . $config->getEnvironment()->label() . "\n";
echo "URL Base: " . $config->getBaseUrl() . "\n";
echo "Timeout: " . $config->getTimeout() . " segundos\n";
// Convertir a array
$data = $config->toArray();
print_r($data);
<?php
use TecnoFact\Sdk\Enums\Environment;
// Usar enum con autocompletado
$env = Environment::PRODUCTION;
if ($env === Environment::PRODUCTION) {
echo "Entorno de producción\n";
}
// Métodos del enum
echo $env->value; // 'production'
echo $env->isProduction(); // true
echo $env->isSandbox(); // false
echo $env->label(); // 'Producción'
<?php
use TecnoFact\Sdk\Models\Emisor;
$emisor = new Emisor(
rfc: 'XAXX010101000',
nombre: 'EMPRESA EMISORA SA DE CV',
regimenFiscal: '601',
cp: '06300'
);
echo $emisor->getRfc(); // XAXX010101000
echo $emisor->getNombre(); // EMPRESA EMISORA SA DE CV
print_r($emisor->toArray());
<?php
use TecnoFact\Sdk\Models\Receptor;
$receptor = new Receptor(
rfc: 'XAXX010101001',
nombre: 'CLIENTE RECEPTOR',
usoCfdi: 'G03',
domicilioFiscalReceptor: '06300',
regimenFiscalReceptor: '612'
);
<?php
use TecnoFact\Sdk\Models\Concepto;
use TecnoFact\Sdk\Models\ImpuestosConcepto;
use TecnoFact\Sdk\Models\Traslado;
$concepto = new Concepto(
claveProdServ: '01010101',
cantidad: 1,
claveUnidad: 'E48',
descripcion: 'Servicio de desarrollo de software',
valorUnitario: 10000.00,
importe: 10000.00,
objetoImp: '02', // Sí objeto de impuesto
impuestos: new ImpuestosConcepto(
traslados: [
new Traslado(
base: 10000.00,
impuesto: '002', // IVA
tipoFactor: 'Tasa',
tasaOCuota: '0.160000',
importe: 1600.00
)
]
)
);
El SDK lanza excepciones específicas para cada tipo de error:
| Excepción | Descripción | Código HTTP |
|---|---|---|
AuthenticationException | Credenciales inválidas | 401 |
ValidationException | Datos inválidos | 400 |
TimbradoException | Error de timbrado | 422 |
CancelacionException | Error de cancelación | 422 |
NotFoundException | Recurso no encontrado | 404 |
RateLimitException | Límite excedido | 429 |
ServerException | Error del servidor | 5xx |
<?php
use TecnoFact\Sdk\Config\Config;
use TecnoFact\Sdk\Exceptions\ValidationException;
use TecnoFact\Sdk\Exceptions\AuthenticationException;
use TecnoFact\Sdk\Exceptions\TecnoFactException;
try {
$config = new Config(
apiKey: 'test-api-key-1234567890',
apiSecret: 'test-api-secret-12345678901234567890'
);
// Tu lógica aquí
} catch (ValidationException $e) {
echo "Error de validación: " . $e->getMessage() . "\n";
print_r($e->getErrors());
} catch (AuthenticationException $e) {
echo "Error de autenticación: " . $e->getMessage() . "\n";
} catch (TecnoFactException $e) {
echo "Error del SDK: " . $e->getMessage() . "\n";
echo "Request ID: " . $e->getRequestId() . "\n";
}
# Con Docker
docker-compose run --rm sdk vendor/bin/phpunit
# O local (si tienes PHP 8.3)
composer install
vendor/bin/phpunit
PHPUnit 10.x by Sebastian Bergmann and contributors.
Runtime: PHP 8.3.x
Configuration: phpunit.xml
.......... 10 / 10 (100%)
Time: 00:00.XXX, Memory: 8.00 MB
OK (10 tests, 27 assertions)
# Con Docker
docker-compose run --rm sdk vendor/bin/phpstan analyse
# O local
vendor/bin/phpstan analyse --level=8
parameters:
level: 8
paths:
- src
- tests
ignoreErrors:
- '#Method .+::__construct\(\) has parameter .+ with no value type#'
Este proyecto utiliza Semantic Versioning y genera automáticamente versiones y changelog basado en Conventional Commits.
MAJOR.MINOR.PATCH
Los commits deben seguir el formato:
<tipo>(<alcance>): <descripción>
# Ejemplos:
feat: agregar soporte para CFDI 4.0 # MINOR (1.x.0)
fix: corregir validación de RFC # PATCH (1.0.x)
feat!: cambiar estructura de API # MAJOR (x