Integrating Factur-X into an Existing PHP Application
As the French e-invoicing reform (RFE) moved closer to implementation, I needed to make my billing system compliant without replacing the existing application. Rather than switching to a SaaS platform or adopting an ERP, I chose to integrate the Factur-X standard directly into an existing PHP application running on a standard Apache server.
This article explains the architecture I built, what the standard actually requires, and the technical challenges I encountered along the way.
What is Factur-X?
Factur-X is a Franco-German standard for structured electronic invoicing that combines two elements into a single document:
- A human-readable PDF/A-3 invoice
- An embedded XML document compliant with the EN16931 European standard
Both are required. The PDF is intended for people, while the XML is intended for accounting software and automated processing. Together, they form a single electronic invoice.
Although Factur-X originated in France and Germany, it aligns with the European EN16931 standard and is part of the broader transition toward mandatory e-invoicing across Europe.
Links
The VAT Legal Mentions, the Part Most Developers Miss
Generating a valid Factur-X file is only part of the job. The invoice itself must also include the correct VAT legal mention according to the client's location. Getting this wrong isn't a formatting mistake, it's a fiscal compliance issue.
When the issuer is based in France, there are three possible situations.
French client
The issuer is a micro-enterprise or is not subject to VAT. The invoice must include the following legal mention:
TVA non applicable, art. 293B du CGI
No VAT is applied, no VAT column appears on the invoice, and the legal mention is mandatory.
EU client (B2B with a VAT number)
The transaction falls under the reverse charge mechanism, meaning the customer declares the VAT in their own country. The invoice must include:
Autoliquidation – TVA due par le preneur, art. 283-2 du CGI
VAT is set to 0% and the legal mention replaces the usual VAT information.
Non-EU client
The service is exported outside the European Union. VAT exemption applies under the French tax code, and the invoice must include:
Exonération de TVA – art. 262 I du CGI
Again, VAT is set to 0%, but the legal mention remains mandatory.
These aren't optional notes added for convenience. They explain why VAT is absent or transferred, and using the wrong one can become a compliance issue during a tax audit.
In my billing system, the correct legal mention is selected automatically from the client's ISO country code and VAT number. The developer doesn't choose it manually. The business rules do.
The Technical Chain: How Factur-X Is Actually Generated
Generating a Factur-X invoice is split into two distinct phases, each handled by a dedicated component. This separation is intentional because XML generation and PDF/A-3 conversion solve different problems and have different technical requirements.
Phase 1: Building the XML
The first step is handled by a PHP component responsible for generating the EN16931-compliant XML document.
It reads the invoice data, including issuer and client details, service lines, VAT amounts, totals, and payment terms, then maps every value to its corresponding EN16931 business term. The generated document follows the Factur-X Comfort profile, covering the information required for standard B2B invoicing.
Several business rules must be respected during this phase:
- Amounts use strict decimal formatting with no implicit rounding
- VAT is aggregated by rate rather than by invoice line
- Seller and buyer identifiers (SIREN, SIRET, VAT number) are placed in the appropriate XML elements according to the client's location
- The VAT legal mention determined earlier is written as structured XML data, not only as visible text in the PDF
The generated XML is stored temporarily before the second phase begins.
Phase 2: Injecting the XML into the PDF
The second step is handled by a Python component using the Factur-X library developed by Akretion, one of the organizations behind the standard.
Its role is straightforward:
- Read the PDF generated by the PHP billing engine using mPDF
- Embed the EN16931 XML document
- Convert the final document to the PDF/A-3b format required by Factur-X
I chose Python for this stage because the Factur-X library provides reliable PDF/A-3 conversion and XML embedding without introducing heavy PHP dependencies. It also validates the generated XML against the EN16931 schemas before embedding it, providing an additional compliance check.
The result is a single PDF/A-3 document containing the embedded XML, fully compliant with the Factur-X EN16931 Comfort profile.
Temporary Files
The XML only exists for as long as it is needed.
It is written to a dedicated temporary directory, embedded into the PDF during the second phase, then deleted automatically once the final document has been generated. Only the completed Factur-X invoice is retained.
What This Architecture Delivers
The result of this pipeline is a single document that is both human-readable and machine-readable: a Factur-X EN16931-compliant PDF/A-3 containing its embedded XML, ready for transmission to a French Partner Dematerialization Platform (PDP) or direct exchange with a client.
Beyond compliance, this architecture provides several practical advantages.
Self-Hosted by Design
The entire generation pipeline runs on the same server as the billing system. No external API is called during invoice generation, and no financial data leaves the infrastructure.
For organizations that require full control over their accounting data, this removes the dependency on third-party cloud services during document generation.
Independent from an ERP
The system doesn't rely on an ERP or existing accounting software.
Invoices are generated directly from the billing workflow, using the client information, service lines, VAT rules, and payment terms already managed by the application.
This makes the solution suitable for businesses that need Factur-X compliance without replacing their existing processes.
Compliance Built into the Workflow
Compliance isn't added at the end of the process.
VAT rates, legal mentions, and business rules are determined before the document is generated, then represented consistently in both the visible PDF and the embedded XML.
The result isn't simply a document that looks compliant.
It's a workflow designed to produce compliant invoices by construction.
Conclusion
Integrating Factur-X into an existing billing system isn't only about generating XML or converting a PDF to PDF/A-3.
The real challenge is translating business rules into structured data before the invoice is created.
The architecture described here, PHP for XML generation and Python for PDF/A-3 conversion and XML embedding, has allowed me to integrate Factur-X into an existing application without introducing an ERP, a SaaS platform, or unnecessary complexity.
If you're working on a similar integration, I hope this overview helps clarify where the real challenges lie.
Once the business rules are modeled correctly, generating a compliant Factur-X invoice becomes the easiest part of the process.
Go Further
Explore more technical articles
Read more technical notes

Top comments (0)