lib-fints 1.0.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.
Files changed (306) hide show
  1. package/LICENSE +504 -0
  2. package/README.md +216 -0
  3. package/dist/accountBalance.js +1 -0
  4. package/dist/bankAccount.js +34 -0
  5. package/dist/bankAnswer.js +1 -0
  6. package/dist/bankTransaction.js +1 -0
  7. package/dist/bankingInformation.js +1 -0
  8. package/dist/bpd.js +1 -0
  9. package/dist/client.js +165 -0
  10. package/dist/codes.js +79 -0
  11. package/dist/config.js +181 -0
  12. package/dist/dataElements/AlphaNumeric.js +24 -0
  13. package/dist/dataElements/Amount.js +6 -0
  14. package/dist/dataElements/Binary.js +20 -0
  15. package/dist/dataElements/Country.js +6 -0
  16. package/dist/dataElements/Currency.js +6 -0
  17. package/dist/dataElements/Dat.js +18 -0
  18. package/dist/dataElements/DataElement.js +37 -0
  19. package/dist/dataElements/Digits.js +23 -0
  20. package/dist/dataElements/Float.js +21 -0
  21. package/dist/dataElements/Identification.js +6 -0
  22. package/dist/dataElements/Numeric.js +26 -0
  23. package/dist/dataElements/Text.js +21 -0
  24. package/dist/dataElements/Time.js +18 -0
  25. package/dist/dataElements/YesNo.js +18 -0
  26. package/dist/dataGroups/Account.js +12 -0
  27. package/dist/dataGroups/Balance.js +15 -0
  28. package/dist/dataGroups/BankIdentification.js +8 -0
  29. package/dist/dataGroups/DataGroup.js +54 -0
  30. package/dist/dataGroups/InternationalAccount.js +15 -0
  31. package/dist/dataGroups/Money.js +8 -0
  32. package/dist/dataGroups/RefMessage.js +8 -0
  33. package/dist/dataGroups/TimeStamp.js +8 -0
  34. package/dist/decoder.js +97 -0
  35. package/dist/dialog.js +189 -0
  36. package/dist/encoder.js +47 -0
  37. package/dist/format.js +6 -0
  38. package/dist/httpClient.js +41 -0
  39. package/dist/httpClientNode.js +59 -0
  40. package/dist/index.js +15 -0
  41. package/dist/interactions/balanceInteraction.js +47 -0
  42. package/dist/interactions/customerInteraction.js +55 -0
  43. package/dist/interactions/initDialogInteraction.js +155 -0
  44. package/dist/interactions/statementInteraction.js +44 -0
  45. package/dist/interactions/tanMediaInteraction.js +27 -0
  46. package/dist/message.js +198 -0
  47. package/dist/mt940parser.js +307 -0
  48. package/dist/parser.js +30 -0
  49. package/dist/partedSegment.js +8 -0
  50. package/dist/segment.js +59 -0
  51. package/dist/segmentDefinition.js +11 -0
  52. package/dist/segmentHeader.js +13 -0
  53. package/dist/segments/HIBPA.js +23 -0
  54. package/dist/segments/HIKAZ.js +13 -0
  55. package/dist/segments/HIKAZS.js +13 -0
  56. package/dist/segments/HIKIM.js +11 -0
  57. package/dist/segments/HIKOM.js +23 -0
  58. package/dist/segments/HIPINS.js +22 -0
  59. package/dist/segments/HIRMG.js +20 -0
  60. package/dist/segments/HIRMS.js +20 -0
  61. package/dist/segments/HISAL.js +31 -0
  62. package/dist/segments/HISYN.js +16 -0
  63. package/dist/segments/HITAB.js +37 -0
  64. package/dist/segments/HITAN.js +23 -0
  65. package/dist/segments/HITANS.js +48 -0
  66. package/dist/segments/HIUPA.js +18 -0
  67. package/dist/segments/HIUPD.js +34 -0
  68. package/dist/segments/HKEND.js +11 -0
  69. package/dist/segments/HKIDN.js +18 -0
  70. package/dist/segments/HKKAZ.js +24 -0
  71. package/dist/segments/HKSAL.js +21 -0
  72. package/dist/segments/HKSYN.js +11 -0
  73. package/dist/segments/HKTAB.js +12 -0
  74. package/dist/segments/HKTAN.js +35 -0
  75. package/dist/segments/HKVVB.js +18 -0
  76. package/dist/segments/HNHBK.js +20 -0
  77. package/dist/segments/HNHBS.js +11 -0
  78. package/dist/segments/HNSHA.js +17 -0
  79. package/dist/segments/HNSHK.js +43 -0
  80. package/dist/segments/HNVSD.js +11 -0
  81. package/dist/segments/HNVSK.js +45 -0
  82. package/dist/segments/businessTransactionParameter.js +20 -0
  83. package/dist/segments/registry.js +71 -0
  84. package/dist/tanMethod.js +1 -0
  85. package/dist/tests/HIBPA.test.js +26 -0
  86. package/dist/tests/HIPINS.test.js +14 -0
  87. package/dist/tests/HIRMG.test.js +24 -0
  88. package/dist/tests/HITAB.test.js +19 -0
  89. package/dist/tests/HITANS.test.js +19 -0
  90. package/dist/tests/HIUPA.test.js +11 -0
  91. package/dist/tests/HIUPD.test.js +11 -0
  92. package/dist/tests/HKIDN.test.js +22 -0
  93. package/dist/tests/HKSAL.test.js +45 -0
  94. package/dist/tests/HKTAN.test.js +21 -0
  95. package/dist/tests/HNSHK.test.js +11 -0
  96. package/dist/tests/HNVSK.test.js +11 -0
  97. package/dist/tests/client.test.js +33 -0
  98. package/dist/tests/datatypes.test.js +8 -0
  99. package/dist/tests/message.test.js +80 -0
  100. package/dist/tests/mt940parser.test.js +56 -0
  101. package/dist/tests/parser.test.js +20 -0
  102. package/dist/types/accountBalance.d.ts +9 -0
  103. package/dist/types/accountBalance.d.ts.map +1 -0
  104. package/dist/types/bankAccount.d.ts +27 -0
  105. package/dist/types/bankAccount.d.ts.map +1 -0
  106. package/dist/types/bankAnswer.d.ts +6 -0
  107. package/dist/types/bankAnswer.d.ts.map +1 -0
  108. package/dist/types/bankTransaction.d.ts +6 -0
  109. package/dist/types/bankTransaction.d.ts.map +1 -0
  110. package/dist/types/bankingInformation.d.ts +20 -0
  111. package/dist/types/bankingInformation.d.ts.map +1 -0
  112. package/dist/types/bpd.d.ts +17 -0
  113. package/dist/types/bpd.d.ts.map +1 -0
  114. package/dist/types/client.d.ts +86 -0
  115. package/dist/types/client.d.ts.map +1 -0
  116. package/dist/types/codes.d.ts +68 -0
  117. package/dist/types/codes.d.ts.map +1 -0
  118. package/dist/types/config.d.ts +99 -0
  119. package/dist/types/config.d.ts.map +1 -0
  120. package/dist/types/dataElements/AlphaNumeric.d.ts +8 -0
  121. package/dist/types/dataElements/AlphaNumeric.d.ts.map +1 -0
  122. package/dist/types/dataElements/Amount.d.ts +5 -0
  123. package/dist/types/dataElements/Amount.d.ts.map +1 -0
  124. package/dist/types/dataElements/Binary.d.ts +8 -0
  125. package/dist/types/dataElements/Binary.d.ts.map +1 -0
  126. package/dist/types/dataElements/Country.d.ts +5 -0
  127. package/dist/types/dataElements/Country.d.ts.map +1 -0
  128. package/dist/types/dataElements/Currency.d.ts +5 -0
  129. package/dist/types/dataElements/Currency.d.ts.map +1 -0
  130. package/dist/types/dataElements/Dat.d.ts +8 -0
  131. package/dist/types/dataElements/Dat.d.ts.map +1 -0
  132. package/dist/types/dataElements/DataElement.d.ts +14 -0
  133. package/dist/types/dataElements/DataElement.d.ts.map +1 -0
  134. package/dist/types/dataElements/Digits.d.ts +8 -0
  135. package/dist/types/dataElements/Digits.d.ts.map +1 -0
  136. package/dist/types/dataElements/Float.d.ts +8 -0
  137. package/dist/types/dataElements/Float.d.ts.map +1 -0
  138. package/dist/types/dataElements/Identification.d.ts +5 -0
  139. package/dist/types/dataElements/Identification.d.ts.map +1 -0
  140. package/dist/types/dataElements/Numeric.d.ts +9 -0
  141. package/dist/types/dataElements/Numeric.d.ts.map +1 -0
  142. package/dist/types/dataElements/Text.d.ts +8 -0
  143. package/dist/types/dataElements/Text.d.ts.map +1 -0
  144. package/dist/types/dataElements/Time.d.ts +8 -0
  145. package/dist/types/dataElements/Time.d.ts.map +1 -0
  146. package/dist/types/dataElements/YesNo.d.ts +7 -0
  147. package/dist/types/dataElements/YesNo.d.ts.map +1 -0
  148. package/dist/types/dataGroups/Account.d.ts +14 -0
  149. package/dist/types/dataGroups/Account.d.ts.map +1 -0
  150. package/dist/types/dataGroups/Balance.d.ts +12 -0
  151. package/dist/types/dataGroups/Balance.d.ts.map +1 -0
  152. package/dist/types/dataGroups/BankIdentification.d.ts +5 -0
  153. package/dist/types/dataGroups/BankIdentification.d.ts.map +1 -0
  154. package/dist/types/dataGroups/DataGroup.d.ts +10 -0
  155. package/dist/types/dataGroups/DataGroup.d.ts.map +1 -0
  156. package/dist/types/dataGroups/InternationalAccount.d.ts +13 -0
  157. package/dist/types/dataGroups/InternationalAccount.d.ts.map +1 -0
  158. package/dist/types/dataGroups/Money.d.ts +9 -0
  159. package/dist/types/dataGroups/Money.d.ts.map +1 -0
  160. package/dist/types/dataGroups/RefMessage.d.ts +9 -0
  161. package/dist/types/dataGroups/RefMessage.d.ts.map +1 -0
  162. package/dist/types/dataGroups/TimeStamp.d.ts +9 -0
  163. package/dist/types/dataGroups/TimeStamp.d.ts.map +1 -0
  164. package/dist/types/decoder.d.ts +4 -0
  165. package/dist/types/decoder.d.ts.map +1 -0
  166. package/dist/types/dialog.d.ts +21 -0
  167. package/dist/types/dialog.d.ts.map +1 -0
  168. package/dist/types/encoder.d.ts +3 -0
  169. package/dist/types/encoder.d.ts.map +1 -0
  170. package/dist/types/format.d.ts +3 -0
  171. package/dist/types/format.d.ts.map +1 -0
  172. package/dist/types/httpClient.d.ts +8 -0
  173. package/dist/types/httpClient.d.ts.map +1 -0
  174. package/dist/types/httpClientNode.d.ts +8 -0
  175. package/dist/types/httpClientNode.d.ts.map +1 -0
  176. package/dist/types/index.d.ts +17 -0
  177. package/dist/types/index.d.ts.map +1 -0
  178. package/dist/types/interactions/balanceInteraction.d.ts +15 -0
  179. package/dist/types/interactions/balanceInteraction.d.ts.map +1 -0
  180. package/dist/types/interactions/customerInteraction.d.ts +41 -0
  181. package/dist/types/interactions/customerInteraction.d.ts.map +1 -0
  182. package/dist/types/interactions/initDialogInteraction.d.ts +16 -0
  183. package/dist/types/interactions/initDialogInteraction.d.ts.map +1 -0
  184. package/dist/types/interactions/statementInteraction.d.ts +17 -0
  185. package/dist/types/interactions/statementInteraction.d.ts.map +1 -0
  186. package/dist/types/interactions/tanMediaInteraction.d.ts +13 -0
  187. package/dist/types/interactions/tanMediaInteraction.d.ts.map +1 -0
  188. package/dist/types/message.d.ts +30 -0
  189. package/dist/types/message.d.ts.map +1 -0
  190. package/dist/types/mt940parser.d.ts +83 -0
  191. package/dist/types/mt940parser.d.ts.map +1 -0
  192. package/dist/types/parser.d.ts +2 -0
  193. package/dist/types/parser.d.ts.map +1 -0
  194. package/dist/types/partedSegment.d.ts +14 -0
  195. package/dist/types/partedSegment.d.ts.map +1 -0
  196. package/dist/types/segment.d.ts +11 -0
  197. package/dist/types/segment.d.ts.map +1 -0
  198. package/dist/types/segmentDefinition.d.ts +11 -0
  199. package/dist/types/segmentDefinition.d.ts.map +1 -0
  200. package/dist/types/segmentHeader.d.ts +11 -0
  201. package/dist/types/segmentHeader.d.ts.map +1 -0
  202. package/dist/types/segments/HIBPA.d.ts +27 -0
  203. package/dist/types/segments/HIBPA.d.ts.map +1 -0
  204. package/dist/types/segments/HIKAZ.d.ts +16 -0
  205. package/dist/types/segments/HIKAZ.d.ts.map +1 -0
  206. package/dist/types/segments/HIKAZS.d.ts +16 -0
  207. package/dist/types/segments/HIKAZS.d.ts.map +1 -0
  208. package/dist/types/segments/HIKIM.d.ts +17 -0
  209. package/dist/types/segments/HIKIM.d.ts.map +1 -0
  210. package/dist/types/segments/HIKOM.d.ts +27 -0
  211. package/dist/types/segments/HIKOM.d.ts.map +1 -0
  212. package/dist/types/segments/HIPINS.d.ts +23 -0
  213. package/dist/types/segments/HIPINS.d.ts.map +1 -0
  214. package/dist/types/segments/HIRMG.d.ts +22 -0
  215. package/dist/types/segments/HIRMG.d.ts.map +1 -0
  216. package/dist/types/segments/HIRMS.d.ts +17 -0
  217. package/dist/types/segments/HIRMS.d.ts.map +1 -0
  218. package/dist/types/segments/HISAL.d.ts +32 -0
  219. package/dist/types/segments/HISAL.d.ts.map +1 -0
  220. package/dist/types/segments/HISYN.d.ts +19 -0
  221. package/dist/types/segments/HISYN.d.ts.map +1 -0
  222. package/dist/types/segments/HITAB.d.ts +39 -0
  223. package/dist/types/segments/HITAB.d.ts.map +1 -0
  224. package/dist/types/segments/HITAN.d.ts +25 -0
  225. package/dist/types/segments/HITAN.d.ts.map +1 -0
  226. package/dist/types/segments/HITANS.d.ts +41 -0
  227. package/dist/types/segments/HITANS.d.ts.map +1 -0
  228. package/dist/types/segments/HIUPA.d.ts +21 -0
  229. package/dist/types/segments/HIUPA.d.ts.map +1 -0
  230. package/dist/types/segments/HIUPD.d.ts +42 -0
  231. package/dist/types/segments/HIUPD.d.ts.map +1 -0
  232. package/dist/types/segments/HKEND.d.ts +16 -0
  233. package/dist/types/segments/HKEND.d.ts.map +1 -0
  234. package/dist/types/segments/HKIDN.d.ts +22 -0
  235. package/dist/types/segments/HKIDN.d.ts.map +1 -0
  236. package/dist/types/segments/HKKAZ.d.ts +25 -0
  237. package/dist/types/segments/HKKAZ.d.ts.map +1 -0
  238. package/dist/types/segments/HKSAL.d.ts +22 -0
  239. package/dist/types/segments/HKSAL.d.ts.map +1 -0
  240. package/dist/types/segments/HKSYN.d.ts +17 -0
  241. package/dist/types/segments/HKSYN.d.ts.map +1 -0
  242. package/dist/types/segments/HKTAB.d.ts +19 -0
  243. package/dist/types/segments/HKTAB.d.ts.map +1 -0
  244. package/dist/types/segments/HKTAN.d.ts +39 -0
  245. package/dist/types/segments/HKTAN.d.ts.map +1 -0
  246. package/dist/types/segments/HKVVB.d.ts +22 -0
  247. package/dist/types/segments/HKVVB.d.ts.map +1 -0
  248. package/dist/types/segments/HNHBK.d.ts +23 -0
  249. package/dist/types/segments/HNHBK.d.ts.map +1 -0
  250. package/dist/types/segments/HNHBS.d.ts +16 -0
  251. package/dist/types/segments/HNHBS.d.ts.map +1 -0
  252. package/dist/types/segments/HNSHA.d.ts +24 -0
  253. package/dist/types/segments/HNSHA.d.ts.map +1 -0
  254. package/dist/types/segments/HNSHK.d.ts +66 -0
  255. package/dist/types/segments/HNSHK.d.ts.map +1 -0
  256. package/dist/types/segments/HNVSD.d.ts +20 -0
  257. package/dist/types/segments/HNVSD.d.ts.map +1 -0
  258. package/dist/types/segments/HNVSK.d.ts +40 -0
  259. package/dist/types/segments/HNVSK.d.ts.map +1 -0
  260. package/dist/types/segments/businessTransactionParameter.d.ts +18 -0
  261. package/dist/types/segments/businessTransactionParameter.d.ts.map +1 -0
  262. package/dist/types/segments/registry.d.ts +4 -0
  263. package/dist/types/segments/registry.d.ts.map +1 -0
  264. package/dist/types/tanMethod.d.ts +10 -0
  265. package/dist/types/tanMethod.d.ts.map +1 -0
  266. package/dist/types/tests/HIBPA.test.d.ts +2 -0
  267. package/dist/types/tests/HIBPA.test.d.ts.map +1 -0
  268. package/dist/types/tests/HIPINS.test.d.ts +2 -0
  269. package/dist/types/tests/HIPINS.test.d.ts.map +1 -0
  270. package/dist/types/tests/HIRMG.test.d.ts +2 -0
  271. package/dist/types/tests/HIRMG.test.d.ts.map +1 -0
  272. package/dist/types/tests/HITAB.test.d.ts +2 -0
  273. package/dist/types/tests/HITAB.test.d.ts.map +1 -0
  274. package/dist/types/tests/HITANS.test.d.ts +2 -0
  275. package/dist/types/tests/HITANS.test.d.ts.map +1 -0
  276. package/dist/types/tests/HIUPA.test.d.ts +2 -0
  277. package/dist/types/tests/HIUPA.test.d.ts.map +1 -0
  278. package/dist/types/tests/HIUPD.test.d.ts +2 -0
  279. package/dist/types/tests/HIUPD.test.d.ts.map +1 -0
  280. package/dist/types/tests/HKIDN.test.d.ts +2 -0
  281. package/dist/types/tests/HKIDN.test.d.ts.map +1 -0
  282. package/dist/types/tests/HKSAL.test.d.ts +2 -0
  283. package/dist/types/tests/HKSAL.test.d.ts.map +1 -0
  284. package/dist/types/tests/HKTAN.test.d.ts +2 -0
  285. package/dist/types/tests/HKTAN.test.d.ts.map +1 -0
  286. package/dist/types/tests/HNSHK.test.d.ts +2 -0
  287. package/dist/types/tests/HNSHK.test.d.ts.map +1 -0
  288. package/dist/types/tests/HNVSK.test.d.ts +2 -0
  289. package/dist/types/tests/HNVSK.test.d.ts.map +1 -0
  290. package/dist/types/tests/client.test.d.ts +2 -0
  291. package/dist/types/tests/client.test.d.ts.map +1 -0
  292. package/dist/types/tests/datatypes.test.d.ts +2 -0
  293. package/dist/types/tests/datatypes.test.d.ts.map +1 -0
  294. package/dist/types/tests/message.test.d.ts +2 -0
  295. package/dist/types/tests/message.test.d.ts.map +1 -0
  296. package/dist/types/tests/mt940parser.test.d.ts +2 -0
  297. package/dist/types/tests/mt940parser.test.d.ts.map +1 -0
  298. package/dist/types/tests/parser.test.d.ts +2 -0
  299. package/dist/types/tests/parser.test.d.ts.map +1 -0
  300. package/dist/types/unknownSegment.d.ts +14 -0
  301. package/dist/types/unknownSegment.d.ts.map +1 -0
  302. package/dist/types/upd.d.ts +8 -0
  303. package/dist/types/upd.d.ts.map +1 -0
  304. package/dist/unknownSegment.js +8 -0
  305. package/dist/upd.js +1 -0
  306. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # Lib-FinTS
