How To Migrate to the V2 Produced Report
|
The V1 Notification Service API is now deprecated and will be removed as part of the 2026.4.0 IPF release. If you are using the Payment Notification service, you must migrate to the V2 API before then. |
Why you would want to migrate
The V1 Produced Report is tightly coupled to the core IPF Supported Message Definitions, specifically the pain.001.001.09 and pain.002.001.10 definitions.
As IPF development progresses, supported for newer versions of ISO message definitions will be introduced. As a result, we cannot guarantee that the ProducedReport will function correctly when using a pain.001 message of a future version (e.g. pain.001.001.10).
A similar limitation exists the PDS objects attached to the V1 Produced Report. These objects do not specify their type or version, making it impossible for the consumer to deduce the structure of the provided PDS objects.
The V2 Produced Report is designed to be version-agnostic, ensuring compatibility regardless of the ISO message version being used or generated. Additionally, the V2 report supplies PDS type and version, enabling consumers to infer the structure of the provided PDS objects.
Data Structure Differences
The key differences between the V1 and V2 Produced Reports revolve around the versioning of produced ISO messages and PDS objects.
ISO messages
-
V1 ProducedReport:
-
The
reportfield is of typecom.iconsolutions.iso20022.message.definitions.payments_initiation.pain002.CustomerPaymentStatusReportV10 -
The
pain001field is of typecom.iconsolutions.iso20022.message.definitions.payments_initiation.pain001.CustomerCreditTransferInitiationV09.
-
In this version, the ISO messages are tightly coupled to the specific message definitions mentioned above, reducing flexibility
-
V2 ProducedReport:
-
Both the
reportandpain001fields have been updated to use theIsoMessageWrapperJava type. -
This change decouples the produced ISO messages from exact message definitions. Instead, the wrapper provides the ISO message definition, allowing consumers to infer the structure of the underlying ISO message.
-
public record IsoMessageWrapper(String messageDefinition,
JsonNode isoMessage) {
}
PDS Objects
-
V1 ProducedReport:
-
Contains solely the
nameandcontentof a PDS object. Making the PDS content structure inference more challenging for consumers.
-
-
V2 ProducedReport:
-
Uses the new
PdsObjectWrapperJava type which includes two new fields:typeNameandversion.
-
-
These fields enable consumers to infer the structure of the underlying PDS content more easily.
public record PdsObjectWrapper(String name,
String typeName,
Integer version,
JsonNode content) {
}
Removal of the NotificationEnvelope result field
The V1 NotificationEnvelope included a result field, which was used internally by the notification service application’s Resequencer. As this field is not required for the produced report, it has been removed in the V2 NotificationEnvelope model.
Comparison
Below are JSON string representations of the same produced report for both the V1 and V1 APIs.
V1 ProducedReport
{
"uniqueId": "29786d8ae74d4f798476a068568ac5d3",
"envelope": {
"context": {
"unitOfWorkId": "a9d84622-4e00-44e2-8705-7a42029c2754",
"clientRequestId": "client-request-id-uXTNk",
"processingEntity": "unit-of-work-KUvgO",
"associationId": "a9d84622-4e00-44e2-8705-7a42029c2754"
},
"processFlowEvent": {
"class": "com.iconsolutions.ipf.processingdata.process.ProcessFlowEvent",
"eventId": "DebtorCT-Scheme Rules Validated-1",
"eventName": "Scheme Rules Validated",
"processFlowDefinitionId": "DebtorCT",
"processFlowId": "DebtorCT",
"causedBy": "caused-by-ipyDQ",
"processFlowSequence": 1,
"status": {
"originatingStatus": "Booking",
"resultingStatus": "Completed",
"globalStatus": "Completed"
},
"reasonCode": "1",
"reasonText": "Invalid credit account number",
"content": "flow-event-content-MlWxm",
"createdAt": "2025-10-31T10:26:49.690Z"
},
"matchingSetting": {
"domainEvent": "Scheme Rules Validated",
"processFlow": "DebtorCT",
"status": "ACCC",
"transport": "kafka",
"endpoints": [
{
"topic": "PAYMENT_STATUS_NOTIFICATION"
}
],
"proprietary": "validated"
},
"result": {
"completedExceptionally": false,
"numberOfDependents": 1,
"done": false,
"cancelled": false
}
},
"report": {
"grpHdr": {
"msgId": "578db9ec-d71f-43fb-9954-4320f6f4",
"creDtTm": "2025-10-31T10:26:49.750390909Z"
},
"orgnlPmtInfAndSts": [
{
"txInfAndSts": [
{
"orgnlInstrId": "instrId-1",
"txSts": "ACCC",
"stsRsnInf": [
{
"rsn": {
"cd": "1"
},
"addtlInf": [ "additionalInfo" ]
}, {
"rsn": {
"prtry": "validated"
},
"addtlInf": [ "additionalInfo" ]
}
]
}
]
}
],
"orgnlGrpInfAndSts": {
"orgnlMsgNmId": "pain.001.001.09",
"orgnlNbOfTxs": "1"
},
"splmtryData": [ ]
},
"pain001": {
"grpHdr": {
"nbOfTxs": "1"
},
"pmtInf": [
{
"cdtTrfTxInf": [
{
"pmtId": {
"instrId": "instrId-1"
}
}
]
}
],
"splmtryData": [ ]
},
"customData": [
{
"name": "BusinessData",
"content": "custom-business-data"
}, {
"name": "IPFProcessingData",
"content": "custom-processing-data"
}
],
"pdsData": [
{
"name": "Csm",
"content": {
"value": "STET"
}
}, {
"name": "ClientSpecificBusinessData",
"content": {
"someField": "someValue"
}
}
]
}
V2 ProducedReport
{
"uniqueId": "29786d8ae74d4f798476a068568ac5d3",
"envelope": {
"context": {
"unitOfWorkId": "a9d84622-4e00-44e2-8705-7a42029c2754",
"clientRequestId": "client-request-id-uXTNk",
"processingEntity": "unit-of-work-KUvgO",
"associationId": "a9d84622-4e00-44e2-8705-7a42029c2754"
},
"processFlowEvent": {
"eventId": "DebtorCT-Scheme Rules Validated-1",
"eventName": "Scheme Rules Validated",
"processFlowDefinitionId": "DebtorCT",
"processFlowId": "DebtorCT",
"causedBy": "caused-by-ipyDQ",
"processFlowSequence": 1,
"status": {
"originatingStatus": "Booking",
"resultingStatus": "Completed",
"globalStatus": "Completed"
},
"reasonCode": "1",
"reasonText": "Invalid credit account number",
"content": "flow-event-content-MlWxm",
"createdAt": "2025-10-31T10:26:49.690Z"
},
"matchingSetting": {
"domainEvent": "Scheme Rules Validated",
"processFlow": "DebtorCT",
"status": "ACCC",
"transport": "kafka",
"endpoints": [
{
"topic": "PAYMENT_STATUS_NOTIFICATION"
}
],
"proprietary": "validated"
}
},
"report": {
"messageDefinition": "pain.002.001.10",
"isoMessage": {
"grpHdr": {
"msgId": "578db9ec-d71f-43fb-9954-4320f6f4",
"creDtTm": "2025-10-31T10:26:49.750390909Z"
},
"orgnlPmtInfAndSts": [
{
"txInfAndSts": [
{
"orgnlInstrId": "instrId-1",
"txSts": "ACCC",
"stsRsnInf": [
{
"rsn": {
"cd": "1"
},
"addtlInf": [ "additionalInfo" ]
}, {
"rsn": {
"prtry": "validated"
},
"addtlInf": [ "additionalInfo" ]
}
]
}
]
}
],
"orgnlGrpInfAndSts": {
"orgnlMsgNmId": "pain.001.001.09",
"orgnlNbOfTxs": "1"
}
}
},
"pain001": {
"messageDefinition": "pain.001.001.09",
"isoMessage": {
"grpHdr": {
"nbOfTxs": "1"
},
"pmtInf": [
{
"cdtTrfTxInf": [
{
"pmtId": {
"instrId": "instrId-1"
}
}
]
}
],
"splmtryData": [ ]
}
},
"customData": [
{
"name": "BusinessData",
"content": "custom-business-data"
}, {
"name": "IPFProcessingData",
"content": "custom-processing-data"
}
],
"pdsData": [
{
"name": "Csm",
"typeName": "Csm",
"version": 1,
"content": {
"value": "STET"
}
}, {
"name": "ClientSpecificBusinessData",
"typeName": "ClientJavaClass",
"version": 3,
"content": {
"someField": "someValue"
}
}
]
}
ProducedReport Java Type Maps
To aid with the adoption of the new model, we provide the complete mappings for Java references.
- IMPORTANT
-
The new model leverages Java records, which introduce a key change in how fields are accessed. Fields previously accessed using getters are now accessed directly by name:
-
Old:
producedReport.getEnvelope() -
New:
producedReport.envelope()
-
| Old Model | New Model |
|---|---|
com.iconsolutions.ipf.product.notification.api.model.ProducedReport |
com.iconsolutions.ipf.product.notification.api.model.v2.ProducedReport |
com.iconsolutions.ipf.product.notification.api.model.NotificationEnvelope |
com.iconsolutions.ipf.product.notification.api.model.v2.NotificationEnvelope |
com.iconsolutions.ipf.core.shared.domain.context.ProcessingContext |
com.iconsolutions.ipf.product.notification.api.model.v2.ProcessingContext |
com.iconsolutions.ipf.processingdata.process.ProcessFlowEvent |
com.iconsolutions.ipf.product.notification.api.model.v2.ProcessFlowEvent |
com.iconsolutions.ipf.core.shared.domain.event.Status |
com.iconsolutions.ipf.product.notification.api.model.v2.ProcessFlowEvent.Status |
com.iconsolutions.ipf.product.notification.api.model.PaymentStatusNotification |
com.iconsolutions.ipf.product.notification.api.model.v2.PaymentStatusNotification |
com.iconsolutions.ipf.product.notification.api.model.Endpoint |
com.iconsolutions.ipf.product.notification.api.model.v2.Endpoint |
com.iconsolutions.ipf.processingdata.custom.CustomObjectWrapper |
com.iconsolutions.ipf.product.notification.api.model.v2.CustomObjectWrapper |
com.iconsolutions.ipf.product.notification.api.model.PdsObjectWrapper |
com.iconsolutions.ipf.product.notification.api.model.v2.PdsObjectWrapper |
Steps to Migrate
Update Payment Notification Service Config to produce V1 messages
By default, the notification service will emit a V2 ProducedReport. The first thing to do before adopting the latest version will be to configure the application to keep emitting a V1 ProducedReport while you update your consumer.
payment-status-notification.schema-version = 1
Update Consumer
Before you can start producing messages from the Notification Service using the V2 model, you must first update your consuming application to be able to handle the V2 messages.
The payload created by Notification Service contains the header ipf_schema_version, the value of which will define what version of the ProducedReport model is contained within.
| Message Header | Description |
|---|---|
ipf_schema_version = 2 |
The inbound message utilises the V2 Produced Report model |
ipf_schema_version = 1 |
The inbound message utilises the V1 Produced Report model |
ipf_schema_version is not set |
The inbound message utilises the V1 Produced Report model. This will have originated from a previous version of the Notification Service that only contained the V1 data model. |
When updating a consumer of Notification Service messages, you should add a check for the ipf_schema_version header to identify which data model version to utilise when handling the inbound message.
Refer to data structure differences for a detailed comparison between the V1 and V2 models.
Once your consuming application is able to handle V2 messages, you can update the Payment Notification Service to start producing V2 messages.
Update Extension Points
If you have built client-specific notification service and have overridden any of the V1 extension points, you will need to supply the V2 equivalent for each.
- NOTE
-
If both V1 and V2 extension points are provided, the V2 implementation is used by default.
Extension Point Java Type Maps
To aid with the adoption of the new extension points, we provide the complete mappings for Java references.
| Old Model | New Model |
|---|---|
com.iconsolutions.ipf.product.notification.api.handler.AdditionalMdsObjectHandler |
com.iconsolutions.ipf.product.notification.api.handler.v2.AdditionalMdsObjectHandler |
com.iconsolutions.ipf.product.notification.api.processor.PostEventProcessor |
com.iconsolutions.ipf.product.notification.api.processor.v2.PostEventProcessor |
MessageLogEntryEnricher<com.iconsolutions.ipf.product.notification.api.model.ProducedReport> |
MessageLogEntryEnricher<com.iconsolutions.ipf.product.notification.api.model.v2.ProducedReport> |
SendTransportMessageConverter<com.iconsolutions.ipf.product.notification.api.model.ProducedReport> |
SendTransportMessageConverter<com.iconsolutions.ipf.product.notification.api.model.v2.ProducedReport> |
Update Payment Notification Service Config to produce V2 messages
Now that your consumer is able to handle V2 ProducedReport messages, you can configure the notification service application to produce V2 messages.
You can do this by removing the previously configured value:
payment-status-notification.schema-version = 1
You can either remove the line entirely or update its value as follows:
payment-status-notification.schema-version = 2