Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Dieleman committed Nov 6, 2023
1 parent 16b3739 commit 7707f35
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 88 deletions.
54 changes: 39 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
PHP Factur-X library
------------------
Factur-X is the e-invoicing standard for France and Germany. The Factur-X specifications are available on the FNFE-MPE website. The Factur-X standard is also called ZUGFeRD 2.0 in Germany.

Factur-X is a Franco-German e-invoicing standard which complies with the European e-invoicing standard [EN 16931](https://ec.europa.eu/digital-building-blocks/wikis/display/DIGITAL/Obtaining+a+copy+of+the+European+standard+on+eInvoicing).
The Factur-X specifications are available on the [FNFE-MPE](http://fnfe-mpe.org/factur-x/) website in English and French.
The Factur-X standard is also called [ZUGFeRD 2.2](https://www.ferd-net.de/standards/zugferd-2.2/zugferd-2.2.html) in Germany.

This library enable you to manage your Factur-X PDF invoices files :
* **Generate Factur-X PDF invoice** from regular PDF invoice and Factur-X XML file
* **Extract Factur-X XML** from Factur-X PDF invoice
* **Check Factur-X XML** against the official Factur-X XML Schema Definition
* **Validate Factur-X XML** against the official Factur-X XML Schema Definition

Table of contents:
------------------
Expand All @@ -14,12 +17,12 @@ Table of contents:
- [Installation](#installation)
- [Usage](#usage)
- [License](#license)
- [Changelog](#changelog)
- [Contributing](CONTRIBUTING.md)

Requirements
------------
- Apache2
- PHP 5.6+
- PHP 7.4+
- Composer
- [FPDI](https://github.com/Setasign/FPDI) (MIT License)
- [Smalot](https://github.com/smalot/pdfparser) (LGPL License)
Expand All @@ -28,7 +31,7 @@ Requirements
Installation
------------

#### Download with Composer
#### Install with Composer

```bash
composer require atgp/factur-x
Expand All @@ -37,24 +40,45 @@ composer require atgp/factur-x
Usage
-----
You can see the code from test page from "tests" directory, also here some simple examples of implementation :

```php
<?php
// Include or autoload (with Composer) all library classes

// Generating Factur-X PDF invoice from PDF and Factur-X XML
$facturx = new Facturx();
$facturxPdf = $facturx->generateFacturxFromFiles($pdf, $facturxXml);
// Generates Factur-X PDF invoice from PDF and Factur-X XML
$writer = new \Atgp\FacturX\Writer();
$facturxPdf = $writer->generate($pdf, $facturxXml);

// Extract Factur-X XML
$facturx = new Facturx();
$facturxXml = $facturx->getFacturxXmlFromPdf($facturxPdf);
// Extracts Factur-X XML
$reader = new \Atgp\FacturX\Reader();
$facturxXml = $reader->extractXML($facturxPdf);

// Check Factur-X XML against official Factur-X XML Schema Definition
$facturx = new Facturx();
$isValid = $facturx->checkFacturxXsd($facturxXml);
// Validates Factur-X XML against official Factur-X XML Schema Definition
$validator = new \Atgp\FacturX\XsdValidator();
if (false === ($isValid = $validator->validate($facturxXml)) {
var_dump($validator->getErrors());
}
// ... or throw exceptions if error(s) are occurred
$validator->validateWithException($facturxXml);
```
More options are available, look at source code for more informations

More options are available, look at source code for more information.

License
-------
This project is licensed under MIT License

Changelog
---------

- v2.0.0 [BC] : 2023-11-06
- Requires php 7.4+
- Refactor classes to clarify uses
- Simplify requirements for "smalot/pdfparser"
- Import external links on generated factur-x pdf
- v1.1.0 : 2019-01-09
- Upgrade Factur-x xsd to v1.0.06
- Fix PDF-A compliance regarding endobj and ICC profile
- v1.0.0 : 2019-01-09
- Requires php 5.6+
- First version of the library to read, check and write factur-x documents
143 changes: 70 additions & 73 deletions tests/index.php
Original file line number Diff line number Diff line change
@@ -1,79 +1,76 @@
<?php
include_once '../vendor/autoload.php';
$resultHeaderClass = 'warning';
$resultHeaderHtml = '';
$resultBodyHtml = '';

if (isset($_FILES['pdf_facturx_extract']) && !empty($_FILES['pdf_facturx_extract'])) {
$resultHeaderHtml = 'Extract Factur-X XML from PDF result';
$reader = new \Atgp\FacturX\Reader();
$resultBodyHtml .= "<h4 class='text-primary'>File ".$_FILES['pdf_facturx_extract']['name'].' : </h4>';
try {
$content = file_get_contents($_FILES['pdf_facturx_extract']['tmp_name']);
$result = $reader->extractXML($content, true);
$resultHeaderClass = 'success';
$doc = new DOMDocument('1.0');
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($result);
$resultBodyHtml .= '<pre lang="xml">'.htmlentities($doc->saveXML()).'</pre>';
} catch (Exception $e) {
$resultBodyHtml .= '<div class="alert alert-danger">'.$e.'</div>';
}
}

if (isset($_FILES['xml_facturx_check']) && !empty($_FILES['xml_facturx_check'])) {
$validator = new \Atgp\FacturX\XsdValidator();
$resultHeaderHtml = 'Check XML Factur-X result';
$resultBodyHtml = "<h4 class='text-primary'>File ".$_FILES['xml_facturx_check']['name'].' : </h4>';
$content = file_get_contents($_FILES['xml_facturx_check']['tmp_name']);

try {
if (!$validator->validate($content)) {
$resultBodyHtml .= '<div class="alert alert-warning">'.implode('<br />', $validator->getErrors()).'</div>';
} else {
$resultHeaderClass = 'success';
$resultBodyHtml .= '<div class="alert alert-success">XML Factur-X valid.</div>';
}
} catch (Exception $e) {
$resultBodyHtml .= '<pre>Error while checking the XML :'.$e.'</pre>';
}
}

if (isset($_FILES['pdf_classic']) && !empty($_FILES['pdf_classic'])) {
$writer = new \Atgp\FacturX\Writer();
$resultHeaderHtml = 'Generate PDF Factur-X from PDF and Factur-X XML result';
try {
$pdf = file_get_contents($_FILES['pdf_classic']['tmp_name']);
$xml = file_get_contents($_FILES['xml_facturx_tolink']['tmp_name']);
$attachment_files = [];
if (!empty($_FILES['attachment']['tmp_name'])) {
$attachment_files[] = [
'name' => $_FILES['attachment']['name'],
'desc' => $_POST['attachment_desc'],
'path' => $_FILES['attachment']['tmp_name'],
];
}
$result = $writer->generate($pdf, $xml, null, true, $attachment_files, true, $_POST['relationship']);
} catch (Exception $e) {
$resultBodyHtml = 'Error while generating the Factur-X :<pre>'.$e.'</pre>';
}
if (!empty($result)) {
header('Content-disposition: attachment; filename="facturx.pdf"');
header('Content-Type: application/pdf');
header('Content-Length: '.strlen($result));
echo $result;
exit;
}
$resultBodyHtml = '<div class="alert alert-warning">Impossible to generate the Factur-X PDF file.</div>'.$resultBodyHtml;
}
?>
<html lang="en">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<body>
<?php
include_once '../vendor/autoload.php';
$resultHeaderClass = 'warning';
$resultHeaderHtml = '';
$resultBodyHtml = '';
if ($_FILES['pdf_facturx_extract']) {
$resultHeaderHtml = 'Extract Factur-X XML from PDF result';
$facturx = new \Atgp\FacturX\Facturx();
$resultBodyHtml .= "<h4 class='text-primary'>File ".$_FILES['pdf_facturx_extract']['name'].' : </h4>';
try {
$result = $facturx->getFacturxXmlFromPdf($_FILES['pdf_facturx_extract']['tmp_name'], true);
} catch (Exception $e) {
$resultBodyHtml .= '<pre>Error while retrieving XML Factur-X :'.$e.'</pre>';
}
if (!$result) {
$resultBodyHtml .= '<div class="alert alert-danger">No valid XML Factur-X found.</div>';
} else {
$resultHeaderClass = 'success';
$doc = new DomDocument('1.0');
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($result);
$resultBodyHtml .= '<pre lang="xml">'.htmlentities($doc->saveXML()).'</pre>';
}
}
if ($_FILES['xml_facturx_check']) {
$facturx = new \Atgp\FacturX\Facturx();
$resultHeaderHtml = 'Check XML Factur-X result';
$resultBodyHtml = "<h4 class='text-primary'>File ".$_FILES['xml_facturx_check']['name'].' : </h4>';
try {
$result = $facturx->checkFacturxXsd($_FILES['xml_facturx_check']['tmp_name']);
} catch (Exception $e) {
$resultBodyHtml .= '<pre>Error while checking the XML :'.$e.'</pre>';
}
if (true === $result) {
$resultHeaderClass = 'success';
$resultBodyHtml .= '<div class="alert alert-success">XML Factur-X valid.</div>';
} else {
$resultBodyHtml .= '<div class="alert alert-warning">XML Factur-X invalid.</div>';
}
}
if ($_FILES['pdf_classic'] && $_FILES['xml_facturx_tolink']) {
$facturx = new \Atgp\FacturX\Facturx();
$resultHeaderHtml = 'Generate PDF Factur-X from PDF and Factur-X XML result';
try {
if ('true' == $_POST['file_as_string']) {
$pdf = file_get_contents($_FILES['pdf_classic']['tmp_name']);
$facturx_xml = file_get_contents($_FILES['xml_facturx_tolink']['tmp_name']);
} else {
$pdf = $_FILES['pdf_classic']['tmp_name'];
$facturx_xml = $_FILES['xml_facturx_tolink']['tmp_name'];
}
$attachment_files = [];
if (!empty($_FILES['attachment']['tmp_name'])) {
$attachment_files[] = [
'name' => $_FILES['attachment']['name'],
'desc' => $_POST['attachment_desc'],
'path' => $_FILES['attachment']['tmp_name'],
];
}
$result = $facturx->generateFacturxFromFiles($pdf, $facturx_xml,
'autodetect', true, __DIR__.'/', $attachment_files, true, $_POST['relationship']);
} catch (Exception $e) {
$resultBodyHtml = 'Error while generating the Factur-X :<pre>'.$e.'</pre>';
}
if (!empty($result)) {
$resultHeaderClass = 'success';
$resultBodyHtml = '<div class="alert alert-success">Factur-X PDF file successfully generated.</div>';
} else {
$resultBodyHtml = '<div class="alert alert-warning">Impossible to generate the Factur-X PDF file.</div>'.$resultBodyHtml;
}
}
?>
<div class="container-fluid">
<div class="card">
<div class="card-header bg-info text-white">
Expand Down

0 comments on commit 7707f35

Please sign in to comment.