Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Eseperio/verifactu-php/llms.txt

Use this file to discover all available pages before exploring further.

The Verifactu class is the primary entry point for all interactions with Spain’s AEAT VERI*FACTU system. Every method is static — no instantiation is required. Call Verifactu::config() once during application bootstrap, then use the operation methods wherever you need them.
use eseperio\verifactu\Verifactu;

Constants

Environment constants

ConstantValueDescription
Verifactu::ENVIRONMENT_PRODUCTION'production'Live AEAT production environment
Verifactu::ENVIRONMENT_SANDBOX'sandbox'Homologation / test environment (pre-production)

Certificate type constants

ConstantValueDescription
Verifactu::TYPE_CERTIFICATE'certificate'Standard personal or company certificate
Verifactu::TYPE_SEAL'seal'Electronic seal certificate (sello electrónico)

SOAP endpoint URL constants

ConstantValue
Verifactu::URL_PRODUCTIONhttps://www1.agenciatributaria.gob.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP
Verifactu::URL_PRODUCTION_SEALhttps://www10.agenciatributaria.gob.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP
Verifactu::URL_TESThttps://prewww1.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP
Verifactu::URL_TEST_SEALhttps://prewww10.aeat.es/wlpl/TIKE-CONT/ws/SistemaFacturacion/VerifactuSOAP

QR verification URL constants

ConstantValue
Verifactu::QR_VERIFICATION_URL_PRODUCTIONhttps://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR
Verifactu::QR_VERIFICATION_URL_TESThttps://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR
The correct SOAP endpoint and QR URL are selected automatically by config() based on the environment and certificate type you provide — you never need to reference the URL constants directly in normal usage.

Methods

config()

Initialises the library with your certificate and target environment. Must be called once before any other method. Call it during application bootstrap (e.g. in a service provider or bootstrap file).
Verifactu::config(
    certPath: '/path/to/certificate.p12',
    certPassword: 'secret',
    certType: Verifactu::TYPE_CERTIFICATE,
    environment: Verifactu::ENVIRONMENT_SANDBOX
);
certPath
string
required
Absolute filesystem path to the PKCS#12 (.p12 / .pfx) certificate file issued by a recognised Spanish certification authority (e.g. FNMT).
certPassword
string
required
Password that protects the certificate file.
certType
string
required
Type of certificate. Use Verifactu::TYPE_CERTIFICATE for a personal/company certificate or Verifactu::TYPE_SEAL for an electronic seal. The value determines which AEAT SOAP endpoint is selected.
environment
string
default:"Verifactu::ENVIRONMENT_PRODUCTION"
Target environment. Use Verifactu::ENVIRONMENT_SANDBOX for development and testing against the AEAT homologation platform, or Verifactu::ENVIRONMENT_PRODUCTION for live submissions. Defaults to ENVIRONMENT_PRODUCTION.
Throws: \InvalidArgumentException if an unrecognised value is passed to $environment.

registerInvoice()

Submits a new invoice record (Alta / RegistroAlta) to AEAT via SOAP.
use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceSubmission;

$invoice = new InvoiceSubmission();
// ... populate the invoice ...

$response = Verifactu::registerInvoice($invoice);

if ($response->submissionStatus === 'Correcto') {
    echo 'Accepted. CSV: ' . $response->csv;
} else {
    print_r($response->getErrors());
}
invoice
InvoiceSubmission
required
A fully populated and valid InvoiceSubmission instance. Call $invoice->validate() before submitting to catch any model-level errors early.
return
InvoiceResponse
An InvoiceResponse object containing the AEAT response. Check submissionStatus against InvoiceResponse::STATUS_OK ('Correcto') to determine success. The csv property holds the AEAT-generated Secure Verification Code when accepted.
Throws:
  • \DOMException — if the internal XML document cannot be constructed.
  • \SoapFault — if the SOAP call to AEAT fails (network error, invalid credentials, endpoint unavailable, etc.).

cancelInvoice()

Sends a cancellation record (Anulación / RegistroAnulacion) to AEAT to void a previously registered invoice.
use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceCancellation;

$cancellation = new InvoiceCancellation();
// ... populate the cancellation ...

$response = Verifactu::cancelInvoice($cancellation);

if ($response->submissionStatus === 'Correcto') {
    echo 'Cancellation accepted.';
}
cancellation
InvoiceCancellation
required
A fully populated InvoiceCancellation instance. The invoiceId, chaining, systemInfo, recordTimestamp, and issuerName fields are required.
return
InvoiceResponse
An InvoiceResponse object. A successful cancellation sets submissionStatus to 'Correcto'.
Throws: \SoapFault on SOAP-level transport or authentication failures.

queryInvoices()

Queries previously submitted invoice records from AEAT. Supports filtering by year, period, series number, date, counterparty, and pagination.
use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceQuery;

$query = new InvoiceQuery();
$query->year   = '2025';
$query->period = '01';
$query->setIssuerparty('B12345678');

