Dolibarr est l’un des ERP/CRM open source les plus utilisés par les TPE et PME françaises. Avec, selon les estimations communautaires, plus de 50 000 installations actives en France et une communauté de contributeurs très impliquée, il est le logiciel de gestion de référence pour les petites structures qui veulent rester sur une solution libre, autohébergeable et modulaire.
La réforme de facturation électronique française impose un calendrier précis. A compter du 1er septembre 2026, toutes les entreprises assujetties à la TVA devront être en mesure de recevoir des factures électroniques structurées via le Portail Public de Facturation (PPF) ou une Plateforme de Dématérialisation Partenaire (PDP). L’obligation d’émission sera progressive entre 2026 et 2027 selon la taille de l’entreprise.
Pour les utilisateurs de Dolibarr, cela signifie que les factures PDF générées par l’ERP devront embarquer un fichier XML CII conforme au standard Factur-X/EN16931 et que le PDF lui-meme devra respecter la norme ISO 19005-3 (PDF/A-3). Ce guide couvre la configuration du module Factur-X, les erreurs de validation les plus fréquentes et comment les corriger, puis l’intégration d’un pipeline de validation automatisé.
Pour le contexte complet de la réforme et du calendrier, voir Facturation électronique 2026 : le guide technique complet.
Le module Factur-X dans Dolibarr
Dolibarr ne gère pas Factur-X nativement dans son coeur. Le support Factur-X est apporté par un module complémentaire, le plus souvent distribué via le DoliStore ou directement sur GitHub. Plusieurs modules existent dans l’écosystème communautaire, avec des niveaux de maturité variables.
Le module le plus répandu utilise la bibliothèque PHP atgp/factur-x (maintenue par AIFE/ATGP) pour générer le XML CII et l’embarquer dans le PDF. D’autres modules utilisent des bibliothèques alternatives ou une génération XML manuelle.
Vérifier la version de Dolibarr
Le support Factur-X via module complémentaire est disponible à partir de Dolibarr 14+, mais les versions récentes (18, 19, 20) offrent une meilleure intégration. Pour vérifier votre version : Accueil > Informations système affiche la version installée.
Les points de vigilance selon la version :
| Version Dolibarr | Support Factur-X | Remarques |
|---|---|---|
| < 14 | Non supporté | Mise à jour nécessaire |
| 14 - 16 | Module externe | Compatibilité variable, vérifier la version du module |
| 17 - 18 | Module externe optimisé | Meilleure intégration PDF, hooks disponibles |
| 19+ | Module externe recommandé | Support amélioré de TCPDF, options PDF/A, intégration progressive de la facturation électronique |
Installer le module
L’installation suit le processus standard des modules Dolibarr :
- Télécharger le module depuis le DoliStore ou le dépot GitHub du développeur
- Extraire l’archive dans le répertoire
htdocs/custom/de votre installation Dolibarr - Aller dans Accueil > Configuration > Modules/Applications
- Chercher “Factur-X” dans la liste et activer le module
- Configurer le module via le lien Configuration qui apparait après activation
Après installation, le module ajoute généralement une option dans la génération PDF des factures : lors de la création ou du téléchargement d’une facture, un bouton ou une option permet de générer la version Factur-X.
Configuration des informations société
La conformité EN16931 commence par la fiche société de Dolibarr. Les champs renseignés dans Accueil > Configuration > Société/Organisation alimentent directement les nœuds XML du vendeur (BG-4).
SIRET — BT-30 (identifiant d’enregistrement légal du vendeur)
Le champ BT-30 correspond à l’identifiant d’enregistrement légal du vendeur. En France, il s’agit du SIRET (14 chiffres) identifiant l’établissement. Dans le XML CII, il doit être accompagné du schemeID="0002" (code ICD attribué au registre SIRENE par l’ISO 6523).
Dans Dolibarr : Accueil > Configuration > Société/Organisation > onglet “Identité”. Le champ “SIRET” doit contenir les 14 chiffres sans espaces ni tirets.
<ram:SellerTradeParty>
<ram:Name>Ma Société SAS</ram:Name>
<ram:SpecifiedLegalOrganization>
<ram:ID schemeID="0002">12345678901234</ram:ID>
</ram:SpecifiedLegalOrganization>
</ram:SellerTradeParty>
Si le champ SIRET est vide ou mal formaté dans Dolibarr, le module ne pourra pas générer un XML conforme. La règle Schematron BR-CO-26 exige qu’au moins un identifiant vendeur soit présent parmi BT-29, BT-30 et BT-31.
Pour la cartographie complète des BT obligatoires, voir Champs obligatoires EN16931 : cartographie et mapping ERP.
TVA intracommunautaire — BT-31
Le numéro de TVA intracommunautaire (BT-31) se configure dans le meme onglet. Format attendu : FRXX999999999 (préfixe pays + clé + SIREN). Le schemeID dans le XML doit être VA.
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">FR32123456789</ram:ID>
</ram:SpecifiedTaxRegistration>
Dans Dolibarr : le champ “N° TVA intra.” dans la fiche société. Vérifier que le format est bien celui attendu par l’administration fiscale (avec le préfixe FR).
Adresse complète — BT-35 à BT-40
L’adresse du vendeur est obligatoire en EN16931. Les champs BT-35 (ligne d’adresse), BT-37 (ville), BT-38 (code postal) et BT-40 (code pays) doivent tous être renseignés.
Dans Dolibarr : vérifier dans Configuration > Société/Organisation que l’adresse, la ville, le code postal et le pays sont tous remplis. Le code pays doit être un code ISO 3166-1 alpha-2 (FR pour la France). Dolibarr gère nativement les codes pays ISO, donc si le pays est sélectionné dans la liste déroulante, le code sera correct.
Coordonnées bancaires — BG-17
Les coordonnées bancaires sont nécessaires si le moyen de paiement est un virement (code UNTDID 4461 = 30 ou 58 pour SEPA). Le nœud XML correspondant (BG-17) attend l’IBAN (BT-84) et optionnellement le BIC (BT-86).
Dans Dolibarr : Accueil > Configuration > Société/Organisation > onglet “Comptes bancaires”. L’IBAN doit être renseigné sans espaces.
Conditions de paiement — BG-20
Les conditions de paiement sont techniquement optionnelles en EN16931 (BT-9 date d’échéance = 0..1, BT-20 conditions en texte = 0..1), mais certains cadres d’échange ou implémentations sectorielles exigent leur présence. Une facture sans date d’échéance sera techniquement valide mais opérationnellement suspecte pour la plupart des destinataires.
Dans Dolibarr : les conditions de paiement se configurent dans Accueil > Configuration > Dictionnaires > Conditions de paiement. Le module Factur-X mappe ces conditions vers le nœud SpecifiedTradePaymentTerms du XML CII.
Configuration des fiches clients
Les informations de l’acheteur (BG-7) sont tirées de la fiche tiers dans Dolibarr. Pour chaque client soumis à la réforme, vérifier :
| Champ Dolibarr | BT EN16931 | Cardinalité | Où le renseigner |
|---|---|---|---|
| Nom | BT-44 (nom acheteur) | 1..1 | Fiche tiers > Nom |
| Adresse | BT-50 (adresse) | 1..1 | Fiche tiers > Adresse |
| Ville | BT-52 | 1..1 | Fiche tiers > Ville |
| Code postal | BT-53 | 0..1 | Fiche tiers > Code postal |
| Pays | BT-55 (code pays) | 1..1 | Fiche tiers > Pays |
| SIRET | BT-47 (id légal acheteur) | 0..1 | Fiche tiers > Id prof 2 (SIRET) |
| TVA intra. | BT-48 (TVA acheteur) | 0..1 | Fiche tiers > N° TVA intra. |
BT-44 — Nom de l’acheteur est le champ le plus souvent manquant dans les exports Factur-X issus de Dolibarr. La raison : certaines fiches tiers sont créées avec un nom abrégé ou un code interne, et le module utilise ce champ tel quel pour le XML. Si le champ “Nom” de la fiche tiers est vide ou contient un placeholder, la validation Schematron échouera.
Choix du profil Factur-X
Le profil Factur-X détermine le niveau de détail du XML embarqué. Le module Dolibarr propose généralement un choix dans sa configuration.
| Profil | Niveau | Usage |
|---|---|---|
| MINIMUM | Identifiants seulement | Insuffisant pour la réforme B2B |
| BASIC WL | Sans lignes de détail | Limité, pas de détail articles |
| BASIC | Avec lignes | Acceptable pour de nombreux cas |
| EN16931 | Conforme CEN | Recommandé pour la réforme |
| EXTENDED | Champs supplémentaires | Pour les besoins spécifiques (B2G, exports) |
Pour la réforme française B2B, le profil EN16931 est le niveau recommandé. Le profil MINIMUM ne contient pas assez d’information pour satisfaire les exigences de la plupart des cadres d’échange. Le profil BASIC peut suffire dans certains cas mais ne couvre pas toutes les règles Schematron.
Le choix du profil se fait dans la configuration du module : Accueil > Configuration > Modules > Factur-X > Configuration. Sélectionner “EN16931” comme profil par défaut.
Pour comprendre les différences entre chaque profil, voir Profils Factur-X : MINIMUM, BASIC, EN16931, EXTENDED.
Les erreurs de validation courantes et leurs corrections
Erreur 1 — PDF non conforme PDF/A-3
Symptome : la validation retourne une erreur de conformité PDF/A-3 alors que le PDF s’ouvre correctement.
Cause : Dolibarr utilise TCPDF comme bibliothèque de génération PDF. TCPDF peut produire du PDF/A-1 dans certaines configurations, mais la génération PDF/A-3 conforme (ISO 19005-3) est plus exigeante. Les problèmes les plus fréquents :
- Polices non embarquées : TCPDF n’embarque pas toujours les sous-ensembles de polices requis. Les polices système référencées sans embedding violent la clause PDF/A sur l’autonomie du document.
- Profil ICC manquant : le dictionnaire
OutputIntentsdoit contenir un profil colorimétrique ICC valide. TCPDF ne l’ajoute pas automatiquement dans tous les cas. - Métadonnées XMP incomplètes : les propriétés
pdfaid:part=3etpdfaid:conformance=Bdoivent figurer dans le flux XMP, accompagnées des descriptions d’extension de schéma Factur-X. - AFRelationship incorrect : la pièce jointe XML doit avoir un attribut
/AFRelationshipavec la valeur/Alternative(pour Factur-X 1.x).
Corrections possibles :
La solution la plus fiable est de post-traiter le PDF avec un outil dédié. Le module Factur-X s’appuie souvent sur la bibliothèque atgp/factur-x qui gère elle-meme l’embedding XML dans un PDF/A-3. Si le module utilise cette bibliothèque correctement, le PDF/A-3 est pris en charge.
Si le PDF produit n’est pas conforme, vérifier dans la configuration du module :
- Que l’option “Générer en PDF/A” est activée (si disponible)
- Que les polices configurées dans Dolibarr sont bien des polices TrueType embarquées (pas des polices core PDF)
- Que la bibliothèque
atgp/factur-xest bien installée via Composer
# Vérifier l'installation de la bibliothèque dans le répertoire du module
cd /var/www/dolibarr/htdocs/custom/facturx
composer show atgp/factur-x
Pour un diagnostic approfondi des erreurs PDF/A-3, voir PDF/A-3 pour Factur-X : checklist de conformité.
Erreur 2 — Champs obligatoires manquants
Symptome : erreurs Schematron de type BR-CO-26, BR-05, BR-09.
Causes et corrections :
BR-CO-26 — Aucun identifiant vendeur : au moins un des champs BT-29, BT-30 ou BT-31 doit être présent. Solution : renseigner le SIRET (BT-30) dans la fiche société Dolibarr comme décrit plus haut.
BR-05 — Devise absente : le code devise (BT-5) n’est pas renseigné dans le XML. Dans Dolibarr, vérifier que la devise par défaut est configurée dans Accueil > Configuration > Société/Organisation > onglet “Identité” (champ “Devise”). La devise doit être un code ISO 4217 alpha-3 (EUR).
BR-09 — Code pays vendeur absent : le pays de l’émetteur n’est pas dans le XML. Vérifier que le pays est bien sélectionné dans la fiche société Dolibarr.
Erreur 3 — BT-44 nom de l’acheteur manquant
Symptome : erreur Schematron sur le nœud BuyerTradeParty/Name.
Cause : la fiche tiers du client dans Dolibarr a un nom vide ou non exploitable. Le module Factur-X lit le champ nom de la table llx_societe pour alimenter BT-44. Si ce champ est vide, l’erreur est inévitable.
Correction : dans Dolibarr, ouvrir la fiche du tiers client et vérifier que le champ “Nom” est renseigné avec la raison sociale complète. Pour vérifier toutes les fiches en lot :
-- Identifier les tiers sans nom (à exécuter dans phpMyAdmin ou en CLI)
SELECT rowid, nom, code_client
FROM llx_societe
WHERE fournisseur = 0
AND (nom IS NULL OR nom = '');
Erreur 4 — Déclaration de profil incohérente
Symptome : le validateur indique une incohérence entre le profil déclaré dans les métadonnées et le contenu XML.
Cause : le profil Factur-X est déclaré dans le nœud GuidelineSpecifiedDocumentContextParameter du XML. Si le module déclare le profil EN16931 mais que le XML ne contient pas tous les champs requis par ce profil, la validation échoue.
L’identifiant de profil EN16931 dans le XML CII pour Factur-X 1.08 est :
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
Correction : s’assurer que le profil configuré dans le module correspond au niveau de détail effectivement renseigné dans Dolibarr. Si les fiches articles, clients et la fiche société sont complètes, le profil EN16931 peut etre alimenté. Si des informations manquent, soit les renseigner, soit réduire le profil déclaré (en gardant en tete que MINIMUM est insuffisant pour la réforme).
Erreur 5 — Arrondis et incohérences de montants (BR-CO-*)
Symptome : erreurs BR-CO-10, BR-CO-13, BR-CO-14, BR-CO-15 — les totaux ne correspondent pas.
Cause : Dolibarr calcule les montants avec sa propre logique d’arrondi (configurable dans Accueil > Configuration > Divers > Calculs). Le module Factur-X reprend ces montants pour le XML. Si la logique d’arrondi de Dolibarr et la vérification arithmétique Schematron ne concordent pas, des écarts d’un centime apparaissent.
Les règles Schematron concernées :
| Regle | Verification |
|---|---|
| BR-CO-10 | Somme des montants nets de ligne = total HT lignes (BT-106) |
| BR-CO-13 | Total HT (BT-109) = lignes + charges - remises |
| BR-CO-14 | Total TVA = somme des montants TVA par catégorie |
| BR-CO-15 | Total TTC (BT-112) = HT (BT-109) + TVA (BT-110) |
| BR-CO-17 | Montant TVA catégorie = base x taux / 100 (arrondi 2 décimales) |
Corrections :
-
Dans Accueil > Configuration > Divers, vérifier le paramètre “Nombre de décimales pour les arrondis de montants”. La valeur doit être 2 pour les devises à 2 décimales (EUR).
-
Vérifier le paramètre “Calcul TVA” : les modes “par ligne” et “sur total” produisent des résultats différents. Le mode “par ligne” (calcul de la TVA sur chaque ligne puis somme) est plus fiable pour la conformité Schematron car il évite les écarts d’arrondi cumulés.
-
Si des remises globales ou des frais sont appliqués, vérifier que le module les inclut dans les nœuds
AllowanceChargedu XML. Un écart entre les totaux Dolibarr et les totaux recalculés par Schematron provient souvent d’une remise ou d’un frais non transcrit dans le XML.
Pour comprendre en détail les règles BR-CO et le fonctionnement de la validation Schematron, voir Valider EN16931/Factur-X : XSD vs Schematron, erreurs BR-*.
Erreur 6 — Unité de mesure non conforme (BT-130)
Symptome : erreur Schematron sur BilledQuantity/@unitCode.
Cause : Dolibarr stocke les unités dans un dictionnaire interne (Accueil > Configuration > Dictionnaires > Unités de mesure). Le module Factur-X doit mapper ces unités vers les codes UN/ECE Rec 20. Si le mapping n’est pas configuré, le XML contient un label en clair (“pièce”, “heure”) au lieu du code normalisé (C62, HUR).
Codes UN/ECE les plus utilisés :
| Code | Signification |
|---|---|
C62 | Unité / pièce |
HUR | Heure |
DAY | Jour |
MON | Mois |
KGM | Kilogramme |
MTR | Mètre |
LTR | Litre |
SET | Ensemble / lot |
Correction : vérifier dans la configuration du module Factur-X que chaque unité Dolibarr est mappée vers un code UN/ECE. Si le module ne propose pas de table de mapping, il faut modifier les valeurs du dictionnaire Dolibarr pour qu’elles correspondent aux codes normalisés, ou intervenir dans le code du module.
Intégrer l’API FacturX pour la validation pre-envoi
La validation manuelle d’une facture est suffisante pour un test ponctuel. Mais dans un contexte de production, avec des dizaines ou des centaines de factures par mois, il faut un pipeline automatisé qui valide chaque facture avant l’envoi à la PDP.
L’API FacturX permet d’automatiser cette validation via un appel HTTP depuis Dolibarr ou un script intermédiaire.
Validation d’un fichier PDF Factur-X
curl -X POST https://facturxapi.com/api/v1/validate \
-H "X-API-Key: votre-cle-api" \
-F "[email protected]"
La réponse indique si le fichier est conforme et, le cas échéant, la liste exhaustive des erreurs :
{
"valid": false,
"profile": "EN16931",
"errors": [
{
"id": "BR-CO-15",
"type": "error",
"message": "Le montant TTC (BT-112) doit être égal au montant HT (BT-109) plus le total TVA (BT-110).",
"location": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeSettlement"
}
],
"warnings": [],
"pdfConformance": {
"valid": true,
"standard": "PDF/A-3b"
}
}
Appel depuis un hook Dolibarr (PHP)
Dolibarr dispose d’un système de hooks qui permet d’exécuter du code personnalisé lors d’événements précis. Le hook le plus pertinent pour la validation Factur-X est celui déclenché après la génération du PDF.
Voici un exemple d’implémentation dans un module personnalisé Dolibarr :
<?php
// htdocs/custom/monmodule/class/actions_monmodule.class.php
class ActionsMonmodule
{
/**
* Hook exécuté après la génération du PDF de facture.
* Valide le fichier Factur-X via l'API avant tout envoi.
*/
public function afterPDFCreation($parameters, &$object, &$action, $hookmanager)
{
if ($object->element !== 'facture') {
return 0;
}
$filePath = $parameters['file'];
if (!file_exists($filePath)) {
return 0;
}
$apiKey = getDolGlobalString('FACTURX_API_KEY');
if (empty($apiKey)) {
dol_syslog('FacturX API key not configured', LOG_WARNING);
return 0;
}
$result = $this->validateFacturX($filePath, $apiKey);
if ($result === false) {
dol_syslog('FacturX validation: API call failed', LOG_ERR);
return 0;
}
if (!$result['valid']) {
$errorMessages = [];
foreach ($result['errors'] as $error) {
$errorMessages[] = $error['id'] . ': ' . $error['message'];
dol_syslog('FacturX validation error: ' . $error['id'] . ' - ' . $error['message'], LOG_ERR);
}
setEventMessages(
'Factur-X non conforme : ' . implode(' | ', $errorMessages),
null,
'errors'
);
// Retourner 1 pour signaler un avertissement (ne bloque pas la génération)
// Retourner -1 pour bloquer (selon la politique de l'entreprise)
return 1;
}
setEventMessages('Factur-X validé avec succès (profil ' . $result['profile'] . ')', null, 'mesgs');
return 0;
}
/**
* Appel à l'API de validation FacturX.
*
* @param string $filePath Chemin du fichier PDF
* @param string $apiKey Clé API FacturX
* @return array|false Résultat de la validation ou false en cas d'erreur
*/
private function validateFacturX(string $filePath, string $apiKey)
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://facturxapi.com/api/v1/validate',
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $apiKey,
],
CURLOPT_POSTFIELDS => [
'file' => new CURLFile($filePath, 'application/pdf'),
],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error !== '' || $httpCode !== 200) {
dol_syslog(
'FacturX API error: HTTP ' . $httpCode . ' - ' . $error,
LOG_ERR
);
return false;
}
$decoded = json_decode($response, true);
if (!is_array($decoded)) {
dol_syslog('FacturX API: invalid JSON response', LOG_ERR);
return false;
}
return $decoded;
}
}
Pour activer ce hook, ajouter la classe dans le descripteur du module (core/modules/modMonModule.class.php) avec le hook afterPDFCreation. La clé API se configure dans un paramètre Dolibarr via Accueil > Configuration > Divers > Paramètres divers (constante FACTURX_API_KEY).
Configurer la clé API dans Dolibarr
La clé API ne doit pas etre codée en dur dans le code source. Dolibarr fournit un mécanisme de constantes globales pour stocker ce type de configuration.
Via l’interface : Accueil > Configuration > Divers > Paramètres divers. Ajouter une entrée :
- Nom de la constante :
FACTURX_API_KEY - Valeur : votre clé API
- Entité :
0(toutes les entités) ou l’entité spécifique
Via la CLI Dolibarr (si disponible) :
php scripts/setup_const.php FACTURX_API_KEY "votre-cle-api" 0
Workflow complet : Dolibarr vers la PDP
Le workflow recommandé pour une utilisation en production est le suivant :
Dolibarr (saisie facture)
│
▼
Génération PDF + XML CII (module Factur-X)
│
▼
Validation API FacturX (hook afterPDFCreation)
│
├── ✓ Conforme → facture prête pour envoi
│ │
│ ▼
│ Envoi vers la PDP (manuellement ou via connecteur)
│
└── ✗ Non conforme → erreurs affichées dans Dolibarr
│
▼
Correction des données (fiche société, tiers, articles)
│
▼
Régénération du PDF → nouvelle validation
Ce pipeline permet de garantir que chaque facture envoyée à la PDP sera acceptée au premier passage. Les rejets PDP ont des conséquences directes : retard de paiement, relances manuelles, et potentiellement des pénalités en cas de manquement répété aux obligations de dématérialisation.
Validation en lot
Pour les entreprises qui génèrent un volume important de factures, un script de validation en lot peut compléter le hook unitaire :
<?php
// scripts/validate_facturx_batch.php
// Valide toutes les factures d'un mois donné
require '../htdocs/master.inc.php';
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
$apiKey = getDolGlobalString('FACTURX_API_KEY');
if (empty($apiKey)) {
print "Erreur : constante FACTURX_API_KEY non configurée\n";
exit(1);
}
$year = $argv[1] ?? date('Y');
$month = $argv[2] ?? date('m');
$sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "facture";
$sql .= " WHERE datef BETWEEN '" . $db->escape($year . '-' . $month . '-01') . "'";
$sql .= " AND LAST_DAY('" . $db->escape($year . '-' . $month . '-01') . "')";
$sql .= " AND fk_statut > 0";
$resql = $db->query($sql);
if (!$resql) {
print "Erreur SQL : " . $db->lasterror() . "\n";
exit(1);
}
$total = 0;
$valid = 0;
$invalid = 0;
$errors = [];
while ($obj = $db->fetch_object($resql)) {
$facture = new Facture($db);
$facture->fetch($obj->rowid);
$dir = $conf->facture->dir_output . '/' . get_exdir(0, 0, 0, 1, $facture, 'invoice');
$file = $dir . '/' . $facture->ref . '.pdf';
if (!file_exists($file)) {
$errors[] = $facture->ref . ' : fichier PDF introuvable';
$total++;
continue;
}
// Appel API (réutiliser la fonction validateFacturX du hook)
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://facturxapi.com/api/v1/validate',
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . $apiKey],
CURLOPT_POSTFIELDS => ['file' => new CURLFile($file, 'application/pdf')],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$total++;
if ($httpCode !== 200) {
$errors[] = $facture->ref . ' : erreur API (HTTP ' . $httpCode . ')';
continue;
}
$result = json_decode($response, true);
if (!is_array($result)) {
$errors[] = $facture->ref . ' : réponse API invalide';
continue;
}
if ($result['valid']) {
$valid++;
print " ✓ " . $facture->ref . " — conforme (" . $result['profile'] . ")\n";
} else {
$invalid++;
$errIds = array_map(fn($e) => $e['id'], $result['errors']);
print " ✗ " . $facture->ref . " — " . implode(', ', $errIds) . "\n";
}
}
print "\n";
print "Résultats pour $month/$year :\n";
print " Total : $total\n";
print " Conformes : $valid\n";
print " Invalides : $invalid\n";
print " Erreurs : " . count($errors) . "\n";
if (!empty($errors)) {
print "\nDétail des erreurs :\n";
foreach ($errors as $err) {
print " - $err\n";
}
}
Exécution :
php scripts/validate_facturx_batch.php 2026 09
Ce script permet d’auditer un lot de factures avant une échéance (par exemple, avant la date d’obligation de réception en septembre 2026) et d’identifier systématiquement les fiches clients ou les configurations à corriger.
Conseils pour les développeurs qui étendent le module
Structure du XML CII Factur-X
Le XML CII (Cross-Industry Invoice) suit la structure UN/CEFACT D22B (pour Factur-X 1.08, extension rétrocompatible de D16B). Le namespace racine est urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100.
Les nœuds principaux :
<?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">
<!-- Contexte : profil, process -->
<rsm:ExchangedDocumentContext>
<ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
</ram:BusinessProcessSpecifiedDocumentContextParameter>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<!-- En-tête : numéro, type, date -->
<rsm:ExchangedDocument>
<ram:ID>FA-2026-001</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="102">20260901</udt:DateTimeString>
</ram:IssueDateTime>
</rsm:ExchangedDocument>
<!-- Corps : parties, lignes, totaux -->
<rsm:SupplyChainTradeTransaction>
<!-- ... -->
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
Utiliser la bibliothèque atgp/factur-x
La bibliothèque atgp/factur-x simplifie la génération du PDF Factur-X depuis PHP. Elle prend un PDF existant et un XML CII, et produit un PDF/A-3 avec le XML embarqué.
<?php
use Atgp\FacturX\Facturx;
$facturx = new Facturx();
// Générer le PDF Factur-X à partir du PDF Dolibarr et du XML CII
$pdfFacturx = $facturx->generateFacturX(
$pdfContent, // Contenu du PDF original (string)
$xmlContent, // Contenu du XML CII (string)
'EN16931' // Profil Factur-X
);
file_put_contents('/path/to/facture-facturx.pdf', $pdfFacturx);
La bibliothèque gère les aspects PDF/A-3 : profil ICC, métadonnées XMP, embedding avec AFRelationship. Cela évite d’avoir à manipuler les structures PDF bas niveau.
Points d’attention pour les contributeurs
Versionnement Factur-X : la version 1.08 (publiée en 2024) est basée sur CII D22B. C’est une extension rétrocompatible de D16B qui ajoute des champs optionnels sans casser les fichiers existants. Vérifier que le module référence les bons schémas XSD et Schematron.
Tests de non-régression : après chaque modification du module, valider un jeu de factures représentatives (facture simple, avoir, facture avec remise globale, facture multi-TVA, facture B2G). Chaque cas exerce des chemins de code différents dans la génération XML.
Hooks Dolibarr disponibles : au-delà de afterPDFCreation, les hooks beforePDFCreation (pour modifier les données avant génération), createFrom (lors de la création d’avoir depuis une facture), et formObjectOptions (pour ajouter des champs dans le formulaire de facture) peuvent etre utiles pour enrichir l’intégration Factur-X.
Checklist de conformité Dolibarr + Factur-X
CONFIGURATION DOLIBARR POUR FACTUR-X — CHECKLIST
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Fiche société (Configuration > Société/Organisation)
☐ Raison sociale renseignée (BT-27)
☐ SIRET 14 chiffres sans espaces (BT-30)
☐ N° TVA intracommunautaire format FRXX... (BT-31)
☐ Adresse complète : rue, ville, code postal, pays (BT-35 à BT-40)
☐ Devise par défaut = EUR (BT-5)
☐ Compte bancaire avec IBAN (BT-84)
Fiches tiers clients
☐ Nom / raison sociale renseigné (BT-44)
☐ Adresse complète : rue, ville, code postal, pays (BT-50 à BT-55)
☐ SIRET client pour B2B (BT-47)
☐ N° TVA client si intracommunautaire (BT-48)
Module Factur-X
☐ Module installé et activé
☐ Profil par défaut = EN16931
☐ Bibliothèque atgp/factur-x installée
☐ Mapping unités de mesure → codes UN/ECE Rec 20
Calculs et arrondis
☐ Nombre de décimales = 2 pour EUR
☐ Mode de calcul TVA = par ligne (recommandé)
☐ Remises/frais correctement transcrits dans le XML
Validation
☐ Clé API FacturX configurée (FACTURX_API_KEY)
☐ Hook de validation activé
☐ Test sur une facture représentative : validation OK
☐ Test sur un avoir : validation OK
☐ Test sur une facture multi-TVA : validation OK
Ressources
- Facturation électronique 2026 : le guide technique complet — calendrier, obligations, architecture technique
- Champs obligatoires EN16931 : cartographie et mapping ERP — tous les BT obligatoires et leur mapping
- PDF/A-3 pour Factur-X : checklist de conformité — diagnostic et correction des erreurs PDF/A-3
- Valider EN16931/Factur-X : XSD vs Schematron, erreurs BR-* — comprendre les erreurs Schematron
- Profils Factur-X : MINIMUM, BASIC, EN16931, EXTENDED — choisir le bon profil