@develit-services/bank 0.0.13 → 0.0.15

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 (29) hide show
  1. package/dist/database/schema.d.cts +1 -1
  2. package/dist/database/schema.d.mts +1 -1
  3. package/dist/database/schema.d.ts +1 -1
  4. package/dist/export/worker.cjs +42 -24
  5. package/dist/export/worker.d.cts +5 -4
  6. package/dist/export/worker.d.mts +5 -4
  7. package/dist/export/worker.d.ts +5 -4
  8. package/dist/export/worker.mjs +43 -25
  9. package/dist/export/wrangler.d.cts +4 -3
  10. package/dist/export/wrangler.d.mts +4 -3
  11. package/dist/export/wrangler.d.ts +4 -3
  12. package/dist/shared/{bank.BYxCT5rk.d.ts → bank.BlmUZQ6s.d.cts} +20 -8
  13. package/dist/shared/{bank.DxGqqFhD.d.cts → bank.CJFy17-g.d.cts} +3 -1
  14. package/dist/shared/{bank.DxGqqFhD.d.mts → bank.CJFy17-g.d.mts} +3 -1
  15. package/dist/shared/{bank.DxGqqFhD.d.ts → bank.CJFy17-g.d.ts} +3 -1
  16. package/dist/shared/{bank.BU2_AKRG.cjs → bank.Ce58djRL.cjs} +500 -320
  17. package/dist/shared/{bank.TOYdvcg7.mjs → bank.DZS4d3MJ.mjs} +498 -322
  18. package/dist/shared/{bank.CBNQZ5Pd.d.cts → bank.DiMNzl60.d.cts} +8 -6
  19. package/dist/shared/{bank.CBNQZ5Pd.d.mts → bank.DiMNzl60.d.mts} +8 -6
  20. package/dist/shared/{bank.CBNQZ5Pd.d.ts → bank.DiMNzl60.d.ts} +8 -6
  21. package/dist/shared/{bank.BULPVep1.d.cts → bank.j2Z-uViN.d.ts} +20 -8
  22. package/dist/shared/{bank.Dxfp5h5B.d.mts → bank.tyFkXmr8.d.mts} +20 -8
  23. package/dist/{@types.cjs → types.cjs} +8 -3
  24. package/dist/{@types.d.cts → types.d.cts} +142 -22
  25. package/dist/{@types.d.mts → types.d.mts} +142 -22
  26. package/dist/{@types.d.ts → types.d.ts} +142 -22
  27. package/dist/types.mjs +11 -0
  28. package/package.json +4 -4
  29. package/dist/@types.mjs +0 -10
@@ -1,10 +1,11 @@
1
- import { createInternalError, useResult, uuidv4 } from '@develit-io/backend-sdk';
1
+ import { uuidv4, useResult, createInternalError } from '@develit-io/backend-sdk';
2
2
  import { s as schema } from './bank.BeH-ZCJJ.mjs';
3
3
  import { and, eq } from 'drizzle-orm';
4
- import { format, parseISO } from 'date-fns';
5
- import { importPKCS8, SignJWT } from 'jose';
6
- import { COUNTRY_CODES_2, CURRENCY_CODES } from '@develit-io/general-codes';
7
4
  import { z } from 'zod';
5
+ import { COUNTRY_CODES_2, CURRENCY_CODES } from '@develit-io/general-codes';
6
+ import { importPKCS8, SignJWT } from 'jose';
7
+ import 'superjson';
8
+ import { format, parseISO } from 'date-fns';
8
9
 
9
10
  const tables = schema;
10
11
 
@@ -32,12 +33,102 @@ const COUNTRY_CODES = COUNTRY_CODES_2;
32
33
  class IBankConnector {
33
34
  }
34
35
 
