PHPackages                             aichadigital/lara-verifactu - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. aichadigital/lara-verifactu

ActiveLibrary[Payment Processing](/categories/payments)

aichadigital/lara-verifactu
===========================

Laravel package for AEAT Verifactu compliance with agnostic architecture

v1.0.0(1w ago)05211[1 issues](https://github.com/AichaDigital/lara-verifactu/issues)[1 PRs](https://github.com/AichaDigital/lara-verifactu/pulls)1MITPHPPHP ^8.3CI passing

Since Oct 12Pushed 5d agoCompare

[ Source](https://github.com/AichaDigital/lara-verifactu)[ Packagist](https://packagist.org/packages/aichadigital/lara-verifactu)[ Docs](https://github.com/aichadigital/lara-verifactu)[ RSS](/packages/aichadigital-lara-verifactu/feed)WikiDiscussions main Synced today

READMEChangelog (2)Dependencies (35)Versions (24)Used By (1)

Lara Verifactu
==============

[](#lara-verifactu)

[![Latest Version](https://camo.githubusercontent.com/b99e8cfd79122e1272ecac1c5b9ad388e90939e0d8a2102890a30e68c5f29912/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61696368616469676974616c2f6c6172612d7665726966616374752e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aichadigital/lara-verifactu)[![Total Downloads](https://camo.githubusercontent.com/9838e5a8496fc553c239d508d7c7c8a461ca60c203e238bef89af0858776262c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f61696368616469676974616c2f6c6172612d7665726966616374752e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aichadigital/lara-verifactu)[![Tests](https://camo.githubusercontent.com/f7fc12ef0a5f3f1d3fdaff91a3e882fba74ca5707e94afeb5842852b826696d8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f41696368614469676974616c2f6c6172612d7665726966616374752f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/AichaDigital/lara-verifactu/actions?query=workflow%3Arun-tests+branch%3Amain)[![Code Style](https://camo.githubusercontent.com/4dcf121f583e1639b36bb51cf6acc0ff3eb0600d27ba13002036280d2cc3930c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f41696368614469676974616c2f6c6172612d7665726966616374752f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/AichaDigital/lara-verifactu/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![PHPStan level 8](https://camo.githubusercontent.com/ee72f8a269650133b45ea2894a9006d60f67b5e3ec09114d4d78b850db8b4279/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230382d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://phpstan.org/)[![PHP Version](https://camo.githubusercontent.com/301d6588fb50563e647b2a040f68beb8ecb57d5b9237f8ffc6d2565a9d7da094/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f61696368616469676974616c2f6c6172612d7665726966616374752e7376673f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://packagist.org/packages/aichadigital/lara-verifactu)[![Laravel Version](https://camo.githubusercontent.com/18f881b50e044a91960c1023095094599e65c156497c42fffd139e2e14059fc7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31322e7825323025374325323031332e782d7265642e7376673f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)[![License](https://camo.githubusercontent.com/08c3f886ff6d40b3c7cf53d994fde3eee4baf2c070e4ff732c8392baae048287/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f61696368616469676974616c2f6c6172612d7665726966616374752e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aichadigital/lara-verifactu)

Laravel package for **VERI\*FACTU (AEAT) compliance** — Spain's invoicing records regulation (Real Decreto 1007/2023). It generates AEAT-conformant chained fingerprints (huella), validation QR codes and registration XML, and submits registration and cancellation records to the AEAT web service.

> **Status: 0.11.x — sandbox-validated beta.**
>
> Every artifact this package produces has been validated against the official AEAT specifications, and the full submission flow has been **accepted live by the AEAT external testing environment** (Pruebas Externas): real registration and cancellation records submitted with a representative certificate, answered `Correcto` with CSV, including AEAT-side validation of the chained fingerprint. Pending before 1.0: production hardening and high-volume testing.

Conformance
-----------

[](#conformance)

- **Fingerprint (huella)** per the official hash spec v0.1.2 — the three official AEAT test vectors are part of the test suite.
- **QR** per the official QR spec v0.4.7: cotejo URL with exactly `nif`, `numserie`, `fecha`, `importe`; error correction level M.
- **XML** validated against the official `SuministroLR.xsd` in CI; the official schemas and WSDL are bundled with the package (offline SOAP client, endpoint forced per environment and certificate type).
- **Endpoints** from the official WSDL port bindings: `sello` certificates use the `www10`/`prewww10` hosts; `ciudadano`/`representante` use `www1`/`prewww1`.

### Regulatory deadlines

[](#regulatory-deadlines)

The adaptation deadline for obligated taxpayers was extended to **2027** by [Real Decreto-ley 15/2025](https://www.boe.es/buscar/doc.php?id=BOE-A-2025-24446)(2 December 2025), which amended the final provision of RD 1007/2023:

- **July 29, 2025**: invoicing software / SIF must already meet the requirements.
- **January 1, 2027**: mandatory for Corporate Income Tax payers (was 2026).
- **July 1, 2027**: mandatory for the remaining obligated parties, including freelancers (was 2026).

Support matrix (v1.0 honest core)
---------------------------------

[](#support-matrix-v10-honest-core)

The package implements an **honest core**: it emits only what it can produce correctly and **rejects fail-loud** (a `ValidationException`) anything it cannot, rather than sending XSD-valid XML the AEAT would reject — or accept *con errores*(subsanable).

### Core — supported and emitted

[](#core--supported-and-emitted)

AreaSupported in the core`TipoFactura`F1, F2, F3, R1, R5`Impuesto`01 IVA, 02 IPSI, 03 IGIC`ClaveRegimen`01 (general regime)`CalificacionOperacion`S1; **N2** (no sujeta por reglas de localización — intra-EU B2B services)Recipient (`Destinatario`)Spanish `NIF`; **`IDOtro`** for a foreign counterpart (NIF-IVA 02 without `CodigoPais`; 04 / 06 with a non-ES `CodigoPais`)`OperacionExenta`E1, E4, E6 (E2/E3 only with IPSI; rule 1199)Recargo de equivalencia21% → 5,2 / 1,75 · 10% → 1,4 · 4% → 0,5Anulación`RegistroAnulacion` + `SinRegistroPrevio` / `RechazoPrevio` + `GeneradoPor` / `Generador`RectificativasR1 (`S`/`I`), F3 substitution of simplified invoicesCoherence guards (fail-loud)`ImporteTotal`/`CuotaTotal` (±10 €), per-line `CuotaRepercutida` (±10 €), `Macrodato` (≥ 100 M), F2 ≤ 3.000 €, date validity### Rejected fail-loud (post-1.0)

[](#rejected-fail-loud-post-10)

- `TipoFactura` R2 / R3 / R4 (Art. 80.3 / 80.4 / Resto)
- `Impuesto` 05 (Otros)
- `ClaveRegimen` ≠ 01 (special regimes)
- `CalificacionOperacion` S2 / N1 (inversión del sujeto pasivo / no sujeta art. 7, 14)
- `OperacionExenta` E2 / E3 with IVA or IGIC, and E5 (intra-community supply of goods)
- `Generador` identified by `IDOtro` in the anulación block (the recipient `IDOtro` is now core)
- Recipient `IDType` 07 (No Censado — Spanish non-censused, a domestic edge)
- Date-windowed surcharge rates (5 %, 0 %, 2 %, 7,5 % — rules 1165-1170 / 1277)

### Out of scope

[](#out-of-scope)

- **TicketBAI** (Basque Country) — a different system.
- **SII del IGIC** (Canary libros registro, remitted to the ATC) — see the note.

### Notes

[](#notes)

- **IGIC**: Veri*Factu (RD 1007/2023) applies to Canary issuers, with references to IVA read as IGIC; IGIC (`Impuesto=03`) is emitted in the Veri*Factu flow to the **AEAT** like any other tax. The separate **SII del IGIC** — the Canary libros-registro reporting to the **Agencia Tributaria Canaria (ATC)** — is a different obligation and is out of scope here. ([AEAT ámbitos de aplicación](https://sede.agenciatributaria.gob.es/Sede/iva/sistemas-informaticos-facturacion-verifactu/preguntas-frecuentes/cuestiones-generales-ambitos-aplicacion.html), [BOE RD 1007/2023](https://www.boe.es/buscar/act.php?id=BOE-A-2023-24840), [SII del IGIC — ATC](https://www3.gobiernodecanarias.org/tributos/atc/en/w/suministro-inmediato-de-informacion-del-igic-sii-1))
- **XSD vs official lists**: the XSD `OperacionExentaType` accepts E7/E8, but AEAT list L10 documents only E1-E6 (the enum models E1-E6). The XSD admits `ClaveRegimen` 21 (IGIC simplified), absent from list L8A. Neither is emitted by the core.

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 12.x or 13.x
- Extensions: `soap`, `openssl`, `dom`, `libxml`
- A digital certificate (PKCS#12) for AEAT submission: `representante`, `sello` or `ciudadano`

Installation
------------

[](#installation)

```
composer require aichadigital/lara-verifactu

php artisan verifactu:install
```

Configure your environment:

```
# Environment: production | sandbox (AEAT Pruebas Externas)
VERIFACTU_ENVIRONMENT=sandbox

# PKCS#12 certificate (keep it OUTSIDE the project tree)
VERIFACTU_CERT_PATH=/secure/path/company-representative.p12
VERIFACTU_CERT_PASSWORD=secret
VERIFACTU_CERT_TYPE=representante   # ciudadano | representante | sello

# Issuer (obligado a expedir factura) — must match the AEAT census
VERIFACTU_COMPANY_TAX_ID=B00000000
VERIFACTU_COMPANY_NAME="YOUR COMPANY SL"
```

> **Note:** macOS Keychain exports `.p12` files with legacy RC2-40 encryption that OpenSSL 3.x rejects (misleadingly reported as a wrong password). Re-package with modern encryption:
>
> ```
> /usr/bin/openssl pkcs12 -in legacy.p12 -nodes -out tmp.pem \
>   && openssl pkcs12 -export -in tmp.pem -out modern.p12 && rm tmp.pem
> ```

Verify your setup against AEAT:

```
php artisan verifactu:test-connection             # full check incl. mutual-TLS probe
php artisan verifactu:test-connection --cert-info # certificate details only
```

Usage
-----

[](#usage)

### Facade

[](#facade)

```
use AichaDigital\LaraVerifactu\Facades\Verifactu;

// Register an invoice (creates the chained registry record, the QR and
// the XML; submits to AEAT unless told otherwise)
$registry = Verifactu::register($invoice);
$registry = Verifactu::register($invoice, submitToAeat: false);

// Cancel an invoice (RegistroAnulacion, chained like any other record)
$registry = Verifactu::cancel($invoice);

// Latest registry of an invoice (null if never registered)
$registry = Verifactu::status($invoice);

// AEAT cotejo QR for an invoice (SVG or PNG per config)
$qr = Verifactu::qr($invoice);

// Verify the integrity of the whole fingerprint chain
['valid' => $valid, 'errors' => $errors] = Verifactu::validateChain();
```

### Testing your integration

[](#testing-your-integration)

```
use AichaDigital\LaraVerifactu\Facades\Verifactu;

Verifactu::fake();

// ... code under test ...

Verifactu::assertRegistered($invoice);
Verifactu::assertCancelled($invoice);
Verifactu::assertNotSent($otherInvoice);
```

### Artisan commands

[](#artisan-commands)

```
php artisan verifactu:test-connection   # certificate + mutual-TLS check
php artisan verifactu:register {id}     # register an invoice
php artisan verifactu:retry-failed      # retry failed submissions
php artisan verifactu:verify-blockchain # verify the fingerprint chain
php artisan verifactu:status            # system status
```

### Custom invoice models

[](#custom-invoice-models)

Any model implementing `AichaDigital\LaraVerifactu\Contracts\InvoiceContract` can be registered — the bundled `Invoice` model (native mode) is optional. See `config/verifactu.php` for the model bindings.

Architecture notes
------------------

[](#architecture-notes)

- **VERI\*FACTU mode does not sign records**: the chained fingerprint replaces the signature. XAdES signing is available behind `verifactu.signing.enabled` (default `false`) for the non-Verifactu modality.
- Cancellations are **links of the fingerprint chain** in their own right (`registry_type`), keeping the chain verifiable end to end.
- Submissions are sequential by design (dedicated `fiscal_verification`queue with a unique lock) to preserve chain ordering.
- `AceptadoConErrores` responses map to success: AEAT registered the record, so it must not be resubmitted; the error details are persisted.
- **Rectifications**: `TipoRectificativa` derives from `getRectificationType()` (`S` substitution / `I` incremental). A substitution (`S`) requires the substituted amounts via `getRectificationAmounts()` (native mode reads `metadata['rectification_amounts']`), emitted as `ImporteRectificacion`; a missing block raises `ValidationException`.
- **Substitution of simplified invoices (`F3`)**: invoice type `InvoiceTypeEnum::SUBSTITUTE` emits `FacturasSustituidas` (the substituted simplified invoices via `getSubstitutedInvoices()`; native mode reads `metadata['substituted_invoices']`). An F3 requires a recipient (AEAT rule 1189) and at least one substituted invoice, otherwise it raises `ValidationException`.

Sandbox validation
------------------

[](#sandbox-validation)

The suite includes `tests/Feature/RealSandboxSubmissionTest.php`, which performs a **real registration and cancellation against AEAT Pruebas Externas**. It is skipped automatically unless a real certificate is configured through the `VERIFACTU_*` environment variables — CI never contacts AEAT.

```
set -a; source .env; set +a
vendor/bin/pest tests/Feature/RealSandboxSubmissionTest.php
```

Testing &amp; quality
---------------------

[](#testing--quality)

```
composer test          # Pest
composer phpstan       # PHPStan level 8 (no baseline debt on new code)
composer format        # Laravel Pint
composer quality       # all of the above + coverage
```

### Running the suite (MariaDB / MySQL)

[](#running-the-suite-mariadb--mysql)

The suite runs against **MariaDB/MySQL** (the deployment engines), not SQLite, so it surfaces schema and engine behavior SQLite silently masks. One-time local setup (this repo's dev box runs MariaDB on port 3307):

```
mariadb -uroot --port=3307 --protocol=tcp
