georgesks/facter-sdk-php
Composer 安装命令:
composer require georgesks/facter-sdk-php
包简介
API pública para timbrar **CFDI 4.0** usando la infraestructura de Facter. **Modelo comercial:** un **cliente principal** (plan PREPAGO) compra timbres; sus **emisores** (cada uno un tenant con su propio RFC y CSD) consumen del saldo del principal. El contrato de entrada es el **JSON canónico CFDI
README 文档
README
SDK oficial en PHP para el API Externo de Facter: timbra CFDI 4.0 (Ingreso, Egreso y Pagos 2.0), administra emisores, consulta tu saldo de timbres y recibe webhooks — todo con la infraestructura de timbrado de Facter.
📚 Documentación interactiva del API: https://v2.facter.com.mx/developers
El SDK se genera desde la especificación OpenAPI oficial. No contiene lógica de negocio ni secretos: es un cliente HTTP tipado sobre el contrato público.
Instalación
composer require georgesks/facter-sdk-php
Requisitos: PHP 7.4+ u 8.x, extensiones ext-json y ext-curl. Guzzle se
instala como dependencia.
Ambientes
El ambiente es el host. Una API key de Demo solo funciona contra
demo.facter.com.mx; una de Producción solo contrav2.facter.com.mx. No son intercambiables. Empieza siempre en Demo (timbra contra el sandbox del SAT, sin cobro real).
| Ambiente | Host | Cobro |
|---|---|---|
Environment::DEMO |
demo.facter.com.mx |
No (sandbox) |
Environment::LIVE |
v2.facter.com.mx |
Sí (consume timbres) |
Inicio rápido
<?php require 'vendor/autoload.php'; use Facter\Sdk\Configuration; use Facter\Sdk\Environment; use Facter\Sdk\Api\CFDIsApi; use Facter\Sdk\Model\StampRequest; use Facter\Sdk\Idempotency; use GuzzleHttp\Client; // 1. Configura tu key y el ambiente (empieza en DEMO). $config = Configuration::getDefaultConfiguration() ->setAccessToken(getenv('FACTER_API_KEY')) // fct_live_xxx ->setHost(Environment::baseUrl(Environment::DEMO)); $cfdis = new CFDIsApi(new Client(), $config); // 2. Arma el comprobante (JSON canónico CFDI 4.0). $req = new StampRequest([ 'emisor_rfc' => 'EKU9003173C9', 'external_ref'=> 'FACTURA-2026-00042', // tu folio interno (opcional) 'cfdi' => [ /* ...comprobante CFDI 4.0... */ ], ]); // 3. Timbra. La clave de idempotencia evita doble cobro ante reintentos. $idempotencyKey = Idempotency::newKey(); try { $resp = $cfdis->stampCfdi($idempotencyKey, $req); echo "Timbrado UUID: " . $resp->getData()->getUuid() . PHP_EOL; } catch (\Facter\Sdk\ApiException $e) { $error = json_decode($e->getResponseBody(), true); fwrite(STDERR, "Error {$e->getCode()}: {$error['error']['code']}\n"); }
La estructura completa del
cfdi(el JSON canónico CFDI 4.0) está documentada, con ejemplos verificados, en el portal: https://v2.facter.com.mx/developers.
Idempotencia (timbrar = dinero)
Timbrar consume un timbre. El API exige Idempotency-Key en los mutadores para
garantizar consumo exactamente una vez. El SDK te da claves seguras:
use Facter\Sdk\Idempotency; $key = Idempotency::newKey(); // UUID v4 aleatorio $key = Idempotency::fromReference('FACTURA-2026-42'); // determinista por folio
Regla: una clave por intento lógico. Si reintentas el mismo CFDI tras un timeout, reusa la misma clave — el API hace replay de la respuesta original en vez de timbrar otra vez.
Reintentos automáticos (respetan Retry-After)
Monta el middleware incluido para reintentar de forma segura 429 RATE_LIMITED,
409 IDEMPOTENCY_IN_FLIGHT y errores de red, respetando el header Retry-After:
use Facter\Sdk\Http\RetryMiddleware; use GuzzleHttp\HandlerStack; use GuzzleHttp\Client; $stack = HandlerStack::create(); $stack->push(RetryMiddleware::create()); // 3 reintentos por default $cfdis = new CFDIsApi(new Client(['handler' => $stack]), $config);
Nunca reintenta errores de negocio (402 sin saldo, 422 validación) — reintentar no cambiaría el resultado.
Validar sin timbrar (dry-run)
Verifica estructura, aritmética y catálogos SAT sin consumir timbre ni requerir idempotencia:
$resultado = $cfdis->validateCfdi($req);
Webhooks: verifica la firma
Facter firma cada webhook con HMAC-SHA256. Siempre verifica antes de confiar en el payload:
use Facter\Sdk\Webhook; $raw = file_get_contents('php://input'); $sigHdr = $_SERVER['HTTP_X_FACTER_SIGNATURE'] ?? ''; if (!Webhook::verifySignature($raw, $sigHdr, getenv('FACTER_WEBHOOK_SECRET'))) { http_response_code(401); exit; } $evento = json_decode($raw, true); // cfdi.timbrado, cfdi.cancelado, ...
Manejo de errores
Toda respuesta de error sigue el envoltorio estándar del API. Las excepciones son
Facter\Sdk\ApiException:
try { $cfdis->stampCfdi($idempotencyKey, $req); } catch (\Facter\Sdk\ApiException $e) { $body = json_decode($e->getResponseBody(), true); // $e->getCode() → HTTP status (402, 422, 429, ...) // $body['error']['code'] → código de negocio (NO_STAMPS_AVAILABLE, ...) // $body['error']['docs'] → enlace a la doc del error }
Operaciones disponibles
| Recurso | Clase | Operaciones |
|---|---|---|
| CFDIs | CFDIsApi |
Timbrar, validar, listar, consultar, XML, PDF |
| Cancelaciones | CancelacionesApi |
Solicitar y consultar cancelación SAT |
| Emisores | EmisoresApi |
Alta, listar, detalle, subir CSD |
| Timbres | TimbresApi |
Saldo del pool, reporte de consumo |
| Webhooks | WebhooksApi |
Consultar y configurar |
Referencia método por método en docs/ y en el portal
https://v2.facter.com.mx/developers.
Versionado y soporte
- SemVer. Cada release acompaña un cambio del contrato del API; el changelog de releases es la referencia de cambios.
- Soporte: portal de desarrolladores · issues de este repositorio.
Licencia
MIT.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-25