[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libeufin] branch master updated: fix pain parsing
From: |
gnunet |
Subject: |
[libeufin] branch master updated: fix pain parsing |
Date: |
Wed, 22 Jul 2020 21:00:45 +0200 |
This is an automated email from the git hooks/post-receive script.
ms pushed a commit to branch master
in repository libeufin.
The following commit(s) were added to refs/heads/master by this push:
new 3c295e0 fix pain parsing
3c295e0 is described below
commit 3c295e0d1d6bbee577caf2b4d9ce4e71a03fc82c
Author: MS <ms@taler.net>
AuthorDate: Wed Jul 22 21:00:29 2020 +0200
fix pain parsing
---
.../test-ebics-double-payment-submission.py | 221 +++++++++++++++++++++
integration-tests/util.py | 4 +-
.../tech/libeufin/sandbox/EbicsProtocolBackend.kt | 35 ++--
util/src/main/kotlin/Ebics.kt | 2 +-
4 files changed, 243 insertions(+), 19 deletions(-)
diff --git a/integration-tests/test-ebics-double-payment-submission.py
b/integration-tests/test-ebics-double-payment-submission.py
new file mode 100755
index 0000000..5fb5ee7
--- /dev/null
+++ b/integration-tests/test-ebics-double-payment-submission.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python3
+
+from subprocess import check_call
+from requests import post, get
+from time import sleep
+import os
+import hashlib
+import base64
+
+from util import startNexus, startSandbox
+
+# Steps implemented in this test.
+#
+# 0 Prepare sandbox.
+# -> (a) Make a EBICS host, (b) make a EBICS subscriber
+# for the test runner, and (c) assign a IBAN to such
+# subscriber.
+#
+# 1 Prepare nexus.
+# -> (a) Make a Nexus user, (b) make a EBICS subscriber
+# associated to that user
+#
+# 2 Prepare the Ebics bank connection for the nexus user.
+# -> (a) Upload keys from Nexus to the Bank (INI & HIA),
+# (b) Download key from the Bank (HPB) to the Nexus,
+# and (c) Fetch the bank account owned by that subscriber
+# at the bank.
+
+# 3 Request history from the Nexus to the Bank (C53).
+# 4 Verify that history is empty.
+# 5 Issue a payment from Nexus
+# -> (a) Prepare & (b) trigger CCT.
+# 6 Request history after submitting the payment,
+# from Nexus to Bank.
+# 7 Verify that previous payment shows up.
+
+# Nexus user details
+USERNAME = "person"
+PASSWORD = "y"
+USER_AUTHORIZATION_HEADER = "basic {}".format(
+ base64.b64encode(b"person:y").decode("utf-8")
+)
+
+# Admin authentication
+ADMIN_AUTHORIZATION_HEADER = "basic {}".format(
+ base64.b64encode(b"admin:x").decode("utf-8")
+)
+
+# EBICS details
+EBICS_URL = "http://localhost:5000/ebicsweb"
+HOST_ID = "HOST01"
+PARTNER_ID = "PARTNER1"
+USER_ID = "USER1"
+EBICS_VERSION = "H004"
+
+# Subscriber's bank account
+SUBSCRIBER_IBAN = "GB33BUKB20201555555555"
+SUBSCRIBER_BIC = "BUKBGB22"
+SUBSCRIBER_NAME = "Oliver Smith"
+BANK_ACCOUNT_LABEL = "savings"
+
+# Databases
+NEXUS_DB = "test-nexus.sqlite3"
+
+
+def fail(msg):
+ print(msg)
+ exit(1)
+
+
+def assertResponse(response):
+ if response.status_code != 200:
+ print("Test failed on URL: {}".format(response.url))
+ # stdout/stderr from both services is A LOT of text.
+ # Confusing to dump all that to console.
+ print("Check nexus.log and sandbox.log, probably under /tmp")
+ exit(1)
+ # Allows for finer grained checks.
+ return response
+
+
+startNexus(NEXUS_DB)
+startSandbox()
+
+# 0.a
+assertResponse(
+ post(
+ "http://localhost:5000/admin/ebics/host",
+ json=dict(hostID=HOST_ID, ebicsVersion=EBICS_VERSION),
+ )
+)
+
+# 0.b
+assertResponse(
+ post(
+ "http://localhost:5000/admin/ebics/subscribers",
+ json=dict(hostID=HOST_ID, partnerID=PARTNER_ID, userID=USER_ID),
+ )
+)
+
+# 0.c
+assertResponse(
+ post(
+ "http://localhost:5000/admin/ebics/bank-accounts",
+ json=dict(
+ subscriber=dict(hostID=HOST_ID, partnerID=PARTNER_ID,
userID=USER_ID),
+ iban=SUBSCRIBER_IBAN,
+ bic=SUBSCRIBER_BIC,
+ name=SUBSCRIBER_NAME,
+ label=BANK_ACCOUNT_LABEL,
+ ),
+ )
+)
+
+# 1.a, make a new nexus user.
+assertResponse(
+ post(
+ "http://localhost:5001/users",
+ headers=dict(Authorization=ADMIN_AUTHORIZATION_HEADER),
+ json=dict(username=USERNAME, password=PASSWORD),
+ )
+)
+
+print("creating bank connection")
+
+# 1.b, make a ebics bank connection for the new user.
+assertResponse(
+ post(
+ "http://localhost:5001/bank-connections",
+ json=dict(
+ name="my-ebics",
+ source="new",
+ type="ebics",
+ data=dict(
+ ebicsURL=EBICS_URL, hostID=HOST_ID, partnerID=PARTNER_ID,
userID=USER_ID
+ ),
+ ),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+print("connecting")
+
+assertResponse(
+ post(
+ "http://localhost:5001/bank-connections/my-ebics/connect",
+ json=dict(),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+
+# 2.c, fetch bank account information
+assertResponse(
+ post(
+
"http://localhost:5001/bank-connections/my-ebics/ebics/import-accounts",
+ json=dict(),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+# 3, ask nexus to download history
+assertResponse(
+ post(
+
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/fetch-transactions",
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+# 4, make sure history is empty
+resp = assertResponse(
+ get(
+
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/transactions",
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+if len(resp.json().get("transactions")) != 0:
+ fail("unexpected number of transactions")
+
+# 5.a, prepare a payment
+resp = assertResponse(
+ post(
+ "http://localhost:5001/bank-accounts/{}/payment-initiations".format(
+ BANK_ACCOUNT_LABEL
+ ),
+ json=dict(
+ iban="FR7630006000011234567890189",
+ bic="AGRIFRPP",
+ name="Jacques La Fayette",
+ subject="integration test",
+ amount="EUR:1",
+ ),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+PREPARED_PAYMENT_UUID = resp.json().get("uuid")
+if PREPARED_PAYMENT_UUID == None:
+ fail("Payment UUID not received")
+
+# 5.b, submit payment initiation
+assertResponse(
+ post(
+
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/payment-initiations/{PREPARED_PAYMENT_UUID}/submit",
+ json=dict(),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+# hack the database
+check_call(["sqlite3", NEXUS_DB, f"UPDATE PaymentInitiations SET submitted =
false WHERE id = '{PREPARED_PAYMENT_UUID}'"])
+
+# 5.b, submit payment initiation AGAIN
+assertResponse(
+ post(
+
f"http://localhost:5001/bank-accounts/{BANK_ACCOUNT_LABEL}/payment-initiations/{PREPARED_PAYMENT_UUID}/submit",
+ json=dict(),
+ headers=dict(Authorization=USER_AUTHORIZATION_HEADER),
+ )
+)
+
+print("Test passed!")
diff --git a/integration-tests/util.py b/integration-tests/util.py
index 09d08ad..ab38ea5 100644
--- a/integration-tests/util.py
+++ b/integration-tests/util.py
@@ -84,11 +84,11 @@ def startNexus(dbname="nexus-test.sqlite3"):
stderr=open("nexus-stderr.log", "w"),
)
atexit.register(lambda: kill("nexus", nexus))
- for i in range(10):
+ for i in range(80):
try:
get("http://localhost:5001/")
except:
- if i == 9:
+ if i == 79:
nexus.terminate()
print("Nexus timed out")
exit(77)
diff --git
a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
index 51e8259..a44d619 100644
--- a/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
+++ b/sandbox/src/main/kotlin/tech/libeufin/sandbox/EbicsProtocolBackend.kt
@@ -509,41 +509,44 @@ private fun parsePain001(paymentRequest: String,
initiatorName: String): PainPar
return destructXml(painDoc) {
requireRootElement("Document") {
requireUniqueChildNamed("CstmrCdtTrfInitn") {
- val msgId = requireOnlyChild {
+ val msgId = requireUniqueChildNamed("GrpHdr") {
requireUniqueChildNamed("MsgId") {
focusElement.textContent }
}
requireUniqueChildNamed("PmtInf") {
val pmtInfId = requireUniqueChildNamed("PmtInfId") {
focusElement.textContent }
val creditorIban = requireUniqueChildNamed("CdtTrfTxInf") {
requireUniqueChildNamed("CdtrAcct") {
- requireUniqueChildNamed("id") {
+ requireUniqueChildNamed("Id") {
requireUniqueChildNamed("IBAN") {
focusElement.textContent }
}
}
}
- val creditorName = requireUniqueChildNamed("Cdt") {
- requireUniqueChildNamed("Nm") {
focusElement.textContent }
+ val txInf = requireUniqueChildNamed("CdtTrfTxInf") {
+ val amt = requireUniqueChildNamed("Amt") {
+ requireOnlyChild {
+ focusElement
+ }
+ }
+ val creditorName = requireUniqueChildNamed("Cdtr") {
+ requireUniqueChildNamed("Nm") {
focusElement.textContent }
+ }
+ val subject = requireUniqueChildNamed("RmtInf") {
+ requireUniqueChildNamed("Ustrd") {
focusElement.textContent }
+ }
+ object {val amt = amt; val subject = subject; val
creditorName = creditorName}
}
val debitorIban = requireUniqueChildNamed("DbtrAcct") {
requireOnlyChild {
requireOnlyChild { focusElement.textContent }
}
}
- val subject = requireUniqueChildNamed("RmtInf") {
- requireUniqueChildNamed("Ustrd") {
focusElement.textContent }
- }
- val amt = requireUniqueChildNamed("Amt") {
- requireOnlyChild {
- focusElement
- }
- }
PainParseResult(
- currency = amt.getAttribute("Ccy"),
- amount = Amount(amt.textContent),
- subject = subject,
+ currency = txInf.amt.getAttribute("Ccy"),
+ amount = Amount(txInf.amt.textContent),
+ subject = txInf.subject,
debitorIban = debitorIban,
debitorName = initiatorName,
- creditorName = creditorName,
+ creditorName = txInf.creditorName,
creditorIban = creditorIban,
pmtInfId = pmtInfId,
msgId = msgId
diff --git a/util/src/main/kotlin/Ebics.kt b/util/src/main/kotlin/Ebics.kt
index b867d79..3beb1ce 100644
--- a/util/src/main/kotlin/Ebics.kt
+++ b/util/src/main/kotlin/Ebics.kt
@@ -435,7 +435,7 @@ fun parseAndValidateEbicsResponse(
} catch (e: Exception) {
throw EbicsProtocolError(
HttpStatusCode.InternalServerError,
- "Invalid XML (as EbicsResponse) received from bank"
+ "Invalid XML (as EbicsResponse) received from bank: $responseStr"
)
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libeufin] branch master updated: fix pain parsing,
gnunet <=