krato/verifactu-laravel
Composer 安装命令:
composer require krato/verifactu-laravel
包简介
SDK Laravel para cumplimiento Verifactu. Minimal, desacoplado, production-ready.
README 文档
README
Actualmente en Desarrollo - No usar todavía
SDK Laravel para cumplimiento Verifactu. Minimal. Desacoplado. Production-ready.
DX inspirada en Stripe PHP SDK: configuración mínima, contratos claros, funciona desde el primer composer require.
// Enviar una factura a AEAT en 3 líneas $invoice = new InvoiceRecord($tuFactura); $result = Verifactu::submit($invoice); // → SubmissionResult { status: Accepted, csv: "CSV-001" }
Lo que hace
- Registros de facturación Verifactu (alta F1/F2)
- Hash SHA-256 encadenado según especificación AEAT
- Envío síncrono y asíncrono (queues) a AEAT
- Autenticación por certificado digital (PKCS#12)
- Persistencia de requests/responses y cadena de hashes
- Multi-tenant con
forTenant() - Testing helpers completos
Lo que NO hace (deliberadamente)
- NO genera facturas — solo registros de facturación Verifactu
- NO tiene UI/dashboard — backend puro
- NO impone modelos Eloquent — solo contratos que tú implementas
- NO almacena datos de facturas — solo hashes, envíos y respuestas AEAT
Requisitos
- PHP 8.1+
- Laravel 10, 11 o 12
- Extensiones:
curl,dom,openssl - Certificado digital (.p12/.pfx) para envíos a AEAT
Instalación
composer require krato/verifactu-laravel
php artisan verifactu:install
Esto publica la configuración, las migraciones y ejecuta las migraciones.
Añade a tu .env:
VERIFACTU_ENV=testing VERIFACTU_SIF_NAME="Tu Software" VERIFACTU_SIF_NIF=B12345678 VERIFACTU_SIF_VERSION=1.0.0 VERIFACTU_CERT_PATH=/path/to/certificate.p12 VERIFACTU_CERT_PASSWORD=tu-password
Uso rápido
1. Implementa el contrato InvoiceRecord
El paquete no depende de tus modelos. Tú implementas el contrato:
use Krato\Verifactu\Contracts\InvoiceRecord; use Krato\Verifactu\DTOs\InvoiceIdentifier; use Krato\Verifactu\DTOs\Issuer; use Krato\Verifactu\DTOs\Recipient; use Krato\Verifactu\DTOs\TaxBreakdown; use Krato\Verifactu\Enums\InvoiceType; use Krato\Verifactu\Enums\TaxRegime; use Krato\Verifactu\Enums\TaxType; class MyInvoiceRecord implements InvoiceRecord { public function __construct(private Invoice $invoice) {} public function getIdentifier(): InvoiceIdentifier { return new InvoiceIdentifier( series: $this->invoice->series, number: $this->invoice->number, issueDate: $this->invoice->issue_date, ); } public function getIssuer(): Issuer { return new Issuer( nif: config('verifactu.sif.nif'), name: config('verifactu.sif.name'), ); } public function getRecipient(): ?Recipient { return new Recipient( nif: $this->invoice->customer->nif, name: $this->invoice->customer->name, ); } public function getInvoiceType(): InvoiceType { return InvoiceType::F1; } public function getDescription(): string { return $this->invoice->description; } public function getTaxBreakdowns(): array { return [ new TaxBreakdown( taxType: TaxType::IVA, taxRegime: TaxRegime::General, taxBase: 1000.00, taxRate: 21.00, taxAmount: 210.00, ), ]; } public function getTotalAmount(): float { return $this->invoice->total; } public function getIssueDate(): \DateTimeInterface { return $this->invoice->issue_date; } }
2. Envía a AEAT
use Krato\Verifactu\Facades\Verifactu; // Síncrono $result = Verifactu::submit(new MyInvoiceRecord($invoice)); if ($result->isAccepted()) { // $result->csv contiene el CSV de AEAT } // Asíncrono (via queue) Verifactu::dispatch(new MyInvoiceRecord($invoice));
API
Verifactu::submit($invoice)
Envía un registro de facturación a AEAT de forma síncrona. Devuelve SubmissionResult.
$result = Verifactu::submit($invoice); $result->status; // SubmissionStatus enum $result->csv; // string|null — CSV de AEAT $result->xmlResponse; // string|null — XML completo de respuesta $result->errors; // SubmissionError[] — errores si los hay $result->isAccepted(); // bool $result->isRejected(); // bool
Verifactu::dispatch($invoice)
Envía de forma asíncrona vía queue. Usa la configuración de verifactu.queue y verifactu.retry.
Verifactu::dispatch($invoice);
Verifactu::forTenant($nif)
Para aplicaciones multi-tenant. Devuelve una instancia configurada para ese NIF.
Verifactu::forTenant('B12345678')->submit($invoice); Verifactu::forTenant('A87654321')->dispatch($invoice);
Requiere implementar CertificateResolver para resolver el certificado por NIF:
use Krato\Verifactu\Contracts\CertificateResolver; use Krato\Verifactu\DTOs\CertificateCredentials; class MyCertificateResolver implements CertificateResolver { public function resolve(string $nif): CertificateCredentials { $tenant = Tenant::where('nif', $nif)->firstOrFail(); return new CertificateCredentials( path: $tenant->certificate_path, password: $tenant->certificate_password, ); } } // En un ServiceProvider: $this->app->bind(CertificateResolver::class, MyCertificateResolver::class);
Testing
El paquete incluye helpers para testing sin enviar nada a AEAT:
use Krato\Verifactu\Facades\Verifactu; use Krato\Verifactu\Testing\InvoiceRecordFactory; it('submits invoice to AEAT', function () { // Activa el modo fake $fake = Verifactu::fake(); // Envía con la factory incluida $invoice = InvoiceRecordFactory::make() ->withIdentifier('FA', '001') ->withIssuer('B12345678', 'Mi Empresa S.L.') ->withTotalAmount(1210.00); Verifactu::submit($invoice); // Assertions $fake->assertSubmitted('FA-001'); $fake->assertSubmittedCount(1); });
InvoiceRecordFactory
Factory fluida para crear facturas de test:
$invoice = InvoiceRecordFactory::make() ->withIdentifier('FA', '001', new DateTime('2027-01-15')) ->withIssuer('B12345678', 'Mi Empresa S.L.') ->withRecipient('A87654321', 'Cliente S.A.') ->withInvoiceType(InvoiceType::F2) ->withDescription('Servicios de consultoría') ->withTotalAmount(1210.00) ->withTaxBreakdowns([ new TaxBreakdown(TaxType::IVA, TaxRegime::General, 1000.00, 21.00, 210.00), ]) ->withIssueDate(new DateTime('2027-01-15'));
FakeTransport
$fake = Verifactu::fake(); // Assertions disponibles $fake->assertSubmitted('FA-001'); $fake->assertSubmittedCount(2); $fake->assertNothingSubmitted(); $fake->submissions(); // array de envíos registrados $fake->reset(); // Respuesta personalizada $fake->respondWith($customXmlResponse);
FakeHashChainStore
Para tests unitarios de la cadena de hashes:
use Krato\Verifactu\Testing\FakeHashChainStore; $store = new FakeHashChainStore; $store->getLastHash('B12345678', 'FA'); // null (cadena vacía) $store->append('B12345678', 'FA', $link); $store->getChain('B12345678', 'FA'); // [HashChainLink]
Configuración
Publica el fichero de configuración:
php artisan vendor:publish --tag=verifactu-config
Entorno
// config/verifactu.php 'environment' => env('VERIFACTU_ENV', 'testing'), // 'production' o 'testing'
testing: sandbox AEAT (prewww1.aeat.es)production: producción AEAT (www1.agenciatributaria.gob.es)
Software de facturación (SIF)
'sif' => [ 'name' => env('VERIFACTU_SIF_NAME', 'Mi Software'), 'nif' => env('VERIFACTU_SIF_NIF'), 'version' => env('VERIFACTU_SIF_VERSION', '1.0.0'), 'id' => env('VERIFACTU_SIF_ID'), ],
Certificado
'certificate' => [ 'path' => env('VERIFACTU_CERT_PATH'), // Ruta al .p12/.pfx 'password' => env('VERIFACTU_CERT_PASSWORD'), ],
Colas
'queue' => [ 'enabled' => env('VERIFACTU_QUEUE_ENABLED', true), 'connection' => env('VERIFACTU_QUEUE_CONNECTION', 'default'), 'queue' => env('VERIFACTU_QUEUE_NAME', 'verifactu'), ],
Reintentos
'retry' => [ 'max_attempts' => env('VERIFACTU_RETRY_MAX', 3), 'backoff' => [60, 300, 900], // segundos entre reintentos ],
Stores personalizados
'bindings' => [ 'hash_chain_store' => DatabaseHashChainStore::class, // o FileHashChainStore::class 'submission_store' => DatabaseSubmissionStore::class, ],
Puedes implementar tus propios stores implementando HashChainStore y SubmissionStore.
Tipos de factura
| Enum | Valor | Descripción |
|---|---|---|
InvoiceType::F1 |
F1 |
Factura completa (art. 6, 7.2 y 7.3 del RD 1619/2012) |
InvoiceType::F2 |
F2 |
Factura simplificada (art. 6.1.d y 7.1 del RD 1619/2012) |
Tipos de impuesto
| Enum | Valor | Descripción |
|---|---|---|
TaxType::IVA |
01 |
Impuesto sobre el Valor Añadido |
TaxType::IGIC |
02 |
Impuesto General Indirecto Canario |
TaxType::IPSI |
03 |
Impuesto sobre la Producción, Servicios e Importación |
Regímenes fiscales
| Enum | Valor | Descripción |
|---|---|---|
TaxRegime::General |
01 |
Régimen general |
TaxRegime::Export |
02 |
Exportación |
TaxRegime::SpecialGoods |
03 |
Bienes usados |
TaxRegime::InvestmentGold |
04 |
Oro de inversión |
TaxRegime::TravelAgencies |
05 |
Agencias de viaje |
TaxRegime::EntityGroups |
06 |
Grupos de entidades en IVA |
TaxRegime::CashBasis |
07 |
Criterio de caja |
TaxRegime::SimplifiedRegime |
11 |
Recargo de equivalencia |
TaxRegime::EqualizationCharge |
12 |
Régimen simplificado |
Arquitectura
src/
├── Contracts/ ← Interfaces que tú implementas
│ ├── InvoiceRecord
│ ├── CertificateResolver
│ ├── HashChainStore
│ └── SubmissionStore
├── DTOs/ ← Value objects inmutables
├── Enums/ ← InvoiceType, TaxType, TaxRegime, etc.
├── Hash/ ← SHA-256 hash chaining (spec AEAT)
├── Xml/ ← XML builder, SOAP envelope, response parser
├── Transport/ ← cURL client, endpoints, certificados
├── Support/ ← Implementaciones por defecto (DB, ficheros)
├── Testing/ ← FakeTransport, InvoiceRecordFactory
├── Jobs/ ← SubmitInvoiceRecord (async)
├── Commands/ ← verifactu:install
├── Facades/ ← Verifactu
├── VerifactuManager ← Orquestador principal
└── VerifactuServiceProvider
Flujo de envío
Tu app → Verifactu::submit($invoice)
1. ChainManager genera hash SHA-256 encadenado
2. RecordBuilder genera XML del registro
3. XsdValidator valida el XML
4. SubmissionEnvelope envuelve en SOAP
5. SubmissionStore guarda el request (ANTES de enviar)
6. SoapClient envía a AEAT (HTTPS + certificado)
7. ResponseParser parsea la respuesta
8. SubmissionStore guarda la respuesta
9. HashChainStore persiste el hash (solo si aceptada)
→ SubmissionResult devuelto
Roadmap
v0.1 — Core de envío (actual)
Alta de facturas (F1, F2), hash chaining, envío AEAT, persistencia de respuestas, async con queues, testing helpers.
v0.2 — Casos fiscales
Rectificativas (R1-R5), anulaciones, QR, eventos Laravel, retry automático.
v0.3 — Consultas y auditoría
Query API contra AEAT, auditoría cruzada, comandos operativos, exportación.
v1.0 — Estable
Cuando haya 10+ empresas en producción y 4 semanas sin bugs críticos.
Testing del paquete
composer test
Changelog
Ver CHANGELOG.
Licencia
MIT. Ver LICENSE.
krato/verifactu-laravel 适用场景与选型建议
krato/verifactu-laravel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 04 月 05 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「tax」 「laravel」 「spain」 「fiscal」 「facturacion」 「verifactu」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 krato/verifactu-laravel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 krato/verifactu-laravel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 krato/verifactu-laravel 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
API client for validating Tax Identification Number.
Validate the format of EU vat numbers.
Module allowing creation of tax rates and categories in the CMS via SiteConfig
Validation library for some Spanish codes.
Australian Tax Rules for OroCommerce
Custom Post Type UI Plugin for Wordpress found at https://wordpress.org/plugins/custom-post-type-ui/
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 33
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-04-05