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.

Spain’s AEAT Verifactu regulation requires every submitted invoice to carry a machine-readable QR code on the printed or PDF document. When a recipient scans the code their device opens an AEAT verification URL that displays the official record, confirming the invoice was registered by the issuer. The QR code encodes a URL with the following query parameters:
ParameterSourceDescription
nifInvoiceId::$issuerNifNIF of the invoice issuer
numInvoiceId::$seriesNumberSeries and invoice number
fechaInvoiceId::$issueDateInvoice issue date
huellaInvoiceRecord::$hashSHA-256 hash (Huella) of the record
An example URL looks like:
https://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR
  ?nif=B12345678
  &num=FA2024%2F001
  &fecha=2024-07-01
  &huella=1234567890abcdef...
The huella query parameter is omitted when the invoice record’s hash property is null or empty. For VERI*FACTU invoices the hash is calculated automatically during registerInvoice() / cancelInvoice(). Always generate the QR after submitting the invoice so that the hash is available.

Dependency

QR generation requires the bacon/bacon-qr-code package. Install it via Composer:
composer require bacon/bacon-qr-code ^3
The Verifactu PHP library does not pull this dependency automatically; add it explicitly when you need QR generation.

Choosing the Right Method

The library exposes QR generation at two levels:
MethodArgumentsUse when
Verifactu::generateInvoiceQr(InvoiceRecord $record)Record onlyYou want the default PNG output (GD renderer, 300 px, string destination) and have already called Verifactu::config()
VerifactuService::generateInvoiceQr($record, $destination, $size, $engine)Record + optionsYou need a specific renderer, size, or file destination
QrGeneratorService::generateQr($record, $baseUrl, $destination, $size, $engine)Record + base URL + optionsYou manage the base URL yourself, or use the service in isolation

The Facade Method

Verifactu::generateInvoiceQr() is the simplest entry point. It accepts a single InvoiceRecord argument, reads the correct AEAT base URL from the configuration set by Verifactu::config(), and returns raw PNG binary data using the GD renderer at 300 px.
use eseperio\verifactu\Verifactu;

// Returns raw PNG binary data (GD renderer, 300 px, string destination)
$pngData = Verifactu::generateInvoiceQr($invoice);
The method signature is:
Verifactu::generateInvoiceQr(InvoiceRecord $record): string
To control the renderer, output size, or destination, call VerifactuService::generateInvoiceQr() directly (see below).

Custom Options via VerifactuService

VerifactuService::generateInvoiceQr() exposes the full set of options. It also reads the base URL from the library’s configuration, so you still only need to call Verifactu::config() once.
use eseperio\verifactu\services\VerifactuService;
use eseperio\verifactu\services\QrGeneratorService;

$qrData = VerifactuService::generateInvoiceQr(
    $invoice,                               // InvoiceRecord (submission or cancellation)
    QrGeneratorService::DESTINATION_STRING, // destination: 'string' (default) or 'file'
    300,                                    // size in pixels (default 300)
    QrGeneratorService::RENDERER_GD         // renderer: 'gd' (default), 'imagick', or 'svg'
);
The full signature is:
VerifactuService::generateInvoiceQr(
    InvoiceRecord $record,
    string        $destination = QrGeneratorService::DESTINATION_STRING,
    int           $size        = 300,
    string        $engine      = QrGeneratorService::RENDERER_GD
): string

Available Renderers

ConstantValueOutputRequirement
QrGeneratorService::RENDERER_GD'gd'PNG binaryPHP ext-gd (widely available)
QrGeneratorService::RENDERER_IMAGICK'imagick'PNG binaryPHP ext-imagick + ImageMagick
QrGeneratorService::RENDERER_SVG'svg'SVG markupNone (pure PHP)

Destination Options

ConstantValueReturns
QrGeneratorService::DESTINATION_STRING'string'Raw image data (PNG bytes or SVG markup)
QrGeneratorService::DESTINATION_FILE'file'Absolute path to a temporary file

Code Examples

Uses PHP’s built-in GD library. This is the default renderer and the most portable option.
use eseperio\verifactu\services\VerifactuService;
use eseperio\verifactu\services\QrGeneratorService;

// Returns raw PNG binary data
$pngData = VerifactuService::generateInvoiceQr(
    $invoice,
    QrGeneratorService::DESTINATION_STRING,
    300,
    QrGeneratorService::RENDERER_GD
);

// Save manually
file_put_contents('/var/invoices/qr_FA2024_001.png', $pngData);

// Or embed in an HTTP response
header('Content-Type: image/png');
echo $pngData;

Destination Options

use eseperio\verifactu\services\VerifactuService;
use eseperio\verifactu\services\QrGeneratorService;

// Returns the raw image bytes / SVG markup directly
$imageData = VerifactuService::generateInvoiceQr(
    $invoice,
    QrGeneratorService::DESTINATION_STRING,  // <-- default
    300,
    QrGeneratorService::RENDERER_GD
);

Embedding in HTML (base64)

use eseperio\verifactu\Verifactu;

// Facade returns raw PNG binary — encode it for embedding
$pngData = Verifactu::generateInvoiceQr($invoice);

$base64 = base64_encode($pngData);
echo '<img src="data:image/png;base64,' . $base64 . '" alt="Invoice QR Code" />';

Full Workflow: Submit Then Generate QR

The recommended pattern is to submit the invoice first, store the CSV, then generate the QR once the hash has been set by the library.
<?php

use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceResponse;
use eseperio\verifactu\services\VerifactuService;
use eseperio\verifactu\services\QrGeneratorService;

// ... build $invoice as shown in the Register Invoice guide ...

// 1. Register the invoice
$response = Verifactu::registerInvoice($invoice);

if ($response->submissionStatus === InvoiceResponse::STATUS_OK) {
    // 2. The library has now set $invoice->hash automatically
    echo "Registered. CSV: " . $response->csv . "\n";

    // 3. Simple facade call — PNG string, GD renderer, 300 px
    $pngData = Verifactu::generateInvoiceQr($invoice);

    // 4. Save to a temp file using VerifactuService for full control
    $qrPath = VerifactuService::generateInvoiceQr(
        $invoice,
        QrGeneratorService::DESTINATION_FILE,
        300,
        QrGeneratorService::RENDERER_GD
    );
    echo "QR saved to: $qrPath\n";

    // 5. Or generate as base64 for embedding in your invoice PDF
    $base64Qr = base64_encode($pngData);
    // Pass $base64Qr to your PDF rendering template
} else {
    foreach ($response->getErrors() as $code => $description) {
        echo "[$code] $description\n";
    }
}

Resolution / Size

The $size parameter controls the output dimensions in pixels. The default is 300. Use a higher value for print-quality output:
use eseperio\verifactu\services\VerifactuService;
use eseperio\verifactu\services\QrGeneratorService;

// High-resolution QR for print (600 px)
$hiResQr = VerifactuService::generateInvoiceQr(
    $invoice,
    QrGeneratorService::DESTINATION_STRING,
    600,
    QrGeneratorService::RENDERER_GD
);
For SVG output the $size value sets the width/height attributes of the generated SVG element, but the image remains fully scalable via CSS regardless of the value used.

Production vs. Sandbox QR URLs

Verifactu::config() automatically selects the correct base URL for the QR:
EnvironmentBase URL
ENVIRONMENT_PRODUCTIONhttps://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR
ENVIRONMENT_SANDBOXhttps://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR
QR codes generated in sandbox mode point to the AEAT homologation verifier. Re-generate stored QR codes when you move from sandbox to production.

Build docs developers (and LLMs) love