# How to integrate WooCommerce with VeriFactu without duplicating fiscal logic inside WordPress

> To integrate WooCommerce with VeriFactu safely, separate three responsibilities. WooCommerce supplies order and refund facts through CRUD; a server-side MappingProfile transforms that data into the fiscal contract and preflight validates it before issuance; the fiscal engine manages classification, certificate, chaining, transport and status. Define invoice number and date explicitly, never convert a refund automatically into R1-R5, use a stable idempotency key and reconcile rather than reissue once a recordId exists. Automate only after testing the manual flow, PDF presentation and failure paths. This architecture preserves HPOS and the WordPress ecosystem without turning the store into a second fiscal engine.

Canonical: https://kairoseth.com/en/blog/how-integrate-woocommerce-verifactu-hpos-refunds
Product: [VeriFactu Software](https://kairoseth.com/products/kairoseth-fiscal)
Primary query: how to integrate WooCommerce with VeriFactu
Intent: informational-how-woocommerce-verifactu-integration-works
Published: 2026-10-07
Updated: 2026-10-07
Geographic scope: España
Geographic context: This guide applies to WooCommerce stores preparing invoicing for Spain's SIF/VERI*FACTU framework. HPOS, CRUD and Action Scheduler are global WooCommerce capabilities, while MappingProfile, fiscal classification, certificates and the AEAT gate belong to the Spanish adaptation and require current regulatory review before production.

A robust WooCommerce-to-VeriFactu integration does not start by sending orders. It starts by discovering where the real invoice is created, using HPOS-compatible APIs, validating data before fiscalization, preserving identity across retries and separating refunds, PDF rendering and fiscal classification. This guide explains the architecture used by Kairoseth Fiscal WooCommerce connector v0.3.0 and what a store should verify before automation.

WooCommerce offers an extremely flexible order model, and that flexibility makes assumption-driven fiscal integrations dangerous. Two stores on the same version can have completely different invoice numbering, PDF generation, taxes and return workflows. In addition, HPOS has been stable since WooCommerce 8.2 and is enabled by default for new installations, so modern extensions should work through order objects and CRUD APIs rather than depending on posts and postmeta. Puente VeriFactu follows that pattern: the WooCommerce plugin is a thin adapter that captures commercial facts, calls preflight, uses idempotency keys and persists normalized status, while XML, certificates, hashes, fiscal classification and transport remain in the engine. The result is an integration that is easier to test, update and reconcile.

## 1. WooCommerce should remain the commercial source, not become the fiscal engine

The most important architectural boundary is deciding what each component is allowed to know. WooCommerce knows the order: customer, lines, calculated taxes, discounts, shipping, currency and states. It may also know a fiscal invoice number when another extension has generated one. What it should not decide is sensitive fiscal classification driven by business configuration and regulation: invoiceType, regime, operation class, corrective keys or AEAT credentials. Replicating those rules in PHP inside every store would increase drift, security surface and update cost.

Connector v0.3.0 builds neutral payloads and delegates mapping to the Bridge. That separation lets the same store keep its sales workflow while the fiscal engine is versioned centrally. It also improves support: a data problem appears in preflight, a transport problem belongs to the fiscal runtime and a presentation problem belongs to the PDF renderer. Each incident has a clear owner and evidence instead of being mixed into one plugin that is difficult to audit.

## 2. HPOS changes order storage, while CRUD keeps the extension contract stable

High-Performance Order Storage introduces dedicated tables for orders and addresses and removes the need for new stores to depend on traditional post storage. WooCommerce documents HPOS as stable since 8.2 and recommends extensions use its CRUD APIs. This matters because an integration reading _posts, _postmeta or specific tables directly can fail when the authoritative store changes. The connector does not use get_post_meta, update_post_meta or direct order-table access for its fiscal workflow.

Orders and refunds are represented through WC_Order and WC_Order_Refund, both within WooCommerce's order abstraction. The same principle is used to persist recordId, normalized status, last error, synchronization time and payload fingerprint. The code therefore does not need one fiscal branch for HPOS and another for legacy storage. CI installs the real ZIP and enables HPOS to validate behavior, while admin status columns still support both HPOS and the legacy order list.

## 3. The order number must not silently become the fiscal invoice number

WooCommerce creates orders and allows numbering to be customized, but that does not prove the identifier is the series and number of an issued fiscal invoice. Many stores use a PDF extension that assigns a number when the document is generated; others receive numbering from an ERP; some have deliberately chosen the order number as their fiscal invoice number. The connector requires a source to be selected and prefers an explicit meta key from the existing invoicing system when that is the real authority.

Using the order number is available only when the merchant explicitly confirms that it also represents the fiscal invoice number. When no source is configured, invoice_number stays empty and preflight must block. The date follows the same philosophy: it can initially derive from order creation, while an extension point allows the real invoice issue date to replace it. This detail prevents a technically successful automation from creating records with the wrong documentary identity.

## 4. Mapping and preflight are the barrier before any fiscal side effect

The ordinary payload contains source identifiers, invoice number and date, description, currency, recipient, total and tax lines. It can represent multiple tax rates. By design it does not let WooCommerce inject taxCode, regimeKey, operationClass or invoiceType. Those fields are resolved by a server-side MappingProfile that can be versioned per organization or installation. A rule update therefore does not require sensitive fiscal logic to be deployed to every store.

Preflight executes the contract before issue. It can expose a missing tax ID, empty invoice number, incomplete mapping, unavailable EUR conversion or totals that fail cent-level reconciliation. The correct response is to block without issuing and provide an actionable cause. For the store this is safer than partially accepting bad data and correcting it later, because the commercial fact or mapping can be fixed while the operation still has no fiscal side effect. Manual mode makes preflight useful during onboarding.

## 5. Idempotency and reconciliation solve the retry problem

Sending from WordPress means accepting network failures, timeouts and repeated asynchronous executions. The idempotency key turns multiple attempts for one operation into one identity. While a new operation still has no recordId, retries reuse exactly the same key. Once a recordId exists, the contract changes: the connector only calls GET /v1/fiscal-records/{recordId} to reconcile and never falls back to POST because of a synchronization error.

This rule prevents a dangerous class of bug: treating a response timeout as evidence that the server never received the record and creating another. Even a retryable reconciliation failure preserves the existing identity. Normalized states and _pv_last_error can show that review or retry is required without lying about what happened. A later successful reconciliation can clear the error and return the operational indicator to green without creating an additional invoice.

## 6. A refund is a commercial event; corrective fiscal treatment is a separate decision

When WooCommerce emits woocommerce_order_refunded, the connector can build a neutral operation associated with WC_Order_Refund. Every refund gets its own idempotency key and requires the original invoice to have a recordId. It also needs its own corrective fiscal invoice number. Amounts and signs are preserved exactly as represented by the refund, while the store does not decide whether the case is R1, R2, R3, R4 or R5 or which correction method applies.

Those decisions are delegated to a server-side refund_profile_id. Automatic refunds are disabled by default so a merchant who has not yet defined corrective numbering or treatment cannot accidentally fiscalize returns. Onboarding tests a representative return, including partial refunds when they are part of the business. The aggregate order indicator can become red when a refund is blocked even if the main invoice is accepted, because both operations require independent attention.

## 7. QR and texts belong to presentation, not to a second issuance from the PDF layer

WooCommerce has no single standard PDF invoice extension. Coupling fiscal logic directly to one provider would therefore create an unnecessary dependency. Connector v0.3.0 persists a neutral presentation contract and exposes a function, filter and action so a renderer can consume the URL, QR and texts associated with the record. Presentation comes from the fiscal engine and the PDF extension only renders it rather than recalculating or reinterpreting rules.

This design also separates reprinting from issuance. Downloading an invoice again, emailing it or regenerating its PDF must not create a new fiscal record. Testing verifies that presentation is associated with the correct recordId, appears in the intended documents and that renderer failures do not change fiscal state. When the store uses multiple document types or PDF providers, diagnosis identifies reliable hooks before compatibility is promised.

## 8. Automating after manual testing reduces the failure radius

The connector can be configured so selected WooCommerce states trigger automatic sending, but there is no need to start there. A new implementation is safer when one order is validated, issued manually, refreshed and checked in the PDF layer first. A representative automatic state can then be enabled while Action Scheduler, retries and reconciliation are observed. Refund automation has its own switch. This progression exposes unexpected business conditions before they affect a large volume of orders.

Action Scheduler is used when available and WP-Cron acts as a fallback so fiscal HTTP is not executed inside the synchronous WooCommerce hook. Retryable technical errors can make up to five attempts with backoff, while validation errors remain blocked. The operation does not change identity during that cycle. A CSV/XLSX operational fallback also exists if a future WooCommerce update temporarily breaks the connector, decoupling fiscal continuity from the store release cycle.

## 9. A useful test plan covers failures, not only the happy-path order

The minimum smoke should include a valid ordinary invoice, a preflight blocked by missing data, a technical retry using the same identity, reconciliation of an existing recordId and a refund when the merchant uses returns. Multiple VAT rates, discounts, shipping and PDF generation should also be exercised. If the store sells in other currencies, add one case with valid conversion and another with a missing rate to confirm that preflight blocks.

The product matrix already validates the real ZIP on WordPress 6.5/WooCommerce 8.2/PHP 7.4, WordPress 7.0.4/WooCommerce 11.0.1/PHP 8.2 and WordPress 7.1/WooCommerce 11.1/PHP 8.3, with HPOS and invoice/refund scenarios. That evidence does not replace QA on the actual store: theme, checkout, fiscal plugins, multicurrency, subscriptions, ERP synchronization and PDF renderer can introduce conditions that do not exist in a clean installation.

## 10. Connector readiness and AEAT production are different states

A store can have the connector installed, mapping validated, accepted tests and technically ready automation without being enabled for fiscal production. Preserving that distinction matters for both security and regulatory change. The certificate and sensitive credentials remain outside WooCommerce, and commercial entitlement cannot bypass the technical and regulatory gate. The team can complete all reversible work before making a production activation decision.

At go-live, the regulation in force, fiscal identity, certificate, configuration, evidence, rollback and explicit authorization are reviewed again. This rule prevents a WordPress deployment from becoming an implicit regulatory decision. It also improves support: a connector update can be tested without changing production, and a regulatory review can block the gate without forcing the prepared integration to be uninstalled. The same philosophy separates ecommerce, adaptation and the fiscal engine throughout the lifecycle.

## Key takeaways

- Do not assume the order number is the fiscal invoice number: configure the real source and let preflight block when it is missing.
- Use WooCommerce CRUD and order/refund objects to preserve HPOS compatibility without duplicating a legacy path.
- Keep MappingProfile, certificate, XML and fiscal classification outside WordPress; the connector should transport neutral commercial facts.
- Once recordId exists, reconcile that record instead of issuing again; retries for new operations preserve the same idempotency key.
- Treat every refund as an operation with its own identity and enable automation only after numbering, corrective profile and PDF presentation are tested.

## Sources

- [Technical README for WooCommerce connector v0.3.0](https://github.com/Emmakex/puente-verifactu/blob/main/connectors/woocommerce/README.md) — Kairoseth / Puente VeriFactu
- [WooCommerce Developer — High-Performance Order Storage](https://developer.woocommerce.com/docs/features/orders/high-performance-order-storage/) — WooCommerce
- [WooCommerce — HPOS enablement documentation](https://woocommerce.com/document/high-performance-order-storage/) — WooCommerce
- [Spanish Tax Agency — invoicing software systems and VERI*FACTU](https://sede.agenciatributaria.gob.es/Sede/iva/sistemas-informaticos-facturacion-verifactu.html) — Agencia Estatal de Administración Tributaria

## External resources

- [Official HPOS developer documentation](https://developer.woocommerce.com/docs/features/orders/high-performance-order-storage/): Explains HPOS order storage and WooCommerce CRUD APIs.

## Related product

- [VeriFactu Software](https://kairoseth.com/products/kairoseth-fiscal): VeriFactu software for connecting WooCommerce, PrestaShop, ERP, CRM, Excel, custom software and local systems to Spain's VeriFactu framework without replacing the source system.
- [Custom request](https://kairoseth.com/custom-requests)
