---
title: Comment générer une Factur-X en PHP (guide pas à pas)
source: https://synapx.fr/blog/generer-factur-x-php/
date: 2026-06-27
category: Facturation électronique
site: SynapxLab
---

# Comment générer une Factur-X en PHP (guide pas à pas)

Générer un PDF en PHP, tout le monde sait faire. Générer une **Factur-X conforme**, c'est autre chose : il faut produire le bon **XML (CII)**, l'**embarquer** dans un **PDF/A-3** et y injecter les **métadonnées XMP** attendues. Rater une de ces trois étapes, et la facture est techniquement invalide — même si le PDF s'affiche parfaitement.

Bonne nouvelle : une librairie gère la partie la plus délicate. Voici le chemin complet, du XML au fichier validé.

> 🔎 À la fin, **vérifiez toujours** votre fichier dans le **[Testeur de factures Factur-X](/sdk/FactureX/)** — c'est le réflexe qui évite les rejets en production.

## Le principe : deux couches, un seul fichier

```
facture.pdf  (Factur-X)
├── 📄 Couche visuelle  → un PDF/A-3 lisible
└── 🤖 Couche données    → factur-x.xml (CII) embarqué
```

Vous fournissez **deux choses** : le **PDF visuel** de votre facture (celui que vous générez déjà) et le **XML Factur-X**. La librairie assemble les deux en un **PDF/A-3 conforme**. Pour le contexte complet du format, voir le guide **[Factur-X : comprendre le format](/blog/factur-x-comprendre-valider/)**.

## Étape 1 — Installer la librairie

La référence en PHP est **`atgp/factur-x`** (PHP 7.4+) :

```bash
composer require atgp/factur-x
```

Elle s'appuie sur `setasign/fpdf`, `setasign/fpdi` et `smalot/pdfparser`, et sait **générer**, **extraire** et **valider** le XML embarqué.

## Étape 2 — Construire le XML Factur-X (CII)

C'est **votre** responsabilité : la librairie n'invente pas vos données. Voici un squelette **profil MINIMUM** (le plus simple — sans lignes de détail) à adapter :

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice
    xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
    xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
    xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:factur-x.eu:1p0:minimum</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>FA-2026-0042</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">20260627</udt:DateTimeString>
    </ram:IssueDateTime>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>Ma Société SARL</ram:Name>
        <ram:SpecifiedLegalOrganization>
          <ram:ID schemeID="0002">123456789</ram:ID>
        </ram:SpecifiedLegalOrganization>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>Client SAS</ram:Name>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeDelivery/>
    <ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:TaxBasisTotalAmount>1000.00</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="EUR">200.00</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>1200.00</ram:GrandTotalAmount>
        <ram:DuePayableAmount>1200.00</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
```

Points de vigilance : la **date** est au format `102` (`AAAAMMJJ`), la **devise** suit ISO 4217, et **`TaxBasis + TaxTotal = GrandTotal`** (sinon rejet — voir [les 20 erreurs](/blog/20-erreurs-factur-x-frequentes/)). Pour un profil **EN 16931 (COMFORT)** avec les lignes de détail, le XML est plus riche ; on l'assemble souvent par gabarit ou via une librairie d'écriture dédiée plutôt qu'à la main.

## Étape 3 — Embarquer le XML dans le PDF/A-3

C'est là que `atgp/factur-x` fait le travail difficile (PDF/A-3 + XMP) :

```php
<?php
require 'vendor/autoload.php';

use Atgp\FacturX\Facturx;

$pdfVisuel = file_get_contents('facture.pdf');   // votre PDF existant
$xml       = file_get_contents('factur-x.xml');  // le XML de l'étape 2

$facturx = new Facturx();

// Assemble un PDF/A-3 conforme contenant le XML embarqué
$facturxPdf = $facturx->generateFacturxFromFiles($pdfVisuel, $xml);

file_put_contents('facture-facturx.pdf', $facturxPdf);
```

La librairie nomme automatiquement la pièce jointe **`factur-x.xml`**, pose la bonne relation de fichier et écrit les métadonnées XMP — les erreurs n°1 à 4 de [la checklist](/blog/20-erreurs-factur-x-frequentes/) sont ainsi éliminées d'office.

## Étape 4 — Valider le résultat

Ne **jamais** mettre en production sans valider. D'abord le schéma, en local :

```php
$isValid = $facturx->checkFacturxXsd($xml); // true / exception si non conforme
```

Puis une validation complète (schéma **+** règles métier EN 16931 **+** cohérence PDF) :

> 🔎 **Test rapide** — le **[Testeur Factur-X de SynapxLab](/sdk/FactureX/)** : présence du XML, PDF/A-3, profil, montants, mentions. Gratuit, aucune donnée conservée.

> 🏛️ **Validation faisant autorité** — le **[validateur du FNFE-MPE](https://services.fnfe-mpe.org/)**, avant toute mise en production.

## Lire / extraire le XML d'une Factur-X existante

L'opération inverse est tout aussi simple :

```php
$pdf = file_get_contents('facture-facturx.pdf');
$xml = $facturx->getFacturxXmlFromPdf($pdf);   // récupère le XML embarqué
```

À détailler dans un prochain article du cluster : **comment lire et exploiter le XML embarqué**.

## Et après ? Générer ≠ transmettre

Produire un fichier conforme n'est **qu'une étape**. La réforme impose ensuite de le **transmettre via une plateforme agréée (PA)**, de gérer les **statuts** (reçue, acceptée, encaissée) et l'**e-reporting**. Une librairie traite le **format** ; elle ne fait ni la transmission, ni les statuts, ni l'e-reporting.

> 💡 Pour un flux complet sans tout recoder, un ERP/CRM génère la Factur-X **et** la transmet via une PA, avec suivi du cycle de vie. Le cadre complet est détaillé dans notre **[guide de la réforme](/blog/factur-x-comprendre-valider/)**.

---

## ❓ FAQ

**Quelle librairie PHP pour générer une Factur-X ?**
**`atgp/factur-x`** : elle embarque le XML dans un **PDF/A-3** conforme, et sait aussi l'extraire et le valider.

**La librairie génère-t-elle le XML à ma place ?**
Non : vous fournissez le **PDF** et le **XML** (CII). La librairie gère l'embarquement conforme et les métadonnées XMP.

**Comment vérifier que ma Factur-X est valide ?**
`checkFacturxXsd()` en local pour le schéma, puis le [testeur Factur-X](/sdk/FactureX/) ou le [FNFE-MPE](https://services.fnfe-mpe.org/) pour une validation complète.

**Ai-je besoin de Ghostscript ?**
Pas pour l'embarquement de base. Mais normaliser des PDF d'origines variées en **PDF/A-3** strict peut nécessiter un outil de conversion ou de contrôle (Ghostscript, veraPDF).

## Pour aller plus loin

- 🔎 **[Testeur de factures Factur-X](/sdk/FactureX/)** — validez votre fichier généré, gratuitement.
- 🛠️ **[Les 20 erreurs Factur-X les plus fréquentes](/blog/20-erreurs-factur-x-frequentes/)** — la checklist à garder ouverte pendant le dev.
- 🧩 **[Pourquoi ma facture Factur-X est invalide ?](/blog/pourquoi-facture-factur-x-invalide/)** — les grandes familles de causes.
- 📘 **[Factur-X : comprendre le format et valider ses factures](/blog/factur-x-comprendre-valider/)** — le guide complet.
- 🏛️ **[Librairie atgp/factur-x sur GitHub](https://github.com/atgp/factur-x)** — code source, README et exemples.
