Iso20022Test.kt (34588B)
1 /* 2 * This file is part of LibEuFin. 3 * Copyright (C) 2024, 2025, 2026 Taler Systems S.A. 4 5 * LibEuFin is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as 7 * published by the Free Software Foundation; either version 3, or 8 * (at your option) any later version. 9 10 * LibEuFin is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General 13 * Public License for more details. 14 15 * You should have received a copy of the GNU Affero General Public 16 * License along with LibEuFin; see the file COPYING. If not, see 17 * <http://www.gnu.org/licenses/> 18 */ 19 20 import org.junit.Test 21 import tech.libeufin.common.* 22 import tech.libeufin.nexus.* 23 import tech.libeufin.nexus.iso20022.* 24 import tech.libeufin.ebics.* 25 import kotlin.io.path.* 26 import kotlin.test.* 27 import java.time.Instant 28 29 class Iso20022Test { 30 @Test 31 fun pain001() { 32 val creditor = IbanAccountMetadata( 33 iban = "CH4189144589712575493", 34 bic = null, 35 name = "Test" 36 ) 37 val msg = Pain001Msg( 38 messageId = "MESSAGE_ID", 39 timestamp = dateToInstant("2024-09-09"), 40 debtor = IbanAccountMetadata( 41 iban = "CH7789144474425692816", 42 bic = "BIC", 43 name = "myname" 44 ), 45 sum = TalerAmount("CHF:47.32"), 46 txs = listOf( 47 Pain001Tx( 48 creditor = creditor, 49 amount = TalerAmount("CHF:42"), 50 subject = "Test 42", 51 endToEndId = "TX_FIRST" 52 ), 53 Pain001Tx( 54 creditor = creditor, 55 amount = TalerAmount("CHF:5.11"), 56 subject = "Test 5.11", 57 endToEndId = "TX_SECOND" 58 ), 59 Pain001Tx( 60 creditor = creditor, 61 amount = TalerAmount("CHF:0.21"), 62 subject = "Test 0.21", 63 endToEndId = "TX_THIRD" 64 ) 65 ) 66 ) 67 for (dialect in Dialect.entries) { 68 assertEquals( 69 Path("sample/platform/${dialect}_pain001.xml").readText().replace("VERSION", VERSION), 70 createPain001(msg, dialect, false).asUtf8() 71 ) 72 } 73 } 74 75 @Test 76 fun hac() { 77 assertContentEquals( 78 parseCustomerAck(Path("sample/platform/hac.xml").inputStream()), 79 listOf( 80 CustomerAck( 81 actionType = HacAction.FILE_DOWNLOAD, 82 orderId = null, 83 code = ExternalStatusReasonCode.TS01, 84 info = "", 85 timestamp = dateTimeToInstant("2024-09-02T15:47:30.350Z") 86 ), 87 CustomerAck( 88 actionType = HacAction.FILE_UPLOAD, 89 orderId = "ORDER_SUCCESS", 90 code = ExternalStatusReasonCode.TS01, 91 info = "", 92 timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") 93 ), 94 CustomerAck( 95 actionType = HacAction.ES_VERIFICATION, 96 orderId = "ORDER_SUCCESS", 97 code = ExternalStatusReasonCode.DS01, 98 info = "", 99 timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") 100 ), 101 CustomerAck( 102 actionType = HacAction.ORDER_HAC_FINAL_POS, 103 orderId = "ORDER_SUCCESS", 104 code = null, 105 info = "Some multiline info", 106 timestamp = dateTimeToInstant("2024-09-02T20:48:43.153Z") 107 ), 108 CustomerAck( 109 actionType = HacAction.FILE_DOWNLOAD, 110 orderId = null, 111 code = ExternalStatusReasonCode.TD01, 112 info = "", 113 timestamp = dateTimeToInstant("2024-09-02T15:47:31.754Z") 114 ), 115 CustomerAck( 116 actionType = HacAction.FILE_UPLOAD, 117 orderId = "ORDER_FAILURE", 118 code = ExternalStatusReasonCode.TS01, 119 info = "", 120 timestamp = dateTimeToInstant("2024-08-23T15:34:11.987") 121 ), 122 CustomerAck( 123 actionType = HacAction.ES_VERIFICATION, 124 orderId = "ORDER_FAILURE", 125 code = ExternalStatusReasonCode.TD03, 126 info = "", 127 timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") 128 ), 129 CustomerAck( 130 actionType = HacAction.ORDER_HAC_FINAL_NEG, 131 orderId = "ORDER_FAILURE", 132 code = null, 133 info = "", 134 timestamp = dateTimeToInstant("2024-08-23T15:34:13.307") 135 ), 136 ) 137 ) 138 } 139 140 @Test 141 fun postfinance_camt054() { 142 assertContentEquals( 143 parseTx(Path("sample/platform/postfinance_camt054.xml").inputStream()), 144 listOf(AccountTransactions( 145 iban = "CH9289144596463965762", 146 currency = "CHF", 147 txs = listOf( 148 OutgoingPayment( 149 id = OutgoingId("ZS1PGNTSV0ZNDFAJBBWWB8015G", "ZS1PGNTSV0ZNDFAJBBWWB8015G", null), 150 amount = TalerAmount("CHF:3.00"), 151 subject = null, 152 executionTime = dateToInstant("2024-01-15"), 153 creditor = null 154 ), 155 IncomingPayment( 156 id = IncomingId("62e2b511-7313-4ccd-8d40-c9d8e612cd71", null, "231121CH0AZWCR9T"), 157 amount = TalerAmount("CHF:10"), 158 subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YBG", 159 executionTime = dateToInstant("2023-12-19"), 160 debtor = ibanPayto("CH7389144832588726658", "Mr Test") 161 ), 162 IncomingPayment( 163 id = IncomingId("62e2b511-7313-4ccd-8d40-c9d8e612cd71", null, "231121CH0AZWCVR1"), 164 amount = TalerAmount("CHF:2.53"), 165 subject = "G1XTY6HGWGMVRM7E6XQ4JHJK561ETFDFTJZ7JVGV543XZCB27YB", 166 executionTime = dateToInstant("2023-12-19"), 167 debtor = ibanPayto("CH7389144832588726658", "Mr Test") 168 ), 169 OutgoingReversal( 170 endToEndId = "50820f78-9024-44ff-978d-63a18c", 171 msgId = "50820f78-9024-44ff-978d-63a18c", 172 reason = "", 173 executionTime = dateToInstant("2024-01-15") 174 ), 175 OutgoingBatch( 176 msgId = "ZS1PGNTSV0ZNDFAJBBWWB8015G", 177 executionTime = dateToInstant("2024-01-15") 178 ) 179 ) 180 )) 181 ) 182 } 183 184 @Test 185 fun postfinance_camt053() { 186 assertContentEquals( 187 parseTx(Path("sample/platform/postfinance_camt053.xml").inputStream()), 188 listOf(AccountTransactions( 189 iban = "CH9289144596463965762", 190 currency = "CHF", 191 txs = listOf( 192 OutgoingReversal( 193 endToEndId = "889d1a80-1267-49bd-8fcc-85701a", 194 msgId = "889d1a80-1267-49bd-8fcc-85701a", 195 reason = "InconsistenWithEndCustomer 'Identification of end customer is not consistent with associated account number, organisation ID or private ID.' - 'more info here ...'", 196 executionTime = dateToInstant("2023-11-22") 197 ), 198 OutgoingReversal( 199 endToEndId = "4cc61cc7-6230-49c2-b5e2-b40bbb", 200 msgId = "4cc61cc7-6230-49c2-b5e2-b40bbb", 201 reason = "MissingCreditorNameOrAddress 'Specification of the creditor’s name and/or address needed for regulatory requirements is insufficient or missing.' - 'more info here ...'", 202 executionTime = dateToInstant("2023-11-22") 203 ), 204 OutgoingBatch( 205 msgId = "EB4D22D428214261B2B3012D2A8CEC36", 206 executionTime = dateToInstant("2024-08-26") 207 ) 208 ) 209 )) 210 ) 211 } 212 213 @Test 214 fun valiant_camt052() { 215 assertContentEquals( 216 parseTx(Path("sample/platform/valiant_camt052.xml").inputStream()), 217 listOf(AccountTransactions( 218 iban = "CH7389144832588726658", 219 currency = "CHF", 220 txs = listOf( 221 OutgoingPayment( 222 id = OutgoingId("MJDJO2BDDBL7YSL2P96SXHG3TQZEZQD26L", "4UWWIDGTEIGDU6Z721QE95PYJSIEA48PYE", "ZV20251030/511372/1"), 223 amount = TalerAmount("CHF:0.1"), 224 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 225 subject = "single 2025-10-30T09:46:04.55293090 9Z", 226 executionTime = dateToInstant("2025-10-30") 227 ), 228 OutgoingPayment( 229 id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "SKMU2891PAAYBDW22DBWX2W7KTFZ1CDFO8", "ZV20251030/511373/1"), 230 amount = TalerAmount("CHF:0.1"), 231 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 232 subject = "multi 0 2025-10-30T09:46:10.3877961 30Z", 233 executionTime = dateToInstant("2025-10-30") 234 ), 235 OutgoingPayment( 236 id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "RC9YD301NZ17YKD6WDWLNOROFHIIN29VJN", "ZV20251030/511373/2"), 237 amount = TalerAmount("CHF:0.11"), 238 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 239 subject = "multi 1 2025-10-30T09:46:10.3877961 30Z", 240 executionTime = dateToInstant("2025-10-30") 241 ), 242 OutgoingPayment( 243 id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "GKDGTHLB82X6XVHBJIJ1CK8MEGU9XJ2EL7", "ZV20251030/511373/3"), 244 amount = TalerAmount("CHF:0.12"), 245 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 246 subject = "multi 2 2025-10-30T09:46:10.3877961 30Z", 247 executionTime = dateToInstant("2025-10-30") 248 ), 249 OutgoingPayment( 250 id = OutgoingId("5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", "PXCH2VVVTXEXBVDWICP23HZ4NV0H2CWW28", "ZV20251030/511373/4"), 251 amount = TalerAmount("CHF:0.13"), 252 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 253 subject = "multi 3 2025-10-30T09:46:10.3877961 30Z", 254 executionTime = dateToInstant("2025-10-30") 255 ), 256 IncomingPayment( 257 id = IncomingId(null, "51030655601.0001", "ZV20251030/514778/1"), 258 amount = TalerAmount("CHF:0.85"), 259 subject = "fun stuff", 260 executionTime = dateToInstant("2025-10-30"), 261 debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 262 ), 263 IncomingPayment( 264 id = IncomingId(null, "51030655601.0002", "ZV20251030/514779/1"), 265 amount = TalerAmount("CHF:0.95"), 266 subject = "Taler PC2MKG0B7CK32K1T7DP08P6E1B7FHB6HY6R Q0PT3VTPBPRPYM1B0", 267 executionTime = dateToInstant("2025-10-30"), 268 debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 269 ), 270 OutgoingPayment( 271 id = OutgoingId("X166701F6RV59LP71RVWVIW9SV2AFZYLG4", "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX", "ZV20251030/524078/1"), 272 amount = TalerAmount("CHF:0.21"), 273 creditor = ibanPayto("CH6208704048981247126", "John Smith"), 274 subject = "bad name 2025-10-30T12:03:24.997478 811Z", 275 executionTime = dateToInstant("2025-10-30") 276 ), 277 OutgoingPayment( 278 id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "02WDIX4J90Z1M1WNFHLNSXY59SHXQTQCMQ", "ZV20251030/524079/1"), 279 amount = TalerAmount("CHF:0.1"), 280 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans"), 281 subject = "single 2025-10-30T12:04:00.37042083 6Z", 282 executionTime = dateToInstant("2025-10-30") 283 ), 284 OutgoingPayment( 285 id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y", "ZV20251030/524079/2"), 286 amount = TalerAmount("CHF:0.21"), 287 creditor = ibanPayto("CH6208704048981247126", "John Smith"), 288 subject = "bad name 2025-10-30T12:03:53.042190 686Z", 289 executionTime = dateToInstant("2025-10-30") 290 ), 291 OutgoingReversal( 292 endToEndId = "XAP5L7HVWPLCEMECU4GZK6GKUPBL0TD13Y", 293 reason = "Error msg in german", 294 executionTime = dateToInstant("2025-10-30") 295 ), 296 OutgoingReversal( 297 endToEndId = "R48UBIIB7B4LX0DMVOSI0ZTJWMMG8FMNKX", 298 reason = "Error msg in german", 299 executionTime = dateToInstant("2025-10-30") 300 ), 301 OutgoingPayment( 302 id = OutgoingId("OLAMDPI6YPMNRZHQ5PQ6JCVUQV2AN5NW6P", "TU2WJ54DR9Z6HT5VE494BNH4EXUSM0DRF7", "ZV20251030/524077/1"), 303 amount = TalerAmount("CHF:0.23"), 304 debitFee = TalerAmount("CHF:5"), 305 creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), 306 subject = "foreign iban 2025-10-30T12:03:44.0972 63765Z", 307 executionTime = dateToInstant("2025-10-30") 308 ), 309 OutgoingPayment( 310 id = OutgoingId("6OZN5T9W7MK6BIZYE01E62NHGP5JLMUD4X", "GM8I8GIETR72LP6CFBGRBUDKNO2CEQBGOE", "ZV20251030/524080/1"), 311 amount = TalerAmount("CHF:0.23"), 312 debitFee = TalerAmount("CHF:5"), 313 creditor = ibanPayto("DE48330605920000686018", "Christian Grothoff"), 314 subject = "foreign iban 2025-10-30T12:03:58.0046 73747Z", 315 executionTime = dateToInstant("2025-10-30") 316 ), 317 IncomingPayment( 318 id = IncomingId("7b76d488-05d5-44ab-9d77-31d4165ec158", "00204EQY370", "ZV20251118/685062/1"), 319 amount = TalerAmount("CHF:4.55"), 320 subject = "TEST", 321 executionTime = dateToInstant("2025-11-18"), 322 debtor = null 323 ), 324 ) 325 )) 326 ) 327 } 328 329 @Test 330 fun raiffeisen_camt053() { 331 assertContentEquals( 332 parseTx(Path("sample/platform/raiffeisen_camt053.xml").inputStream()), 333 listOf(AccountTransactions( 334 iban = "CH7389144832588726658", 335 currency = null, 336 txs = listOf( 337 IncomingPayment( 338 id = IncomingId(null, null, "A200020494367552"), 339 amount = TalerAmount("CHF:20000"), 340 subject = "1. TZ 2025", 341 executionTime = dateToInstant("2025-12-23"), 342 debtor = ibanPayto("CH7389144832588726658", "KANTON BERN") 343 ), 344 OutgoingPayment( 345 id = OutgoingId(null, null, "19868398389"), 346 amount = TalerAmount("CHF:15"), 347 executionTime = dateToInstant("2025-12-31"), 348 subject = null, 349 creditor = null 350 ), 351 OutgoingPayment( 352 id = OutgoingId(null, null, "19890406743"), 353 amount = TalerAmount("CHF:2"), 354 executionTime = dateToInstant("2025-12-31"), 355 subject = null, 356 creditor = null 357 ), 358 OutgoingPayment( 359 id = OutgoingId(null, null, "19885172770"), 360 amount = TalerAmount("CHF:3"), 361 executionTime = dateToInstant("2025-12-31"), 362 subject = null, 363 creditor = null 364 ), 365 ) 366 )) 367 ) 368 } 369 370 @Test 371 fun gls_camt052() { 372 assertContentEquals( 373 parseTx(Path("sample/platform/gls_camt052.xml").inputStream()), 374 listOf(AccountTransactions( 375 iban = "DE84500105177118117964", 376 currency = "EUR", 377 txs = listOf( 378 OutgoingPayment( 379 id = OutgoingId("COMPAT_SUCCESS", "COMPAT_SUCCESS", "2024041801514102000"), 380 amount = TalerAmount("EUR:2"), 381 subject = "TestABC123", 382 executionTime = dateToInstant("2024-04-18"), 383 creditor = ibanPayto("DE20500105172419259181", "John Smith") 384 ), 385 OutgoingReversal( 386 endToEndId = "8XK8Z7RAX224FGWK832FD40GYC", 387 reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", 388 executionTime = dateToInstant("2024-09-05") 389 ), 390 IncomingPayment( 391 id = IncomingId(null, "BYLADEM1WOR-G2910276709458A2", "2024041210041357000"), 392 amount = TalerAmount("EUR:3"), 393 subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", 394 executionTime = dateToInstant("2024-04-12"), 395 debtor = ibanPayto("DE84500105177118117964", "John Smith") 396 ), 397 OutgoingReversal( 398 endToEndId = "COMPAT_FAILURE", 399 reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", 400 executionTime = dateToInstant("2024-04-12") 401 ), 402 OutgoingPayment( 403 id = OutgoingId("BATCH_SINGLE_SUCCESS", "FD622SMXKT5QWSAHDY0H8NYG3G", "2024090216552232000"), 404 amount = TalerAmount("EUR:1.1"), 405 subject = "single 2024-09-02T14:29:52.875253314Z", 406 executionTime = dateToInstant("2024-09-02"), 407 creditor = ibanPayto("DE89500105173198527518", "Grothoff Hans") 408 ), 409 OutgoingPayment( 410 id = OutgoingId("YF5QBARGQ0MNY0VK59S477VDG4", "YF5QBARGQ0MNY0VK59S477VDG4", "2024041810552821000"), 411 amount = TalerAmount("EUR:1.1"), 412 subject = "Simple tx", 413 executionTime = dateToInstant("2024-04-18"), 414 creditor = ibanPayto("DE20500105172419259181", "John Smith") 415 ), 416 OutgoingBatch( 417 msgId = "BATCH_MANY_SUCCESS", 418 executionTime = dateToInstant("2024-09-20"), 419 ), 420 OutgoingPayment( 421 id = OutgoingId("BATCH_SINGLE_RETURN", "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", "2024092100252498000"), 422 amount = TalerAmount("EUR:0.42"), 423 subject = "This should fail because bad iban", 424 executionTime = dateToInstant("2024-09-23"), 425 creditor = ibanPayto("DE18500105173385245163", "John Smith") 426 ), 427 OutgoingReversal( 428 endToEndId = "KLJJ28S1LVNDK1R2HCHLN884M7EKM5XGM5", 429 reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN fehlerhaft und ungültig'", 430 executionTime = dateToInstant("2024-09-24") 431 ), 432 ) 433 )) 434 ) 435 } 436 437 @Test 438 fun gls_camt053() { 439 assertContentEquals( 440 parseTx(Path("sample/platform/gls_camt053.xml").inputStream()), 441 listOf(AccountTransactions( 442 iban = "DE84500105177118117964", 443 currency = "EUR", 444 txs = listOf( 445 OutgoingPayment( 446 id = OutgoingId("COMPAT_SUCCESS", "COMPAT_SUCCESS", "2024041801514102000"), 447 amount = TalerAmount("EUR:2"), 448 subject = "TestABC123", 449 executionTime = dateToInstant("2024-04-18"), 450 creditor = ibanPayto("DE20500105172419259181", "John Smith") 451 ), 452 OutgoingReversal( 453 endToEndId = "KGTDBASWTJ6JM89WXD3Q5KFQC4", 454 reason = "Retoure aus SEPA Überweisung multi line", 455 executionTime = dateToInstant("2024-09-04") 456 ), 457 OutgoingBatch( 458 msgId = "BATCH_MANY_PART", 459 executionTime = dateToInstant("2024-09-04") 460 ), 461 IncomingPayment( 462 id = IncomingId(null, "BYLADEM1WOR-G2910276709458A2", "2024041210041357000"), 463 amount = TalerAmount("EUR:3"), 464 subject = "Taler FJDQ7W6G7NWX4H9M1MKA12090FRC9K7DA6N0FANDZZFXTR6QHX5G Test.,-", 465 executionTime = dateToInstant("2024-04-12"), 466 debtor = ibanPayto("DE84500105177118117964", "John Smith") 467 ), 468 OutgoingReversal( 469 endToEndId = "COMPAT_FAILURE", 470 reason = "IncorrectAccountNumber 'Format of the account number specified is not correct' - 'IBAN ...'", 471 executionTime = dateToInstant("2024-04-12") 472 ), 473 OutgoingPayment( 474 id = OutgoingId("BATCH_SINGLE_SUCCESS", "FD622SMXKT5QWSAHDY0H8NYG3G", "2024090216552232000"), 475 amount = TalerAmount("EUR:1.1"), 476 subject = "single 2024-09-02T14:29:52.875253314Z", 477 executionTime = dateToInstant("2024-09-02"), 478 creditor = ibanPayto("DE89500105173198527518", "Grothoff Hans") 479 ), 480 OutgoingPayment( 481 id = OutgoingId("YF5QBARGQ0MNY0VK59S477VDG4", "YF5QBARGQ0MNY0VK59S477VDG4", "2024041810552821000"), 482 amount = TalerAmount("EUR:1.1"), 483 subject = "Simple tx", 484 executionTime = dateToInstant("2024-04-18"), 485 creditor = ibanPayto("DE20500105172419259181", "John Smith") 486 ), 487 )) 488 ) 489 ) 490 } 491 492 @Test 493 fun gls_camt054() { 494 assertContentEquals( 495 parseTx(Path("sample/platform/gls_camt054.xml").inputStream()), 496 listOf(AccountTransactions( 497 iban = "DE84500105177118117964", 498 currency = "EUR", 499 txs = listOf<TxNotification>( 500 IncomingPayment( 501 id = IncomingId(null, "IS11PGENODEFF2DA8899900378806", null), 502 amount = TalerAmount("EUR:2.5"), 503 subject = "Test ICT", 504 executionTime = dateToInstant("2024-05-05"), 505 debtor = ibanPayto("DE84500105177118117964", "Mr Test") 506 ) 507 ) 508 )) 509 ) 510 } 511 512 @Test 513 fun maerki_baumann_camt053() { 514 assertContentEquals( 515 parseTx(Path("sample/platform/maerki_baumann_camt053.xml").inputStream()), 516 listOf(AccountTransactions( 517 iban = "CH7389144832588726658", 518 currency = "CHF", 519 txs = listOf<TxNotification>( 520 IncomingPayment( 521 id = IncomingId("adbe4a5a-6cea-4263-b259-8ab964561a32", "41103099704.0002", "ZV20241104/765446/1"), 522 amount = TalerAmount("CHF:1"), 523 creditFee = TalerAmount("CHF:0.2"), 524 subject = "SFHP6H24C16A5J05Q3FJW2XN1PB3EK70ZPY 5SJ30ADGY68FWN68G", 525 executionTime = dateToInstant("2024-11-04"), 526 debtor = ibanPayto("CH7389144832588726658", "Mr Test") 527 ), 528 IncomingPayment( 529 id = IncomingId("7371795e-62fa-42dd-93b7-da89cc120faa", "41103099704.0003", "ZV20241104/765447/1"), 530 amount = TalerAmount("CHF:1"), 531 creditFee = TalerAmount("CHF:0.2"), 532 subject = "Random subject", 533 executionTime = dateToInstant("2024-11-04"), 534 debtor = ibanPayto("CH7389144832588726658", "Mr Test") 535 ), 536 IncomingPayment( 537 id = IncomingId(null, "50523424675.0001", "ZV20250523/851716/1"), 538 amount = TalerAmount("CHF:0.5"), 539 creditFee = TalerAmount("CHF:0.2"), 540 subject = null, 541 executionTime = dateToInstant("2025-05-23"), 542 debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 543 ), 544 OutgoingPayment( 545 id = OutgoingId("BATCH_SINGLE_REPORTING", "5IBJZOWESQGPCSOXSNNBBY49ZURI5W7Q4H", "ZV20241121/773541/1"), 546 amount = TalerAmount("CHF:0.1"), 547 subject = "multi 0 2024-11-21T15:21:59.8859234 63Z", 548 executionTime = dateToInstant("2024-11-27"), 549 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 550 ), 551 OutgoingPayment( 552 id = OutgoingId("BATCH_SINGLE_REPORTING", "XZ15UR0XU52QWI7Q4XB88EDS44PLH7DYXH", "ZV20241121/773541/4"), 553 amount = TalerAmount("CHF:0.13"), 554 subject = "multi 3 2024-11-21T15:21:59.8859234 63Z", 555 executionTime = dateToInstant("2024-11-27"), 556 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 557 ), 558 OutgoingPayment( 559 id = OutgoingId("BATCH_SINGLE_REPORTING", "A09R35EW0359SZ51464E7TC37A0P2CBK04", "ZV20241121/773541/3"), 560 amount = TalerAmount("CHF:0.12"), 561 subject = "multi 2 2024-11-21T15:21:59.8859234 63Z", 562 executionTime = dateToInstant("2024-11-27"), 563 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 564 ), 565 OutgoingPayment( 566 id = OutgoingId("BATCH_SINGLE_REPORTING", "UYXZ78LE9KAIMBY6UNXFYT1K8KNY8VLZLT", "ZV20241121/773541/2"), 567 amount = TalerAmount("CHF:0.11"), 568 subject = "multi 1 2024-11-21T15:21:59.8859234 63Z", 569 executionTime = dateToInstant("2024-11-27"), 570 creditor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 571 ), 572 IncomingPayment( 573 id = IncomingId("f203fbb4-6e13-4c78-9b2a-d852fea6374a", "41202060702.0001", "ZV20241202/778108/1"), 574 amount = TalerAmount("CHF:0.05"), 575 creditFee = TalerAmount("CHF:0.2"), 576 subject = "mini", 577 executionTime = dateToInstant("2024-12-02"), 578 debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 579 ), 580 IncomingPayment( 581 id = IncomingId("81b0d8c6-a677-4577-b75e-a639dcc03681", "41120636093.0001", "ZV20241121/773118/1"), 582 amount = TalerAmount("CHF:0.1"), 583 creditFee = TalerAmount("CHF:0.2"), 584 subject = "small transfer test", 585 executionTime = dateToInstant("2024-11-21"), 586 debtor = ibanPayto("CH7389144832588726658", "Grothoff Hans") 587 ), 588 OutgoingPayment( 589 id = OutgoingId(null, null, "GB20241220/205792/1"), 590 amount = TalerAmount("CHF:3000"), 591 subject = null, 592 executionTime = dateToInstant("2024-12-20"), 593 creditor = null 594 ), 595 IncomingPayment( 596 id = IncomingId(null, null, "ZV20250114/796191/1"), 597 amount = TalerAmount("CHF:3003"), 598 subject = "Fix bad payment by MB.", 599 executionTime = dateToInstant("2025-01-27"), 600 debtor = null 601 ), 602 IncomingPayment( 603 id = IncomingId(null, "F000787951230001", "ZV20250526/852733/1"), 604 amount = TalerAmount("CHF:1.38"), 605 creditFee = TalerAmount("CHF:0.2"), 606 subject = "Taler XT3D9MADR4V85JBWX47SMJFDQD2FDZDHHPH8R25YDG1KNVTSEH6G", 607 executionTime = dateToInstant("2025-05-26"), 608 debtor = ibanPayto("DE20500105172419259181", "Mr German") 609 ), 610 ) 611 )) 612 ) 613 } 614 615 @Test 616 fun pain002() { 617 assertEquals( 618 parseCustomerPaymentStatusReport(Path("sample/platform/pain002_part.xml").inputStream()), 619 MsgStatus( 620 id = "05BD4C5B4A2649B5B08F6EF6A31F197A", 621 code = ExternalPaymentGroupStatusCode.PART, 622 reasons = emptyList(), 623 payments = listOf( 624 PmtStatus( 625 id = "NOTPROVIDED", 626 code = ExternalPaymentGroupStatusCode.PART, 627 reasons = listOf( 628 Reason( 629 code = ExternalStatusReasonCode.DT06, 630 information = "Due date is not a working day. Order will be executed on the next working day" 631 ) 632 ), 633 transactions = listOf( 634 TxStatus( 635 id = "AQCXNCPWD8PHW5JTN65Y5XTF7R", 636 endToEndId = "AQCXNCPWD8PHW5JTN65Y5XTF7R", 637 code = ExternalPaymentTransactionStatusCode.RJCT, 638 reasons = listOf( 639 Reason( 640 code = ExternalStatusReasonCode.AC04, 641 information = "Error message" 642 ) 643 ) 644 ), 645 TxStatus( 646 id = "EE9SX76FC5YSC657EK3GMVZ9TC", 647 endToEndId = "EE9SX76FC5YSC657EK3GMVZ9TC", 648 code = ExternalPaymentTransactionStatusCode.RJCT, 649 reasons = listOf( 650 Reason( 651 code = ExternalStatusReasonCode.MS03, 652 information = "Error message" 653 ) 654 ) 655 ), 656 TxStatus( 657 id = "V5B3MXPEWES9VQW1JDRD6VAET4", 658 endToEndId = "V5B3MXPEWES9VQW1JDRD6VAET4", 659 code = ExternalPaymentTransactionStatusCode.RJCT, 660 reasons = listOf( 661 Reason( 662 code = ExternalStatusReasonCode.RR02, 663 information = "Error message" 664 ) 665 ) 666 ) 667 ) 668 ) 669 ) 670 ) 671 ) 672 assertEquals( 673 parseCustomerPaymentStatusReport(Path("sample/platform/pain002_accp.xml").inputStream()), 674 MsgStatus( 675 id = "5HIS3433VVIBAANHW3GX9DR1AXRS43KZ4U", 676 code = ExternalPaymentGroupStatusCode.ACCP, 677 reasons = listOf( 678 Reason( 679 code = null, 680 information = "PN10630020F0297329.20251030104613.EBTUAAAC.PN1.0002372" 681 ) 682 ), 683 payments = emptyList() 684 ) 685 ) 686 } 687 }