@n42/edelivery
v0.1.79
Published
Node42's pure Node.js eDelivery toolkit — SMP lookup, document validation and AS4 signing, encryption and sending. No Java, no third-party AP dependencies.
Downloads
767
Maintainers
Readme
Node42 eDelivery
Pure Node.js Peppol AS4 Sender & Toolkit
Intended for interoperability testing, validation, troubleshooting, and controlled AS4 message transmission (e.g., dispatching UBL documents).
Low-Level Cryptographic Implementation
A deliberate choice was made to keep this a super lightweight, pure Node.js implementation with zero platform dependencies.
All cryptographic operations:
RSA-OAEPkey wrappingAES-128-GCMencryptionRSA-SHA256signingX.509certificate handling
are implemented directly using Node.js's built-in crypto module and the xml-crypto library, with no native addons, no external binaries, and no compilation required.
Features
- SML lookup + Peppol SMP discovery
- Send AS4 messages (validate, sign, encrypt, verify)
- Built-in schematron validation
- Transaction reporting
- Replay last message byte-for-byte
- Zero native dependencies, zero compilation
- Works on Linux, macOS and Windows
Background
If you’d like a deeper understanding of the protocol before exploring the code, the accompanying Medium articles provide additional context. They walk through the AS4 transport protocol, explain how Peppol messaging works in practice, and describe the reasoning behind building this implementation.
Peppol AS4 Under the Microscope: From TCP Handshake to Encrypted Invoice
A Fully Working Peppol AS4 Sender in Node.js - In ~500 Lines of Code
Installation
Requirements
- Node.js 18+ (Node 20 recommended)
- npm
Install globally
npm install -g @n42/edeliveryVerify installation:
n42-edelivery --versionCommands
init
Initialize local Node42 workspace with certificates, schematrons, and JSON control structure (for dynamic UBL document creation)
.node42/
├── certs/
│ ├── cert.pem
│ ├── key.pem
│ └── truststore.pem
└── templates/
└── ubl.jsonCertificates can be placed in ~/.node42/certs/ using the naming convention above, or their paths specified explicitly via --cert, --key and --truststore flags.
pki
Display PKI configuration — certificate, private key and truststore used for AS4 signing, encryption and peer validation.
send peppol
Send a Peppol UBL document via AS4.
| Argument | Description |
|--------------------|------------------------------------------------------|
| --replay | Re-send transaction using stored artefacts |
| --document | Path to the UBL XML document to send |
| --data | Path to JSON document data |
| --schematron | Path to schematron XSL files for validation |
| --env | Target environment: test or prod |
| --cert-id | Node42 Probe certificate ID |
| --cert | Public certificate (PEM) |
| --key | Private key (PEM) |
| --key-pass | Private key passphrase |
| --truststore | Truststore (PEM) |
| --sender-id | Peppol participant ID of sender |
| --receiver-id | Peppol participant ID of receiver |
| --sender-country | Sender country code |
| --endpoint-url | Override the SMP-discovered endpoint URL |
| --hostname | Hostname used in message IDs |
| --strip-sbdh | Strip SBDH and re-wrap using provided context |
| --dryrun | Prepare and resolve but do not transmit |
| --persist | Persist transaction data to disk |
| --verbose | Enable detailed output |
validate peppol
Validate a Peppol UBL document against schematron rules.
| Argument | Description |
|-----------------|--------------------------------------------|
| --document | Path to UBL XML document (required) |
| --schematron | Path to schematron XSL files |
| --persist | Persist validation errors to disk |
| --verbose | Enable detailed output |
report peppol
Generate Peppol reporting data
| Argument | Description |
|-----------------|--------------------------------------|
| --from | Start date of the reporting period |
| --to | End date of the reporting period |
Usage
Send a prepared document directly:
n42-edelivery send peppol \
--env "test" \
--document "~/<path_to_document>/invoice.xml"Send a test document dynamically built from CLI arguments and an UBL document descriptor:
n42-edelivery send peppol \
--env "test" \
--sender-id "iso6523-actorid-upis::0007:node42" \
--receiver-id "iso6523-actorid-upis::0007:node42" \
--sender-country SE \
--ubl "./ubl.json"The --ubl document descriptor:
{
"document_type" : "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
"process_id" : "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"seller": {
"name": "Test Sender",
"endpoint_scheme": "0007",
"street": "Sender Street 1",
"city": "Stockholm",
"zip": "11122",
"vat": "SE556677889901",
"company_id": "5566778899"
},
"buyer": {
"name": "Test Receiver",
"endpoint_scheme": "0008",
"street": "Receiver Street 1",
"city": "Brussels",
"zip": "1000",
"country": "BE",
"company_id": "6677889900"
},
"invoice": {
"currency": "EUR",
"payment_means": "30",
"items": [
{
"name": "Consulting Services",
"quantity": 2,
"unit": "HUR",
"unit_price": "100.00",
"net_amount": "200.00",
"vat_percent": 25
},
{
"name": "Software License",
"quantity": 1,
"unit": "EA",
"unit_price": "50.00",
"net_amount": "50.00",
"vat_percent": 25
}
]
}
}Validate a document:
n42-edelivery validate peppol \
--document "~/<path_to_document>/invoice.xml"Replay
The replay command resends a previously sent AS4 message byte-for-byte using its stored artefacts.
n42-edelivery replayThe last sent transaction is automatically selected. To replay a specific transaction, pass its ID:
n42-edelivery replay <transactionId>The original message headers, and body are loaded from disk and transmitted as-is to the original endpoint — identical bytes, identical message ID.
- The receiving Access Point (C3) must have duplicate message detection disabled before replaying.
By default, most AS4 implementations reject messages with a previously seen message ID.
Persistence
When --persist is enabled, the tool stores execution artefacts for later inspection.
.node42/
└── artefacts/
├── discovery/
├── validations/
└── transactions/
├── <uuid>_context.json
├── <uuid>_document.xml
├── <uuid>_validation.xml
├── <uuid>_soap_envelope.xml
├── <uuid>_signing_input.txt
├── <uuid>_message_headers.json
├── <uuid>_message_body.txt
└── <uuid>_as4_signal.jsonWorkspace
Node42 stores runtime data, generated artefacts, certificates, and configuration in the user workspace located at ~/.node42.
.node42/
├── artefacts/
├── certs/
├── schematrons/
│ ├── billing/
│ ├── reporting/
│ └── schxslt/
├── templates/
├── reports/
├── db.json
├── replay.txt
└── .env.localThis directory contains all local data required by the CLI, including cached artefacts, validation rules, certificates, templates, and execution history.
Disclaimer
Production deployment requires proper certificate lifecycle management, secure key storage, monitoring, and full compliance with applicable Peppol policies and transport requirements.
License
Apache-2.0
Author
Alex Olsson
LinkedIn
