=== CatCode Verifactu for WooCommerce ===
Contributors: catcode
Tags: verifactu, aeat, factura, woocommerce, spain
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

VERI*FACTU for WooCommerce: chained, hashed invoicing records sent to the AEAT, and the tax QR code in e-mails and on the order page.

== Description ==

Spain's anti-fraud invoicing rules (Real Decreto 1007/2023, Orden HAC/1177/2024) require invoicing software to create a tamper-evident record for every invoice. In VERI*FACTU mode each record is sent to the Spanish Tax Agency (AEAT) right away, and every invoice carries a QR code the customer can check at the AEAT. The obligation applies from 1 January 2027 to companies and from 1 July 2027 to everyone else (Real Decreto-ley 15/2025).

This plugin makes a WooCommerce shop a VERI*FACTU system.

Free:

* An invoicing record (registro de alta) for every order when it reaches the status you choose (Completed or Processing).
* Simplified invoices (F2) with their own consecutive series, per year if you like (T2027-000001…).
* SHA-256 hash chain exactly as specified by the AEAT; each record points at the previous one. Records are never edited — a fix is a new chained record.
* Tax breakdown from the taxes WooCommerce charged: Spanish VAT rates (S1), exports (exempt, regime 02), optional EU OSS distance sales (N2, regime 17), zero-rated domestic lines. IGIC supported as the tax type for shops in the Canary Islands.
* Automatic submission to the AEAT web service (SOAP) with your electronic certificate (.p12/.pfx upload, or files defined in wp-config.php). The AEAT waiting time between submissions is respected; up to 1,000 records per submission.
* Network trouble never loses a record: it stays queued and is retried with increasing delays.
* AEAT answers per record: accepted, accepted with errors, rejected — with the AEAT error code, in the order notes and in the record log.
* One-click correction (subsanación) of rejected or accepted-with-errors records, with the Subsanacion / RechazoPrevio flags set the way the AEAT expects.
* The tax QR code ("QR tributario:" + "VERI*FACTU") at the top of customer e-mails and of the order / thank-you page.
* Test portal and production kept apart: separate chains and separate invoice counters.
* "Check connection" button that proves the certificate is accepted without registering anything.
* Record log with filters, full XML of each record, hash and previous hash.
* HPOS and block checkout compatible. Translations: Spanish, Ukrainian.

Pro (licence from catcode.com.ua):

* Full invoices (F1) with the customer's NIF / NIE / CIF or EU VAT number — a checkout field on classic and block checkout, with check-digit validation. Orders above the simplified-invoice limit need it.
* Intra-EU B2B sales without VAT reported as E5 (goods) / N2 (services).
* Corrective invoices (R5 for simplified, R1 or R4 for full invoices, "por diferencias") created from WooCommerce refunds, including amount-only refunds.
* Voiding (anulación) of a record issued by mistake.
* "PDF Invoices & Packing Slips" integration: the QR at the top of the PDF invoice; optionally that plugin's invoice numbers.
* CSV and XML export of the records for your accountant.
* E-mail alerts on rejected records and failing deliveries.

== Installation ==

1. Upload the plugin and activate it.
2. WooCommerce → Verifactu → Settings: enter the issuer NIF and name exactly as registered at the AEAT, choose the order status that issues the invoice, and the invoice series.
3. Upload your electronic certificate (.p12/.pfx) and its password, or define CCVF_CERT_FILE, CCVF_KEY_FILE and CCVF_CERT_PASSWORD in wp-config.php (recommended: files outside the web root).
4. Keep the environment on "Test portal", press "Check connection", switch "Generate Verifactu records" on and place a test order.
5. When the test records are accepted, switch to Production.

== Frequently Asked Questions ==

= Which certificate do I need? =
An electronic certificate of the issuer (company or self-employed person), of a representative authorised to submit on the issuer's behalf, or an electronic seal certificate (choose "sello" in the settings). The same certificate works for the AEAT test portal.

= My .p12 file does not open. =
Certificates exported with old algorithms (RC2/3DES) cannot be read by OpenSSL 3. Re-export it: `openssl pkcs12 -legacy -in old.p12 -nodes | openssl pkcs12 -export -out new.p12`.

= Is the certificate safe on the server? =
The private key is re-encrypted with a key derived from your site salts and stored in a folder with a random name under uploads, closed with .htaccess. On nginx add a rule that denies wp-content/uploads/ccvf-*, or use the wp-config.php constants with files outside the web root.

= Can I test without a certificate? =
On a staging site define `CCVF_AEAT_MOCK` in wp-config.php (`ok`, `errors`, `reject`, `reject-once`, `duplicate`, `fault`, `down`). Nothing leaves the site and the answers follow the AEAT response schema. It is ignored in production.

= What happens if the AEAT is down? =
Records stay in the queue and are retried automatically (1, 2, 4… minutes, up to 6 hours between attempts). The invoice and its QR code are valid from the moment the record is created.

= The AEAT rejected a record. =
Open WooCommerce → Verifactu, read the AEAT error, fix the order data or the settings and press "Correct & resend". A new record with the same invoice number is chained and sent.

= Does it replace my accountant's software? =
No. It creates and submits the invoicing records of your web shop. Tax treatment defaults fit a typical shop in mainland Spain; confirm the settings with your tax adviser.

= Can I delete the plugin data? =
Invoicing records are tax records and must be kept. Uninstalling keeps them unless `CCVF_DELETE_DATA` is defined as true in wp-config.php.

= Free and Pro =
The free version is complete for shops that issue simplified invoices, with no time limit. Pro features are unlocked with a licence key from catcode.com.ua. The 7-day trial starts only when you click it. A purchased licence keeps its Pro features after the term ends — only updates and support stop.

== Changelog ==

= 1.0.0 =
* First release.
