commit cc0ccb35adb2e4854168f409156c9318f7508319
parent 76572686b1e5947afa1a36329ceddc90b15c9875
Author: Antoine A <>
Date: Thu, 30 Oct 2025 11:57:28 +0100
nexus: fix pain.002 parsing for valiant
Diffstat:
4 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/nexus/sample/platform/valiant_pain002.xml b/nexus/sample/platform/valiant_pain002.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.002.001.10">
+ <CstmrPmtStsRpt>
+ <GrpHdr>
+ <MsgId>pain.002/20251030/104854310674000</MsgId>
+ <CreDtTm>2025-10-30T10:48:54+01:00</CreDtTm>
+ <InitgPty>
+ <Id>
+ <OrgId>
+ <AnyBIC>VABECH22XXX</AnyBIC>
+ </OrgId>
+ </Id>
+ </InitgPty>
+ </GrpHdr>
+ <OrgnlGrpInfAndSts>
+ <OrgnlMsgId>5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U</OrgnlMsgId>
+ <OrgnlMsgNmId>pain.001</OrgnlMsgNmId>
+ <GrpSts>ACCP</GrpSts>
+ <StsRsnInf>
+ <AddtlInf>PN10630020F0297329.20251030104613.EBTUAAAC.PN1.0002372</AddtlInf>
+ </StsRsnInf>
+ </OrgnlGrpInfAndSts>
+ </CstmrPmtStsRpt>
+</Document>
+\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt
@@ -264,15 +264,15 @@ class EbicsSetup: TalerCmd() {
if (partner.name != null) {
append("'")
append(partner.name)
- append("' - ")
+ append("'")
}
for ((currency, iban, bic) in partner.accounts) {
+ append(' ')
append(currency)
- append('_')
+ append('-')
append(iban)
- append('_')
+ append('-')
append(bic)
- append(' ')
}
append('\n')
}
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/camt.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/camt.kt
@@ -120,11 +120,8 @@ data class BatchId(
): OutId {
fun ref(): String = msgId
override fun toString(): String = buildString {
- append('(')
- if (msgId != null) {
- append("msg=")
- append(msgId.toString())
- }
+ append("(msg=")
+ append(msgId)
if (acctSvcrRef != null) {
if (length != 1) append(" ")
append("ref=")
@@ -277,7 +274,7 @@ private fun XmlDestructor.outgoingId(ref: String?): OutId =
} else {
OutgoingId(msgId, endToEndId, ref)
}
- } ?: OutgoingId(null, null, ref)
+ } ?: OutgoingId(acctSvcrRef = ref)
/** Parse transaction ids as provided by bank*/
private fun XmlDestructor.incomingId(ref: String?): IncomingId =
@@ -285,7 +282,7 @@ private fun XmlDestructor.incomingId(ref: String?): IncomingId =
val uetr = opt("UETR")?.uuid()
val txId = opt("TxId")?.text()
IncomingId(uetr, txId, ref)
- } ?: IncomingId(null, null, ref)
+ } ?: IncomingId(acctSvcrRef = ref)
/** Parse and format transaction return reasons */
@@ -445,7 +442,7 @@ private fun XmlDestructor.optBankTransactionCode(): BankTransactionCode? {
/** Parse transaction wire transfer subject */
private fun XmlDestructor.wireTransferSubject(): String? = opt("RmtInf") {
- map("Ustrd") { text() }?.joinToString("")?.trim()
+ map("Ustrd") { text() }.joinToString("").trim()
}
/** Parse account information */
@@ -532,17 +529,15 @@ fun parseTx(notifXml: InputStream, dialect: Dialect): List<AccountTransactions>
// Amount
val txAmount = complexAmount()
val amount = if (unique) {
- if (entryAmount != null && txAmount != null) {
+ if (txAmount != null) {
entryAmount.resolve(txAmount)
} else {
- requireNotNull(entryAmount ?: txAmount) { "Missing unique tx amount" }
+ entryAmount
}
} else {
requireNotNull(txAmount) { "Missing batch tx amount" }
}
- if (entryAmount != null) {
- totalAmount = totalAmount?.let { it + amount.amount } ?: amount.amount
- }
+ totalAmount = totalAmount?.let { it + amount.amount } ?: amount.amount
// Ref
val txRef = opt("Refs")?.opt("AcctSvcrRef")?.text()
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain002.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/iso20022/pain002.kt
@@ -36,12 +36,15 @@ private fun fmtMsg(code: String?, description: String?, reasons: List<Reason>) =
}
for (reason in reasons) {
append(" ")
- append(reason.code.isoCode)
- append(" '")
- append(reason.code.description)
- append("'")
- if (reason.information.isNotEmpty()) {
+ if (reason.code != null) {
+ append(reason.code.isoCode)
append(" '")
+ append(reason.code.description)
+ append("'")
+ }
+ if (reason.information.isNotEmpty()) {
+ if (reason.code != null) append(" ")
+ append("'")
append(reason.information)
append("'")
}
@@ -103,11 +106,11 @@ data class TxStatus(
val code: ExternalPaymentTransactionStatusCode,
val reasons: List<Reason>
) {
- fun msg() = fmtMsg(code?.isoCode, code?.description, reasons)
+ fun msg() = fmtMsg(code.isoCode, code.description, reasons)
}
data class Reason (
- val code: ExternalStatusReasonCode,
+ val code: ExternalStatusReasonCode?,
val information: String
)
@@ -115,7 +118,7 @@ data class Reason (
fun parseCustomerPaymentStatusReport(xml: InputStream): MsgStatus {
fun XmlDestructor.reasons(): List<Reason> {
return map("StsRsnInf") {
- val code = one("Rsn").one("Cd").enum<ExternalStatusReasonCode>()
+ val code = opt("Rsn")?.one("Cd")?.enum<ExternalStatusReasonCode>()
val info = map("AddtlInf") { text() }.joinToString("")
Reason(code, info)
}