$result = Verifactu::queryInvoices($query);

echo 'Found: ' . count($result->foundRecords ?? []) . ' records';

// Paginate if more results exist
if ($result->paginationIndicator === 'S') {
    $query->setPaginationKey(2, 10); // next page number, page size
    $nextPage = Verifactu::queryInvoices($query);
}
query
InvoiceQuery
required
A populated InvoiceQuery instance. year and period are required; all other filters are optional.
return
QueryResponse
A QueryResponse object. The foundRecords array holds the matched invoice records. paginationKey is set when there are more pages of results.
Throws: \SoapFault on communication errors.

generateInvoiceQr()

Generates a QR code for a submitted invoice. The QR encodes a URL pointing to the AEAT verification portal with the invoice’s identifying parameters appended as query string arguments. The return value is the raw QR image data (binary PNG by default) — it is not base64-encoded automatically. Encode it yourself if you need to embed it in HTML or store it as text.
use eseperio\verifactu\Verifactu;

// $invoice is an InvoiceSubmission that has already been registered
$qrRaw = Verifactu::generateInvoiceQr($invoice);

// Save raw PNG to a file
file_put_contents('invoice_qr.png', $qrRaw);

// Embed in HTML — encode it yourself
echo '<img src="data:image/png;base64,' . base64_encode($qrRaw) . '" alt="Invoice QR">';
record
InvoiceRecord
required
Any InvoiceRecord subclass instance — typically an InvoiceSubmission. The record must have invoiceId, hash, and totalAmount populated (i.e. it should have been submitted or at least have its hash computed).
return
string
Raw QR image data (binary PNG when using the default GD renderer). The value is not base64-encoded — call base64_encode() yourself if you need a data-URI or text-safe representation.

Full bootstrap example

<?php

use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceSubmission;
use eseperio\verifactu\models\InvoiceId;
use eseperio\verifactu\models\Chaining;
use eseperio\verifactu\models\ComputerSystem;
use eseperio\verifactu\models\LegalPerson;
use eseperio\verifactu\models\BreakdownDetail;
use eseperio\verifactu\models\enums\InvoiceType;
use eseperio\verifactu\models\enums\YesNoType;
use eseperio\verifactu\models\enums\TaxType;
use eseperio\verifactu\models\enums\RegimeType;
use eseperio\verifactu\models\enums\OperationQualificationType;

// 1. Configure once at boot
Verifactu::config(
    certPath:    '/certs/empresa.p12',
    certPassword: getenv('CERT_PASS'),
    certType:    Verifactu::TYPE_CERTIFICATE,
    environment: Verifactu::ENVIRONMENT_SANDBOX
);

// 2. Build the invoice
$invoice = new InvoiceSubmission();
$invoice->issuerName         = 'Mi Empresa S.L.';
$invoice->invoiceType        = InvoiceType::STANDARD;
$invoice->operationDescription = 'Consulting services — January 2025';
$invoice->taxAmount          = 210.0;
$invoice->totalAmount        = 1210.0;
$invoice->recordTimestamp    = date('Y-m-d\TH:i:sP');

$invoice->setInvoiceId([
    'issuerNif'    => 'B12345678',
    'seriesNumber' => 'A-2025/001',
    'issueDate'    => '2025-01-15',
]);

$invoice->setAsFirstRecord(); // or ->setChaining($previousChaining)

$provider = new LegalPerson();
$provider->name = 'Verifactu PHP';
$provider->nif  = 'B87654321';

$system = new ComputerSystem();
$system->providerName       = 'Verifactu PHP';
$system->systemName         = 'MyERP';
$system->systemId           = '01';
$system->version            = '1.0.0';
$system->installationNumber = '1';
$system->onlyVerifactu      = YesNoType::YES;
$system->multipleObligations    = YesNoType::NO;
$system->hasMultipleObligations = YesNoType::NO;
$system->setProviderId($provider);
$invoice->setSystemInfo($system);

$detail = new BreakdownDetail();
$detail->taxableBase             = 1000.0;
$detail->taxRate                 = 21.0;
$detail->taxAmount               = 210.0;
$detail->taxType                 = TaxType::IVA;
$detail->regimeKey               = RegimeType::GENERAL;
$detail->operationQualification  = OperationQualificationType::SUBJECT_NO_EXEMPT_NO_REVERSE;
$invoice->addBreakdownDetail($detail);

$recipient = new LegalPerson();
$recipient->name = 'Client Corp S.A.';
$recipient->nif  = 'A87654321';
$invoice->addRecipient($recipient);

// 3. Submit
$response = Verifactu::registerInvoice($invoice);

// 4. Handle response
if ($response->submissionStatus === 'Correcto') {
    $qr = Verifactu::generateInvoiceQr($invoice); // raw PNG binary
    // store $response->csv and file_put_contents('qr.png', $qr)
}

Build docs developers (and LLMs) love