-
Notifications
You must be signed in to change notification settings - Fork 18
Receiving Process
The receiving process handles inbound Peppol documents arriving at the AP (C3) via AS4 from a remote sending AP (C2) and forwards them to the Receiver Backend (an internal system within C3).
-
Receive via AS4 - phase4 servlet receives the AS4 message. Duplicate detection is applied on two levels (AS4 Message ID, SBDH Instance Identifier) — configurable: reject or store-and-flag.
-
Verify receiver is serviced - Check whether this AP services the addressed receiver participant for the given document type and process. This is implemented via a pluggable SPI (
IReceiverCheckor similar) — e.g., by querying the AP's own SMP registration or a local configuration. If the receiver is not serviced, an AS4 error with codeEBMS:0004/PEPPOL:NOT_SERVICEDis returned to C2. No database entry is created. -
Store document and metadata - The document is written to disk under
storage.inbound.pathand the file path, metadata, phase4 Incoming ID, and MLS configuration (MLS_TO from SBDH extension, MLS_TYPE from instance config) are persisted to theinbound_transactiontable in PostgreSQL. -
If storage fails - Respond with an AS4 error to the remote sending AP (C2). The transaction is not recorded.
-
Optional verification - The received document is validated via the pluggable verification SPI (
IDocumentVerifier). By default, thephoss-ap-validationmodule calls the phorm Validation Service to validate the document against Peppol BIS rules. If verification fails, the transaction status is set torejected, a notification is triggered, an MLS response with code RE (Rejection) and business rule violation (BV) issues is sent back to C2, and no forwarding attempt is made. -
Forward to Receiver Backend - Deliver the SBD via the forwarding mode configured by the
forwarding.modeproperty:-
http_post_async— HTTP POST (async reporting) -
http_post_sync— HTTP POST with sync response (C4 country code in response) -
s3_link— S3 + link forwarding -
sftp— SFTP
-
-
Record forwarding attempt - Insert a row into
inbound_forwarding_attemptwith the outcome (success or failure + error details). Update the parentinbound_transactionstatus accordingly. -
If forwarding fails - The document will be retried by a periodic scheduler. Each retry creates a new
inbound_forwarding_attemptrow. -
Reporting - Either triggered synchronously (from HTTP POST response containing C4 country code) or asynchronously (Receiver Backend calls reporting API with SBDH Instance ID + C4 country code).
-
On permanent forwarding failure - Notification via generic interface. An MLS response with code RE (Rejection) and status reason FD (Failure of Delivery) is sent back to C2.
-
Send MLS response - Based on the forwarding outcome and the MLS_TYPE configuration, the AP generates an MLS response and sends it back to C2. The response code depends on the outcome and forwarding mode:
- RE (Rejection) — On verification failure (status reason BV) or permanent forwarding failure (status reason FD)
-
AP (Approved) — On successful forwarding via HTTP (
http_post_syncorhttp_post_async), since HTTP provides delivery confirmation - AB (Accepted Blind) — On successful forwarding via SFTP or S3, since these modes do not provide delivery confirmation
The MLS sending is recorded as an
outbound_transactionwithtransaction_type = mls_response, linked viamls_inbound_transaction_id. The inbound transaction'smls_outbound_transaction_idis set to reference it.
sequenceDiagram
participant RA as Remote AP (C2)
participant PS as phase4 Servlet
participant RC as Receiver Check
participant DB as DB
participant FM as Forwarding Module
participant RB as Receiver Backend
RA->>PS: AS4 UserMessage
PS->>DB: 1. Duplicate check (AS4, SBDH)
DB-->>PS: result
note over PS: If duplicate and reject mode: return AS4 error
PS->>RC: 2. Verify receiver is serviced
RC-->>PS: result
note over PS: If not serviced: return AS4 error PEPPOL:NOT_SERVICED
PS->>DB: 3. Store doc to disk + insert inbound_transaction (incl. MLS config)
note over PS: If store fails: return AS4 error
DB-->>PS: stored OK
PS-->>RA: AS4 Receipt
PS->>PS: 4. Verify doc (optional)
note over PS: If rejected: update DB, notify, send MLS RE
PS->>FM: 5. Forward SBD
FM->>RB: Deliver SBD
RB-->>FM: Response (sync mode: C4 country in response)
PS->>DB: 6. Insert forwarding attempt row
PS->>DB: 7. Update inbound_transaction status
opt Sync reporting mode
PS->>DB: Store reporting record
end
sequenceDiagram
participant AP as AP
participant DB as DB
participant P4 as phase4
participant RA as Remote AP (C2)
AP->>AP: Determine MLS response code (RE, AP, or AB)
AP->>AP: Check MLS_TYPE (ALWAYS_SEND or FAILURE_ONLY)
note over AP: If FAILURE_ONLY and outcome is success: skip MLS
AP->>DB: Create outbound_transaction (transaction_type = mls_response)
AP->>DB: Update inbound_transaction (mls_response_code, mls_outbound_transaction_id)
AP->>P4: Send MLS via AS4
P4->>RA: AS4 UserMessage (MLS)
RA-->>P4: AS4 Receipt
P4-->>AP: AS4 result
AP->>DB: Insert outbound_sending_attempt
AP->>DB: Update outbound_transaction status
sequenceDiagram
participant RB as Receiver Backend
participant API as Reporting API
participant DB as DB
RB->>API: Report message (SBDH Instance ID, C4 country code)
API->>DB: Lookup inbound transaction by SBDH Instance ID
DB-->>API: transaction data
API->>DB: Store reporting record (C4 country + data from SBDH)
API-->>RB: OK
sequenceDiagram
participant S as Scheduler
participant DB as DB
participant FM as Forwarding Module
participant RB as Receiver Backend
S->>DB: Query inbound_transaction where status = failed
DB-->>S: list of pending
loop For each failed transaction
S->>FM: Forward
FM->>RB: Deliver SBD
RB-->>FM: result
FM-->>S: result
S->>DB: Insert forwarding attempt row
S->>DB: Update inbound_transaction status
opt Max retries exhausted
S->>S: Trigger notification
end
end
| Field | Description |
|---|---|
| incoming_id | Unique ID assigned by phase4 on receipt |
| c2_seat_id | Peppol Seat ID of the sending AP (C2) |
| c3_seat_id | Peppol Seat ID of the receiving AP (C3, this AP) |
| signing_cert_cn | Subject CN of the signing certificate from the AS4 message |
| sender_id | Peppol Participant ID of the sender |
| receiver_id | Peppol Participant ID of the receiver |
| doc_type_id | Peppol Document Type Identifier |
| process_id | Peppol Process Identifier |
| document_path | Absolute path to the document file on disk |
| document_size | Size of the received SBD in bytes |
| document_hash | SHA-256 hash of the received SBD payload for integrity verification |
| as4_message_id | AS4 Message ID from the inbound message |
| as4_timestamp | AS4 MessageInfo/Timestamp from the incoming AS4 message (UTC). MLS Milestone M1 for business documents; M2 for MLS messages. |
| sbdh_instance_id | Peppol SBDH Instance Identifier |
| c4_country_code | Country of the final receiver (C4), set via reporting |
| is_duplicate_as4 | Duplicate detected on AS4 Message ID level |
| is_duplicate_sbdh | Duplicate detected on SBDH Instance Identifier level |
| status | received, rejected, forwarding, forwarded, forward_failed, permanently_failed |
| attempt_count | Total number of forwarding attempts (default 0) |
| received_dt | When the message was received via AS4 |
| completed_dt | When the transaction reached its final successful state |
| reporting_status | Whether reporting record has been created (pending, reported) |
| next_retry_dt | Planned date/time of the next forwarding retry (null unless status is forward_failed) |
| error_details | Summary error from the last failed forwarding attempt |
| mls_to | MLS_TO target participant ID (from SBDH extension) |
| mls_type | MLS sending strategy at time of reception (FAILURE_ONLY, ALWAYS_SEND) |
| mls_response_code | MLS response code sent or to be sent (RE, AP, AB) |
| mls_outbound_transaction_id | FK to the outbound_transaction representing the MLS sending |
| Field | Description |
|---|---|
| inbound_transaction_id | FK to the parent inbound transaction |
| attempt_dt | Date and time of this forwarding attempt |
| attempt_status | Outcome of this attempt (success, failed) |
| error_code | Machine-readable error code classifying the failure (null on success) |
| error_details | Error message or reason for failure |
It is appreciated if you star the GitHub project if you like it.
Donation link: https://paypal.me/PhilipHelger
- Home
- News and noteworthy
- Running phoss AP
- Architecture Overview
- API Specification
- Configuration Properties
- Code Lists
- Database Design Notes
- Maven Module Structure
- Runtime Extensions
- OpenTelemetry Integration
- Security Considerations
- Peppol Specifics
- Testing Without Peppol Network
- Known Users
- Migrating from phase4-peppol-standalone
- Contributing