[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] 03/05: refactor payment initiations
From: |
gnunet |
Subject: |
[libeufin] 03/05: refactor payment initiations |
Date: |
Thu, 18 Jun 2020 15:27:05 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository libeufin.
commit a31d6b760ae636dc3f59ea35f75c779f297b8732
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Thu Jun 18 18:50:59 2020 +0530
refactor payment initiations
---
nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt | 44 ++++++++++----------
.../src/main/kotlin/tech/libeufin/nexus/Helpers.kt | 16 ++++----
.../main/kotlin/tech/libeufin/nexus/Iso20022.kt | 47 ++++++++--------------
nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt | 40 +++---------------
.../tech/libeufin/nexus/bankaccount/BankAccount.kt | 38 +++++++++--------
.../kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt | 5 ++-
.../src/main/kotlin/tech/libeufin/sandbox/DB.kt | 4 +-
.../tech/libeufin/sandbox/EbicsProtocolBackend.kt | 40 +++++++++---------
util/src/main/kotlin/JSON.kt | 4 +-
9 files changed, 98 insertions(+), 140 deletions(-)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
index f6315a9..cd2e2d5 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/DB.kt
@@ -46,7 +46,7 @@ object TalerRequestedPayments : LongIdTable() {
// in the sense that a "early" prepared payment might
// get a "high" id because the bank confirmed it "late".
val abstractId = long("abstractId").nullable()
- val preparedPayment = reference("payment", InitiatedPaymentsTable)
+ val preparedPayment = reference("payment", PaymentInitiationsTable)
val requestUId = text("request_uid")
val amount = text("amount")
val exchangeBaseUrl = text("exchange_base_url")
@@ -57,7 +57,7 @@ object TalerRequestedPayments : LongIdTable() {
class TalerRequestedPaymentEntity(id: EntityID<Long>) : LongEntity(id) {
companion object :
LongEntityClass<TalerRequestedPaymentEntity>(TalerRequestedPayments)
var abstractId by TalerRequestedPayments.abstractId
- var preparedPayment by InitiatedPaymentEntity referencedOn
TalerRequestedPayments.preparedPayment
+ var preparedPayment by PaymentInitiationEntity referencedOn
TalerRequestedPayments.preparedPayment
var requestUId by TalerRequestedPayments.requestUId
var amount by TalerRequestedPayments.amount
var exchangeBaseUrl by TalerRequestedPayments.exchangeBaseUrl
@@ -167,7 +167,7 @@ class RawBankTransactionEntity(id: EntityID<Long>) :
LongEntity(id) {
/**
* Represents a prepared payment.
*/
-object InitiatedPaymentsTable : LongIdTable() {
+object PaymentInitiationsTable : LongIdTable() {
/**
* Bank account that wants to initiate the payment.
*/
@@ -193,24 +193,24 @@ object InitiatedPaymentsTable : LongIdTable() {
val rawConfirmation = reference("rawConfirmation",
RawBankTransactionsTable).nullable()
}
-class InitiatedPaymentEntity(id: EntityID<Long>) : LongEntity(id) {
- companion object :
LongEntityClass<InitiatedPaymentEntity>(InitiatedPaymentsTable)
-
- var bankAccount by NexusBankAccountEntity referencedOn
InitiatedPaymentsTable.bankAccount
- var preparationDate by InitiatedPaymentsTable.preparationDate
- var submissionDate by InitiatedPaymentsTable.submissionDate
- var sum by InitiatedPaymentsTable.sum
- var currency by InitiatedPaymentsTable.currency
- var debitorIban by InitiatedPaymentsTable.debitorIban
- var debitorBic by InitiatedPaymentsTable.debitorBic
- var debitorName by InitiatedPaymentsTable.debitorName
- var endToEndId by InitiatedPaymentsTable.endToEndId
- var subject by InitiatedPaymentsTable.subject
- var creditorIban by InitiatedPaymentsTable.creditorIban
- var creditorBic by InitiatedPaymentsTable.creditorBic
- var creditorName by InitiatedPaymentsTable.creditorName
- var submitted by InitiatedPaymentsTable.submitted
- var rawConfirmation by RawBankTransactionEntity optionalReferencedOn
InitiatedPaymentsTable.rawConfirmation
+class PaymentInitiationEntity(id: EntityID<Long>) : LongEntity(id) {
+ companion object :
LongEntityClass<PaymentInitiationEntity>(PaymentInitiationsTable)
+
+ var bankAccount by NexusBankAccountEntity referencedOn
PaymentInitiationsTable.bankAccount
+ var preparationDate by PaymentInitiationsTable.preparationDate
+ var submissionDate by PaymentInitiationsTable.submissionDate
+ var sum by PaymentInitiationsTable.sum
+ var currency by PaymentInitiationsTable.currency
+ var debitorIban by PaymentInitiationsTable.debitorIban
+ var debitorBic by PaymentInitiationsTable.debitorBic
+ var debitorName by PaymentInitiationsTable.debitorName
+ var endToEndId by PaymentInitiationsTable.endToEndId
+ var subject by PaymentInitiationsTable.subject
+ var creditorIban by PaymentInitiationsTable.creditorIban
+ var creditorBic by PaymentInitiationsTable.creditorBic
+ var creditorName by PaymentInitiationsTable.creditorName
+ var submitted by PaymentInitiationsTable.submitted
+ var rawConfirmation by RawBankTransactionEntity optionalReferencedOn
PaymentInitiationsTable.rawConfirmation
}
/**
@@ -345,7 +345,7 @@ fun dbCreateTables(dbName: String) {
addLogger(StdOutSqlLogger)
SchemaUtils.create(
NexusUsersTable,
- InitiatedPaymentsTable,
+ PaymentInitiationsTable,
EbicsSubscribersTable,
NexusBankAccountsTable,
RawBankTransactionsTable,
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
index 177369b..13a993a 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Helpers.kt
@@ -52,9 +52,9 @@ private fun findDuplicate(bankAccountId: String, acctSvcrRef:
String): RawBankTr
fun markInitiatedAsConfirmed(subject: String, debtorIban: String, rawUuid:
Long) {
// not introducing a 'transaction {}' block since
// this function should be always be invoked from one.
- val initiatedPayment = InitiatedPaymentEntity.find {
- InitiatedPaymentsTable.subject eq subject and
- (InitiatedPaymentsTable.debitorIban eq debtorIban)
+ val initiatedPayment = PaymentInitiationEntity.find {
+ PaymentInitiationsTable.subject eq subject and
+ (PaymentInitiationsTable.debitorIban eq debtorIban)
}.firstOrNull()
if (initiatedPayment == null) {
logger.info("Payment '$subject' was never programmatically prepared")
@@ -160,7 +160,7 @@ fun ingestBankMessagesIntoAccount(
* Create a PAIN.001 XML document according to the input data.
* Needs to be called within a transaction block.
*/
-fun createPain001document(paymentData: InitiatedPaymentEntity): String {
+fun createPain001document(paymentData: PaymentInitiationEntity): String {
/**
* Every PAIN.001 document contains at least three IDs:
*
@@ -286,9 +286,9 @@ fun createPain001document(paymentData:
InitiatedPaymentEntity): String {
* Retrieve prepared payment from database, raising exception
* if not found.
*/
-fun getPreparedPayment(uuid: Long): InitiatedPaymentEntity {
+fun getPreparedPayment(uuid: Long): PaymentInitiationEntity {
return transaction {
- InitiatedPaymentEntity.findById(uuid)
+ PaymentInitiationEntity.findById(uuid)
} ?: throw NexusError(
HttpStatusCode.NotFound,
"Payment '$uuid' not found"
@@ -303,9 +303,9 @@ fun getPreparedPayment(uuid: Long): InitiatedPaymentEntity {
* it will be the account whose money will pay the wire transfer being defined
* by this pain document.
*/
-fun addPreparedPayment(paymentData: Pain001Data, debitorAccount:
NexusBankAccountEntity): InitiatedPaymentEntity {
+fun addPreparedPayment(paymentData: Pain001Data, debitorAccount:
NexusBankAccountEntity): PaymentInitiationEntity {
return transaction {
- InitiatedPaymentEntity.new {
+ PaymentInitiationEntity.new {
bankAccount = debitorAccount
subject = paymentData.subject
sum = paymentData.sum
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
index b199dde..2027503 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Iso20022.kt
@@ -17,18 +17,14 @@
* <http://www.gnu.org/licenses/>
*/
-package tech.libeufin.nexus
-
/**
- * Parse ISO 20022 messages
+ * Parse and generate ISO 20022 messages
*/
+package tech.libeufin.nexus
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
-import io.ktor.http.HttpStatusCode
-import org.jetbrains.exposed.sql.and
-import org.jetbrains.exposed.sql.transactions.transaction
import org.w3c.dom.Document
import tech.libeufin.util.*
import java.time.Instant
@@ -224,6 +220,7 @@ class CamtParsingError(msg: String) : Exception(msg)
data class NexusPaymentInitiationData(
val debtorIban: String,
val debtorBic: String,
+ val debtorName: String,
val messageId: String,
val paymentInformationId: String,
val amount: String,
@@ -239,29 +236,17 @@ data class NexusPaymentInitiationData(
* Needs to be called within a transaction block.
*/
fun createPain001document(paymentData: NexusPaymentInitiationData): String {
- /**
- * Every PAIN.001 document contains at least three IDs:
- *
- * 1) MsgId: a unique id for the message itself
- * 2) PmtInfId: the unique id for the payment's set of information
- * 3) EndToEndId: a unique id to be shared between the debtor and
- * creditor that uniquely identifies the transaction
- *
- * For now and for simplicity, since every PAIN entry in the database
- * has a unique ID, and the three values aren't required to be mutually
different,
- * we'll assign the SAME id (= the row id) to all the three aforementioned
- * PAIN id types.
- */
- val debitorBankAccountLabel = run {
- val debitorBankAcount = NexusBankAccountEntity.find {
- NexusBankAccountsTable.iban eq paymentData.debtorIban and
- (NexusBankAccountsTable.bankCode eq paymentData.debtorBic)
- }.firstOrNull() ?: throw NexusError(
- HttpStatusCode.NotFound,
- "Please download bank accounts details first (HTD)"
- )
- debitorBankAcount.id.value
- }
+ // Every PAIN.001 document contains at least three IDs:
+ //
+ // 1) MsgId: a unique id for the message itself
+ // 2) PmtInfId: the unique id for the payment's set of information
+ // 3) EndToEndId: a unique id to be shared between the debtor and
+ // creditor that uniquely identifies the transaction
+ //
+ // For now and for simplicity, since every PAIN entry in the database
+ // has a unique ID, and the three values aren't required to be mutually
different,
+ // we'll assign the SAME id (= the row id) to all the three aforementioned
+ // PAIN id types.
val s = constructXml(indent = true) {
root("Document") {
@@ -287,7 +272,7 @@ fun createPain001document(paymentData:
NexusPaymentInitiationData): String {
text(paymentData.amount)
}
element("InitgPty/Nm") {
- text(debitorBankAccountLabel)
+ text(paymentData.debtorName)
}
}
element("PmtInf") {
@@ -314,7 +299,7 @@ fun createPain001document(paymentData:
NexusPaymentInitiationData): String {
text(importDateFromMillis(dateMillis).toDashedDate())
}
element("Dbtr/Nm") {
- text(debitorBankAccountLabel)
+ text(paymentData.debtorName)
}
element("DbtrAcct/Id/IBAN") {
text(paymentData.debtorIban)
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 4112311..f053d17 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -66,7 +66,8 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.event.Level
-import tech.libeufin.nexus.bankaccount.submitPreparedPayments
+import tech.libeufin.nexus.bankaccount.submitAllPreparedPayments
+import tech.libeufin.nexus.bankaccount.submitPreparedPayment
import tech.libeufin.nexus.ebics.*
import tech.libeufin.util.*
import tech.libeufin.util.CryptoUtil.hashpw
@@ -246,7 +247,7 @@ fun moreFrequentBackgroundTasks(httpClient: HttpClient) {
}
// FIXME: should be done automatically after raw ingestion
reportAndIgnoreErrors { ingestTalerTransactions() }
- reportAndIgnoreErrors { submitPreparedPayments(httpClient) }
+ reportAndIgnoreErrors { submitAllPreparedPayments(httpClient) }
logger.debug("More frequent background jobs done")
delay(Duration.ofSeconds(1))
}
@@ -518,40 +519,9 @@ fun serverMain(dbName: String) {
val uuid = ensureLong(call.parameters["uuid"])
val accountId = ensureNonNull(call.parameters["accountid"])
val res = transaction {
- val user = authenticateRequest(call.request)
- val preparedPayment = getPreparedPayment(uuid)
- if (preparedPayment.submitted) {
- throw NexusError(
- HttpStatusCode.PreconditionFailed,
- "Payment ${uuid} was submitted already"
- )
- }
- val bankAccount =
NexusBankAccountEntity.findById(accountId)
- if (bankAccount == null) {
- throw NexusError(HttpStatusCode.NotFound, "unknown
bank account")
- }
- val defaultBankConnection =
bankAccount.defaultBankConnection
- ?: throw NexusError(HttpStatusCode.NotFound, "needs a
default connection")
- return@transaction object {
- val pain001document =
createPain001document(preparedPayment)
- val bankConnectionType = defaultBankConnection.type
- val connId = defaultBankConnection.id.value
- }
- }
- // type and name aren't null
- when (res.bankConnectionType) {
- "ebics" -> {
- submitEbicsPaymentInitiation(client, res.connId,
res.pain001document)
- }
- else -> throw NexusError(
- HttpStatusCode.NotFound,
- "Transport type '${res.bankConnectionType}' not
implemented"
- )
- }
- transaction {
- val preparedPayment = getPreparedPayment(uuid)
- preparedPayment.submitted = true
+ authenticateRequest(call.request)
}
+ submitPreparedPayment(client, uuid)
call.respondText("Payment ${uuid} submitted")
return@post
}
diff --git
a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
index 3c93828..0a8de16 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/bankaccount/BankAccount.kt
@@ -25,19 +25,29 @@ import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.not
import org.jetbrains.exposed.sql.transactions.transaction
import tech.libeufin.nexus.*
-import tech.libeufin.nexus.ebics.doEbicsUploadTransaction
import tech.libeufin.nexus.ebics.submitEbicsPaymentInitiation
-import tech.libeufin.util.EbicsClientSubscriberDetails
-import tech.libeufin.util.EbicsStandardOrderParams
+suspend fun submitPreparedPayment(httpClient: HttpClient, paymentInitiationId:
Long) {
+ val type = transaction {
+ val paymentInitiation =
PaymentInitiationEntity.findById(paymentInitiationId)
+ if (paymentInitiation == null) {
+ throw NexusError(HttpStatusCode.NotFound, "prepared payment not
found")
+ }
+ paymentInitiation.bankAccount.defaultBankConnection?.type
+ }
+ when (type) {
+ null -> throw NexusError(HttpStatusCode.NotFound, "no default bank
connection")
+ "ebics" -> submitEbicsPaymentInitiation(httpClient,
paymentInitiationId)
+ }
+}
+
/**
* Submit all pending prepared payments.
*/
-suspend fun submitPreparedPayments(httpClient: HttpClient) {
+suspend fun submitAllPreparedPayments(httpClient: HttpClient) {
data class Submission(
- val id: Long,
- val type: String
+ val id: Long
)
logger.debug("auto-submitter started")
val workQueue = mutableListOf<Submission>()
@@ -56,21 +66,15 @@ suspend fun submitPreparedPayments(httpClient: HttpClient) {
return@forEach
}
val bankAccount: NexusBankAccountEntity = it
- InitiatedPaymentEntity.find {
- InitiatedPaymentsTable.debitorIban eq bankAccount.iban and
- not(InitiatedPaymentsTable.submitted)
+ PaymentInitiationEntity.find {
+ PaymentInitiationsTable.debitorIban eq bankAccount.iban and
+ not(PaymentInitiationsTable.submitted)
}.forEach {
- workQueue.add(Submission(it.id.value, bankConnection.type))
+ workQueue.add(Submission(it.id.value))
}
}
}
workQueue.forEach {
- when (it.type) {
- "ebics" -> {
- submitEbicsPaymentInitiation(httpClient, it.id)
- }
- else -> throw NexusError(HttpStatusCode.NotImplemented,
"submission for ${it.type }not supported")
- }
-
+ submitPreparedPayment(httpClient, it.id)
}
}
\ No newline at end of file
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
index 9584798..ccffa96 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/ebics/EbicsNexus.kt
@@ -635,7 +635,7 @@ fun getEbicsKeyLetterPdf(conn: NexusBankConnectionEntity):
ByteArray {
suspend fun submitEbicsPaymentInitiation(httpClient: HttpClient,
paymentInitiationId: Long) {
val r = transaction {
- val paymentInitiation =
InitiatedPaymentEntity.findById(paymentInitiationId)
+ val paymentInitiation =
PaymentInitiationEntity.findById(paymentInitiationId)
?: throw NexusError(HttpStatusCode.NotFound, "payment initiation
not found")
val connId = paymentInitiation.bankAccount.defaultBankConnection?.id
?: throw NexusError(HttpStatusCode.NotFound, "no default bank
connection available for submission")
@@ -653,7 +653,8 @@ suspend fun submitEbicsPaymentInitiation(httpClient:
HttpClient, paymentInitiati
// FIXME(dold): Put date in here as well
paymentInformationId = paymentInitiation.id.toString(),
preparationTimestamp = paymentInitiation.preparationDate,
- subject = paymentInitiation.subject
+ subject = paymentInitiation.subject,
+ debtorName = paymentInitiation.bankAccount.accountHolder
))
object {
val subscriberDetails = subscriberDetails
diff --git a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
index 13b92ab..cc31bbb 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/DB.kt
@@ -251,10 +251,10 @@ class EbicsUploadTransactionChunkEntity(id:
EntityID<String>) : Entity<String>(i
*/
object PaymentsTable : IntIdTable() {
val creditorIban = text("creditorIban")
- val creditorBic = text("creditorBic")
+ val creditorBic = text("creditorBic").nullable()
val creditorName = text("creditorName")
val debitorIban = text("debitorIban")
- val debitorBic = text("debitorBic")
+ val debitorBic = text("debitorBic").nullable()
val debitorName = text("debitorName")
val subject = text("subject")
val amount = text("amount")
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index 1cf902e..37d3611 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -376,23 +376,23 @@ fun buildCamtString(type: Int, subscriberIban: String,
history: MutableList<RawP
text(it.creditorIban)
}
}
- element("RltdAgts") {
- element("CdtrAgt/FinInstnId/BIC") {
- // FIXME: explain this!
- text(
- if
(subscriberIban.equals(it.creditorIban))
- it.debitorBic else
it.creditorBic
- )
- }
- element("DbtrAgt/FinInstnId/BIC") {
- // FIXME: explain this!
- text(
- if
(subscriberIban.equals(it.creditorIban))
- it.creditorBic else
it.debitorBic
- )
- }
-
- }
+// element("RltdAgts") {
+// element("CdtrAgt/FinInstnId/BIC") {
+// // FIXME: explain this!
+// text(
+// if
(subscriberIban.equals(it.creditorIban))
+// it.debitorBic else
it.creditorBic
+// )
+// }
+// element("DbtrAgt/FinInstnId/BIC") {
+// // FIXME: explain this!
+// text(
+// if
(subscriberIban.equals(it.creditorIban))
+// it.creditorBic else
it.debitorBic
+// )
+// }
+//
+// }
element("RmtInf/Ustrd") {
text(it.subject)
}
@@ -488,10 +488,10 @@ private fun handleCct(paymentRequest: String,
initiatorName: String) {
*/
val painDoc = XMLUtil.parseStringIntoDom(paymentRequest)
val creditorIban =
painDoc.pickString("//*[local-name()='CdtrAcct']//*[local-name()='IBAN']")
- val creditorBic =
painDoc.pickString("//*[local-name()='CdtrAgt']//*[local-name()='BIC']")
+ //val creditorBic =
painDoc.pickString("//*[local-name()='CdtrAgt']//*[local-name()='BIC']")
val creditorName =
painDoc.pickString("//*[local-name()='Cdtr']//*[local-name()='Nm']")
val debitorIban =
painDoc.pickString("//*[local-name()='DbtrAcct']//*[local-name()='IBAN']")
- val debitorBic =
painDoc.pickString("//*[local-name()='DbtrAgt']//*[local-name()='BIC']")
+ //val debitorBic =
painDoc.pickString("//*[local-name()='DbtrAgt']//*[local-name()='BIC']")
val debitorName = initiatorName
val subject = painDoc.pickString("//*[local-name()='Ustrd']")
val amount = painDoc.pickString("//*[local-name()='InstdAmt']")
@@ -500,10 +500,8 @@ private fun handleCct(paymentRequest: String,
initiatorName: String) {
transaction {
PaymentEntity.new {
this.creditorIban = creditorIban
- this.creditorBic = creditorBic
this.creditorName = creditorName
this.debitorIban = debitorIban
- this.debitorBic = debitorBic
this.debitorName = debitorName
this.subject = subject
this.amount = amount
diff --git a/util/src/main/kotlin/JSON.kt b/util/src/main/kotlin/JSON.kt
index dc36d2b..02a977d 100644
--- a/util/src/main/kotlin/JSON.kt
+++ b/util/src/main/kotlin/JSON.kt
@@ -26,10 +26,10 @@ package tech.libeufin.util
*/
data class RawPayment(
val creditorIban: String,
- val creditorBic: String,
+ val creditorBic: String?,
val creditorName: String,
val debitorIban: String,
- val debitorBic: String,
+ val debitorBic: String?,
val debitorName: String,
val amount: String,
val currency: String,
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.