35
- const isDeposit = (payment, creditorIban) => {
36
- return payment.creditorIban === creditorIban;
36
+ async function signFinbricksJws({
37
+ privateKeyPem,
38
+ merchantId,
39
+ jwsData
40
+ }) {
41
+ const privateKey = await importPKCS8(privateKeyPem, "RS256");
42
+ const payload = JSON.stringify(jwsData);
43
+ const jws = await new SignJWT(JSON.parse(payload)).setProtectedHeader({
44
+ alg: "RS256",
45
+ kid: merchantId,
46
+ typ: "JWT"
47
+ }).sign(privateKey);
48
+ const [header, , signature] = jws.split(".");
49
+ return `${header}..${signature}`;
50
+ }
51
+
52
+ const useFinbricksFetch = async (config, init) => {
53
+ const {
54
+ baseUrl,
55
+ endpoint,
56
+ method = "GET",
57
+ merchantId,
58
+ privateKeyPem,
59
+ query,
60
+ body,
61
+ correlationId,
62
+ psuIp = "88.205.47.1",
63
+ psuAgent = "Develit/BankService"
64
+ } = config;
65
+ const url = new URL(`${baseUrl}${endpoint}`);
66
+ if (query) {
67
+ for (const [k, v] of Object.entries(query)) {
68
+ if (v !== void 0 && v !== null)
69
+ url.searchParams.append(k, v.toString());
70
+ }
71
+ }
72
+ const uriWithQuery = `${endpoint}${url.search ? `?${url.searchParams.toString()}` : ""}`;
73
+ const bodyString = body ? JSON.stringify(body) : "";
74
+ const jwsSignature = await signFinbricksJws({
75
+ privateKeyPem,
76
+ merchantId,
77
+ jwsData: {
78
+ uri: uriWithQuery,
79
+ body: bodyString
80
+ }
81
+ });
82
+ const headers = {
83
+ "Content-Type": "application/json",
84
+ "JWS-Signature": jwsSignature,
85
+ "PSU-IP-Address": psuIp,
86
+ "PSU-User-Agent": psuAgent,
87
+ ...init?.headers
88
+ };
89
+ if (correlationId) {
90
+ headers["Correlation-ID"] = correlationId;
91
+ }
92
+ const res = await fetch(url.toString(), {
93
+ method,
94
+ headers,
95
+ body: method !== "GET" ? bodyString : void 0
96
+ });
97
+ if (!res.ok) {
98
+ const text = await res.text().catch(() => "unknown error");
99
+ throw new Error(
100
+ `Finbricks API error: ${res.status} ${res.statusText} \u2013 ${text}`
101
+ );
102
+ }
103
+ return await res.json();
37
104
  };
38
- const getPaymentDirection = (payment, iban) => {
39
- if (isDeposit(payment, iban)) return "INCOMING";
40
- return "OUTGOING";
105
+ class FinbricksClient {
106
+ constructor(baseUrl, merchantId, privateKeyPem) {
107
+ this.BASE_URL = baseUrl;
108
+ this.MERCHANT_ID = merchantId;
109
+ this.PRIVATE_KEY_PEM = privateKeyPem;
110
+ }
111
+ async request(params) {
112
+ return useFinbricksFetch({
113
+ baseUrl: this.BASE_URL,
114
+ merchantId: this.MERCHANT_ID,
115
+ privateKeyPem: this.PRIVATE_KEY_PEM,
116
+ ...params
117
+ });
118
+ }
119
+ }
120
+
121
+ const FINBRICKS_ENDPOINTS = {
122
+ AUTHENTICATE_V2: "/v2/auth/authenticate",
123
+ AUTH_TOKEN_STATUS: "/auth/token",
124
+ AUTH_TOKEN_REVOKE: "/auth/revoke",
125
+ ACCOUNT_LIST: "/account/list",
126
+ ACCOUNT_BALANCE: "/account/balance",
127
+ ACCOUNT_TRANSACTIONS: "/account/transactions",
128
+ TRANSACTION_INIT: "/transaction/platform/init",
129
+ TRANSACTION_STATUS: "/transaction/platform/status",
130
+ TRANSACTION_BATCH_INIT: "/transaction/platform/batchPayment/init",
131
+ BATCH_STATUS: "/transaction/platform/batchPayment/status"
41
132
  };
42
133
 
43
134
  const mapReferencesToPayment = (reference) => {
@@ -63,6 +154,376 @@ const mapReferencesToPayment = (reference) => {
63
154
  return symbols;
64
155
  };
65
156
 
157
+ const mapFinbricksStatus = (status) => {
158
+ switch (status) {
159
+ case "BOOK":
160
+ return "COMPLETED";
161
+ case "PDNG":
162
+ return "PENDING";
163
+ case "CANCL":
164
+ return "FAILED";
165
+ case "RJCT":
166
+ return "FAILED";
167
+ case "SCHDL":
168
+ return "PENDING";
169
+ case "HOLD":
170
+ return "PENDING";
171
+ case "INFO":
172
+ return "PENDING";
173
+ default:
174
+ return "PENDING";
175
+ }
176
+ };
177
+ const mapFinbricksTransactionStatus = (status) => {
178
+ switch (status) {
179
+ case "OPENED":
180
+ return "CREATED";
181
+ case "AUTHORIZED":
182
+ return "PENDING";
183
+ case "COMPLETED":
184
+ return "COMPLETED";
185
+ case "BOOKED":
186
+ return "PENDING";
187
+ case "SETTLED":
188
+ return "COMPLETED";
189
+ case "REJECTED":
190
+ return "FAILED";
191
+ case "CLOSED":
192
+ return "FAILED";
193
+ }
194
+ };
195
+ const mapFinbricksBatchStatus = (status) => {
196
+ return status === "REJECTED" ? "FAILED" : status === "AUTHORIZED" ? "PROCESSING" : "READY_TO_SIGN";
197
+ };
198
+ const mapFinbricksTransactionToPayment = (tx, account) => {
199
+ const isIncoming = tx.creditDebitIndicator === "CRDT";
200
+ const related = tx.entryDetails.transactionDetails.relatedParties;
201
+ const base = {
202
+ id: uuidv4(),
203
+ bankRefId: tx.entryReference || tx.fbxReference,
204
+ amount: tx.amount?.value || 0,
205
+ currency: tx.amount?.currency || "CZK",
206
+ paymentType: "DOMESTIC",
207
+ status: mapFinbricksStatus(tx.status),
208
+ message: tx.entryDetails.transactionDetails.remittanceInformation?.unstructured || tx.entryDetails.transactionDetails.additionalRemittanceInformation || null,
209
+ processedAt: new Date(tx.bookingDate.date),
210
+ ...mapReferencesToPayment(
211
+ tx.entryDetails.transactionDetails.remittanceInformation?.structured?.creditorReferenceInformation?.reference || tx.entryDetails.transactionDetails.references?.endToEndIdentification
212
+ ),
213
+ debtorHolderName: isIncoming ? related.debtor?.name || "Unknown" : "Unknown",
214
+ creditorHolderName: isIncoming ? "Unknown" : related.creditor?.name || "Unknown",
215
+ debtorIban: isIncoming ? related.debtorAccount?.identification?.iban || account.identification.iban : account.identification.iban,
216
+ creditorIban: isIncoming ? account.identification.iban : related.creditorAccount?.identification?.iban || account.identification.iban,
217
+ direction: "INCOMING"
218
+ // přepíšeme správným směrem níže
219
+ };
220
+ base.direction = getPaymentDirection(base, account.identification.iban);
221
+ return base;
222
+ };
223
+
224
+ class FinbricksConnector extends IBankConnector {
225
+ constructor(provider, { BASE_URI, MERCHANT_ID, PRIVATE_KEY_PEM }) {
226
+ super();
227
+ this.connectorKey = "FINBRICKS";
228
+ this.PROVIDER = provider;
229
+ this.finbricks = new FinbricksClient(BASE_URI, MERCHANT_ID, PRIVATE_KEY_PEM);
230
+ }
231
+ static {
232
+ this.FETCH_INTERVAL = 60 * 60 * 5;
233
+ }
234
+ async connectUserAccount() {
235
+ const clientId = uuidv4();
236
+ const body = {
237
+ merchantId: this.finbricks.MERCHANT_ID,
238
+ clientId,
239
+ paymentProvider: this.PROVIDER,
240
+ scope: "AISP_PISP",
241
+ callbackUrl: "https://example.com/callback"
242
+ };
243
+ const [response, error] = await useResult(
244
+ this.finbricks.request({
245
+ endpoint: FINBRICKS_ENDPOINTS.AUTHENTICATE_V2,
246
+ method: "POST",
247
+ body
248
+ })
249
+ );
250
+ if (error || !response) {
251
+ throw createInternalError(error, {
252
+ message: "Finbricks: failed to connect user"
253
+ });
254
+ }
255
+ return {
256
+ redirectUrl: response.redirectUrl,
257
+ clientId
258
+ };
259
+ }
260
+ async authenticate({ token: clientId }) {
261
+ if (!!clientId) {
262
+ const isExpired = await this.isClientIdExpired(clientId);
263
+ if (!isExpired) {
264
+ this.lastValidClientId = clientId;
265
+ return clientId;
266
+ }
267
+ }
268
+ const newClientId = uuidv4();
269
+ const body = {
270
+ merchantId: this.finbricks.MERCHANT_ID,
271
+ paymentProvider: this.PROVIDER,
272
+ clientId: newClientId,
273
+ scope: "AISP_PISP",
274
+ callbackUrl: `www.example.com/callback`
275
+ };
276
+ const [res, error] = await useResult(
277
+ this.finbricks.request({
278
+ endpoint: "/v2/auth/authenticate",
279
+ method: "POST",
280
+ body
281
+ })
282
+ );
283
+ if (error || !res) {
284
+ throw createInternalError(error, {
285
+ message: `Finbricks: authentication request failed (${this.PROVIDER})`
286
+ });
287
+ }
288
+ this.lastValidClientId = newClientId;
289
+ return res.redirectUrl;
290
+ }
291
+ async revokeAuthentication(clientId) {
292
+ const [_, error] = await useResult(
293
+ this.finbricks.request({
294
+ endpoint: FINBRICKS_ENDPOINTS.AUTH_TOKEN_REVOKE,
295
+ method: "DELETE",
296
+ query: {
297
+ merchantId: this.finbricks.MERCHANT_ID,
298
+ clientId,
299
+ provider: this.PROVIDER
300
+ }
301
+ })
302
+ );
303
+ if (error) {
304
+ throw createInternalError(error, {
305
+ message: `Finbricks: failed to revoke authentication for clientId ${clientId}`
306
+ });
307
+ }
308
+ this.lastValidClientId = "";
309
+ }
310
+ async isClientIdExpired(clientId) {
311
+ const [response, error] = await useResult(
312
+ this.finbricks.request({
313
+ endpoint: FINBRICKS_ENDPOINTS.AUTH_TOKEN_STATUS,
314
+ method: "GET",
315
+ query: {
316
+ merchantId: this.finbricks.MERCHANT_ID,
317
+ clientId,
318
+ provider: this.PROVIDER
319
+ }
320
+ })
321
+ );
322
+ if (error) {
323
+ throw createInternalError(error, {
324
+ message: `Finbricks: failed to fetch token info for clientId: ${clientId}`
325
+ });
326
+ }
327
+ if (!response || response.length === 0) return true;
328
+ const record = response.find((token) => token.clientId === clientId);
329
+ if (!record) return true;
330
+ const validTo = new Date(record.validTo);
331
+ return validTo.getTime() < Date.now();
332
+ }
333
+ async listAccounts() {
334
+ if (!this.lastValidClientId) {
335
+ throw createInternalError(null, {
336
+ message: "Finbricks: missing valid clientId",
337
+ code: "FINBRICKS_CLIENT_ID_MISSING"
338
+ });
339
+ }
340
+ const [response, error] = await useResult(
341
+ this.finbricks.request({
342
+ endpoint: FINBRICKS_ENDPOINTS.ACCOUNT_LIST,
343
+ method: "GET",
344
+ query: {
345
+ merchantId: this.finbricks.MERCHANT_ID,
346
+ paymentProvider: this.PROVIDER,
347
+ clientId: this.lastValidClientId
348
+ }
349
+ })
350
+ );
351
+ if (error || !response) {
352
+ throw createInternalError(error, {
353
+ message: "Finbricks: failed to list accounts"
354
+ });
355
+ }
356
+ return response.accounts;
357
+ }
358
+ async preparePayment(payment) {
359
+ const bankRefId = uuidv4();
360
+ return {
361
+ ...payment,
362
+ id: uuidv4(),
363
+ bankRefId,
364
+ direction: "OUTGOING",
365
+ paymentType: "DOMESTIC",
366
+ status: "PREPARED",
367
+ initiatedAt: /* @__PURE__ */ new Date()
368
+ };
369
+ }
370
+ async initiateBatchFromPayments({
371
+ payments
372
+ }) {
373
+ const batchId = uuidv4();
374
+ const [response, error] = await useResult(
375
+ this.finbricks.request({
376
+ endpoint: FINBRICKS_ENDPOINTS.TRANSACTION_BATCH_INIT,
377
+ method: "POST",
378
+ body: {
379
+ batchPaymentIdentification: {
380
+ merchantId: this.finbricks.MERCHANT_ID,
381
+ debtorAccountIban: payments[0].debtorIban,
382
+ clientId: this.lastValidClientId,
383
+ callbackUrl: "https://example.com/callback",
384
+ merchantBatchId: batchId
385
+ },
386
+ payments: payments.map((p) => ({
387
+ merchantTransactionId: p.bankRefId,
388
+ creditorAccountIban: p.creditorIban,
389
+ amount: p.amount
390
+ }))
391
+ }
392
+ })
393
+ );
394
+ if (error || !response) {
395
+ throw createInternalError(error, {
396
+ message: "Finbricks: failed to initiate batch payment"
397
+ });
398
+ }
399
+ return {
400
+ id: batchId,
401
+ authorizationUrls: [response.redirectUrl],
402
+ payments: payments.map((p) => ({ ...p, status: "INITIALIZED" }))
403
+ };
404
+ }
405
+ async initiateSinglePayment(payment) {
406
+ const [response, error] = await useResult(
407
+ this.finbricks.request({
408
+ endpoint: FINBRICKS_ENDPOINTS.TRANSACTION_INIT,
409
+ method: "POST",
410
+ body: {
411
+ merchantId: this.finbricks.MERCHANT_ID,
412
+ merchantTransactionId: payment.bankRefId,
413
+ totalPrice: payment.amount,
414
+ debtorAccountIban: payment.debtorIban,
415
+ creditorAccountIban: payment.creditorIban,
416
+ creditorName: payment.creditorHolderName,
417
+ description: payment.message || "",
418
+ variableSymbol: payment.vs || "",
419
+ callbackUrl: "https://example.com/callback",
420
+ paymentProvider: this.PROVIDER
421
+ }
422
+ })
423
+ );
424
+ if (error || !response) {
425
+ throw createInternalError(error, {
426
+ message: "Finbricks: failed to initiate payment"
427
+ });
428
+ }
429
+ return {
430
+ authorizationUrl: response.redirectUrl,
431
+ payment: { ...payment, status: "INITIALIZED" }
432
+ };
433
+ }
434
+ async getAllAccountPayments({
435
+ account,
436
+ lastSync
437
+ }) {
438
+ const dateFormat = "yyyy-MM-dd";
439
+ const dateFrom = format(lastSync.lastSyncedAt, dateFormat);
440
+ const dateTo = format(/* @__PURE__ */ new Date(), dateFormat);
441
+ let cursor = null;
442
+ const allPayments = [];
443
+ const fetchTransactions = async (cursor2) => {
444
+ return useResult(
445
+ this.finbricks.request({
446
+ method: "GET",
447
+ endpoint: FINBRICKS_ENDPOINTS.ACCOUNT_TRANSACTIONS,
448
+ query: {
449
+ merchantId: this.finbricks.MERCHANT_ID,
450
+ clientId: this.lastValidClientId,
451
+ paymentProvider: this.PROVIDER,
452
+ bankAccountId: account.identification.number,
453
+ dateFrom,
454
+ dateTo,
455
+ currency: account.currency,
456
+ size: "20",
457
+ cursor: cursor2 ?? void 0
458
+ }
459
+ })
460
+ );
461
+ };
462
+ do {
463
+ {
464
+ const [response, error] = await fetchTransactions(cursor);
465
+ if (error || !response) {
466
+ throw createInternalError(error, {
467
+ message: "Finbricks: failed to fetch account transactions"
468
+ });
469
+ }
470
+ const { transactions, links } = response;
471
+ cursor = links?.[0]?.value || null;
472
+ for (const tx of transactions) {
473
+ allPayments.push(mapFinbricksTransactionToPayment(tx, account));
474
+ }
475
+ }
476
+ } while (cursor != null);
477
+ return allPayments;
478
+ }
479
+ async getPaymentStatus({
480
+ paymentId
481
+ }) {
482
+ const [response, error] = await useResult(
483
+ this.finbricks.request({
484
+ method: "GET",
485
+ endpoint: FINBRICKS_ENDPOINTS.TRANSACTION_STATUS,
486
+ query: {
487
+ merchantId: this.finbricks.MERCHANT_ID,
488
+ merchantTransactionId: paymentId
489
+ }
490
+ })
491
+ );
492
+ if (error || !response) {
493
+ throw createInternalError(error, {
494
+ message: "Finbricks: failed to fetch payment status"
495
+ });
496
+ }
497
+ return mapFinbricksTransactionStatus(response.resultCode);
498
+ }
499
+ async getBatchStatus({ batchId }) {
500
+ const [response, error] = await useResult(
501
+ this.finbricks.request({
502
+ method: "POST",
503
+ endpoint: FINBRICKS_ENDPOINTS.BATCH_STATUS,
504
+ body: {
505
+ merchantId: this.finbricks.MERCHANT_ID,
506
+ merchantBatchId: batchId
507
+ }
508
+ })
509
+ );
510
+ if (error || !response) {
511
+ throw createInternalError(error, {
512
+ message: "Finbricks: failed to fetch batch status"
513
+ });
514
+ }
515
+ return mapFinbricksBatchStatus(response.batchResultCode);
516
+ }
517
+ }
518
+
519
+ const isDeposit = (payment, creditorIban) => {
520
+ return payment.creditorIban === creditorIban;
521
+ };
522
+ const getPaymentDirection = (payment, iban) => {
523
+ if (isDeposit(payment, iban)) return "INCOMING";
524
+ return "OUTGOING";
525
+ };
526
+
66
527
  class ErsteConnector extends IBankConnector {
67
528
  constructor(config) {
68
529
  super();
@@ -76,6 +537,9 @@ class ErsteConnector extends IBankConnector {
76
537
  this.PAYMENTS_URI = config.PAYMENTS_URI;
77
538
  this.ACCOUNTS_URI = config.ACCOUNTS_URI;
78
539
  }
540
+ connectUserAccount() {
541
+ throw new Error("Method not implemented.");
542
+ }
79
543
  static {
80
544
  this.FETCH_INTERVAL = 60 * 60 * 5;
81
545
  }
@@ -120,6 +584,9 @@ class ErsteConnector extends IBankConnector {
120
584
  this.accessToken = json.access_token;
121
585
  return json.refresh_token || "";
122
586
  }
587
+ listAccounts() {
588
+ throw new Error("Method not implemented.");
589
+ }
123
590
  async preparePayment(payment) {
124
591
  if (!this.accessToken) {
125
592
  throw createInternalError(null, {
@@ -306,319 +773,11 @@ class ErsteConnector extends IBankConnector {
306
773
  });
307
774
  return payments;
308
775
  }
309
- }
310
-
311
- const mapFinbricksStatus = (status) => {
312
- switch (status) {
313
- case "BOOK":
314
- return "COMPLETED";
315
- case "PDNG":
316
- return "PENDING";
317
- case "CANCL":
318
- return "FAILED";
319
- case "RJCT":
320
- return "FAILED";
321
- case "SCHDL":
322
- return "PENDING";
323
- case "HOLD":
324
- return "PENDING";
325
- case "INFO":
326
- return "PENDING";
327
- default:
328
- return "PENDING";
329
- }
330
- };
331
-
332
- class FinbricksConnector extends IBankConnector {
333
- constructor(PROVIDER, { BASE_URI, MERCHANT_ID, PRIVATE_KEY_PEM }) {
334
- super();
335
- this.connectorKey = "FINBRICKS";
336
- this.apiDictionary = /* @__PURE__ */ new Map([
337
- ["single-payment-domestic", "/transaction/platform/init"],
338
- ["batch-payment-domestic", "/transaction/platform/batchPayment/init"],
339
- ["get-accounts", "/account/list"],
340
- ["get-account-transactions", "/account/transactions"],
341
- ["authenticate-client", "/v2/auth/authenticate"],
342
- ["expiration", "/auth/token"]
343
- ]);
344
- this.PROVIDER = PROVIDER;
345
- this.BASE_URI = BASE_URI;
346
- this.MERCHANT_ID = MERCHANT_ID;
347
- this.PRIVATE_KEY_PEM = PRIVATE_KEY_PEM;
348
- }
349
- static {
350
- this.FETCH_INTERVAL = 60 * 60 * 5;
351
- }
352
- async signFinbricksJws({ jwsData }) {
353
- const privateKey = await importPKCS8(this.PRIVATE_KEY_PEM, "RS256");
354
- const payload = JSON.stringify(jwsData);
355
- const jws = await new SignJWT(JSON.parse(payload)).setProtectedHeader({
356
- alg: "RS256",
357
- kid: this.MERCHANT_ID,
358
- typ: "JWT"
359
- }).sign(privateKey);
360
- return jws;
361
- }
362
- async authenticate({ token }) {
363
- this.lastValidClientId = token;
364
- return this.lastValidClientId;
365
- }
366
- async isClientIdExpired(clientId) {
367
- const query = new URLSearchParams({
368
- merchantId: this.MERCHANT_ID,
369
- provider: this.PROVIDER,
370
- clientId
371
- });
372
- const uri = this.apiDictionary.get("expiration");
373
- const fullUri = `${uri}?${query.toString()}`;
374
- const signature = await this.signFinbricksJws({
375
- jwsData: {
376
- body: "",
377
- uri: fullUri
378
- }
379
- });
380
- const [data, error] = await useResult(
381
- fetch(`${this.BASE_URI}${fullUri}`, {
382
- method: "POST",
383
- headers: {
384
- "JWS-Signature": signature,
385
- "Content-Type": "application/json"
386
- },
387
- body: ""
388
- })
389
- );
390
- if (error) {
391
- const body = await data?.json();
392
- throw createInternalError(error, {
393
- message: body?.message || "Finbricks API error"
394
- });
395
- }
396
- if (!data?.ok) {
397
- const body = await data.json();
398
- throw createInternalError(null, {
399
- message: body.message || "Finbricks API error",
400
- code: "FINBRICKS_API_ERROR",
401
- status: data?.status || 500
402
- });
403
- }
404
- const tokens = await data.json();
405
- return !!tokens.find((token) => token.clientId === clientId);
406
- }
407
- async preparePayment(payment) {
408
- const bankRefId = uuidv4();
409
- return {
410
- ...payment,
411
- id: uuidv4(),
412
- bankRefId,
413
- direction: "OUTGOING",
414
- paymentType: "DOMESTIC",
415
- status: "PREPARED",
416
- initiatedAt: /* @__PURE__ */ new Date()
417
- };
418
- }
419
- async initiateBatchFromPayments({
420
- payments
421
- }) {
422
- const uri = this.apiDictionary.get("batch-payment-domestic");
423
- const batchId = uuidv4();
424
- const batchBody = {
425
- batchPaymentIdentification: {
426
- merchantId: this.MERCHANT_ID,
427
- debtorAccountIban: payments[0].debtorIban,
428
- clientId: this.lastValidClientId,
429
- callbackUrl: "https://example.com/callback",
430
- merchantBatchId: batchId
431
- },
432
- payments: payments.map((payment) => ({
433
- merchantTransactionId: payment.bankRefId,
434
- creditorAccountIban: payment.creditorIban,
435
- amount: payment.amount
436
- }))
437
- };
438
- const payload = JSON.stringify(batchBody);
439
- const jwsData = {
440
- uri,
441
- body: payload
442
- };
443
- const signature = await this.signFinbricksJws({
444
- jwsData
445
- });
446
- const [data, error] = await useResult(
447
- fetch(`${this.BASE_URI}${uri}`, {
448
- method: "POST",
449
- headers: {
450
- "JWS-Signature": signature,
451
- "Content-Type": "application/json"
452
- },
453
- body: payload
454
- })
455
- );
456
- const body = await data?.json();
457
- if (error) {
458
- throw createInternalError(error, {
459
- message: body?.message || "Finbricks API error"
460
- });
461
- }
462
- if (!data?.ok) {
463
- console.log("FINBRICKSBODY", body);
464
- throw createInternalError(null, {
465
- message: body?.message || "Finbricks API error",
466
- code: "FINBRICKS_API_ERROR",
467
- status: data?.status || 500
468
- });
469
- }
470
- const { redirectUrl } = body;
471
- return {
472
- id: batchId,
473
- authorizationUrls: [redirectUrl],
474
- payments: payments.map((payment) => ({
475
- ...payment,
476
- status: "INITIALIZED"
477
- }))
478
- };
479
- }
480
- async initiateSinglePayment(payment) {
481
- const uri = this.apiDictionary.get("single-payment-domestic");
482
- const paymentBody = {
483
- merchantId: this.MERCHANT_ID,
484
- merchantTransactionId: payment.bankRefId,
485
- totalPrice: payment.amount,
486
- creditorAccountIban: payment.creditorIban,
487
- debtorAccountIban: payment.debtorIban,
488
- creditorName: payment.creditorHolderName,
489
- description: payment.message || "",
490
- variableSymbol: payment.vs || "",
491
- callbackUrl: "example.com",
492
- paymentProvider: this.PROVIDER
493
- };
494
- const signature = await this.signFinbricksJws({
495
- jwsData: {
496
- body: JSON.stringify(paymentBody),
497
- uri
498
- }
499
- });
500
- const [data, error] = await useResult(
501
- fetch(`${this.BASE_URI}${uri}`, {
502
- method: "POST",
503
- headers: {
504
- "JWS-Signature": signature,
505
- "Content-Type": "application/json"
506
- },
507
- body: JSON.stringify(paymentBody)
508
- })
509
- );
510
- const body = await data?.json();
511
- if (error) {
512
- throw createInternalError(error, {
513
- message: body?.message || "Finbricks API error"
514
- });
515
- }
516
- if (!data?.ok) {
517
- console.log("FINBRICKSBODY", body);
518
- throw createInternalError(null, {
519
- message: body?.message || "Finbricks API error",
520
- code: "FINBRICKS_API_ERROR",
521
- status: data?.status || 500
522
- });
523
- }
524
- const redirectUrl = (await data.json()).redirectUrl;
525
- return {
526
- authorizationUrl: redirectUrl,
527
- payment: { ...payment, status: "INITIALIZED" }
528
- };
776
+ getPaymentStatus(_) {
777
+ throw new Error("Method not implemented.");
529
778
  }
530
- async getAllAccountPayments({
531
- account,
532
- lastSync
533
- }) {
534
- const uri = this.apiDictionary.get("get-account-transactions");
535
- const dateFormat = "yyyy-MM-dd";
536
- let cursor = null;
537
- let allPayments = [];
538
- const dateFrom = format(lastSync.lastSyncedAt, dateFormat);
539
- const dateTo = format(/* @__PURE__ */ new Date(), dateFormat);
540
- do {
541
- const query = new URLSearchParams({
542
- merchantId: this.MERCHANT_ID,
543
- clientId: this.lastValidClientId,
544
- paymentProvider: this.PROVIDER,
545
- bankAccountId: account.identification.number,
546
- dateFrom,
547
- dateTo,
548
- currency: account.currency,
549
- size: "20"
550
- });
551
- console.log("query", query);
552
- if (cursor) query.set("cursor", cursor);
553
- const fullUri = `${uri}?${query.toString()}`;
554
- const jwsData = {
555
- uri: fullUri,
556
- body: ""
557
- };
558
- const signature = await this.signFinbricksJws({ jwsData });
559
- console.log("signature ready", signature);
560
- const [data, error] = await useResult(
561
- fetch(`${this.BASE_URI}${fullUri}`, {
562
- method: "GET",
563
- headers: {
564
- "JWS-Signature": signature,
565
- "Content-Type": "application/json"
566
- }
567
- })
568
- );
569
- if (error) {
570
- const body = await data?.json();
571
- throw createInternalError(error, {
572
- message: body?.message || "Finbricks API error"
573
- });
574
- }
575
- if (!data?.ok) {
576
- const body = await data.json();
577
- throw createInternalError(null, {
578
- message: body.message || "Finbricks API error",
579
- code: "FINBRICKS_API_ERROR",
580
- status: data?.status || 500
581
- });
582
- }
583
- const { transactions, links } = await data.json();
584
- cursor = links?.[0]?.value || null;
585
- allPayments = [
586
- ...allPayments,
587
- ...transactions.map((tx) => {
588
- const isIncoming = tx.creditDebitIndicator === "CRDT";
589
- const relatedParties = tx.entryDetails?.transactionDetails?.relatedParties;
590
- const paymentInsert = {
591
- id: uuidv4(),
592
- bankRefId: tx.entryReference || tx.fbxReference,
593
- amount: tx.amount?.value || 0,
594
- currency: tx.amount?.currency || "CZK",
595
- debtorHolderName: isIncoming ? relatedParties?.debtor?.name || "Unknown" : "Unknown",
596
- debtorIban: isIncoming ? relatedParties?.debtorAccount?.identification?.iban || account.identification.iban : account.identification.iban,
597
- debtorAccountNumberWithBankCode: isIncoming ? relatedParties?.debtorAccount?.identification?.other?.identification || `${account.identification.number}/${account.identification.bankCode}` : `${account.identification.number}/${account.identification.bankCode}`,
598
- creditorHolderName: isIncoming ? "Unknown" : relatedParties?.creditor?.name || "Unknown",
599
- creditorIban: isIncoming ? account.identification.iban : relatedParties?.creditorAccount?.identification?.iban || account.identification.iban,
600
- creditorAccountNumberWithBankCode: isIncoming ? `${account.identification.number}/${account.identification.bankCode}` : relatedParties?.creditorAccount?.identification?.other?.identification || `${account.identification.number}/${account.identification.bankCode}`,
601
- paymentType: "DOMESTIC",
602
- direction: isIncoming ? "INCOMING" : "OUTGOING",
603
- message: tx.entryDetails?.transactionDetails?.remittanceInformation?.unstructured || tx.entryDetails?.transactionDetails?.additionalRemittanceInformation || null,
604
- ...mapReferencesToPayment(
605
- tx.entryDetails?.transactionDetails?.remittanceInformation?.structured?.creditorReferenceInformation?.reference || tx.entryDetails?.transactionDetails?.references?.endToEndIdentification
606
- ),
607
- processedAt: new Date(tx.bookingDate.date),
608
- status: "COMPLETED"
609
- };
610
- return {
611
- ...paymentInsert,
612
- direction: getPaymentDirection(
613
- paymentInsert,
614
- account.identification.iban
615
- ),
616
- status: mapFinbricksStatus(tx.status)
617
- };
618
- })
619
- ];
620
- } while (cursor != null);
621
- return allPayments;
779
+ getBatchStatus(_) {
780
+ throw new Error("Method not implemented.");
622
781
  }
623
782
  }
624
783
 
@@ -633,6 +792,15 @@ class MockConnector extends IBankConnector {
633
792
  async authenticate() {
634
793
  return "";
635
794
  }
795
+ async listAccounts() {
796
+ return [];
797
+ }
798
+ async connectUserAccount() {
799
+ return {
800
+ clientId: uuidv4(),
801
+ redirectUrl: ""
802
+ };
803
+ }
636
804
  async preparePayment(payment) {
637
805
  const bankRefId = uuidv4();
638
806
  return {
@@ -680,6 +848,12 @@ class MockConnector extends IBankConnector {
680
848
  status: "COMPLETED"
681
849
  }));
682
850
  }
851
+ getPaymentStatus(_) {
852
+ throw new Error("Method not implemented.");
853
+ }
854
+ getBatchStatus(_) {
855
+ throw new Error("Method not implemented.");
856
+ }
683
857
  }
684
858
 
685
859
  class MockCobsConnector extends FinbricksConnector {
@@ -700,6 +874,8 @@ const paymentInsertTypeZod = z.object({
700
874
  bankPaymentInitiatedAt: z.coerce.date(),
701
875
  bankPaymentProcessedAt: z.coerce.date(),
702
876
  bankingVs: z.string().max(10),
877
+ bankingSs: z.string().max(10),
878
+ bankingKs: z.string().max(10),
703
879
  message: z.string(),
704
880
  creditorIban: z.string().max(34),
705
881
  creditorHolderName: z.string(),
@@ -707,4 +883,4 @@ const paymentInsertTypeZod = z.object({
707
883
  debtorHolderName: z.string().nullable()
708
884
  });
709
885
 
710
- export { BATCH_STATUSES as B, COUNTRY_CODES as C, ErsteConnector as E, FinbricksConnector as F, IBankConnector as I, MockConnector as M, PAYMENT_TYPES as P, MockCobsConnector as a, PAYMENT_STATUSES as b, PAYMENT_DIRECTIONS as c, getPaymentDirection as g, paymentInsertTypeZod as p, tables as t };
886
+ export { BATCH_STATUSES as B, COUNTRY_CODES as C, ErsteConnector as E, FinbricksConnector as F, IBankConnector as I, MockConnector as M, PAYMENT_TYPES as P, MockCobsConnector as a, FinbricksClient as b, FINBRICKS_ENDPOINTS as c, PAYMENT_STATUSES as d, PAYMENT_DIRECTIONS as e, getPaymentDirection as g, paymentInsertTypeZod as p, signFinbricksJws as s, tables as t, useFinbricksFetch as u };