eInvoice Validator for KoSIT – Manual
1 · Overview
eInvoice Validator for KoSIT is a WordPress plugin. It provides a drop zone on a page of your site on which a visitor drops an e-invoice. The invoice is checked by your own KoSIT validator, the reference validator of the German XRechnung. The validation report appears on the page and can be downloaded as an XML file.
Caution: The plugin contains no validator. It drives a validator that you have installed yourself or run in your own network. It is an independent tool by invoicePress, not a product of KoSIT, has no connection with KoSIT and is not endorsed by it.
Who it is for: for everyone who already runs the KoSIT validator or wants to install it and needs a page on which suppliers, colleagues or customers can check an invoice without using a command line.
What it does:
- It accepts XML invoices as well as ZUGFeRD and Factur-X PDFs by drag and drop or by file selection.
- It checks the invoice in one of two ways: with the validator as a local Java program on the web server, or through a validation service. A validation service is a Validator Bridge or a website with the plugin eInvoice API; both offer the same addresses.
- It shows the report on the page, with a plain-language explanation and the affected field for every finding.
- It offers the complete, unchanged KoSIT report as an XML file for download.
- It optionally shows the invoice in KoSIT's official visualization, if you provide its files.
- It shows a systemcheck on the settings page that says, per backend, which requirement is missing and what to do.
- It optionally remembers the checksum (SHA-256) of the
validator.jarand refuses to validate as soon as the file no longer matches it. - It limits the number of checks per visitor and day, and the file size.
- It also offers the check through the REST address
POST /wp-json/einvoice/v1/validate.
What it does not do:
- It cannot check anything by itself. Without a KoSIT installation or a reachable validation service nothing is checked; the systemcheck says so.
- It does not download or install the validator. The plugin makes no outgoing request of its own accord.
- It does not check whether a newer release of the KoSIT validator has appeared.
- It offers exactly two backends: the local validator and the validation service.
- It is not a queue. A very large invoice occupies the request for as long as the validator needs.
Requirements:
| What | Requirement |
|---|---|
| WordPress | 5.8 or newer (tested up to 7.1) |
| PHP | 8.2 or newer |
| Local backend | a Java runtime from version 17 on the web server, the KoSIT validator (validator.jar and scenario configurations) and the PHP function proc_open |
| Validation service | a running Validator Bridge or a website with eInvoice API, and outgoing HTTP from the web server to the address you enter; no Java on the web server |
| Visitor's browser | JavaScript must be enabled |
screenshots/vk-ablage.en.pngThe drop zone on a page of the site, below it the note on the checks still available today2 · Installation
Option A: upload the ZIP file in WordPress
Option B: copy the folder
Option C: wordpress.org
Distribution through the wordpress.org plugin directory is planned, but the plugin has not been published there yet. Until then use option A or option B.
Providing the KoSIT validator
The plugin only works once it reaches a validator. You provide one of the two ways:
Note: The KoSIT validator, its scenario configurations and the Java runtime have their own licences and their own release cycle. You obtain and update them yourself.
Updating
You replace the plugin with the new version by uploading the new ZIP file as in option A, or by exchanging the folder under /wp-content/plugins/ as in option B. As long as the plugin is not on wordpress.org, WordPress does not announce a new version by itself. The settings are stored in the database and are kept. If you replace the validator.jar itself with a new version and a checksum was pinned, you have to accept the new file (see chapter 4, "The checksum of the validator.jar").
Removing
You deactivate and delete the plugin on the Plugins page. The KoSIT validator and Java are not affected, because they are not part of the plugin. In the database the plugin stores the settings from chapter 5 as well as the accepted version and checksum of the jar (spko_jar_version, spko_jar_sha256). The plugin does not clean up on deletion; all these entries stay in the database, including the key of the validation service. If you do not want that, empty the key field and click Forget accepted hash before deleting.
3 · First steps
screenshots/vk-einstellungen.en.pngThe settings page with the choice of backend and the green note that validator.jar was foundscreenshots/vk-bericht-ok.en.pngA validation report for an invoice without findings, above it the button to download the report4 · Working with eInvoice Validator for KoSIT
Checking an invoice
The visitor drags a file onto the drop zone, or clicks it and chooses a file. The zone can also be operated with the keyboard (Enter or Space). Files ending in .xml or .pdf are accepted, that is CII or UBL XML and ZUGFeRD or Factur-X PDF. During the check the note below the zone says that the validator is running and that this can take up to 15 seconds. Then the report appears.
Checking an invoice from a PDF
With a ZUGFeRD or Factur-X PDF, the visitor's browser takes the embedded invoice XML out of the PDF. Only this XML goes to the server, not the PDF. If the PDF contains no invoice, the page reports that this PDF carries no e-invoice: a PDF that was merely printed has no XML attachment.
Reading the report
Above the report there is a header with the download button. The report itself shows the result and the findings. Since version 1.5.0 it appears in the same view as in the eInvoice Validation Explorer, with a plain-language explanation and the affected field for every finding; this also applies when the Explorer is not installed. A finding about an attachment of the invoice names the attachment.
The result comes from the validator's own recommendation, not from the report's valid flag. A report whose findings are only warnings is an accepted invoice and is shown as such.
Next to the report there is a document view of the invoice. It marks fields that break a rule from the invoice itself with a note below the field. Numbers and dates follow the language of the site.
If the plain-language view cannot be built, the plugin shows a simpler report view. If the report cannot be interpreted at all, the validator's raw output appears as a last resort in a shielded frame in which no scripts run.
screenshots/vk-bericht-befunde.en.pngA validation report with findings: result, list of findings with explanation and affected fieldDownloading the report
The button "Download report.xml" saves the complete KoSIT report as an XML file; the row next to it is called "Validation report". The file is named after the checked invoice with the suffix -report.xml, for example invoice-4711-report.xml. It is the validator's report (rep:report), unchanged.
The button next to it, "Download report.html", saves the report the KoSIT validator also writes as an HTML page, likewise unchanged. The page opens without an internet connection and can be printed and passed on. The KoSIT validator writes it in German, also on an English website.
Showing the invoice
If a suitable folder is entered under "Invoice visualization ( optional )", the button Show invoice stands under the report. It shows the checked invoice in KoSIT's official visualization, the xrechnung-visualization, directly above the report. The visualization is produced on your server with the Java and the validator.jar set for the local backend, also when the check runs through the validation service. On a German site it appears in German, otherwise in English, because KoSIT supplies only these two languages. Each visualization counts against the daily limit like a check.
The systemcheck
Below the settings is the "Systemcheck". It shows a table for each of the two backends; the chosen backend is marked "active". Every row is green (tick) or red (cross). A red row names the next step. Among other things it checks starting processes, Java, the jar and its integrity, the PHP version, extensions and memory. The check runs anew every time the page loads.
Note: The plugin never downloads the validator.jar itself. If it is missing or no longer matches, the row names the way: put the file from KoSIT's release into the folder bin/ by hand and accept it with Accept the file on disk. The plugin needs no write access to the validator directory.
screenshots/vk-systempruefung.en.pngThe systemcheck with green and red rows for both backends, the next step at a red rowTesting the connection
Under each table is the button Test connection. It sends a small test document to the respective backend, also to the one that is not active at the moment. So you can test the validation service while the site still checks locally. On success "Connected. Round trip: … ms." appears in green with the time in milliseconds. On an error the backend's message stands next to it in red.
The checksum of the validator.jar
In the section "validator.jar" of the settings page you see side by side what is on disk (size, version from the jar itself, SHA-256) and what you have accepted (version, SHA-256). If both checksums exist, a row of its own says whether they match.
- The button Accept the file on disk computes the checksum of the existing file and remembers it. Afterwards "Done - reload this page to see the updated systemcheck." appears.
- As long as no checksum is accepted, the jar is not verified before a run.
- If the file later no longer matches the accepted checksum, the plugin refuses to validate until you accept the new file.
- The button Forget accepted hash only appears when one is remembered. It removes the binding.
screenshots/vk-jar-pruefsumme.en.pngThe section validator.jar with both checksums side by side and the row on whether they matchThe daily limit
Below the drop zone stands "Remaining uploads today: …" with the number of checks the visitor still has today. Only successful runs are counted. When the limit is reached, the page reports "You have reached the daily upload limit. Please try again tomorrow."
5 · Settings
All settings are under eInvoice Validator → KoSIT. The page is reserved for users with the right to manage options (manage_options).
Section "E-Invoice Validator KoSIT"
| Setting | Default | Effect |
|---|---|---|
| Validator backend | local validator | Chooses the backend: "Local ( java -jar, on this server )" or "Validation service ( Validator Bridge or eInvoice API, over HTTP )". Both backends produce the same report for the same document. |
| Validator directory ( local ) | empty | Directory containing bin/validator.jar and per format config/<name>/scenarios.xml, for example C:\kosit-validator. |
| Java binary ( local ) | java | How Java is called. java is enough if it is on the search path; otherwise the full path to the Java program. |
| Timeout ( local, seconds ) | 60 | Time limit for a local run, at least 5. Below the field it says a run typically takes 10 to 15 seconds. On a workstation a run against the three scenario collections took about 4 seconds; a weaker web server needs longer. Leave headroom above that. |
| Daily uploads per role | every role 10 | A table with one row for guests ( not logged in ) and one row for each role of the site. Per row: empty means unlimited, 0 means no access, a number means that many checks per calendar day. Logged-in users are counted by user, guests by IP address. A user with several roles gets the most generous value. Administrators are never limited. Until the table is saved for the first time, the previous single value applies to every role. |
| Maximum file size ( MB ) | 8 | Largest file accepted. The smaller of this setting and the WordPress upload limit applies. |
| Trust proxy header | off | Takes the visitor's address from the header X-Forwarded-For. Only enable behind a trusted reverse proxy. |
| Invoice visualization ( optional ) | empty | Folder of KoSIT's unpacked xrechnung-visualization release containing xsl\xrechnung-html.xsl, for example C:\kosit-visualization. Below it, a line says whether the files were found. If the field stays empty, there is no Show invoice button. |
| Design kit | Kit H | Design of drop zone and report. The choice applies to all eInvoice tools on the site. |
Section "Validation service ( Validator Bridge or eInvoice API )"
You only need these fields for the backend "validation service". A validation service is one of two kinds of service that offer the same addresses:
- Validator Bridge: a small free service that runs the KoSIT validator on this or another computer and offers it over HTTP; its manual comes with it.
- eInvoice API: a WordPress website with the plugin eInvoice API, which passes the check on to its own bridge and grants a key and a quota for it.
| Setting | Default | Effect |
|---|---|---|
| Address of the validation service | empty | For a bridge the address it prints at its start, for example http://127.0.0.1:8090. For the eInvoice API of a website its REST address, for example https://example.com/wp-json/einvoice-api/v1. |
| API key of the validation service | empty | For a bridge on a server one of the keys in api.keys of its settings file. For the eInvoice API your API key of that website. A bridge on the same computer needs none. |
Choose "Validation service" under "Validator backend", save, and check in the systemcheck that the rows "The validation service answers" and "KoSIT is available in the validation service" carry a green tick. The first row names whether a Validator Bridge or an eInvoice API answers.
screenshots/vk-pruefdienst.en.pngThe section for the validation service with address and keyShortcode
| Shortcode | Attributes | Effect |
|---|---|---|
[spko_kosit_validator] | none | Shows the drop zone, the message line and the area for the report. |
[spko_kosit_validator]Note: Up to version 1.1.1 the shortcode was called [kosit_validator]. Pages with the old name need the new one.
6 · Special cases
You want to check but have no Java on the web server. Start a Validator Bridge on another computer or use a website with eInvoice API, choose the backend validation service and enter address and key. No Java is then needed on the web server.
Your site sits behind a reverse proxy. Without further setup all visitors would look like one single address for the daily limit. Switch on "Trust proxy header". The address the proxy appended is then counted, not one a visitor can send along themselves.
You replace the validator.jar with a new version. If you had accepted a checksum, the plugin refuses to validate after the exchange. Open the settings page, compare the two checksums and accept the file on disk.
You want to test the validation service before switching. Enter its address, save and click Test connection at the validation service in the systemcheck. The active backend stays the local one meanwhile.
7 · Working with other packages
The cooperation arises solely from the other plugin being active. There is nothing to set up.
| Package | What is added |
|---|---|
| eInvoice Viewer | An invoice already open in the viewer gets a button to check it with the KoSIT validator. |
| eInvoice Validation Explorer for KoSIT | The report appears in the Explorer's presentation, with plain-language sentences and BT/BG references. |
| Extended Profiles add-on | Findings about fields of an extension (BT-X) show their value from the document, and the rules of ZUGFeRD / Factur-X EXTENDED and EXTENDED-CTC-FR are explained. Without the add-on such a finding shows the identifier and the checker's message. |
| eInvoice Validator for VAMPIRE | Not a cooperation but the alternative: a plugin of its own with its own validation engine, for everyone who wants to check without a Java installation. |
screenshots/vk-viewer-knopf.en.pngAn invoice in the eInvoice Viewer with the button to check it with the KoSIT validator8 · Troubleshooting
| Sign | Cause | Remedy |
|---|---|---|
| Settings page: "Not configured yet." in red | The validator directory is empty. | Enter a directory containing bin/validator.jar and a folder config with the scenario configurations. |
| Settings page: "validator.jar was not found" in red | bin/validator.jar is missing in the directory entered. | Check the path; the file must be in the subfolder bin. Or use the validation service. |
| Red row in the systemcheck | A requirement of the backend is missing, for example Java or proc_open. | Carry out the next step the row names and reload the page. |
| Row "Match" with "NO - the file changed since you accepted it. Validation refuses to run until you accept the new one." | The validator.jar no longer matches the accepted checksum. | Check whether the exchange was intended, then Accept the file on disk. |
| Warning "The source you had configured no longer exists." | A backend unknown to this plugin is stored from an earlier installation. Checking runs locally for the time being. | Choose one of the two backends and save. |
| "The adapter responded, but not with the expected result for the connection-test fixture - something in the setup differs from what this plugin expects." | Something answers at the address or in the directory that does not behave like the expected validator. | Check address, directory and scenario configurations. |
| "Please choose a PDF or XML file." | The file has an extension other than .xml or .pdf. | Drop the invoice as XML or as a ZUGFeRD / Factur-X PDF. |
| "This PDF carries no e-invoice. A ZUGFeRD or Factur-X PDF has the invoice attached as XML; a PDF that was merely printed does not." | The PDF has no XML attachment, for example because it was only printed or scanned. | Use the XML invoice or a real ZUGFeRD / Factur-X PDF. |
| "The file is too large." | The file exceeds the configured size or the WordPress upload limit. | Raise "Maximum file size ( MB )" and, if necessary, the server's upload limit. |
| "You have reached the daily upload limit. Please try again tomorrow." | The visitor has used up today's allowed checks. | Try again tomorrow; as the operator, raise the role's number in "Daily uploads per role" or empty the field. |
| "This tool is not available for your account." | The visitor's role has a 0 in "Daily uploads per role". | As the operator, enter a number for this role or empty the field. |
| "Security check failed. Please reload the page." | The request's one-time token was invalid. | Reload the page and drop the file again. |
| "The KoSIT visualization is not configured." | The button was pressed, but the visualization folder is missing or incomplete. | Check "Invoice visualization ( optional )"; below the field it must say "Found". |
| "The validator took too long and was stopped." | The local run exceeded the time limit. | Raise "Timeout ( local, seconds )". |
| "The validator could not be started. Check the java binary and the validator path in the settings." | Java or the validator.jar cannot be started. | Look at the systemcheck; check "Java binary ( local )" and "Validator directory ( local )". |
| "The file on disk does not match the pinned hash - it may have been replaced or corrupted. Validation is refused until this is resolved." | The validator.jar no longer matches the accepted checksum. | As for the row "Match" above. |
| "The validation service could not be reached: …" or "The validation service answered with status …" | The validation service cannot be reached or answers with an error, for example 401 for a wrong key or 429 when the quota of an eInvoice API is used up. | Run "Test connection" at the validation service; check address and key. |
| The report appears as a plain table in a frame | The report could not be interpreted; the validator's raw output is shown. | Download the report; it is complete. Check the version of the validator and its configuration. |
9 · Privacy and security
What stays in the browser: A ZUGFeRD or Factur-X PDF does not leave the browser. The invoice XML is extracted there. The downloaded report file is also created in the browser from the report the page has already received.
What goes to your server: The invoice XML is sent to your own WordPress site. That is necessary because the plugin addresses the validator or the validation service from there.
- With the local backend the plugin writes the file into a throwaway directory, because the validator is a command-line tool and needs a file path. The directory and its content disappear at the end of the request, after success, after failure and after an exception.
- With the validation service the plugin sends the invoice over HTTP to the address you have entered. The plugin ships no address. If the field stays empty, nothing is sent anywhere.
Caution: You decide the address of the validation service. With your own Validator Bridge the invoices stay in your network. With the eInvoice API of another website they go to its operator, and his privacy policy and terms of use apply.
What goes to third parties: Nothing, as long as you do not enter another party's validation service. The plugin makes no outgoing request of its own accord, neither when a page loads nor on upload, during the check or in the admin area. It does not download the validator either.
What is stored: No copy of the invoice remains. Stored are the settings (including the key of the validation service, if entered), the accepted version and checksum of the jar, and the daily limit counter. The counter only records the number of checks: for logged-in users by their ID, for anonymous visitors by a hashed form of their IP address. What was in the file is not recorded.
Protection on upload: Checked are the extension and the actual file type, the size and whether the file really comes from this upload. A one-time token protects against forged requests; it is fetched fresh with every upload and therefore also works on cached pages. The validator is called with an array of arguments and never through a composed command line. The buttons on the settings page are open to administrators only.
10 · For developers
| Kind | Name | Meaning |
|---|---|---|
| Shortcode | spko_kosit_validator | Constant SPKO_SHORTCODE; no attributes. |
| Filter | spko_force_enqueue | Forces script and stylesheet to load on pages whose content does not carry the shortcode itself. Value: bool. |
| Filter | einvoice/report_html | Lets another plugin replace the report view; the Validation Explorer uses it. |
| Filter (used) | spx_force_enqueue | The plugin hooks into this Explorer filter so that the Explorer's script loads on pages with [spko_kosit_validator]. |
| REST | POST /wp-json/einvoice/v1/validate | The same check as on the page. File field file. The one-time token goes in the header X-WP-Nonce; an outside program fetches it first with a POST to admin-ajax.php with action=einvoice_nonce ( answer data.nonce ). Answer of the check: html, view (explainer, lite or raw), cssUrl, xml, filename, remaining. |
| AJAX, public | einvoice_nonce | Returns the one-time token for the REST address. The action belongs to a component that all eInvoice tools share, and is registered only once, even if several of them are active. |
| AJAX, public | spko_nonce, spko_validate, spko_visualize | Fetch the one-time token; check a file (fields nonce and file); show the invoice (fields nonce, file and lang, answer html). |
| AJAX, administrators only | spko_jar_reload, spko_jar_forget_pin, spko_test_connection | Accept checksum, forget checksum, test connection (field adapter). |
| JavaScript | window.SPKO_renderReport( container, data ) | Draws a check result into an element; the viewer uses this function. |
| JavaScript | window.EInvoice.register( 'validator', { renderReport } ) | The same function in the shared registry of the eInvoice tools. |
| Constants | SPKO_VERSION, SPKO_FILE, SPKO_DIR, SPKO_URL, SPKO_SHORTCODE | Version, main file, directory, URL, shortcode name. |
| Options | spko_adapter, spko_validator_dir, spko_java_bin, spko_timeout_seconds, spko_role_limits ( the table per role; until it is saved for the first time, the earlier single value spko_daily_limit applies ), spko_max_filesize_mb, spko_trust_proxy, spko_bridge_url, spko_bridge_key, spko_visualization_dir, spko_jar_version, spko_jar_sha256 | The stored settings. |
HTTP answers of the check: 400 (no, empty or unreadable file), 403 (security check), 413 (too large), 415 (not an XML file), 422 (validator run failed), 429 (daily limit). The server accepts only XML; accepting a PDF happens in the browser.
11 · Versions
| Version | Changes |
|---|---|
| 1.9.1 | New: the button "Download report.html" saves the HTML report of the KoSIT validator. The report and its notes speak of the "result" of a check. |
| 1.9.0 | The daily limit can be set per role, with its own row for guests; 0 means no access. The button in the eInvoice Viewer shows its texts in the language of the page. |
| 1.8.2 | New: under the report, the button "Show invoice" displays the invoice in KoSIT's official visualization once its folder is set in the settings. The note above the marked fields says exactly what is checked. The invoice view no longer marks an IBAN with wrong check digits; the validation report is not affected. The bundled translations also appear when the plugin is network-activated and on older WordPress versions. |
| 1.8.1 | Texts without a font of their own appear in the font of the chosen design kit. The document view marks fields that break a rule from the invoice itself. |
| 1.8.0 | The rules of ZUGFeRD / Factur-X EXTENDED and EXTENDED-CTC-FR are only explained with the "Extended Profiles" add-on. Behind a reverse proxy, the daily limit counts the address the proxy appended. |
| 1.7.0 | With the Extended Profiles add-on, findings about fields of an extension (BT-X) show their value from the document. |
| 1.6.0 | The design kit can be chosen in the settings. A finding about an attachment names it. |
| 1.5.0 | The validation report appears in the same view as in the Validation Explorer. |
Older entries are in the plugin's change log.
12 · List of images
This list shows which screenshots this manual expects and which were found in the folder screenshots/ of the package. An image is always named key.language.png, for example vk-ablage.en.png. The images show sample data only.
| Status | File | What it shows |
|---|---|---|
| – | vk-ablage.en.png | The drop zone on a page of the site, below it the note on the checks still available today |
| – | vk-einstellungen.en.png | The settings page with the choice of backend and the green note that validator.jar was found |
| – | vk-bericht-ok.en.png | A validation report for an invoice without findings, above it the button to download the report |
| – | vk-bericht-befunde.en.png | A validation report with findings: result, list of findings with explanation and affected field |
| – | vk-systempruefung.en.png | The systemcheck with green and red rows for both backends, the next step at a red row |
| – | vk-jar-pruefsumme.en.png | The section validator.jar with both checksums side by side and the row on whether they match |
| – | vk-pruefdienst.en.png | The section for the validation service with address and key |
| – | vk-viewer-knopf.en.png | An invoice in the eInvoice Viewer with the button to check it with the KoSIT validator |