lib-fints 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Node.js CI with pnpm](https://github.com/robocode13/lib-fints/actions/workflows/build-test.yml/badge.svg?branch=main)](https://github.com/robocode13/lib-fints/actions/workflows/build-test.yml)
2
+
1
3
  # Lib-FinTS
2
4
 
3
5
  A Typescript/Javascript client library for Online-Banking via the FinTS 3.0 protocol with PIN/TAN, supporting PSD2 and decoupled TAN methods. The library has no dependencies on other libraries
@@ -186,15 +188,48 @@ config.debugEnabled = true;
186
188
 
187
189
  This will print out all sent messages and received responses to the console in a structured format.
188
190
 
191
+ ## Supported Transactions
192
+
193
+ The following table shows all transactions supported by the FinTSClient interface:
194
+
195
+ | Transaction | Method | Description | FinTS Segment(s) | TAN Support | Account-Specific |
196
+ | -------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -------------------------- | ----------- | ---------------- |
197
+ | **Synchronization** | `synchronize()` | Synchronizes bank and account information, updating config.bankingInformation | HKIDN, HKVVB, HKSYN, HKTAB | ✓ | ❌ |
198
+ | **Account Balance** | `getAccountBalance(accountNumber)` | Fetches the current balance for a specific account | HKSAL | ✓ | ✓ |
199
+ | **Account Statements** | `getAccountStatements(accountNumber, from?, to?)` | Fetches account transactions/statements for a date range | HKKAZ | ✓ | ✓ |
200
+ | **Portfolio** | `getPortfolio(accountNumber, currency?, priceQuality?, maxEntries?)` | Fetches securities portfolio information for depot accounts | HKWPD | ✓ | ✓ |
201
+ | **Credit Card Statements** | `getCreditCardStatements(accountNumber, from?)` | Fetches credit card statements for credit card accounts | DKKKU | ✓ | ✓ |
202
+ | **TAN Method Selection** | `selectTanMethod(tanMethodId)` | Selects a TAN method by ID from available methods | - | ❌ | ❌ |
203
+ | **TAN Media Selection** | `selectTanMedia(tanMediaName)` | Selects a specific TAN media device by name | - | ❌ | ❌ |
204
+
205
+ ### Transaction Support Checking
206
+
207
+ For each account-specific transaction, the client provides corresponding `can*` methods to check if the bank or specific account supports the transaction:
208
+
209
+ | Support Check Method | Purpose |
210
+ | -------------------------------------------- | ------------------------------------------------------ |
211
+ | `canGetAccountBalance(accountNumber?)` | Checks if account balance fetching is supported |
212
+ | `canGetAccountStatements(accountNumber?)` | Checks if account statements fetching is supported |
213
+ | `canGetPortfolio(accountNumber?)` | Checks if portfolio information fetching is supported |
214
+ | `canGetCreditCardStatements(accountNumber?)` | Checks if credit card statements fetching is supported |
215
+
216
+ ### TAN Continuation Methods
217
+
218
+ Every transaction that supports TAN authentication has a corresponding `*WithTan` method for continuing the transaction after TAN entry:
219
+
220
+ - `synchronizeWithTan(tanReference, tan?)`
221
+ - `getAccountBalanceWithTan(tanReference, tan?)`
222
+ - `getAccountStatementsWithTan(tanReference, tan?)`
223
+ - `getPortfolioWithTan(tanReference, tan?)`
224
+ - `getCreditCardStatementsWithTan(tanReference, tan?)`
225
+
226
+ The `tan` parameter can be omitted when using decoupled TAN methods.
227
+
189
228
  ## Limitations
190
229
 
191
230
  - Only FinTS 3.0 is supported (older versions may not work)
192
- - Only PIN/TAN security is supported (inluding decoupled TAN methods)
193
- - Currently only the following transactions are supported:
194
- - Synchronize bank and account information
195
- - Fetching account balances
196
- - Fetching account statements
197
- - Fetching the portfolio of a securities account
231
+ - Only PIN/TAN security is supported (including decoupled TAN methods)
232
+ - No support for payment transactions or transfers yet
198
233
 
199
234
  Implementing further transactions should be straight forward and contributions are highly appreciated
200
235
 
package/dist/client.js CHANGED
@@ -8,7 +8,9 @@ import { TanMediaInteraction } from './interactions/tanMediaInteraction.js';
8
8
  import { HKSAL } from './segments/HKSAL.js';
9
9
  import { HKKAZ } from './segments/HKKAZ.js';
10
10
  import { HKWPD } from './segments/HKWPD.js';
11
+ import { DKKKU } from './segments/DKKKU.js';
11
12
  import { InitDialogInteraction } from './interactions/initDialogInteraction.js';
13
+ import { CreditCardStatementInteraction } from "./interactions/creditcardStatementInteraction.js";
12
14
  /**
13
15
  * A client to communicate with a bank over the FinTS protocol
14
16
  */
@@ -161,6 +163,36 @@ export class FinTSClient {
161
163
  async getPortfolioWithTan(tanReference, tan) {
162
164
  return this.continueCustomerInteractionWithTan(tanReference, tan);
163
165
  }
166
+ /**
167
+ * Checks if the bank supports fetching credit card statements in general or for the given account number
168
+ * @param accountNumber when the account number is provided, checks if the account supports fetching of statements
169
+ * @returns true if the bank (and account) supports fetching credit card statements
170
+ */
171
+ canGetCreditCardStatements(accountNumber) {
172
+ return accountNumber
173
+ ? this.config.isAccountTransactionSupported(accountNumber, DKKKU.Id)
174
+ : this.config.isTransactionSupported(DKKKU.Id);
175
+ }
176
+ /**
177
+ * Fetches the credit card statements for the given account number
178
+ * @param accountNumber - the account number to fetch the statements for, must be a credit card account available
179
+ * in the config.baningInformation.UPD.accounts
180
+ * @param from - an optional start date of the period to fetch the statements for
181
+ * @param to - an optional end date of the period to fetch the statements for
182
+ * @returns an account statements response containing an array of statements
183
+ */
184
+ async getCreditCardStatements(accountNumber, from) {
185
+ return this.startCustomerOrderInteraction(new CreditCardStatementInteraction(accountNumber, from));
186
+ }
187
+ /**
188
+ * Continues the credit card statements fetching when a TAN is required
189
+ * @param tanReference The TAN reference provided in the first call's response
190
+ * @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
191
+ * @returns a credit card statements response containing an array of statements
192
+ */
193
+ async getCreditCardStatementsWithTan(tanReference, tan) {
194
+ return this.continueCustomerInteractionWithTan(tanReference, tan);
195
+ }
164
196
  async startCustomerOrderInteraction(interaction) {
165
197
  const dialog = new Dialog(this.config);
166
198
  const syncResponse = await this.initDialog(dialog, false, interaction);
@@ -0,0 +1 @@
1
+ export {};
package/dist/dialog.js CHANGED
@@ -7,7 +7,6 @@ import { HKTAN } from './segments/HKTAN.js';
7
7
  import { HNHBK } from './segments/HNHBK.js';
8
8
  import { decode } from './segment.js';
9
9
  import { PARTED } from './partedSegment.js';
10
- import { HttpClientNode } from './httpClientNode.js';
11
10
  export class Dialog {
12
11
  config;
13
12
  dialogId = '0';
@@ -182,11 +181,6 @@ export class Dialog {
182
181
  }
183
182
  }
184
183
  getHttpClient() {
185
- if (typeof fetch === 'function') {
186
- return new HttpClient(this.config.bankingUrl, this.config.debugEnabled);
187
- }
188
- else {
189
- return new HttpClientNode(this.config.bankingUrl, this.config.debugEnabled);
190
- }
184
+ return new HttpClient(this.config.bankingUrl, this.config.debugEnabled);
191
185
  }
192
186
  }
@@ -0,0 +1,106 @@
1
+ import { CustomerOrderInteraction } from './customerInteraction.js';
2
+ import { DKKKU } from '../segments/DKKKU.js';
3
+ import { DIKKU } from '../segments/DIKKU.js';
4
+ export class CreditCardStatementInteraction extends CustomerOrderInteraction {
5
+ accountNumber;
6
+ from;
7
+ constructor(accountNumber, from) {
8
+ super(DKKKU.Id, DIKKU.Id);
9
+ this.accountNumber = accountNumber;
10
+ this.from = from;
11
+ }
12
+ createSegments(init) {
13
+ const bankAccount = init.getBankAccount(this.accountNumber);
14
+ if (!init.isAccountTransactionSupported(this.accountNumber, this.segId)) {
15
+ throw Error(`Account ${this.accountNumber} does not support business transaction '${this.segId}'`);
16
+ }
17
+ const account = { ...bankAccount, iban: undefined };
18
+ const version = 2;
19
+ const dkkku = {
20
+ header: { segId: DKKKU.Id, segNr: 0, version: version },
21
+ account,
22
+ accountNumber: account.accountNumber,
23
+ subAccountId: account.subAccountId,
24
+ from: this.from,
25
+ };
26
+ return [dkkku];
27
+ }
28
+ handleResponse(response, clientResponse) {
29
+ function parseGermanFloat(value) {
30
+ const valueFloatStr = value.replaceAll('.', '').replaceAll(',', '.');
31
+ return parseFloat(valueFloatStr);
32
+ }
33
+ const dikku = response.findSegment(DIKKU.Id);
34
+ if (dikku) {
35
+ const creditDebit = dikku.balance.creditDebit;
36
+ const balanceAmount = dikku.balance.amount.value * (creditDebit === 'D' ? -1 : 1);
37
+ const balanceCurrency = dikku.balance.amount.currency;
38
+ const balanceDateTime = dikku.balance.date;
39
+ if (dikku.balance.time) {
40
+ balanceDateTime.setUTCHours(dikku.balance.time.getUTCHours());
41
+ balanceDateTime.setUTCMinutes(dikku.balance.time.getUTCMinutes());
42
+ balanceDateTime.setUTCSeconds(dikku.balance.time.getUTCSeconds());
43
+ }
44
+ clientResponse.balance = {
45
+ balance: balanceAmount,
46
+ date: balanceDateTime,
47
+ currency: balanceCurrency,
48
+ };
49
+ clientResponse.statements = [];
50
+ if (dikku.transactions) {
51
+ for (let i = 0; i < dikku.transactions.length; i++) {
52
+ const parts = dikku.transactions[i].split(':');
53
+ // const accountNumber = parts[0];
54
+ const transactionDateStr = parts[1];
55
+ const valueDateStr = parts[2];
56
+ const currencyOrig = parts[5];
57
+ const depositMarkerOrig = parts[6];
58
+ const amountOrig = parseGermanFloat(parts[4]) * (depositMarkerOrig === 'D' ? -1 : 1);
59
+ const exchangeRate = parseGermanFloat(parts[7]);
60
+ const currency = parts[9];
61
+ const depositMarker = parts[10];
62
+ const amount = parseGermanFloat(parts[8]) * (depositMarker === 'D' ? -1 : 1);
63
+ const tYear = parseInt(transactionDateStr.substring(0, 4));
64
+ const tMonth = parseInt(transactionDateStr.substring(4, 6));
65
+ const tDay = parseInt(transactionDateStr.substring(6, 8));
66
+ const vYear = parseInt(valueDateStr.substring(0, 4));
67
+ const vMonth = parseInt(valueDateStr.substring(4, 6));
68
+ const vDay = parseInt(valueDateStr.substring(6, 8));
69
+ let purpose = '';
70
+ let pIdx = 11;
71
+ do {
72
+ let partPurpose = parts[pIdx].trim();
73
+ if (partPurpose === 'J') {
74
+ break;
75
+ }
76
+ purpose = purpose + partPurpose;
77
+ if (purpose.endsWith('Betrag?')) {
78
+ purpose = purpose.slice(0, purpose.length - 7) + ' Betrag ';
79
+ }
80
+ else if (purpose[purpose.length - 1] === '?') {
81
+ purpose = purpose.slice(0, purpose.length - 1) + ' ';
82
+ }
83
+ else {
84
+ break;
85
+ }
86
+ pIdx += 1;
87
+ } while (pIdx < 21);
88
+ const statement = {
89
+ transactionDate: new Date(tYear, tMonth - 1, tDay),
90
+ valueDate: new Date(vYear, vMonth - 1, vDay),
91
+ currency: currency,
92
+ amount: amount,
93
+ purpose: purpose,
94
+ originalCurrency: currencyOrig,
95
+ originalAmount: amountOrig,
96
+ exchangeRate: exchangeRate,
97
+ };
98
+ clientResponse.statements = clientResponse.statements.concat(statement);
99
+ }
100
+ }
101
+ }
102
+ else {
103
+ clientResponse.statements = [];
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,23 @@
1
+ import { Binary } from '../dataElements/Binary.js';
2
+ import { SegmentDefinition } from '../segmentDefinition.js';
3
+ import { Identification } from "../dataElements/Identification.js";
4
+ import { Text } from "../dataElements/Text.js";
5
+ import { BalanceGroup } from "../dataGroups/Balance.js";
6
+ /**
7
+ * Credit card transactions within period response
8
+ */
9
+ export class DIKKU extends SegmentDefinition {
10
+ static Id = 'DIKKU';
11
+ version = 2;
12
+ constructor() {
13
+ super(DIKKU.Id);
14
+ }
15
+ elements = [
16
+ new Identification('accountNumber', 1, 1),
17
+ new Text('Ignore', 0, 1),
18
+ new BalanceGroup('balance', 1, 1),
19
+ new Text('Ignore', 0, 1),
20
+ new Text('Ignore', 0, 1),
21
+ new Binary('transactions', 0, 10000, Number.MAX_SAFE_INTEGER),
22
+ ];
23
+ }
@@ -0,0 +1,25 @@
1
+ import { Dat } from '../dataElements/Dat.js';
2
+ import { Numeric } from '../dataElements/Numeric.js';
3
+ import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
4
+ import { AccountGroup } from '../dataGroups/Account.js';
5
+ import { SegmentDefinition } from '../segmentDefinition.js';
6
+ import { Identification } from "../dataElements/Identification.js";
7
+ /**
8
+ * Request credit card transactions in a given period
9
+ */
10
+ export class DKKKU extends SegmentDefinition {
11
+ static Id = 'DKKKU';
12
+ static Version = 2;
13
+ constructor() {
14
+ super(DKKKU.Id);
15
+ }
16
+ version = DKKKU.Version;
17
+ elements = [
18
+ new AccountGroup('account', 1, 1, 1, 6),
19
+ new Identification('accountNumber', 1, 1),
20
+ new Identification('subAccountId', 1, 1),
21
+ new Dat('from', 0, 1),
22
+ new Numeric('maxEntries', 0, 1, 4),
23
+ new AlphaNumeric('continuationMark', 0, 1, 35),
24
+ ];
25
+ }
@@ -29,6 +29,8 @@ import { HIKAZS } from './HIKAZS.js';
29
29
  import { HITAB } from './HITAB.js';
30
30
  import { HKWPD } from './HKWPD.js';
31
31
  import { HIWPD } from './HIWPD.js';
32
+ import { DIKKU } from "./DIKKU.js";
33
+ import { DKKKU } from "./DKKKU.js";
32
34
  import { UNKNOW } from '../unknownSegment.js';
33
35
  import { PARTED } from '../partedSegment.js';
34
36
  const registry = new Map();
@@ -60,6 +62,8 @@ export function registerSegments() {
60
62
  registerSegmentDefinition(new HKSAL());
61
63
  registerSegmentDefinition(new HISAL());
62
64
  registerSegmentDefinition(new HKKAZ());
65
+ registerSegmentDefinition(new DKKKU());
66
+ registerSegmentDefinition(new DIKKU());
63
67
  registerSegmentDefinition(new HIKAZ());
64
68
  registerSegmentDefinition(new HIKAZS());
65
69
  registerSegmentDefinition(new HKWPD());
@@ -103,6 +103,28 @@ export declare class FinTSClient {
103
103
  * @returns a portfolio response containing holdings and total value
104
104
  */
105
105
  getPortfolioWithTan(tanReference: string, tan?: string): Promise<PortfolioResponse>;
106
+ /**
107
+ * Checks if the bank supports fetching credit card statements in general or for the given account number
108
+ * @param accountNumber when the account number is provided, checks if the account supports fetching of statements
109
+ * @returns true if the bank (and account) supports fetching credit card statements
110
+ */
111
+ canGetCreditCardStatements(accountNumber?: string): boolean;
112
+ /**
113
+ * Fetches the credit card statements for the given account number
114
+ * @param accountNumber - the account number to fetch the statements for, must be a credit card account available
115
+ * in the config.baningInformation.UPD.accounts
116
+ * @param from - an optional start date of the period to fetch the statements for
117
+ * @param to - an optional end date of the period to fetch the statements for
118
+ * @returns an account statements response containing an array of statements
119
+ */
120
+ getCreditCardStatements(accountNumber: string, from?: Date): Promise<StatementResponse>;
121
+ /**
122
+ * Continues the credit card statements fetching when a TAN is required
123
+ * @param tanReference The TAN reference provided in the first call's response
124
+ * @param tan The TAN entered by the user, can be omitted if a decoupled TAN method is used
125
+ * @returns a credit card statements response containing an array of statements
126
+ */
127
+ getCreditCardStatementsWithTan(tanReference: string, tan?: string): Promise<StatementResponse>;
106
128
  private startCustomerOrderInteraction;
107
129
  private continueCustomerInteractionWithTan;
108
130
  private initDialog;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAsB,MAAM,sCAAsC,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C,OAAO,EAAyB,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAE9F,MAAM,WAAW,mBAAoB,SAAQ,YAAY;CAAG;AAE5D;;GAEG;AACH,qBAAa,WAAW;IAOJ,MAAM,EAAE,WAAW;IANtC,OAAO,CAAC,wBAAwB,CAA0C;IAE1E;;;OAGG;gBACgB,MAAM,EAAE,WAAW;IAUtC;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAK/C;;;OAGG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1C;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwBjD;;;;;OAKG;IACG,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI1F;;;;OAIG;IACH,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMrD;;;;OAIG;IACG,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAI/E;;;;;OAKG;IACG,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAInG;;;;OAIG;IACH,uBAAuB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMxD;;;;;;OAMG;IACG,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrG;;;;;OAKG;IACG,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIjG;;;;OAIG;IACH,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMhD;;;;;;;OAOG;IACG,YAAY,CACjB,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAM7B;;;;;;OAMG;IACG,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAI3E,6BAA6B;YAqB7B,kCAAkC;YA0ClC,UAAU;CAcxB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAsB,MAAM,sCAAsC,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wCAAwC,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAK3C,OAAO,EAAyB,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAG9F,MAAM,WAAW,mBAAoB,SAAQ,YAAY;CAAG;AAE5D;;GAEG;AACH,qBAAa,WAAW;IAOJ,MAAM,EAAE,WAAW;IANtC,OAAO,CAAC,wBAAwB,CAA0C;IAE1E;;;OAGG;gBACgB,MAAM,EAAE,WAAW;IAUtC;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAK/C;;;OAGG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAI1C;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwBjD;;;;;OAKG;IACG,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI1F;;;;OAIG;IACH,oBAAoB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMrD;;;;OAIG;IACG,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAI/E;;;;;OAKG;IACG,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAInG;;;;OAIG;IACH,uBAAuB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMxD;;;;;;OAMG;IACG,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrG;;;;;OAKG;IACG,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIjG;;;;OAIG;IACH,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAMhD;;;;;;;OAOG;IACG,YAAY,CACjB,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,GAAG,GAAG,GAAG,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAM7B;;;;;;OAMG;IACG,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAKzF;;;;OAIG;IACH,0BAA0B,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;IAM3D;;;;;;;OAOG;IACG,uBAAuB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAI7F;;;;;OAKG;IACG,8BAA8B,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAItF,6BAA6B;YAqB7B,kCAAkC;YA0ClC,UAAU;CAcxB"}
@@ -0,0 +1,11 @@
1
+ export type CreditCardStatement = {
2
+ transactionDate: Date;
3
+ valueDate: Date;
4
+ currency: string;
5
+ amount: number;
6
+ purpose: string;
7
+ originalCurrency: string;
8
+ originalAmount: number;
9
+ exchangeRate: number;
10
+ };
11
+ //# sourceMappingURL=creditCardStatement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"creditCardStatement.d.ts","sourceRoot":"","sources":["../../src/creditCardStatement.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAEhC,eAAe,EAAE,IAAI,CAAC;IAItB,SAAS,EAAE,IAAI,CAAC;IAEhB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAyC,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ9E,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAEjG,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAE9F,qBAAa,MAAM;IAOC,MAAM,EAAE,WAAW;IANtC,QAAQ,EAAE,MAAM,CAAO;IACvB,iBAAiB,SAAK;IACtB,aAAa,UAAS;IACtB,QAAQ,UAAS;IACjB,UAAU,EAAE,UAAU,CAAC;gBAEJ,MAAM,EAAE,WAAW;IAQhC,UAAU,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;IA0DrE,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;IAuCvB,6BAA6B,CAAC,eAAe,SAAS,cAAc,EACzE,WAAW,EAAE,wBAAwB,GACnC,OAAO,CAAC,eAAe,CAAC;IA+FrB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuDjG,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;CAOrB"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAyC,OAAO,EAAE,MAAM,cAAc,CAAC;AAQ9E,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjG,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAE9F,qBAAa,MAAM;IAOC,MAAM,EAAE,WAAW;IANtC,QAAQ,EAAE,MAAM,CAAO;IACvB,iBAAiB,SAAK;IACtB,aAAa,UAAS;IACtB,QAAQ,UAAS;IACjB,UAAU,EAAE,UAAU,CAAC;gBAEJ,MAAM,EAAE,WAAW;IAQhC,UAAU,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;IA0DrE,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;IAuCvB,6BAA6B,CAAC,eAAe,SAAS,cAAc,EACzE,WAAW,EAAE,wBAAwB,GACnC,OAAO,CAAC,eAAe,CAAC;IA+FrB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuDjG,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;CAGrB"}
@@ -0,0 +1,18 @@
1
+ import { ClientResponse, CustomerOrderInteraction } from './customerInteraction.js';
2
+ import { Message } from '../message.js';
3
+ import { Segment } from '../segment.js';
4
+ import { CreditCardStatement } from '../creditCardStatement.js';
5
+ import { FinTSConfig } from '../config.js';
6
+ import { AccountBalance } from "../accountBalance.js";
7
+ export interface CreditCardStatementResponse extends ClientResponse {
8
+ balance: AccountBalance;
9
+ statements: CreditCardStatement[];
10
+ }
11
+ export declare class CreditCardStatementInteraction extends CustomerOrderInteraction {
12
+ accountNumber: string;
13
+ from?: Date | undefined;
14
+ constructor(accountNumber: string, from?: Date | undefined);
15
+ createSegments(init: FinTSConfig): Segment[];
16
+ handleResponse(response: Message, clientResponse: CreditCardStatementResponse): void;
17
+ }
18
+ //# sourceMappingURL=creditcardStatementInteraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"creditcardStatementInteraction.d.ts","sourceRoot":"","sources":["../../../src/interactions/creditcardStatementInteraction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEpD,MAAM,WAAW,2BAA4B,SAAQ,cAAc;IACjE,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,mBAAmB,EAAE,CAAC;CACnC;AAED,qBAAa,8BAA+B,SAAQ,wBAAwB;IACvD,aAAa,EAAE,MAAM;IAAS,IAAI,CAAC;gBAAnC,aAAa,EAAE,MAAM,EAAS,IAAI,CAAC,kBAAM;IAI5D,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,EAAE;IAqB5C,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,2BAA2B;CA8E9E"}
@@ -0,0 +1,20 @@
1
+ import { Binary } from '../dataElements/Binary.js';
2
+ import { SegmentDefinition } from '../segmentDefinition.js';
3
+ import { Segment } from '../segment.js';
4
+ import { Identification } from "../dataElements/Identification.js";
5
+ import { Text } from "../dataElements/Text.js";
6
+ import { BalanceGroup, Balance } from "../dataGroups/Balance.js";
7
+ export type DIKKUSegment = Segment & {
8
+ balance: Balance;
9
+ transactions: string[];
10
+ };
11
+ /**
12
+ * Credit card transactions within period response
13
+ */
14
+ export declare class DIKKU extends SegmentDefinition {
15
+ static Id: string;
16
+ version: number;
17
+ constructor();
18
+ elements: (Identification | Text | Binary | BalanceGroup)[];
19
+ }
20
+ //# sourceMappingURL=DIKKU.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DIKKU.d.ts","sourceRoot":"","sources":["../../../src/segments/DIKKU.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAC,IAAI,EAAC,MAAM,yBAAyB,CAAC;AAC7C,OAAO,EAAC,YAAY,EAAE,OAAO,EAAC,MAAM,0BAA0B,CAAC;AAE/D,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,qBAAa,KAAM,SAAQ,iBAAiB;IAC3C,MAAM,CAAC,EAAE,SAAW;IACpB,OAAO,SAAK;;IAIZ,QAAQ,oDAON;CACF"}
@@ -0,0 +1,24 @@
1
+ import { Dat } from '../dataElements/Dat.js';
2
+ import { Numeric } from '../dataElements/Numeric.js';
3
+ import { AlphaNumeric } from '../dataElements/AlphaNumeric.js';
4
+ import { Account, AccountGroup } from '../dataGroups/Account.js';
5
+ import { SegmentWithContinuationMark } from '../segment.js';
6
+ import { SegmentDefinition } from '../segmentDefinition.js';
7
+ export type DKKKUSegment = SegmentWithContinuationMark & {
8
+ account: Account;
9
+ accountNumber: string;
10
+ subAccountId: string | undefined;
11
+ from?: Date;
12
+ maxEntries?: number;
13
+ };
14
+ /**
15
+ * Request credit card transactions in a given period
16
+ */
17
+ export declare class DKKKU extends SegmentDefinition {
18
+ static Id: string;
19
+ static Version: number;
20
+ constructor();
21
+ version: number;
22
+ elements: (AlphaNumeric | AccountGroup | Numeric | Dat)[];
23
+ }
24
+ //# sourceMappingURL=DKKKU.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DKKKU.d.ts","sourceRoot":"","sources":["../../../src/segments/DKKKU.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D,MAAM,MAAM,YAAY,GAAG,2BAA2B,GAAG;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,qBAAa,KAAM,SAAQ,iBAAiB;IACxC,MAAM,CAAC,EAAE,SAAW;IACpB,MAAM,CAAC,OAAO,SAAK;;IAInB,OAAO,SAAiB;IACxB,QAAQ,kDAON;CACL"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/segments/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAqC5D,wBAAgB,gBAAgB,SAkC/B;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,GACT,iBAAiB,GAAG,SAAS,CAE/B"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/segments/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAuC5D,wBAAgB,gBAAgB,SAoC/B;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,GACT,iBAAiB,GAAG,SAAS,CAE/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lib-fints",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Typescript/Javascript client library for Online-Banking via the FinTS 3.0 protocol with PIN/TAN",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -19,6 +19,12 @@
19
19
  }
20
20
  }
21
21
  },
22
+ "scripts": {
23
+ "build": "rm -rf ./dist && tsc",
24
+ "pack": "npm run build && npm pack --pack-destination ~/npm-repo",
25
+ "test": "vitest",
26
+ "preprepare": "npm run build"
27
+ },
22
28
  "keywords": [
23
29
  "FinTS",
24
30
  "HBCI",
@@ -36,10 +42,5 @@
36
42
  "@types/node": "^20.10.6",
37
43
  "typescript": "^5.3.3",
38
44
  "vitest": "^1.6.0"
39
- },
40
- "scripts": {
41
- "build": "rm -rf ./dist && tsc",
42
- "pack": "npm run build && npm pack --pack-destination ~/npm-repo",
43
- "test": "vitest"
44
45
  }
45
- }
46
+ }
@@ -1,59 +0,0 @@
1
- import { Message } from './message.js';
2
- import * as https from 'https';
3
- export class HttpClientNode {
4
- url;
5
- debug;
6
- constructor(url, debug = false) {
7
- this.url = url;
8
- this.debug = debug;
9
- }
10
- async sendMessage(message) {
11
- const encodedMessage = message.encode();
12
- const requestBuffer = Buffer.from(encodedMessage).toString('base64');
13
- if (this.debug) {
14
- console.log('Request Message:\n' + message.toString());
15
- }
16
- const requestOptions = {
17
- method: 'POST',
18
- headers: { 'Content-Type': 'text/plain' },
19
- };
20
- return new Promise((resolve, reject) => {
21
- const req = https.request(this.url, requestOptions, (res) => {
22
- let data = '';
23
- res.on('data', (chunk) => {
24
- data += chunk;
25
- });
26
- res.on('end', () => {
27
- if (res.statusCode === 200) {
28
- const responseBuffer = Buffer.from(data, 'base64');
29
- const responseText = responseBuffer.toString('latin1');
30
- try {
31
- const customerOrderMessage = message;
32
- const responseMessage = Message.decode(responseText, customerOrderMessage.supportsPartedResponseSegments
33
- ? customerOrderMessage.orderResponseSegId
34
- : undefined);
35
- if (this.debug) {
36
- console.log('Response Message:\n' + responseMessage.toString(true) + '\n');
37
- }
38
- resolve(responseMessage);
39
- }
40
- catch (error) {
41
- console.error('Error decoding response message:', error);
42
- console.error('Response Message Content:\n', responseText.split("'").join('\n'));
43
- reject(error);
44
- }
45
- }
46
- else {
47
- reject(new Error(`Request failed with status code ${res.statusCode}: ${data}`));
48
- }
49
- });
50
- });
51
- req.on('error', (error) => {
52
- console.error('Request error:', error);
53
- reject(error);
54
- });
55
- req.write(requestBuffer);
56
- req.end();
57
- });
58
- }
59
- }
@@ -1,8 +0,0 @@
1
- import { CustomerMessage, Message } from './message.js';
2
- export declare class HttpClientNode {
3
- url: string;
4
- debug: boolean;
5
- constructor(url: string, debug?: boolean);
6
- sendMessage(message: CustomerMessage): Promise<Message>;
7
- }
8
- //# sourceMappingURL=httpClientNode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"httpClientNode.d.ts","sourceRoot":"","sources":["../../src/httpClientNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAwB,OAAO,EAAE,MAAM,cAAc,CAAC;AAG9E,qBAAa,cAAc;IACN,GAAG,EAAE,MAAM;IAAS,KAAK;gBAAzB,GAAG,EAAE,MAAM,EAAS,KAAK,UAAQ;IAE9C,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;CA2D9D"}