Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/josemmo/Verifactu-PHP/llms.txt

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

AeatClient (josemmo\Verifactu\Services\AeatClient) is the primary entry point for communicating with the AEAT VERI*FACTU web service endpoint. It builds the SOAP envelope, attaches your mTLS certificate, and dispatches registration and cancellation records asynchronously using Guzzle’s promise-based HTTP client.

Constructor

public function __construct(
    ComputerSystem $system,
    FiscalIdentifier $taxpayer,
    ?Client $httpClient = null,
)
system
ComputerSystem
required
The SIF (Sistema Informático de Facturación) metadata embedded in every record. See ComputerSystem.
taxpayer
FiscalIdentifier
required
The fiscal entity that issues the invoices (obligado a expedir la factura). See FiscalIdentifier.
httpClient
GuzzleHttp\Client | null
default:"null"
An optional pre-configured Guzzle client. When null, a new Client instance is created automatically. Supply your own to inject middleware, custom timeouts, or proxy settings.

Configuration methods

All configuration methods return static (the same AeatClient instance) so calls can be chained fluently.

setCertificate()

public function setCertificate(
    string $certificatePath,
    ?string $certificatePassword = null,
): static
Configures the mTLS client certificate used to authenticate with AEAT.
certificatePath
string
required
Filesystem path to an encrypted PEM certificate or a PKCS#12 (PFX) bundle.
The path must end with the .p12 extension for Guzzle to recognise the file as a PKCS#12 bundle. PEM files can use any other extension.
certificatePassword
string | null
default:"null"
Password for the certificate. Pass null when the certificate has no password.

setRepresentative()

public function setRepresentative(?FiscalIdentifier $representative): static
Sets a third-party representative that submits records on behalf of the taxpayer.
representative
FiscalIdentifier | null
required
Representative details, or null to clear a previously set representative.
This feature requires the represented fiscal entity to have completed the GENERALLEY58 form at AEAT before submissions are accepted.

setProduction()

public function setProduction(bool $production): static
production
bool
required
Pass true (default) to target the live production endpoint. Pass false to target the pre-production (testing) endpoint.
ValueRegular endpointEntity-seal endpoint
truehttps://www1.agenciatributaria.gob.eshttps://www10.agenciatributaria.gob.es
falsehttps://prewww1.aeat.eshttps://prewww10.aeat.es

setEntitySeal()

public function setEntitySeal(bool $entitySeal): static
entitySeal
bool
required
Pass true when authenticating with an entity-seal certificate (sello de entidad). This switches the base URL to the www10 / prewww10 endpoints. Pass false (default) for regular personal/company certificates.

setVoluntaryRemissionEndDate()

public function setVoluntaryRemissionEndDate(
    ?DateTimeImmutable $endDate,
    bool $isAffectedByIncident = false,
): static
Indicates that this batch is part of a voluntary catch-up submission (remisión voluntaria) and sets the end date of the VERI*FACTU period being reported.
endDate
DateTimeImmutable | null
required
The end date of the voluntary remission period. The time component is ignored. Pass null to clear a previously set value.
isAffectedByIncident
bool
default:"false"
Set to true if the voluntary remission was at any point affected by a technical incident.

setRequirementReference()

public function setRequirementReference(
    ?string $requirementReference,
    bool $isLastRequirementSubmission = false,
): static
Used only for non-voluntary submissions made in response to an AEAT requirement (remisión por requerimiento). Must not be set for ordinary voluntary submissions.
requirementReference
string | null
required
The AEAT requirement reference number, or null to clear.
isLastRequirementSubmission
bool
default:"false"
Set to true to signal that no further records will be submitted for this requirement.

Sending records

send()

public function send(array $records): PromiseInterface
Serialises $records into a SOAP envelope and dispatches the request asynchronously.
records
array<RegistrationRecord|CancellationRecord>
required
The billing records to submit. May contain a mix of RegistrationRecord and CancellationRecord instances. AEAT imposes a hard limit of 1,000 records per call.
Return value: GuzzleHttp\Promise\PromiseInterface<AeatResponse> Call ->wait() on the returned promise to block until the response arrives. The resolved value is an AeatResponse object with the following properties:
PropertyTypeDescription
csvstring|nullAEAT-assigned CSV identifier for the batch (only set when not rejected)
submittedAtDateTimeImmutable|nullTimestamp assigned by AEAT to the submission
waitSecondsintMinimum seconds to wait before the next submission
statusResponseStatusOverall batch status
itemsResponseItem[]Per-record status details

Constants

ConstantValueDescription
AeatClient::NS_SOAPENVhttp://schemas.xmlsoap.org/soap/envelope/SOAP envelope XML namespace
AeatClient::NS_AEAThttps://www2.agenciatributaria.gob.es/…/SuministroLR.xsdAEAT client XML namespace

Exceptions

send() can throw the following exceptions:
  • josemmo\Verifactu\Exceptions\AeatException — thrown when the AEAT server returns a SOAP fault or an unrecognisable XML response body.
  • Psr\Http\Client\ClientExceptionInterface — thrown when the underlying HTTP request fails at the network level (connection refused, timeout, DNS failure, etc.).

Complete example

use josemmo\Verifactu\Models\ComputerSystem;
use josemmo\Verifactu\Models\Records\FiscalIdentifier;
use josemmo\Verifactu\Services\AeatClient;
use josemmo\Verifactu\Exceptions\AeatException;

// 1. Build computer system metadata
$system = new ComputerSystem();
$system->vendorName           = 'Acme Software S.L.';
$system->vendorNif            = 'B12345678';
$system->name                 = 'AcmeBilling';
$system->id                   = 'AB';
$system->version              = '3.1.0';
$system->installationNumber   = 'INST-0001';
$system->onlySupportsVerifactu   = true;
$system->supportsMultipleTaxpayers = false;
$system->hasMultipleTaxpayers      = false;

// 2. Identify the taxpayer
$taxpayer = new FiscalIdentifier('Empresa Ejemplo S.A.', 'A87654321');

// 3. Construct the client
$client = new AeatClient($system, $taxpayer);

// 4. Configure certificate and environment
$client
    ->setCertificate('/certs/empresa.p12', 's3cr3t')
    ->setProduction(false);   // use pre-production for testing

// 5. Optionally set a representative
$representative = new FiscalIdentifier('Gestoría XYZ S.L.', 'B11223344');
$client->setRepresentative($representative);

// 6. Send records (assuming $records is an array of RegistrationRecord / CancellationRecord)
try {
    $response = $client->send($records)->wait();

    echo 'Status:       ' . $response->status->value . PHP_EOL;
    echo 'CSV:          ' . ($response->csv ?? 'N/A') . PHP_EOL;
    echo 'Wait seconds: ' . $response->waitSeconds . PHP_EOL;

    foreach ($response->items as $item) {
        echo $item->invoiceId->invoiceNumber . ': ' . $item->status->value . PHP_EOL;
    }
} catch (AeatException $e) {
    echo 'AEAT server error: ' . $e->getMessage() . PHP_EOL;
}

Build docs developers (and LLMs) love