2
+
3
+ A Typescript/Javascript client library for Online-Banking via the FinTS 3.0 protocol with PIN/TAN. The library has no dependencies on other libraries
4
+
5
+ ## Getting Started
6
+
7
+ These instructions will show you how to install the library on your local machine and give a quick sample of how to use the library
8
+
9
+ ### Prerequisites
10
+
11
+ #### Product Registration
12
+
13
+ In order to communicate with banks via the FinTS protocol you have to register a product ID with the german banking industry (Deutsche Kreditwirtschaft) which you need to pass as part of the configuration to the client:
14
+
15
+ > In order to fulfill the PSD2 requirements regarding transparency about the software used by customers, the German Banking Industry has established a process for registering FinTS products in order to be able to provide customers with information regarding FinTS usage.
16
+ > FinTS product registration is currently offered free of charge by the German Banking Industry.
17
+
18
+ [ZKA Registration Website](https://www.hbci-zka.de/register/prod_register.htm)
19
+
20
+ ### Runtime Environment
21
+
22
+ The library is written in Typescript and compiled to the ES2022 Javascript language standard which means a minimum Node version of 18 is required.
23
+
24
+ **A note about Browsers:**
25
+ It wouldn't be hard to make the code compatible with a browser environment, but communicating directly from the front-end with a bank server will most likely fail because of the imposed CORS restrictions from web browsers and the lack of corresponding CORS headers in bank server responses.
26
+
27
+ ### Installing
28
+
29
+ Installation is straight forward by simply adding the npm package. The package has no further dependencies on other packages.
30
+
31
+ ```
32
+ npm i lib-fints
33
+ ```
34
+
35
+ ### Sample Usage
36
+
37
+ The main public API of this library is the `FinTSClient` class and `FinTSConfig` class. In order to instantiate the client you need to provide a configration instance. There are basically two ways to initialize a configuration object, one is when you communicate with a bank for the first time and the other when you already have banking information from a prevous session available (more on that later).
38
+
39
+ If you don't have any previous banking information available you can use the static `forFirstTimeUse()` factory method like this:
40
+
41
+ ```typescript
42
+ const config = FinTSConfig.forFirstTimeUse(productId, productVersion, bankUrl, bankId, userId, pin);
43
+
44
+ const client = new FinTSClient(config);
45
+ ```
46
+
47
+ Then you should first make a synchronization call to get banking and account information:
48
+
49
+ ```typescript
50
+ let syncResponse = await client.synchronize();
51
+ ```
52
+
53
+ you should always check the `success` and `requiresTan` properties of any response object because other data might only be available when `success=true` and `requiresTan=false`.
54
+ in any case you can also check the `bankAnswers` array for return messages from the bank which may contain the reasons for a failed request.
55
+
56
+ If the call is successfull the response will contain a `bankingInformation` object filled with all the relevant information provided by the bank from synchronization:
57
+
58
+ ```typescript
59
+ export type BankingInformation = {
60
+ systemId: string;
61
+ bpd?: BPD;
62
+ upd?: UPD;
63
+ bankMessages: BankMessage[];
64
+ };
65
+ ```
66
+
67
+ The BPD object (_BankParameterDaten_) contains general information (e.g. available TAN methods and allowed transactions) and the UPD object (_UserParameterDaten_) user-specific information which is mainly the list of the user's bank accounts.
68
+
69
+ Unfortunately with this first synchronization call most banks will most likely only return most of the BPA information but no UPD (accounts) information, which is needed to fetch balances or statements. The reason for this is that you need to specify a TAN method before making the synchronization call, but how would you know which TAN methods are available and how to specify them? This is why you need to make a second synchronization call with a TAN method selected from the `availableTanMethodIds`in the BPA, returned from the first synchronization call:
70
+
71
+ ```typescript
72
+ // for simplicity, we just select the first available TAN method
73
+ client.selectTanMethod(syncResponse.bankingInformation.BPD.availableTanMethodIds[0]);
74
+ ```
75
+
76
+ now you can repeat the syncronization call from above and it will return additional data including the UPD with the account information.
77
+
78
+ Finally you can start fetching balances or statements:
79
+
80
+ ```typescript
81
+ // for simplicity, use the first account
82
+ const account = syncResponse.bankingInformation.upd.bankAccounts[0];
83
+
84
+ // fetch the current balance
85
+ const balanceResponse = await client.getAccountBalance(account.accountNumber);
86
+
87
+ // fetch all available statements
88
+ const statementResponse = await client.getAccountStatements(account.accountNumber);
89
+ ```
90
+
91
+ These are only the most basic steps needed to retrieve information from the bank. It kept many questions unanswered like "how to handle TANs" or "how to avoid synchronizations every time you start a new session". These are explained in the corresponding sections below.
92
+
93
+ ## More detailed API Description
94
+
95
+ ### Handle TAN challenges from the bank
96
+
97
+ Most transactions may require authorization with a two step TAN process. As mentioned above in the sample, every response may set the `requiresTan`property to `true` which means that the response does not include the expected transaction data, but some additional TAN related properties. You first need to handle this TAN challenge by asking the user for the TAN and sending it back to the bank to continue the process and retrieve the actual transaction result:
98
+
99
+ ```typescript
100
+ // we use the node readline interface later to ask the user for a TAN
101
+ const rl = readline.createInterface({
102
+ input: process.stdin,
103
+ output: process.stdout,
104
+ });
105
+
106
+ let response = await client.getAccountStatements(account.accountNumber);
107
+
108
+ if (!response.success) {
109
+ return;
110
+ }
111
+
112
+ // need to check if a TAN is required to continue the transaction
113
+ if (response.requiresTan) {
114
+ // asking the user for the TAN, using the tanChallenge property
115
+ const tan = await rl.question(response.tanChallenge + ': ');
116
+ // continue the transaction by providing the tanReference from the response and the entered TAN
117
+ response = await client.getAccountStatementsWithTan(response.tanReference!, tan);
118
+ }
119
+ ```
120
+
121
+ The `FinTSClient`contains for every transaction method like `synchronize()` or `getAccountStatements()` a corresponding `...WithTan()` method which needs to be called to continue the transaction with the given `tanReference` returned in the first response. The response object of this second call should now contain all transaction related data, assuming `success=true`.
122
+
123
+ ### Starting a session from saved banking information
124
+
125
+ As mentioned earlier there is a second way to initialize the `FinTSClient` with a `FinTSConfig` when you already performed a synchronization in a previous session and this is by providing the `bankingInformation` object received from previous uses. This `bankingInformation` object, which contains the general bank (BPD) and accounts information (UPD), should be persisted after a session and reloaded in the next session.
126
+ This not only saves you from making the same synchronization requests every time before making a transaction, but the sychronization will also assign a `systemId` (a property in `bankingInformation`) to your client which should stay the same once assigned.
127
+
128
+ ```typescript
129
+ const config = FinTSConfig.fromBankingInformation(
130
+ productId,
131
+ productVersion,
132
+ bankingInformation,
133
+ userId,
134
+ pin,
135
+ tanMethodId,
136
+ tanMediaName // when also needed (see below)
137
+ );
138
+ const client = new FinTSClient(config);
139
+ ```
140
+
141
+ You should also set the TAN method to use, by using the optional `tanMethodId` and `tanMediaName` parameters or calling `client.selectTanMethod()` before making the first transaction.
142
+
143
+ #### Tan Media
144
+
145
+ It might be the case that you have more than one active TAN media available (like multiple mobile phones) and the bank requires you to also specify which TAN media to use.
146
+ You can find out if this is the case by inspecting the `TanMethod` object in the BPD.
147
+ You can get a list of all available TAN methods from the `config.availableTanMethods` property or if you already selected a TAN method with `config.selectedTanMethod`.
148
+
149
+ ```typescript
150
+ export type TanMethod = {
151
+ id: number;
152
+ name: string;
153
+ version: number;
154
+ activeTanMediaCount: number;
155
+ activeTanMedia: string[];
156
+ tanMediaRequirement: TanMediaRequirement;
157
+ };
158
+ ```
159
+
160
+ The `TanMethod` object contains a property `tanMediaRequirement` and if this is set to `TanMediaRequirement.Required`, you also need to select a TAN media, either by providing the name in the configuration factory method `FinTSConfig.fromBankingInformation()` or by using `client.selectTanMedia()`.
161
+
162
+ The property `activeTanMedia` contains a list of the TAN media names you can use for selection.
163
+
164
+ #### Banking Information may be updated any time
165
+
166
+ The `bankingInformation` is primarily obtained by the `synchronize()` calls as seen above. But what if the banking information changed since the last synchronization call and how would you know? For this reason the BPD and UPD are versioned and with every transaction made, not just synchronizations, the currently used versions are provided to the bank and if something changed, the bank will sent back new versions of the BPD and UPD respectively. This is all handled by the client but you need to check the `bankingInformationUpdated` property, which is available in every response, which tells you if there were changes and make sure to persist the new version for future sessions. You can always get the up-to-date version of the `bankingInformation` object with `config.bankingInformation`.
167
+
168
+ ### Debugging
169
+
170
+ If you need to debug issues and the `response.bankAnswers` don't provide enough information, you can enable debugging of messages with:
171
+
172
+ ```typescript
173
+ config.debugEnabled = true;
174
+ ```
175
+
176
+ This will print out all sent messages and received responses to the console in a structured format.
177
+
178
+ ## Limitations
179
+
180
+ - Only FinTS 3.0 is supported (older versions may not work)
181
+ - Only PIN/TAN security is supported
182
+ - Currently only the following transactions are supported:
183
+ - Synchronize bank and account information
184
+ - Fetching account balances
185
+ - Fetching account statements
186
+
187
+ Implementing further transactions should be straight forward and contributions are highly appreciated
188
+
189
+ ### Successfully tested with the following banks
190
+
191
+ - DKB
192
+ - ING-DiBa
193
+ - Renault Bank Direkt
194
+
195
+ ## Built With
196
+
197
+ - [Typescript](https://www.typescriptlang.org/) - Programming Language
198
+ - [Vitest](https://vitest.dev/) - Testing Framework
199
+ - [pnpm](https://pnpm.io/) - Package manager
200
+
201
+ ## Contributing
202
+
203
+ Feel free to create an issue if you want to report a bug.
204
+
205
+ If you tested this library with some other bank it would be great to hear from you and update the information on this page
206
+
207
+ As this is a free-time project, a lot of things are still remaining which could be added to this library, especially other kinds of transactions. If you want to contribute with pull-requests this would be highly appreciated
208
+
209
+ ## License
210
+
211
+ This project is licensed under the LGPL 3.0 License - see the [LICENSE.md](LICENSE.md) file for details
212
+
213
+ ## References
214
+
215
+ - [Product Registration](https://www.hbci-zka.de/register/prod_register.htm)
216
+ - [FinTS 3.0 Specification](https://www.hbci-zka.de/spec/3_0.htm)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ export var AccountType;
2
+ (function (AccountType) {
3
+ AccountType["CheckingAccount"] = "CheckingAccount";
4
+ AccountType["SavingsAccount"] = "SavingsAccount";
5
+ AccountType["FixedDepositAccount"] = "FixedDepositAccount";
6
+ AccountType["SecuritiesAccount"] = "SecuritiesAccount";
7
+ AccountType["LoanMortgageAccount"] = "LoanMortgageAccount";
8
+ AccountType["CreditCardAccount"] = "CreditCardAccount";
9
+ AccountType["InvestmentCompanyFund"] = "InvestmentCompanyFund";
10
+ AccountType["HomeSavingsContract"] = "HomeSavingsContract";
11
+ AccountType["InsurancePolicy"] = "InsurancePolicy";
12
+ AccountType["Miscellaneous"] = "Miscellaneous";
13
+ })(AccountType || (AccountType = {}));
14
+ export function finTsAccountTypeToEnum(accountType) {
15
+ if (accountType >= 1 && accountType <= 9)
16
+ return AccountType.CheckingAccount;
17
+ if (accountType >= 10 && accountType <= 19)
18
+ return AccountType.SavingsAccount;
19
+ if (accountType >= 20 && accountType <= 29)
20
+ return AccountType.FixedDepositAccount;
21
+ if (accountType >= 30 && accountType <= 39)
22
+ return AccountType.SecuritiesAccount;
23
+ if (accountType >= 40 && accountType <= 49)
24
+ return AccountType.LoanMortgageAccount;
25
+ if (accountType >= 50 && accountType <= 59)
26
+ return AccountType.CreditCardAccount;
27
+ if (accountType >= 60 && accountType <= 69)
28
+ return AccountType.InvestmentCompanyFund;
29
+ if (accountType >= 70 && accountType <= 79)
30
+ return AccountType.HomeSavingsContract;
31
+ if (accountType >= 80 && accountType <= 89)
32
+ return AccountType.InsurancePolicy;
33
+ return AccountType.Miscellaneous;
34
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/bpd.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/client.js ADDED
@@ -0,0 +1,165 @@
1
+ import { Dialog } from './dialog.js';
2
+ import { HKTAB } from './segments/HKTAB.js';
3
+ import { StatementInteraction } from './interactions/statementInteraction.js';
4
+ import { BalanceInteraction } from './interactions/balanceInteraction.js';
5
+ import { FinTSConfig } from './config.js';
6
+ import { InitDialogInteraction } from './interactions/initDialogInteraction.js';
7
+ import { TanMediaInteraction } from './interactions/tanMediaInteraction.js';
8
+ import { HKSAL } from './segments/HKSAL.js';
9
+ import { HKKAZ } from './segments/HKKAZ.js';
10
+ /**
11
+ * A client to communicate with a bank over the FinTS protocol
12
+ */
13
+ export class FinTSClient {
14
+ config;
15
+ openCustomerInteractions = new Map();
16
+ /**
17
+ * Creates a new FinTS client
18
+ * @param config - the configuration for the client, use the static factory methods FinTSConfig.forFirstTimeUse or FinTSConfig.fromBankingInformation to create a configuration
19
+ */
20
+ constructor(config) {
21
+ this.config = config;
22
+ if (!config) {
23
+ throw new Error('configuration must be provided when creating a FinTSClient');
24
+ }
25
+ if (!(config instanceof FinTSConfig)) {
26
+ throw new Error('configuration must be an instance of class FinTSConfig');
27
+ }
28
+ }
29
+ /**
30
+ * Selects a TAN method by its ID
31
+ * @param tanMethodId - the ID of the TAN method to select, get the ID from FinTSClient.config.availableTanMethods
32
+ * @returns the selected TAN method
33
+ */
34
+ selectTanMethod(tanMethodId) {
35
+ this.config.selectTanMethod(tanMethodId);
36
+ return this.config.selectedTanMethod;
37
+ }
38
+ /**
39
+ * Selects a TAN media by its name
40
+ * @param tanMediaName - the name of the TAN media to select corresponding to a name in TanMethod.activeTanMedia
41
+ */
42
+ selectTanMedia(tanMediaName) {
43
+ this.config.selectTanMedia(tanMediaName);
44
+ }
45
+ /**
46
+ * Synchronizes information with the bank, updating config.bankingInformation
47
+ * @returns the synchronization response
48
+ */
49
+ async synchronize() {
50
+ const dialog = new Dialog(this.config);
51
+ const syncResponse = await this.initDialog(dialog, true);
52
+ if (!syncResponse.success || syncResponse.requiresTan) {
53
+ return syncResponse;
54
+ }
55
+ if (this.config.selectedTanMethod && this.config.isTransactionSupported(HKTAB.Id)) {
56
+ const tanMediaResponse = await dialog.startCustomerOrderInteraction(new TanMediaInteraction());
57
+ let tanMethod = this.config.selectedTanMethod;
58
+ if (tanMethod) {
59
+ tanMethod.activeTanMedia = tanMediaResponse.tanMediaList;
60
+ }
61
+ syncResponse.bankAnswers.push(...tanMediaResponse.bankAnswers);
62
+ }
63
+ await dialog.end();
64
+ return syncResponse;
65
+ }
66
+ /**
67
+ * Continues the synchronization transaction when a TAN is required
68
+ * @param tanReference The TAN reference provided in the first call's response
69
+ * @param tan The TAN entered by the user
70
+ * @returns the synchronization response
71
+ */
72
+ async synchronizeWithTan(tanReference, tan) {
73
+ return this.continueCustomerInteractionWithTan(tanReference, tan);
74
+ }
75
+ /**
76
+ * Checks if the bank supports fetching an account balance in general or for the given account number when provided
77
+ * @param accountNumber when the account number is provided, checks if the account supports fetching the balance
78
+ * @returns true if the bank (and account) supports fetching the account balance
79
+ */
80
+ canGetAccountBalance(accountNumber) {
81
+ return accountNumber
82
+ ? this.config.isAccountTransactionSupported(accountNumber, HKSAL.Id)
83
+ : this.config.isTransactionSupported(HKSAL.Id);
84
+ }
85
+ /**
86
+ * Fetches the account balance for the given account number
87
+ * @param accountNumber - the account number to fetch the balance for, must be an account available in the config.baningInformation.UPD.accounts
88
+ * @returns the account balance response
89
+ */
90
+ async getAccountBalance(accountNumber) {
91
+ return this.startCustomerOrderInteraction(new BalanceInteraction(accountNumber));
92
+ }
93
+ /**
94
+ * Continues the account balance fetching when a TAN is required
95
+ * @param tanReference The TAN reference provided in the first call's response
96
+ * @param tan The TAN entered by the user
97
+ * @returns the account balance response
98
+ */
99
+ async getAccountBalanceWithTan(tanReference, tan) {
100
+ return this.continueCustomerInteractionWithTan(tanReference, tan);
101
+ }
102
+ /**
103
+ * Checks if the bank supports fetching account statements in general or for the given account number when provided
104
+ * @param accountNumber when the account number is provided, checks if the account supports fetching of statements
105
+ * @returns true if the bank (and account) supports fetching account statements
106
+ */
107
+ canGetAccountStatements(accountNumber) {
108
+ return accountNumber
109
+ ? this.config.isAccountTransactionSupported(accountNumber, HKKAZ.Id)
110
+ : this.config.isTransactionSupported(HKKAZ.Id);
111
+ }
112
+ /**
113
+ * Fetches the account statements for the given account number
114
+ * @param accountNumber - the account number to fetch the statements for, must be an account available in the config.baningInformation.UPD.accounts
115
+ * @param from - an optional start date of the period to fetch the statements for
116
+ * @param to - an optional end date of the period to fetch the statements for
117
+ * @returns an account statements response containing an array of statements
118
+ */
119
+ async getAccountStatements(accountNumber, from, to) {
120
+ return this.startCustomerOrderInteraction(new StatementInteraction(accountNumber, from, to));
121
+ }
122
+ /**
123
+ * Continues the account statements fetching when a TAN is required
124
+ * @param tanReference The TAN reference provided in the first call's response
125
+ * @param tan The TAN entered by the user
126
+ * @returns an account statements response containing an array of statements
127
+ */
128
+ async getAccountStatementsWithTan(tanReference, tan) {
129
+ return this.continueCustomerInteractionWithTan(tanReference, tan);
130
+ }
131
+ async startCustomerOrderInteraction(interaction) {
132
+ const dialog = new Dialog(this.config);
133
+ const syncResponse = await this.initDialog(dialog);
134
+ if (!syncResponse.success || syncResponse.requiresTan) {
135
+ return syncResponse;
136
+ }
137
+ const clientResponse = await dialog.startCustomerOrderInteraction(interaction);
138
+ if (clientResponse.requiresTan) {
139
+ this.openCustomerInteractions.set(clientResponse.tanReference, interaction);
140
+ }
141
+ else {
142
+ await dialog.end();
143
+ }
144
+ return clientResponse;
145
+ }
146
+ async continueCustomerInteractionWithTan(tanReference, tan) {
147
+ const interaction = this.openCustomerInteractions.get(tanReference);
148
+ if (!interaction) {
149
+ throw new Error('No open customer interaction found for TAN reference: ' + tanReference);
150
+ }
151
+ const dialog = interaction.dialog;
152
+ const response = await dialog.sendTanMessage(interaction.segId, tanReference, tan);
153
+ await dialog.end();
154
+ this.openCustomerInteractions.delete(tanReference);
155
+ return interaction.getClientResponse(response);
156
+ }
157
+ async initDialog(dialog, syncSystemId = false) {
158
+ const interaction = new InitDialogInteraction(this.config, syncSystemId);
159
+ const initResponse = await dialog.initialize(interaction);
160
+ if (initResponse.requiresTan) {
161
+ this.openCustomerInteractions.set(initResponse.tanReference, interaction);
162
+ }
163
+ return initResponse;
164
+ }
165
+ }
package/dist/codes.js ADDED
@@ -0,0 +1,79 @@
1
+ export var Language;
2
+ (function (Language) {
3
+ Language[Language["Default"] = 0] = "Default";
4
+ Language[Language["German"] = 1] = "German";
5
+ Language[Language["English"] = 2] = "English";
6
+ Language[Language["French"] = 3] = "French";
7
+ })(Language || (Language = {}));
8
+ export var Service;
9
+ (function (Service) {
10
+ Service[Service["Tonline"] = 1] = "Tonline";
11
+ Service[Service["TcpIp"] = 2] = "TcpIp";
12
+ Service[Service["Https"] = 3] = "Https";
13
+ })(Service || (Service = {}));
14
+ export var HashAlgorithm;
15
+ (function (HashAlgorithm) {
16
+ HashAlgorithm[HashAlgorithm["SHA1"] = 1] = "SHA1";
17
+ HashAlgorithm[HashAlgorithm["SHA256"] = 3] = "SHA256";
18
+ HashAlgorithm[HashAlgorithm["SHA384"] = 4] = "SHA384";
19
+ HashAlgorithm[HashAlgorithm["SHA512"] = 5] = "SHA512";
20
+ HashAlgorithm[HashAlgorithm["SHA256_256"] = 6] = "SHA256_256";
21
+ })(HashAlgorithm || (HashAlgorithm = {}));
22
+ export var SyncMode;
23
+ (function (SyncMode) {
24
+ SyncMode[SyncMode["NewSystemId"] = 0] = "NewSystemId";
25
+ SyncMode[SyncMode["LastProcessedMsgNr"] = 1] = "LastProcessedMsgNr";
26
+ SyncMode[SyncMode["SignatureId"] = 2] = "SignatureId";
27
+ })(SyncMode || (SyncMode = {}));
28
+ export var LimitType;
29
+ (function (LimitType) {
30
+ LimitType["SingleOrder"] = "E";
31
+ LimitType["Day"] = "T";
32
+ LimitType["Week"] = "W";
33
+ LimitType["Month"] = "M";
34
+ LimitType["Time"] = "Z";
35
+ })(LimitType || (LimitType = {}));
36
+ export var UpdUsage;
37
+ (function (UpdUsage) {
38
+ UpdUsage[UpdUsage["MissingNotAllowed"] = 0] = "MissingNotAllowed";
39
+ UpdUsage[UpdUsage["MissingUnknown"] = 1] = "MissingUnknown";
40
+ })(UpdUsage || (UpdUsage = {}));
41
+ export var CreditDebit;
42
+ (function (CreditDebit) {
43
+ CreditDebit["Credit"] = "C";
44
+ CreditDebit["Debit"] = "D";
45
+ })(CreditDebit || (CreditDebit = {}));
46
+ export var TanMediaType;
47
+ (function (TanMediaType) {
48
+ TanMediaType[TanMediaType["All"] = 0] = "All";
49
+ TanMediaType[TanMediaType["Active"] = 1] = "Active";
50
+ TanMediaType[TanMediaType["Available"] = 2] = "Available";
51
+ })(TanMediaType || (TanMediaType = {}));
52
+ export var TanMediaClass;
53
+ (function (TanMediaClass) {
54
+ TanMediaClass["All"] = "A";
55
+ TanMediaClass["List"] = "L";
56
+ TanMediaClass["TanGenerator"] = "G";
57
+ TanMediaClass["Mobile"] = "M";
58
+ TanMediaClass["Secoder"] = "S";
59
+ TanMediaClass["Bilateral"] = "B";
60
+ })(TanMediaClass || (TanMediaClass = {}));
61
+ export var TanMediaRequirement;
62
+ (function (TanMediaRequirement) {
63
+ TanMediaRequirement[TanMediaRequirement["NotAllowed"] = 0] = "NotAllowed";
64
+ TanMediaRequirement[TanMediaRequirement["Optional"] = 1] = "Optional";
65
+ TanMediaRequirement[TanMediaRequirement["Required"] = 2] = "Required";
66
+ })(TanMediaRequirement || (TanMediaRequirement = {}));
67
+ export var TanStatus;
68
+ (function (TanStatus) {
69
+ TanStatus[TanStatus["Active"] = 1] = "Active";
70
+ TanStatus[TanStatus["Available"] = 2] = "Available";
71
+ TanStatus[TanStatus["ActiveFollowUpCard"] = 3] = "ActiveFollowUpCard";
72
+ TanStatus[TanStatus["AvailableFollowUpCard"] = 4] = "AvailableFollowUpCard";
73
+ })(TanStatus || (TanStatus = {}));
74
+ export var TanUsage;
75
+ (function (TanUsage) {
76
+ TanUsage[TanUsage["All"] = 0] = "All";
77
+ TanUsage[TanUsage["Single"] = 1] = "Single";
78
+ TanUsage[TanUsage["MobileAndGenerator"] = 2] = "MobileAndGenerator";
79
+ })(TanUsage || (TanUsage = {}));