fints-lib 0.8.0 → 0.9.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 +151 -8
- package/dist/decoupled-tan/decoupled-tan-manager.d.ts +82 -0
- package/dist/decoupled-tan/decoupled-tan-manager.js +307 -0
- package/dist/decoupled-tan/decoupled-tan-manager.js.map +1 -0
- package/dist/decoupled-tan/index.d.ts +5 -0
- package/dist/decoupled-tan/index.js +22 -0
- package/dist/decoupled-tan/index.js.map +1 -0
- package/dist/decoupled-tan/types.d.ts +86 -0
- package/dist/decoupled-tan/types.js +42 -0
- package/dist/decoupled-tan/types.js.map +1 -0
- package/dist/dialog.d.ts +49 -1
- package/dist/dialog.js +75 -2
- package/dist/dialog.js.map +1 -1
- package/dist/errors/decoupled-tan-error.d.ts +49 -0
- package/dist/errors/decoupled-tan-error.js +73 -0
- package/dist/errors/decoupled-tan-error.js.map +1 -0
- package/dist/errors/tan-required-error.d.ts +9 -0
- package/dist/errors/tan-required-error.js +6 -0
- package/dist/errors/tan-required-error.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/pin-tan-client.d.ts +43 -0
- package/dist/pin-tan-client.js +56 -2
- package/dist/pin-tan-client.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,26 +15,56 @@ npm install fints-lib
|
|
|
15
15
|
yarn add fints-lib
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Quick Start Examples
|
|
19
|
+
|
|
20
|
+
### Basic Account Information
|
|
19
21
|
|
|
20
22
|
```typescript
|
|
21
23
|
import { PinTanClient } from "fints-lib";
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
+
// Initialize client with minimal configuration
|
|
26
|
+
const client = new PinTanClient({
|
|
27
|
+
url: "https://banking.example.com/fints",
|
|
28
|
+
name: "username",
|
|
29
|
+
pin: "12345",
|
|
30
|
+
blz: "12345678",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Fetch all accounts
|
|
34
|
+
const accounts = await client.accounts();
|
|
35
|
+
console.log(accounts); // List of all accounts
|
|
36
|
+
|
|
37
|
+
// Get balance for first account
|
|
38
|
+
const balance = await client.balance(accounts[0]);
|
|
39
|
+
console.log(`Balance: ${balance.value.value} ${balance.value.currency}`);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Fetching Transactions
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { PinTanClient } from "fints-lib";
|
|
25
46
|
|
|
26
47
|
const client = new PinTanClient({
|
|
27
|
-
url: "https://example.com/fints",
|
|
48
|
+
url: "https://banking.example.com/fints",
|
|
28
49
|
name: "username",
|
|
29
|
-
pin: 12345,
|
|
30
|
-
blz: 12345678,
|
|
50
|
+
pin: "12345",
|
|
51
|
+
blz: "12345678",
|
|
31
52
|
});
|
|
32
53
|
|
|
33
54
|
const accounts = await client.accounts();
|
|
34
|
-
console.info(accounts); // List of all accounts.
|
|
35
55
|
|
|
56
|
+
// Fetch transactions for a date range
|
|
57
|
+
const startDate = new Date("2024-01-01");
|
|
58
|
+
const endDate = new Date("2024-12-31");
|
|
36
59
|
const statements = await client.statements(accounts[0], startDate, endDate);
|
|
37
|
-
|
|
60
|
+
|
|
61
|
+
// Process transactions
|
|
62
|
+
statements.forEach(statement => {
|
|
63
|
+
console.log(`Statement from ${statement.date}`);
|
|
64
|
+
statement.transactions.forEach(tx => {
|
|
65
|
+
console.log(` ${tx.descriptionStructured?.bookingText}: ${tx.amount} ${tx.currency}`);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
38
68
|
```
|
|
39
69
|
|
|
40
70
|
|
|
@@ -164,6 +194,119 @@ const formatted = formatErrorCode("9942", "Custom message");
|
|
|
164
194
|
// Output: "[9942] PIN falsch - Custom message"
|
|
165
195
|
```
|
|
166
196
|
|
|
197
|
+
## Common Use Cases
|
|
198
|
+
|
|
199
|
+
### Check Account Balance
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { PinTanClient } from "fints-lib";
|
|
203
|
+
|
|
204
|
+
const client = new PinTanClient({
|
|
205
|
+
url: process.env.FINTS_URL,
|
|
206
|
+
name: process.env.FINTS_USERNAME,
|
|
207
|
+
pin: process.env.FINTS_PIN,
|
|
208
|
+
blz: process.env.FINTS_BLZ,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const accounts = await client.accounts();
|
|
212
|
+
|
|
213
|
+
// Get balance for a specific account
|
|
214
|
+
const balance = await client.balance(accounts[0]);
|
|
215
|
+
console.log(`Current Balance: ${balance.value.value} ${balance.value.currency}`);
|
|
216
|
+
console.log(`Available: ${balance.availableBalance?.value || 'N/A'}`);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Fetch Recent Transactions
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { PinTanClient } from "fints-lib";
|
|
223
|
+
|
|
224
|
+
const client = new PinTanClient({
|
|
225
|
+
url: process.env.FINTS_URL,
|
|
226
|
+
name: process.env.FINTS_USERNAME,
|
|
227
|
+
pin: process.env.FINTS_PIN,
|
|
228
|
+
blz: process.env.FINTS_BLZ,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const accounts = await client.accounts();
|
|
232
|
+
|
|
233
|
+
// Get transactions from the last 30 days
|
|
234
|
+
const endDate = new Date();
|
|
235
|
+
const startDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
236
|
+
|
|
237
|
+
const statements = await client.statements(accounts[0], startDate, endDate);
|
|
238
|
+
|
|
239
|
+
statements.forEach(statement => {
|
|
240
|
+
console.log(`\nStatement: ${statement.date}`);
|
|
241
|
+
statement.transactions.forEach(tx => {
|
|
242
|
+
const booking = tx.descriptionStructured?.bookingText || 'Transaction';
|
|
243
|
+
const purpose = tx.purpose || '';
|
|
244
|
+
console.log(` ${booking}: ${tx.amount} ${tx.currency}`);
|
|
245
|
+
if (purpose) console.log(` Purpose: ${purpose}`);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### List All Accounts with Details
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { PinTanClient } from "fints-lib";
|
|
254
|
+
|
|
255
|
+
const client = new PinTanClient({
|
|
256
|
+
url: process.env.FINTS_URL,
|
|
257
|
+
name: process.env.FINTS_USERNAME,
|
|
258
|
+
pin: process.env.FINTS_PIN,
|
|
259
|
+
blz: process.env.FINTS_BLZ,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const accounts = await client.accounts();
|
|
263
|
+
|
|
264
|
+
console.log(`Found ${accounts.length} account(s):\n`);
|
|
265
|
+
|
|
266
|
+
for (const account of accounts) {
|
|
267
|
+
console.log(`Account: ${account.accountName || 'Unnamed'}`);
|
|
268
|
+
console.log(` IBAN: ${account.iban}`);
|
|
269
|
+
console.log(` Type: ${account.accountType || 'N/A'}`);
|
|
270
|
+
console.log(` Number: ${account.accountNumber || 'N/A'}`);
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const balance = await client.balance(account);
|
|
274
|
+
console.log(` Balance: ${balance.value.value} ${balance.value.currency}`);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.log(` Balance: Unable to retrieve`);
|
|
277
|
+
}
|
|
278
|
+
console.log();
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Working with Environment Variables (Recommended)
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { PinTanClient } from "fints-lib";
|
|
286
|
+
|
|
287
|
+
// Create client using environment variables for credentials
|
|
288
|
+
// Ensure environment variables are set before running
|
|
289
|
+
if (!process.env.FINTS_URL || !process.env.FINTS_USERNAME ||
|
|
290
|
+
!process.env.FINTS_PIN || !process.env.FINTS_BLZ) {
|
|
291
|
+
throw new Error("Required environment variables are not set");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const client = new PinTanClient({
|
|
295
|
+
url: process.env.FINTS_URL,
|
|
296
|
+
name: process.env.FINTS_USERNAME,
|
|
297
|
+
pin: process.env.FINTS_PIN,
|
|
298
|
+
blz: process.env.FINTS_BLZ,
|
|
299
|
+
debug: process.env.NODE_ENV === "development",
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Example .env file:
|
|
303
|
+
// FINTS_URL=https://banking.example.com/fints
|
|
304
|
+
// FINTS_USERNAME=myusername
|
|
305
|
+
// FINTS_PIN=mypin
|
|
306
|
+
// FINTS_BLZ=12345678
|
|
307
|
+
// NODE_ENV=development
|
|
308
|
+
```
|
|
309
|
+
|
|
167
310
|
## Missing
|
|
168
311
|
|
|
169
312
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { DecoupledTanStatus, DecoupledTanConfig } from "./types";
|
|
2
|
+
import { Dialog } from "../dialog";
|
|
3
|
+
import { Response } from "../response";
|
|
4
|
+
import { TanMethod } from "../tan-method";
|
|
5
|
+
/**
|
|
6
|
+
* Callback function for status updates during polling
|
|
7
|
+
*/
|
|
8
|
+
export type DecoupledTanStatusCallback = (status: DecoupledTanStatus) => void | Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Manages the lifecycle of a decoupled TAN (asynchronous authentication) process.
|
|
11
|
+
*
|
|
12
|
+
* Implements the FinTS 3.0 Security Sicherheitsverfahren PINTAN specification for
|
|
13
|
+
* decoupled TAN authentication (tanProcess="2"), where transaction approval happens
|
|
14
|
+
* asynchronously on a separate device (e.g., mobile banking app).
|
|
15
|
+
*
|
|
16
|
+
* **FinTS Specification Reference:**
|
|
17
|
+
* - Document: "Sicherheitsverfahren PINTAN" Version 3.0
|
|
18
|
+
* - Section: "Zwei-Schritt-TAN-Verfahren" (Two-Step TAN Procedure)
|
|
19
|
+
* - Process: tanProcess="2" (Decoupled/Asynchronous)
|
|
20
|
+
*
|
|
21
|
+
* **Key Features:**
|
|
22
|
+
* - Automatic polling with configurable fixed intervals
|
|
23
|
+
* - State machine for TAN lifecycle (INITIATED → CHALLENGE_SENT → PENDING_CONFIRMATION → CONFIRMED)
|
|
24
|
+
* - Configurable timeout handling
|
|
25
|
+
* - Server-provided timing parameters from HITANS segment
|
|
26
|
+
* - User cancellation support
|
|
27
|
+
*
|
|
28
|
+
* **Return Code Handling:**
|
|
29
|
+
* - "0030": Order received - TAN/Security clearance required
|
|
30
|
+
* - "3956": Strong customer authentication pending
|
|
31
|
+
* - "3076": PSD2 Strong Customer Authentication required
|
|
32
|
+
*
|
|
33
|
+
* @see https://www.hbci-zka.de/ for FinTS specification documentation
|
|
34
|
+
*/
|
|
35
|
+
export declare class DecoupledTanManager {
|
|
36
|
+
private status;
|
|
37
|
+
private config;
|
|
38
|
+
private dialog;
|
|
39
|
+
private tanMethod?;
|
|
40
|
+
private cancelled;
|
|
41
|
+
private startTime;
|
|
42
|
+
private timeoutHandle?;
|
|
43
|
+
private isPolling;
|
|
44
|
+
constructor(transactionReference: string, challengeText: string, dialog: Dialog, config?: DecoupledTanConfig, tanMethod?: TanMethod);
|
|
45
|
+
/**
|
|
46
|
+
* Get the current status
|
|
47
|
+
*/
|
|
48
|
+
getStatus(): DecoupledTanStatus;
|
|
49
|
+
/**
|
|
50
|
+
* Check if the process is still active
|
|
51
|
+
*/
|
|
52
|
+
isActive(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Cancel the decoupled TAN process
|
|
55
|
+
*/
|
|
56
|
+
cancel(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Start the polling process and wait for confirmation
|
|
59
|
+
*/
|
|
60
|
+
pollForConfirmation(statusCallback?: DecoupledTanStatusCallback): Promise<Response>;
|
|
61
|
+
/**
|
|
62
|
+
* Main polling loop
|
|
63
|
+
*/
|
|
64
|
+
private pollLoop;
|
|
65
|
+
/**
|
|
66
|
+
* Make a single status check request
|
|
67
|
+
*
|
|
68
|
+
* Note: This uses segNo=3 as the HKTAN status request is typically the first business
|
|
69
|
+
* segment after the dialog headers (HNHBK, HNVSK). While the exact segment number may
|
|
70
|
+
* vary in different contexts, segNo=3 is the standard position for standalone HKTAN
|
|
71
|
+
* status requests in the decoupled TAN flow.
|
|
72
|
+
*/
|
|
73
|
+
private checkStatus;
|
|
74
|
+
/**
|
|
75
|
+
* Update the state
|
|
76
|
+
*/
|
|
77
|
+
private updateState;
|
|
78
|
+
/**
|
|
79
|
+
* Wait for a specified duration
|
|
80
|
+
*/
|
|
81
|
+
private wait;
|
|
82
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DecoupledTanManager = void 0;
|
|
13
|
+
const types_1 = require("./types");
|
|
14
|
+
const decoupled_tan_error_1 = require("../errors/decoupled-tan-error");
|
|
15
|
+
const segments_1 = require("../segments");
|
|
16
|
+
const request_1 = require("../request");
|
|
17
|
+
/**
|
|
18
|
+
* FinTS return code constants for decoupled TAN authentication
|
|
19
|
+
*/
|
|
20
|
+
const RETURN_CODE_TAN_REQUIRED = "0030"; // Order received - TAN/Security clearance required
|
|
21
|
+
const RETURN_CODE_PENDING_CONFIRMATION = "3956"; // Strong customer authentication pending
|
|
22
|
+
/**
|
|
23
|
+
* HKTAN process type for decoupled TAN status polling
|
|
24
|
+
*/
|
|
25
|
+
const HKTAN_PROCESS_DECOUPLED_STATUS = "2"; // Decoupled/asynchronous authentication status check
|
|
26
|
+
/**
|
|
27
|
+
* Default configuration for decoupled TAN
|
|
28
|
+
*/
|
|
29
|
+
const DEFAULT_CONFIG = {
|
|
30
|
+
maxStatusRequests: 60,
|
|
31
|
+
waitBeforeFirstStatusRequest: 2000,
|
|
32
|
+
waitBetweenStatusRequests: 2000,
|
|
33
|
+
totalTimeout: 5 * 60 * 1000, // 5 minutes
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Manages the lifecycle of a decoupled TAN (asynchronous authentication) process.
|
|
37
|
+
*
|
|
38
|
+
* Implements the FinTS 3.0 Security Sicherheitsverfahren PINTAN specification for
|
|
39
|
+
* decoupled TAN authentication (tanProcess="2"), where transaction approval happens
|
|
40
|
+
* asynchronously on a separate device (e.g., mobile banking app).
|
|
41
|
+
*
|
|
42
|
+
* **FinTS Specification Reference:**
|
|
43
|
+
* - Document: "Sicherheitsverfahren PINTAN" Version 3.0
|
|
44
|
+
* - Section: "Zwei-Schritt-TAN-Verfahren" (Two-Step TAN Procedure)
|
|
45
|
+
* - Process: tanProcess="2" (Decoupled/Asynchronous)
|
|
46
|
+
*
|
|
47
|
+
* **Key Features:**
|
|
48
|
+
* - Automatic polling with configurable fixed intervals
|
|
49
|
+
* - State machine for TAN lifecycle (INITIATED → CHALLENGE_SENT → PENDING_CONFIRMATION → CONFIRMED)
|
|
50
|
+
* - Configurable timeout handling
|
|
51
|
+
* - Server-provided timing parameters from HITANS segment
|
|
52
|
+
* - User cancellation support
|
|
53
|
+
*
|
|
54
|
+
* **Return Code Handling:**
|
|
55
|
+
* - "0030": Order received - TAN/Security clearance required
|
|
56
|
+
* - "3956": Strong customer authentication pending
|
|
57
|
+
* - "3076": PSD2 Strong Customer Authentication required
|
|
58
|
+
*
|
|
59
|
+
* @see https://www.hbci-zka.de/ for FinTS specification documentation
|
|
60
|
+
*/
|
|
61
|
+
class DecoupledTanManager {
|
|
62
|
+
constructor(transactionReference, challengeText, dialog, config, tanMethod) {
|
|
63
|
+
this.cancelled = false;
|
|
64
|
+
this.isPolling = false;
|
|
65
|
+
this.dialog = dialog;
|
|
66
|
+
this.tanMethod = tanMethod;
|
|
67
|
+
this.startTime = new Date();
|
|
68
|
+
// Merge config with defaults, preferring server-provided values from TanMethod
|
|
69
|
+
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), config);
|
|
70
|
+
// Override with server-provided values if available
|
|
71
|
+
if (tanMethod) {
|
|
72
|
+
if (tanMethod.decoupledMaxStatusRequests !== undefined) {
|
|
73
|
+
this.config.maxStatusRequests = tanMethod.decoupledMaxStatusRequests;
|
|
74
|
+
}
|
|
75
|
+
if (tanMethod.decoupledWaitBeforeFirstStatusRequest !== undefined) {
|
|
76
|
+
this.config.waitBeforeFirstStatusRequest = tanMethod.decoupledWaitBeforeFirstStatusRequest;
|
|
77
|
+
}
|
|
78
|
+
if (tanMethod.decoupledWaitBetweenStatusRequests !== undefined) {
|
|
79
|
+
this.config.waitBetweenStatusRequests = tanMethod.decoupledWaitBetweenStatusRequests;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
this.status = {
|
|
83
|
+
state: types_1.DecoupledTanState.INITIATED,
|
|
84
|
+
transactionReference,
|
|
85
|
+
challengeText,
|
|
86
|
+
statusRequestCount: 0,
|
|
87
|
+
maxStatusRequests: this.config.maxStatusRequests,
|
|
88
|
+
startTime: this.startTime,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get the current status
|
|
93
|
+
*/
|
|
94
|
+
getStatus() {
|
|
95
|
+
return Object.assign({}, this.status);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check if the process is still active
|
|
99
|
+
*/
|
|
100
|
+
isActive() {
|
|
101
|
+
return (this.status.state === types_1.DecoupledTanState.INITIATED ||
|
|
102
|
+
this.status.state === types_1.DecoupledTanState.CHALLENGE_SENT ||
|
|
103
|
+
this.status.state === types_1.DecoupledTanState.PENDING_CONFIRMATION);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Cancel the decoupled TAN process
|
|
107
|
+
*/
|
|
108
|
+
cancel() {
|
|
109
|
+
this.cancelled = true;
|
|
110
|
+
if (this.timeoutHandle) {
|
|
111
|
+
clearTimeout(this.timeoutHandle);
|
|
112
|
+
this.timeoutHandle = undefined;
|
|
113
|
+
}
|
|
114
|
+
this.updateState(types_1.DecoupledTanState.CANCELLED);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Start the polling process and wait for confirmation
|
|
118
|
+
*/
|
|
119
|
+
pollForConfirmation(statusCallback) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
// Prevent multiple simultaneous polling attempts
|
|
122
|
+
if (this.isPolling) {
|
|
123
|
+
throw new Error("Polling is already in progress. Cannot start a new polling session.");
|
|
124
|
+
}
|
|
125
|
+
this.isPolling = true;
|
|
126
|
+
// Set state to CHALLENGE_SENT
|
|
127
|
+
this.updateState(types_1.DecoupledTanState.CHALLENGE_SENT);
|
|
128
|
+
if (statusCallback) {
|
|
129
|
+
yield statusCallback(this.getStatus());
|
|
130
|
+
}
|
|
131
|
+
// Set up total timeout
|
|
132
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
133
|
+
this.timeoutHandle = setTimeout(() => {
|
|
134
|
+
// Check if already cancelled to avoid race condition
|
|
135
|
+
if (!this.cancelled) {
|
|
136
|
+
this.updateState(types_1.DecoupledTanState.TIMED_OUT, "Total timeout exceeded");
|
|
137
|
+
reject(new decoupled_tan_error_1.DecoupledTanError(`Decoupled TAN timed out after ${this.config.totalTimeout}ms`, this.getStatus()));
|
|
138
|
+
}
|
|
139
|
+
}, this.config.totalTimeout);
|
|
140
|
+
});
|
|
141
|
+
try {
|
|
142
|
+
// Wait before first status request
|
|
143
|
+
yield this.wait(this.config.waitBeforeFirstStatusRequest);
|
|
144
|
+
// Start polling
|
|
145
|
+
this.updateState(types_1.DecoupledTanState.PENDING_CONFIRMATION);
|
|
146
|
+
if (statusCallback) {
|
|
147
|
+
yield statusCallback(this.getStatus());
|
|
148
|
+
}
|
|
149
|
+
const response = yield Promise.race([this.pollLoop(statusCallback), timeoutPromise]);
|
|
150
|
+
// Clear timeout
|
|
151
|
+
if (this.timeoutHandle) {
|
|
152
|
+
clearTimeout(this.timeoutHandle);
|
|
153
|
+
this.timeoutHandle = undefined;
|
|
154
|
+
}
|
|
155
|
+
this.updateState(types_1.DecoupledTanState.CONFIRMED);
|
|
156
|
+
if (statusCallback) {
|
|
157
|
+
yield statusCallback(this.getStatus());
|
|
158
|
+
}
|
|
159
|
+
return response;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
// Clear timeout
|
|
163
|
+
if (this.timeoutHandle) {
|
|
164
|
+
clearTimeout(this.timeoutHandle);
|
|
165
|
+
this.timeoutHandle = undefined;
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
this.isPolling = false;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Main polling loop
|
|
176
|
+
*/
|
|
177
|
+
pollLoop(statusCallback) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
while (this.isActive()) {
|
|
180
|
+
// Check if cancelled first
|
|
181
|
+
if (this.cancelled) {
|
|
182
|
+
throw new decoupled_tan_error_1.DecoupledTanError("Decoupled TAN cancelled by user", this.getStatus());
|
|
183
|
+
}
|
|
184
|
+
// Check if we've exceeded max status requests
|
|
185
|
+
if (this.status.statusRequestCount >= this.config.maxStatusRequests) {
|
|
186
|
+
this.updateState(types_1.DecoupledTanState.FAILED, "Maximum status requests exceeded");
|
|
187
|
+
throw new decoupled_tan_error_1.DecoupledTanError("Maximum status requests exceeded", this.getStatus());
|
|
188
|
+
}
|
|
189
|
+
// Make status request
|
|
190
|
+
try {
|
|
191
|
+
const response = yield this.checkStatus();
|
|
192
|
+
// Check response for confirmation or error codes
|
|
193
|
+
const returnValues = response.returnValues();
|
|
194
|
+
// FinTS Return Codes (per FinTS 3.0 PINTAN specification):
|
|
195
|
+
// - "0030": "Order received - TAN/Security clearance required"
|
|
196
|
+
// This code indicates the server accepted the order but needs TAN confirmation.
|
|
197
|
+
// It's a success code (0xxx range) that triggers TAN requirement.
|
|
198
|
+
//
|
|
199
|
+
// - "3956": "Strong customer authentication necessary"
|
|
200
|
+
// This warning code (3xxx range) indicates the decoupled TAN process is still
|
|
201
|
+
// pending user confirmation on their trusted device (e.g., mobile app).
|
|
202
|
+
// The client must continue polling until this code disappears.
|
|
203
|
+
//
|
|
204
|
+
// - "3076": "Strong customer authentication necessary (PSD2)"
|
|
205
|
+
// Similar to 3956, indicates SCA is required per PSD2 regulations.
|
|
206
|
+
// Used to detect initial decoupled TAN requirement.
|
|
207
|
+
// Check for confirmation: 0030 present WITHOUT 3956 means TAN was approved
|
|
208
|
+
// If 3956 is still present, authentication is pending and we must continue polling
|
|
209
|
+
if (returnValues.has(RETURN_CODE_TAN_REQUIRED) && !returnValues.has(RETURN_CODE_PENDING_CONFIRMATION)) {
|
|
210
|
+
// TAN confirmed - increment counter and return
|
|
211
|
+
this.status.statusRequestCount++;
|
|
212
|
+
return response;
|
|
213
|
+
}
|
|
214
|
+
// Check for still pending: 3956 means user hasn't approved yet
|
|
215
|
+
// Continue polling until user confirms in their banking app
|
|
216
|
+
if (returnValues.has(RETURN_CODE_PENDING_CONFIRMATION)) {
|
|
217
|
+
// Still pending - increment counter and continue polling
|
|
218
|
+
this.status.statusRequestCount++;
|
|
219
|
+
if (statusCallback) {
|
|
220
|
+
yield statusCallback(this.getStatus());
|
|
221
|
+
}
|
|
222
|
+
yield this.wait(this.config.waitBetweenStatusRequests);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// Check for errors
|
|
226
|
+
if (!response.success) {
|
|
227
|
+
const errorMessages = response.errors.join(", ");
|
|
228
|
+
this.status.statusRequestCount++;
|
|
229
|
+
this.updateState(types_1.DecoupledTanState.FAILED, errorMessages);
|
|
230
|
+
throw new decoupled_tan_error_1.DecoupledTanError(`Server error: ${errorMessages}`, this.getStatus());
|
|
231
|
+
}
|
|
232
|
+
// Unexpected response, treat as confirmation
|
|
233
|
+
this.status.statusRequestCount++;
|
|
234
|
+
return response;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
if (error instanceof decoupled_tan_error_1.DecoupledTanError) {
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
// Other errors (network, etc.)
|
|
241
|
+
this.updateState(types_1.DecoupledTanState.FAILED, String(error));
|
|
242
|
+
throw new decoupled_tan_error_1.DecoupledTanError(`Error during polling: ${error}`, this.getStatus());
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// If we exit the loop and weren't cancelled, something unexpected happened
|
|
246
|
+
if (this.cancelled) {
|
|
247
|
+
throw new decoupled_tan_error_1.DecoupledTanError("Decoupled TAN cancelled by user", this.getStatus());
|
|
248
|
+
}
|
|
249
|
+
throw new decoupled_tan_error_1.DecoupledTanError("Polling loop exited unexpectedly", this.getStatus());
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Make a single status check request
|
|
254
|
+
*
|
|
255
|
+
* Note: This uses segNo=3 as the HKTAN status request is typically the first business
|
|
256
|
+
* segment after the dialog headers (HNHBK, HNVSK). While the exact segment number may
|
|
257
|
+
* vary in different contexts, segNo=3 is the standard position for standalone HKTAN
|
|
258
|
+
* status requests in the decoupled TAN flow.
|
|
259
|
+
*/
|
|
260
|
+
checkStatus() {
|
|
261
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
262
|
+
const version = this.dialog.hktanVersion >= 7 ? 7 : this.dialog.hktanVersion;
|
|
263
|
+
const segments = [
|
|
264
|
+
new segments_1.HKTAN({
|
|
265
|
+
segNo: 3, // Standard position for HKTAN in status-only requests
|
|
266
|
+
version,
|
|
267
|
+
process: HKTAN_PROCESS_DECOUPLED_STATUS,
|
|
268
|
+
aref: this.status.transactionReference,
|
|
269
|
+
}),
|
|
270
|
+
];
|
|
271
|
+
const { blz, name, pin, systemId, dialogId, msgNo, tanMethods } = this.dialog;
|
|
272
|
+
// Create a proper Request instance instead of using a plain object
|
|
273
|
+
const request = new request_1.Request({
|
|
274
|
+
blz,
|
|
275
|
+
name,
|
|
276
|
+
pin,
|
|
277
|
+
systemId,
|
|
278
|
+
dialogId,
|
|
279
|
+
msgNo,
|
|
280
|
+
segments,
|
|
281
|
+
tanMethods,
|
|
282
|
+
});
|
|
283
|
+
// Send the request using the dialog's connection
|
|
284
|
+
const response = yield this.dialog.connection.send(request);
|
|
285
|
+
return response;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Update the state
|
|
290
|
+
*/
|
|
291
|
+
updateState(state, errorMessage) {
|
|
292
|
+
this.status.state = state;
|
|
293
|
+
if (errorMessage) {
|
|
294
|
+
this.status.errorMessage = errorMessage;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Wait for a specified duration
|
|
299
|
+
*/
|
|
300
|
+
wait(ms) {
|
|
301
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
302
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
exports.DecoupledTanManager = DecoupledTanManager;
|
|
307
|
+
//# sourceMappingURL=decoupled-tan-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decoupled-tan-manager.js","sourceRoot":"","sources":["../../src/decoupled-tan/decoupled-tan-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Decoupled TAN (Asynchronous Authentication) Support
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
__exportStar(require("./types"), exports);
|
|
21
|
+
__exportStar(require("./decoupled-tan-manager"), exports);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decoupled-tan/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,0DAAwC"}
|