Allow setting accessValidForDays and maxHistoricalDays per bank (#334)

* Allow setting accessValidForDays per bank

This also stops taking `accessValidForDays` from the client since it's
hardcoded there anyway and it's simpler to just have these per-bank
values in one place.

Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>

* Get the max allowed maxHistoricalDays value from the GoCardless API

Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>

* Upgrade nordigen-node to 1.4.0

Contrary to the claims in the nordigen-node changelog 1.3.0 did *not*
fix the missing support for passing in accessValidForDays, so we have to
upgrade to 1.4.0 to actually get the fix.

Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>

---------

Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
This commit is contained in:
Johannes Löthberg
2024-04-14 18:21:47 +02:00
committed by GitHub
parent a5a5f30dd7
commit ae0faf467f
23 changed files with 73 additions and 35 deletions

View File

@@ -29,7 +29,7 @@
"express-response-size": "^0.0.3",
"jws": "^4.0.0",
"migrate": "^2.0.1",
"nordigen-node": "^1.3.0",
"nordigen-node": "^1.4.0",
"uuid": "^9.0.0"
},
"devDependencies": {

View File

@@ -40,11 +40,10 @@ app.post('/status', async (req, res) => {
app.post(
'/create-web-token',
handleError(async (req, res) => {
const { accessValidForDays, institutionId } = req.body;
const { institutionId } = req.body;
const { origin } = req.headers;
const { link, requisitionId } = await goCardlessService.createRequisition({
accessValidForDays,
institutionId,
host: origin,
});

View File

@@ -1,32 +1,32 @@
import AmericanExpressAesudef1 from './banks/american-express-aesudef1.js';
import Belfius from './banks/belfius_gkccbebb.js';
import BnpBeGebabebb from './banks/bnp-be-gebabebb.js';
import DanskeBankDabNO22 from './banks/danskebank-dabno22.js';
import IngIngddeff from './banks/ing-ingddeff.js';
import IngPlIngbplpw from './banks/ing-pl-ingbplpw.js';
import IntegrationBank from './banks/integration-bank.js';
import MbankRetailBrexplpw from './banks/mbank-retail-brexplpw.js';
import NorwegianXxNorwnok1 from './banks/norwegian-xx-norwnok1.js';
import SandboxfinanceSfin0000 from './banks/sandboxfinance-sfin0000.js';
import BnpBeGebabebb from './banks/bnp-be-gebabebb.js';
import DanskeBankDabNO22 from './banks/danskebank-dabno22.js';
import SparNordSpNoDK22 from './banks/sparnord-spnodk22.js';
import Belfius from './banks/belfius_gkccbebb.js';
import SpkMarburgBiedenkopfHeladef1mar from './banks/spk-marburg-biedenkopf-heladef1mar.js';
import SEBPrivat from './banks/seb-privat.js';
import SEBKortBankAB from './banks/seb-kort-bank-ab.js';
import SEBPrivat from './banks/seb-privat.js';
import SandboxfinanceSfin0000 from './banks/sandboxfinance-sfin0000.js';
import SparNordSpNoDK22 from './banks/sparnord-spnodk22.js';
import SpkMarburgBiedenkopfHeladef1mar from './banks/spk-marburg-biedenkopf-heladef1mar.js';
const banks = [
AmericanExpressAesudef1,
Belfius,
BnpBeGebabebb,
DanskeBankDabNO22,
IngIngddeff,
IngPlIngbplpw,
MbankRetailBrexplpw,
SandboxfinanceSfin0000,
NorwegianXxNorwnok1,
BnpBeGebabebb,
DanskeBankDabNO22,
SparNordSpNoDK22,
Belfius,
SpkMarburgBiedenkopfHeladef1mar,
SEBPrivat,
SEBKortBankAB,
SEBPrivat,
SandboxfinanceSfin0000,
SparNordSpNoDK22,
SpkMarburgBiedenkopfHeladef1mar,
];
export default (institutionId) =>

View File

@@ -4,6 +4,8 @@ import { amountToInteger, sortByBookingDateOrValueDate } from '../utils.js';
export default {
institutionIds: ['AMERICAN_EXPRESS_AESUDEF1'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -6,6 +6,9 @@ import { Transaction, Balance } from '../gocardless-node.types.js';
export interface IBank {
institutionIds: string[];
accessValidForDays: number;
/**
* Returns normalized object with required data for the frontend
*/

View File

@@ -4,6 +4,8 @@ import Fallback from './integration-bank.js';
export default {
institutionIds: ['BELFIUS_GKCCBEBB'],
accessValidForDays: 180,
normalizeAccount(account) {
return Fallback.normalizeAccount(account);
},

View File

@@ -22,6 +22,8 @@ export default {
'BNP_BE_GEBABEBB',
],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -8,6 +8,8 @@ import {
export default {
institutionIds: ['DANSKEBANK_DABANO22'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -4,6 +4,8 @@ import { printIban, amountToInteger } from '../utils.js';
export default {
institutionIds: ['ING_INGDDEFF'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -4,6 +4,8 @@ import { printIban, amountToInteger } from '../utils.js';
export default {
institutionIds: ['ING_PL_INGBPLPW'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -18,6 +18,14 @@ const SORTED_BALANCE_TYPE_LIST = [
/** @type {import('./bank.interface.js').IBank} */
export default {
institutionIds: ['IntegrationBank'],
// EEA need to allow at least 180 days now but this doesn't apply to UK
// banks, and it's possible that there are EEA banks which still don't follow
// the new requirements. See:
// - https://nordigen.zendesk.com/hc/en-gb/articles/13239212055581-EEA-180-day-access
// - https://nordigen.zendesk.com/hc/en-gb/articles/6760902653085-Extended-history-and-continuous-access-edge-cases
accessValidForDays: 90,
normalizeAccount(account) {
console.log(
'Available account properties for new institution integration',

View File

@@ -4,6 +4,8 @@ import { printIban, amountToInteger } from '../utils.js';
export default {
institutionIds: ['MBANK_RETAIL_BREXPLPW'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -15,6 +15,8 @@ export default {
'NORWEGIAN_FI_NORWNOK1',
],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -8,6 +8,8 @@ import {
export default {
institutionIds: ['SANDBOXFINANCE_SFIN0000'],
accessValidForDays: 90,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -8,6 +8,8 @@ import {
export default {
institutionIds: ['SEB_KORT_AB_SE_SKHSFI21'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -8,12 +8,10 @@ import {
/** @type {import('./bank.interface.js').IBank} */
export default {
institutionIds: ['SEB_ESSESESS_PRIVATE'],
normalizeAccount(account) {
console.log(
'Available account properties for new institution integration',
{ account: JSON.stringify(account) },
);
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,
institution: account.institution,
@@ -48,10 +46,6 @@ export default {
},
sortTransactions(transactions = []) {
console.log(
'Available (first 10) transactions properties for new integration of institution in sortTransactions function',
{ top10Transactions: JSON.stringify(transactions.slice(0, 10)) },
);
return sortByBookingDateOrValueDate(transactions);
},

View File

@@ -22,6 +22,8 @@ export default {
'ANDELSKASSEN_FALLESKASSEN_FAELDKK1',
],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -19,6 +19,8 @@ const SORTED_BALANCE_TYPE_LIST = [
export default {
institutionIds: ['SPK_MARBURG_BIEDENKOPF_HELADEF1MAR'],
accessValidForDays: 180,
normalizeAccount(account) {
return {
account_id: account.id,

View File

@@ -81,7 +81,6 @@ export type GetTransactionsResponse = {
export type CreateRequisitionParams = {
institutionId: string;
accessValidForDays: number;
/**
* Host of your frontend app - on this host you will be redirected after linking with bank

View File

@@ -257,15 +257,18 @@ export const goCardlessService = {
* @throws {ServiceError}
* @returns {Promise<{requisitionId, link}>}
*/
createRequisition: async ({ institutionId, accessValidForDays, host }) => {
createRequisition: async ({ institutionId, host }) => {
await goCardlessService.setToken();
const institution = await goCardlessService.getInstitution(institutionId);
const bank = BankFactory(institutionId);
const response = await client.initSession({
redirectUrl: host + '/gocardless/link',
institutionId,
referenceId: uuid.v4(),
accessValidForDays,
maxHistoricalDays: 90,
accessValidForDays: bank.accessValidForDays,
maxHistoricalDays: institution.transaction_total_days,
userLanguage: 'en',
ssn: null,
redirectImmediate: false,

View File

@@ -242,6 +242,7 @@ describe('goCardlessService', () => {
it('calls goCardlessClient and delete requisition', async () => {
setTokenSpy.mockResolvedValue();
getInstitutionSpy.mockResolvedValue(mockInstitution);
createRequisitionSpy.mockResolvedValue(mockCreateRequisition);
@@ -255,6 +256,7 @@ describe('goCardlessService', () => {
it('handle error if status_code present in the response', async () => {
setTokenSpy.mockResolvedValue();
getInstitutionSpy.mockResolvedValue(mockInstitution);
createRequisitionSpy.mockResolvedValue(mockUnknownError);

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [kyrias]
---
Add support for setting the access validity time per GoCardless bank integration and get the max historical days from the API

View File

@@ -1639,7 +1639,7 @@ __metadata:
jest: "npm:^29.3.1"
jws: "npm:^4.0.0"
migrate: "npm:^2.0.1"
nordigen-node: "npm:^1.3.0"
nordigen-node: "npm:^1.4.0"
prettier: "npm:^2.8.3"
supertest: "npm:^6.3.1"
typescript: "npm:^4.9.5"
@@ -4856,13 +4856,13 @@ __metadata:
languageName: node
linkType: hard
"nordigen-node@npm:^1.3.0":
version: 1.3.0
resolution: "nordigen-node@npm:1.3.0"
"nordigen-node@npm:^1.4.0":
version: 1.4.0
resolution: "nordigen-node@npm:1.4.0"
dependencies:
axios: "npm:^1.2.1"
dotenv: "npm:^10.0.0"
checksum: 033771af257ecf8e36a375b07e10246b08d23b647ef2db737b6efe52a1bcd68f04c88c2aff6790d4cbcd00da0148550247624142a6eea7444d370b2e65f08fc8
checksum: a04ec90480e4e65b2169d909ac9ea3044f764d59283162420d287a6b229808754dc78c758637724d63c87aa77f2237bc47543f521b0b4057ed3980d6db137e1a
languageName: node
linkType: hard