commit a488eecd3cbb88a2bb2167c5e67e1090bf405f59
parent 9b8065058041fdde79794c4d0a43a03727907991
Author: Antoine A <>
Date: Thu, 19 Sep 2024 14:24:58 +0200
nexus: WIP HKD parsing
Diffstat:
2 files changed, 66 insertions(+), 27 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/cli/EbicsSetup.kt
@@ -229,9 +229,15 @@ class EbicsSetup: CliktCommand("Set up the EBICS subscriber") {
if (account.name != null && account.name != cfg.account.name)
logger.warn("Expected NAME '${cfg.account.name}' from config got '${account.name}' from bank")
+ logger.debug("User status: ${hkd.status.name} ${hkd.status.description}")
+ logger.debug("Supported orders:")
for (order in hkd.orders) {
logger.debug("${order.type}${order.params}: ${order.description}")
}
+ logger.debug("Authorized orders:")
+ for (order in hkd.permissions) {
+ logger.debug("${order.type}${order.params}")
+ }
}
}
} catch (e: Exception) {
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsAdministrative.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsAdministrative.kt
@@ -31,7 +31,9 @@ data class VersionNumber(val number: Float, val schema: String) {
data class HKD (
val account: AccountInfo,
- val orders: List<OrderInfo>
+ val orders: List<OrderInfo>,
+ val permissions: List<OrderInfo>,
+ val status: UserStatus
)
data class AccountInfo (
val currency: String?,
@@ -43,6 +45,17 @@ data class OrderInfo (
val params: String,
val description: String,
)
+// TODO use this in ebics setup to get current state and required actions
+enum class UserStatus(val description: String) {
+ Ready("Subscriber is permitted access"),
+ New("Subscriber is established, pending access permission"),
+ INI("Subscriber has sent INI file, but no HIA file yet"),
+ HIA("Subscriber has sent HIA order, but no INI file yet"),
+ Initialised("Subscriber has sent both HIA order and INI file"),
+ SuspendedFailedAttempts("Suspended after several failed attempts, new initialisation via INI and HIA possible"),
+ SuspendedSPR("Suspended after SPR order, new initialisation via INI and HIA possible"),
+ SuspendedBank("Suspended by bank, new initialisation via INI and HIA is not possible, suspension can only be revoked by the bank"),
+}
object EbicsAdministrative {
fun HEV(cfg: NexusEbicsConfig): ByteArray {
@@ -69,8 +82,33 @@ object EbicsAdministrative {
}
fun parseHKD(stream: InputStream): HKD {
+ fun XmlDestructor.orderInfo() = OrderInfo(
+ one("AdminOrderType").text(),
+ opt("Service") {
+ // TODO user a structured type to enable comparison
+ val params = StringBuilder()
+ opt("ServiceName")?.run {
+ params.append(" ${text()}")
+ }
+ opt("Scope")?.run {
+ params.append(" ${text()}")
+ }
+ opt("ServiceOption")?.run {
+ params.append(" ${text()}")
+ }
+ opt("MsgName")?.run {
+ params.append(" ${text()}")
+ }
+ opt("Container")?.run {
+ params.append(" ${attr("containerType")}")
+ }
+ params.toString()
+ } ?: "",
+ opt("Description")?.text() ?: ""
+ )
+ // TODO handle multiple partner, accounts and user using their respective ids
return XmlDestructor.fromStream(stream, "HKDResponseOrderData") {
- one("PartnerInfo") {
+ val (account, orders) = one("PartnerInfo") {
var currency: String? = null
var iban: String? = null
val name = opt("AddressInfo")?.one("Name")?.text()
@@ -82,33 +120,28 @@ object EbicsAdministrative {
}
}
}
- val orders = map("OrderInfo") {
- OrderInfo(
- one("AdminOrderType").text(),
- opt("Service") {
- val params = StringBuilder()
- opt("ServiceName")?.run {
- params.append(" ${text()}")
- }
- opt("Scope")?.run {
- params.append(" ${text()}")
- }
- opt("ServiceOption")?.run {
- params.append(" ${text()}")
- }
- opt("MsgName")?.run {
- params.append(" ${text()}")
- }
- opt("Container")?.run {
- params.append(" ${attr("containerType")}")
- }
- params.toString()
- } ?: "",
- one("Description").text()
- )
+ val orders = map("OrderInfo") { orderInfo() }
+ Pair(AccountInfo(currency, iban, name), orders)
+ }
+ val (permissions, status) = one("UserInfo") {
+ val userId = one("UserID").text()
+ val status = when (val status = one("UserID").attr("Status")) {
+ "1" -> UserStatus.Ready
+ "2" -> UserStatus.New
+ "3" -> UserStatus.INI
+ "4" -> UserStatus.HIA
+ "5" -> UserStatus.Initialised
+ "6" -> UserStatus.SuspendedFailedAttempts
+ // 7 is not applicable per spec
+ "8" -> UserStatus.SuspendedSPR
+ "9" -> UserStatus.SuspendedBank
+ else -> throw Exception("Unknown user statte $status")
}
- HKD(AccountInfo(currency, iban, name), orders)
+ val userName = opt("Name")?.text()
+ val permissions = map("Permission") { orderInfo() }
+ Pair(permissions, status)
}
+ HKD(account, orders, permissions, status)
}
}
}