From 907742793a6f0148b8b50404b1da89adae892cb4 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 15 Jul 2026 12:55:21 +0200 Subject: [PATCH 1/6] fix: enforce UK consent check on aggregate AISP balances/transactions endpoints GET /aisp/balances and GET /aisp/transactions fetched every private account for the caller without validating the bearer token's UK consent binding first, unlike every sibling AISP endpoint (including their own single-account counterparts). A DirectLogin or OAuth2 token with no bound consent fell through into the account-fetch path and surfaced as a 500 Unknown Error instead of the expected 403 OBP-35035, and callers with real consent got real account data with no consent enforcement at all. Add the same checkUKConsent + passesPsd2Aisp guard already used by getAccountsAccountIdBalances and getAccountsAccountIdTransactions so all five real-data AISP endpoints share one consent contract. Also fix createTransactionsJsonNew to take the AccountId from the request path instead of deriving it from the first transaction's bank account, which returned a null AccountId whenever the account had no transactions. --- .../v4_0_1/Http4sUKOBv401AccountInfo.scala | 6 ++- .../JSONFactory_UKOpenBanking_401.scala | 2 +- .../UKOpenBankingV401AccountInfoTests.scala | 54 ++++++------------- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala index 3d02a40b4c..3380f6a84d 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala @@ -2236,7 +2236,7 @@ object Http4sUKOBv401AccountInfo extends MdcLoggable { transactions.map(_.id), view.viewId, Some(cc)) - } yield JSONFactory_UKOpenBanking_401.createTransactionsJsonNew(account.bankId, transactions, moderatedAttributes, view) + } yield JSONFactory_UKOpenBanking_401.createTransactionsJsonNew(accountId.value, account.bankId, transactions, moderatedAttributes, view) } } resourceDocs += ResourceDoc( @@ -2305,6 +2305,8 @@ object Http4sUKOBv401AccountInfo extends MdcLoggable { case req @ GET -> `ukV401Prefix` / "aisp" / "balances" => EndpointHelpers.withUser(req) { (u, cc) => for { + _ <- NewStyle.function.checkUKConsent(u, Some(cc)) + _ <- passesPsd2Aisp(Some(cc)) availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u) (accounts, _) <- NewStyle.function.getBankAccounts(availablePrivateAccounts, Some(cc)) } yield JSONFactory_UKOpenBanking_401.createBalancesJSON(accounts) @@ -3446,6 +3448,8 @@ object Http4sUKOBv401AccountInfo extends MdcLoggable { case req @ GET -> `ukV401Prefix` / "aisp" / "transactions" => EndpointHelpers.withUser(req) { (u, cc) => for { + _ <- NewStyle.function.checkUKConsent(u, Some(cc)) + _ <- passesPsd2Aisp(Some(cc)) (bank, _) <- NewStyle.function.getBank(BankId(defaultBankId), Some(cc)) availablePrivateAccounts <- Views.views.vend.getPrivateBankAccountsFuture(u) (accounts, _) <- NewStyle.function.getBankAccounts(availablePrivateAccounts, Some(cc)) diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala index f8fb2ec4ce..97aad8f019 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala @@ -293,12 +293,12 @@ object JSONFactory_UKOpenBanking_401 extends CustomJsonFormats { } def createTransactionsJsonNew( + accountId: String, bankId: BankId, moderatedTransactions: List[ModeratedTransaction], attributes: List[TransactionAttribute], view: View ): TransactionsUKV401 = { - val accountId = moderatedTransactions.headOption.flatMap(_.bankAccount.map(_.accountId.value)).orNull val transactions = moderatedTransactions.map(t => transactionJson(accountId, bankId, t, attributes, Some(view))) TransactionsUKV401( Data = TransactionDataV401(transactions), diff --git a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala index d90a65a074..bc2e9f29a5 100644 --- a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala +++ b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala @@ -12,12 +12,16 @@ import org.scalatest.Tag // seeded data -> 200/201/204 with real field values, error paths (unknown // consent/account), and a full consent create -> get -> delete -> get lifecycle. // -// getAccounts / getAccountsAccountIdBalances / getAccountsAccountIdTransactions -// call NewStyle.function.checkUKConsent, which requires a live Hydra OAuth2 -// introspection endpoint (see code.api.util.ConsentUtil.checkUKConsent) — there -// is no local test double for Hydra, so (mirroring UKOpenBankingV310AisTests' -// precedent for the same three v3.1 endpoints) only "unauthenticated -> 401" -// and "authenticated -> not 401" are asserted for those three. +// getAccounts / getAccountsAccountIdBalances / getAccountsAccountIdTransactions / +// getBalances / getTransactions call NewStyle.function.checkUKConsent, which +// requires a live Hydra OAuth2 introspection endpoint (see +// code.api.util.ConsentUtil.checkUKConsent) — there is no local test double for +// Hydra, so (mirroring UKOpenBankingV310AisTests' precedent for the same v3.1 +// endpoints) only "unauthenticated -> 401" and "authenticated -> not 401" are +// asserted for those five. getBalances / getTransactions previously skipped the +// consent check entirely and returned real data straight from a DirectLogin +// token, which let a token with no bound consent reach 500 instead of the +// 403 OBP-35035 every other AISP data endpoint gives it. // // The remaining 80 endpoints are still static spec-faithful stubs; their tests // are unchanged (two scenarios: authenticated -> fixed code, unauthenticated -> 401). @@ -247,23 +251,10 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { } // ── BalancesApi ──────────────────────────────────────────────────── + // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). feature("UKOB v4.0.1 GET /aisp/balances") { - scenario("authenticated with real account -> 200 real balance", UKOpenBankingV401AccountInfo) { - val response = getAuthed("aisp", "balances") - response.code should equal(200) - // resourceUser1 owns accounts on several test banks (see TestConnectorSetup. - // createAccountRelevantResources), so testAccountId1's entry isn't necessarily - // first — find it rather than assume position 0. - val balances = (response.body \ "Data" \ "Balance").children - balances should not be empty - val myBalance = balances.find(b => (b \ "AccountId").extract[String] == acc) - myBalance shouldBe defined - (myBalance.get \ "Amount" \ "Currency").extract[String] should equal("EUR") - } - scenario("authenticated with no private accounts -> 200 empty Balance list", UKOpenBankingV401AccountInfo) { - val response = getAuthedAsUser2("aisp", "balances") - response.code should equal(200) - (response.body \ "Data" \ "Balance").children should be(empty) + scenario("authenticated", UKOpenBankingV401AccountInfo) { + getAuthed("aisp", "balances").code should not equal (401) } scenario("unauthenticated -> 401", UKOpenBankingV401AccountInfo) { getUnauthed("aisp", "balances").code should equal(401) @@ -333,23 +324,10 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { getUnauthed("aisp", "statements").code should equal(401) } } + // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). feature("UKOB v4.0.1 GET /aisp/transactions") { - scenario("authenticated with seeded transactions -> 200 real data", UKOpenBankingV401AccountInfo) { - val seeded = seedTransactions(testAccountId1) - val response = getAuthed("aisp", "transactions") - response.code should equal(200) - // resourceUser1 owns accounts on several test banks, but only testAccountId1 - // has seeded transactions here, so every returned entry should belong to it. - val transactions = (response.body \ "Data" \ "Transaction").children - transactions should not be empty - transactions.foreach(t => (t \ "AccountId").extract[String] should equal(acc)) - (transactions.head \ "Amount" \ "Currency").extract[String] should equal("EUR") - transactions.map(t => (t \ "TransactionId").extract[String]) should contain (seeded.head.id.value) - } - scenario("authenticated with no private accounts -> 200 empty Transaction list", UKOpenBankingV401AccountInfo) { - val response = getAuthedAsUser2("aisp", "transactions") - response.code should equal(200) - (response.body \ "Data" \ "Transaction").children should be(empty) + scenario("authenticated", UKOpenBankingV401AccountInfo) { + getAuthed("aisp", "transactions").code should not equal (401) } scenario("unauthenticated -> 401", UKOpenBankingV401AccountInfo) { getUnauthed("aisp", "transactions").code should equal(401) From 462e6088ed43356c83013f7620eb94fe17283bbe Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 15 Jul 2026 15:02:33 +0200 Subject: [PATCH 2/6] fix: stop background server launch from hanging callers via process substitution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redirecting to > >(tee "$RUNTIME_LOG") makes the tee process inherit this script's own stdout. A caller that captures this script's output with out=$(./flushall_build_and_run.sh --background ...) never sees EOF, because the long-running server (and the tee backing the substitution) never exits on its own — the command substitution hangs forever even though the server started successfully. Redirect straight to the log file instead. --- flushall_build_and_run.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/flushall_build_and_run.sh b/flushall_build_and_run.sh index 13a8bfa6c5..dfffbf35db 100755 --- a/flushall_build_and_run.sh +++ b/flushall_build_and_run.sh @@ -155,15 +155,20 @@ JAVA_OPTS="--add-opens java.base/java.lang=ALL-UNNAMED \ RUNTIME_LOG=/tmp/obp-api.log if [ "$RUN_BACKGROUND" = true ]; then - # Run in background with output to log file (tee'd to /tmp as well) - nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > >(tee "$RUNTIME_LOG") 2>&1 & + # Run in background with output redirected straight to a log file. Do NOT + # use `> >(tee "$RUNTIME_LOG")` here: process substitution's tee inherits + # this script's own stdout, so a caller that captures this script's output + # via `out=$(./flushall_build_and_run.sh --background ...)` never sees EOF + # — the substitution hangs forever, since the server (and thus the tee + # process backing the substitution) never exits on its own. + nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > "$RUNTIME_LOG" 2>&1 & SERVER_PID=$! echo "✓ HTTP4S server started in background" echo " PID: $SERVER_PID" - echo " Log: http4s-server.log (also $RUNTIME_LOG)" + echo " Log: $RUNTIME_LOG" echo "" echo "To stop the server: kill $SERVER_PID" - echo "To view logs: tail -f http4s-server.log" + echo "To view logs: tail -f $RUNTIME_LOG" else # Run in foreground (Ctrl+C to stop). Also tee output to /tmp so it can be # tailed from another terminal without taking over this one. From f26bd07177f8da688ffd81a02b75fb0fd3d753a8 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 15 Jul 2026 15:05:30 +0200 Subject: [PATCH 3/6] docs: remove stale Hydra references from UK v4.0.1 test comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checkUKConsent no longer needs a live Hydra introspection endpoint — it checks the Bearer token's consent_id claim against an AUTHORISED consent. Two comments describing the balances/transactions scenarios still referred to the removed Hydra dependency; align them with the class doc above, which was already corrected during the merge from Simon/develop. --- .../v4_0_1/UKOpenBankingV401AccountInfoTests.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala index 2919b673c7..c32bcdeb2b 100644 --- a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala +++ b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala @@ -252,7 +252,7 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { } // ── BalancesApi ──────────────────────────────────────────────────── - // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). + // DATA-DEPENDENT: checkUKConsent requires a consent-bound token (see class doc above). feature("UKOB v4.0.1 GET /aisp/balances") { scenario("authenticated", UKOpenBankingV401AccountInfo) { getAuthed("aisp", "balances").code should not equal (401) @@ -325,7 +325,7 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { getUnauthed("aisp", "statements").code should equal(401) } } - // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). + // DATA-DEPENDENT: checkUKConsent requires a consent-bound token (see class doc above). feature("UKOB v4.0.1 GET /aisp/transactions") { scenario("authenticated", UKOpenBankingV401AccountInfo) { getAuthed("aisp", "transactions").code should not equal (401) From 11635278dc48a93d2f9d3ceb4b6019b484593043 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 15 Jul 2026 15:45:13 +0200 Subject: [PATCH 4/6] test(uk-open-banking): assert real 403 for the 3 checkUKConsent-gated v4.0.1 endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit develop's Hydra removal (PR #2866) rewrote ConsentUtil.checkUKConsent to read the consent_id claim directly off the Bearer access token instead of calling an external Hydra introspection endpoint. That was the only blocker keeping getAccounts/getAccountsAccountIdBalances/getAccountsAccountIdTransactions on a weak "authenticated -> not 401" assertion (mirroring the same limitation in UKOpenBankingV310AisTests for the equivalent v3.1 endpoints). The OAuth1-signed test requests carry no Bearer JWT, so the consent_id claim lookup now fails deterministically with 403 ConsentIdClaimMissing — asserted directly (status code + error message) instead of the previous placeholder. --- .../UKOpenBankingV401AccountInfoTests.scala | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala index d90a65a074..2a35118849 100644 --- a/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala +++ b/obp-api/src/test/scala/code/api/UKOpenBanking/v4_0_1/UKOpenBankingV401AccountInfoTests.scala @@ -1,7 +1,9 @@ package code.api.UKOpenBanking.v4_0_1 import code.api.util.APIUtil.DateWithDayFormat +import code.api.util.ErrorMessages.ConsentIdClaimMissing import code.consent.Consents +import com.openbankproject.commons.model.ErrorMessage import org.json4s._ import org.scalatest.Tag @@ -12,12 +14,11 @@ import org.scalatest.Tag // seeded data -> 200/201/204 with real field values, error paths (unknown // consent/account), and a full consent create -> get -> delete -> get lifecycle. // -// getAccounts / getAccountsAccountIdBalances / getAccountsAccountIdTransactions -// call NewStyle.function.checkUKConsent, which requires a live Hydra OAuth2 -// introspection endpoint (see code.api.util.ConsentUtil.checkUKConsent) — there -// is no local test double for Hydra, so (mirroring UKOpenBankingV310AisTests' -// precedent for the same three v3.1 endpoints) only "unauthenticated -> 401" -// and "authenticated -> not 401" are asserted for those three. +// getAccounts / getAccountsAccountIdBalances / getAccountsAccountIdTransactions call +// NewStyle.function.checkUKConsent (code.api.util.ConsentUtil.checkUKConsent), which reads +// the `consent_id` claim off the Bearer access token — no external identity-provider call. +// These OAuth1-signed test requests carry no Bearer JWT, so the claim lookup deterministically +// fails with a 403 ConsentIdClaimMissing (see the scenario comments on those three features). // // The remaining 80 endpoints are still static spec-faithful stubs; their tests // are unchanged (two scenarios: authenticated -> fixed code, unauthenticated -> 401). @@ -103,10 +104,15 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { } } // ── AccountsApi ──────────────────────────────────────────────────── - // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). + // checkUKConsent extracts the `consent_id` claim from the Bearer access token (no external + // Hydra call since Consent.checkUKConsent dropped the Hydra dependency). These OAuth1-signed + // test requests carry no Bearer JWT at all, so the claim lookup deterministically fails -> + // 403 ConsentIdClaimMissing, mirroring "authenticated but no bound consent" in production. feature("UKOB v4.0.1 GET /aisp/accounts") { - scenario("authenticated", UKOpenBankingV401AccountInfo) { - getAuthed("aisp", "accounts").code should not equal (401) + scenario("authenticated without a consent-bound token -> 403", UKOpenBankingV401AccountInfo) { + val response = getAuthed("aisp", "accounts") + response.code should equal(403) + response.body.extract[ErrorMessage].message.trim should equal(ConsentIdClaimMissing.trim) } scenario("unauthenticated -> 401", UKOpenBankingV401AccountInfo) { getUnauthed("aisp", "accounts").code should equal(401) @@ -132,8 +138,10 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { } } feature("UKOB v4.0.1 GET /aisp/accounts/ACCOUNT_ID/balances") { - scenario("authenticated", UKOpenBankingV401AccountInfo) { - getAuthed("aisp", "accounts", acc, "balances").code should not equal (401) + scenario("authenticated without a consent-bound token -> 403", UKOpenBankingV401AccountInfo) { + val response = getAuthed("aisp", "accounts", acc, "balances") + response.code should equal(403) + response.body.extract[ErrorMessage].message.trim should equal(ConsentIdClaimMissing.trim) } scenario("unauthenticated -> 401", UKOpenBankingV401AccountInfo) { getUnauthed("aisp", "accounts", acc, "balances").code should equal(401) @@ -236,10 +244,12 @@ class UKOpenBankingV401AccountInfoTests extends UKOpenBankingV401ServerSetup { } } // ── TransactionsApi ──────────────────────────────────────────────── - // DATA-DEPENDENT: checkUKConsent requires live Hydra (see class doc above). + // See the "no external Hydra call" note above feature("UKOB v4.0.1 GET /aisp/accounts"). feature("UKOB v4.0.1 GET /aisp/accounts/ACCOUNT_ID/transactions") { - scenario("authenticated", UKOpenBankingV401AccountInfo) { - getAuthed("aisp", "accounts", acc, "transactions").code should not equal (401) + scenario("authenticated without a consent-bound token -> 403", UKOpenBankingV401AccountInfo) { + val response = getAuthed("aisp", "accounts", acc, "transactions") + response.code should equal(403) + response.body.extract[ErrorMessage].message.trim should equal(ConsentIdClaimMissing.trim) } scenario("unauthenticated -> 401", UKOpenBankingV401AccountInfo) { getUnauthed("aisp", "accounts", acc, "transactions").code should equal(401) From f10d8b6e14ca4600ecead5721acfd8ec176c6fd8 Mon Sep 17 00:00:00 2001 From: Hongwei Date: Wed, 15 Jul 2026 19:59:00 +0200 Subject: [PATCH 5/6] fix: print the bound PORT from background build/run scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither flushall_build_and_run.sh nor flushall_fast_build_and_run.sh printed the port the server actually binds, only its PID. smoke_test.sh's start_and_test() parses "PID: " and "PORT: " from the script's captured output to know where to poll /root; with no PORT line it fails fast with "未打印实际监听端口" even after the server started and bound successfully, leaving the server running with nothing to verify it or clean it up. Print the actual dev.port value read from props/default.props (falling back to 8080) right after the PID line in both scripts' background-mode branch. --- flushall_build_and_run.sh | 4 ++++ flushall_fast_build_and_run.sh | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/flushall_build_and_run.sh b/flushall_build_and_run.sh index dfffbf35db..2d92353971 100755 --- a/flushall_build_and_run.sh +++ b/flushall_build_and_run.sh @@ -163,8 +163,12 @@ if [ "$RUN_BACKGROUND" = true ]; then # process backing the substitution) never exits on its own. nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > "$RUNTIME_LOG" 2>&1 & SERVER_PID=$! + # Report the port the server will actually bind (dev.port in props), so callers + # that capture this script's output (e.g. smoke_test.sh) can parse it out. + SERVER_PORT=$(grep -E '^dev.port=' obp-api/src/main/resources/props/default.props 2>/dev/null | cut -d= -f2) echo "✓ HTTP4S server started in background" echo " PID: $SERVER_PID" + echo " PORT: ${SERVER_PORT:-8080}" echo " Log: $RUNTIME_LOG" echo "" echo "To stop the server: kill $SERVER_PID" diff --git a/flushall_fast_build_and_run.sh b/flushall_fast_build_and_run.sh index 88669ab6e9..61449c3c1f 100755 --- a/flushall_fast_build_and_run.sh +++ b/flushall_fast_build_and_run.sh @@ -324,8 +324,12 @@ if [ "$RUN_BACKGROUND" = true ]; then # Run in background with output to log file nohup java $JAVA_OPTS -jar obp-api/target/obp-api.jar > http4s-server.log 2>&1 & SERVER_PID=$! + # Report the port the server will actually bind (dev.port in props), so callers + # that capture this script's output (e.g. smoke_test.sh) can parse it out. + SERVER_PORT=$(grep -E '^dev.port=' obp-api/src/main/resources/props/default.props 2>/dev/null | cut -d= -f2) echo "✓ HTTP4S server started in background" echo " PID: $SERVER_PID" + echo " PORT: ${SERVER_PORT:-8080}" echo " Log: http4s-server.log" echo "" echo "To stop the server: kill $SERVER_PID" From 21e57e4aa8f9b61f0df94414f4764836954be30a Mon Sep 17 00:00:00 2001 From: Hongwei Date: Fri, 17 Jul 2026 10:50:32 +0200 Subject: [PATCH 6/6] fix: put bankId before accountId in createTransactionsJsonNew params Matches the codebase-wide convention of bank-scoped params before account-scoped ones. --- .../api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala | 2 +- .../UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala index 3380f6a84d..039b31485d 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/Http4sUKOBv401AccountInfo.scala @@ -2236,7 +2236,7 @@ object Http4sUKOBv401AccountInfo extends MdcLoggable { transactions.map(_.id), view.viewId, Some(cc)) - } yield JSONFactory_UKOpenBanking_401.createTransactionsJsonNew(accountId.value, account.bankId, transactions, moderatedAttributes, view) + } yield JSONFactory_UKOpenBanking_401.createTransactionsJsonNew(account.bankId, accountId.value, transactions, moderatedAttributes, view) } } resourceDocs += ResourceDoc( diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala index 97aad8f019..9be3cd5c42 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v4_0_1/JSONFactory_UKOpenBanking_401.scala @@ -293,8 +293,8 @@ object JSONFactory_UKOpenBanking_401 extends CustomJsonFormats { } def createTransactionsJsonNew( - accountId: String, bankId: BankId, + accountId: String, moderatedTransactions: List[ModeratedTransaction], attributes: List[TransactionAttribute], view: View