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.
When to Cancel vs. When to Rectify
AEAT distinguishes two ways to correct an already-submitted invoice:| Situation | Action |
|---|---|
| The invoice was submitted to AEAT but the underlying commercial transaction should not have been invoiced at all, or the invoice was sent by mistake | Cancel (InvoiceCancellation) |
| The invoice was valid but details (amount, tax rate, recipient…) need correction | Rectify — issue a new InvoiceSubmission of type R1–R5 referencing the original |
InvoiceCancellation to annul a record. This creates a RegistroAnulacion entry in the
AEAT ledger and does not issue a replacement invoice. Once cancelled, the original invoice
cannot be amended further; a rectification invoice must be submitted if the underlying
transaction still took place.
Building an InvoiceCancellation Step by Step
The
InvoiceId must match the original invoice exactly — same issuerNif, seriesNumber, and
issueDate as the previously registered record.use eseperio\verifactu\models\InvoiceCancellation;
use eseperio\verifactu\models\InvoiceId;
$cancellation = new InvoiceCancellation();
$invoiceId = new InvoiceId();
$invoiceId->issuerNif = 'B12345678'; // Must match the original submission
$invoiceId->seriesNumber = 'FA2024/001'; // Must match the original submission
$invoiceId->issueDate = '2024-07-01'; // Must match the original submission (YYYY-MM-DD)
$cancellation->setInvoiceId($invoiceId);
The
issuerName field is required on cancellations (fix for issue #27).
It must match the original issuer name submitted to AEAT.Just like invoice submissions, cancellations participate in the hash chain. Reference the hash
of the most recent record in the chain (which may be an invoice submission or another
cancellation).
use eseperio\verifactu\models\Chaining;
$chaining = new Chaining();
// Reference the previous record's hash
$chaining->setPreviousInvoice([
'issuerNif' => 'B12345678',
'seriesNumber' => 'FA2024/001', // series+number of the previous record
'issueDate' => '2024-07-01', // issue date of the previous record
'hash' => '<sha256-hash-of-previous-record>',
]);
$cancellation->setChaining($chaining);
You do not calculate the cancellation’s own hash.
Verifactu::cancelInvoice() calls
HashGeneratorService::generate() internally before transmitting the SOAP request.Attach the same
ComputerSystem block used for invoice submissions. It identifies the invoicing
software and its registered provider.use eseperio\verifactu\models\ComputerSystem;
use eseperio\verifactu\models\LegalPerson;
use eseperio\verifactu\models\enums\YesNoType;
$provider = new LegalPerson();
$provider->name = 'Software Provider SL';
$provider->nif = 'B87654321';
$computerSystem = new ComputerSystem();
$computerSystem->systemName = 'ERP Company';
$computerSystem->version = '1.0';
$computerSystem->providerName = 'Software Provider SL';
$computerSystem->systemId = '01';
$computerSystem->installationNumber = '1';
$computerSystem->onlyVerifactu = YesNoType::YES;
$computerSystem->multipleObligations = YesNoType::NO;
$computerSystem->hasMultipleObligations = YesNoType::NO;
$computerSystem->setProviderId($provider);
$cancellation->setSystemInfo($computerSystem);
noPreviousRecordYesNoTypeYES when no previous registration exists for this invoice in AEATpreviousRejectionYesNoTypeYES when cancelling a record that was previously rejectedgeneratorGeneratorTypegeneratorDataLegalPerson (via setGeneratorData())fechaFinVeriFactustring (DD-MM-YYYY)ISSUERERECIPIENTDTHIRD_PARTYTuse eseperio\verifactu\models\enums\GeneratorType;
$cancellation->noPreviousRecord = YesNoType::NO;
$cancellation->previousRejection = YesNoType::NO;
$cancellation->generator = GeneratorType::ISSUER;
// Only required when generator is RECIPIENT or THIRD_PARTY
// $cancellation->setGeneratorData($generatorLegalPerson);
Validate and Submit
Handle the InvoiceResponse
ThecancelInvoice() method returns the same InvoiceResponse type as registerInvoice().