@develit-services/bank 0.8.7 → 0.8.8
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/dist/database/schema.cjs +1 -1
- package/dist/database/schema.d.cts +1 -1
- package/dist/database/schema.d.mts +1 -1
- package/dist/database/schema.d.ts +1 -1
- package/dist/database/schema.mjs +1 -1
- package/dist/export/worker.cjs +236 -276
- package/dist/export/worker.d.cts +26 -26
- package/dist/export/worker.d.mts +26 -26
- package/dist/export/worker.d.ts +26 -26
- package/dist/export/worker.mjs +237 -277
- package/dist/export/workflows.cjs +58 -96
- package/dist/export/workflows.mjs +59 -97
- package/dist/export/wrangler.d.cts +2 -1
- package/dist/export/wrangler.d.mts +2 -1
- package/dist/export/wrangler.d.ts +2 -1
- package/dist/shared/{bank.Cns5ss41.d.cts → bank.B-NJB8GB.d.cts} +12 -25
- package/dist/shared/{bank.Cns5ss41.d.mts → bank.B-NJB8GB.d.mts} +12 -25
- package/dist/shared/{bank.Cns5ss41.d.ts → bank.B-NJB8GB.d.ts} +12 -25
- package/dist/shared/{bank.DEmzZGZW.mjs → bank.B5bZRvgq.mjs} +2 -5
- package/dist/shared/{bank.CQBfbG8u.d.cts → bank.BP_3WMIF.d.cts} +1 -0
- package/dist/shared/{bank.CQBfbG8u.d.mts → bank.BP_3WMIF.d.mts} +1 -0
- package/dist/shared/{bank.CQBfbG8u.d.ts → bank.BP_3WMIF.d.ts} +1 -0
- package/dist/shared/{bank.CA5ytXxp.mjs → bank.BoZtXQpG.mjs} +1 -1
- package/dist/shared/{bank.D1jqaHaF.mjs → bank.BtszLapg.mjs} +128 -20
- package/dist/shared/{bank.CO89tR9U.d.cts → bank.BzobShUU.d.cts} +1 -1
- package/dist/shared/{bank.C0UN6luZ.mjs → bank.C6jjS1Pl.mjs} +0 -2
- package/dist/shared/{bank.CreoSb2d.d.mts → bank.CAVvvZZO.d.mts} +1 -1
- package/dist/shared/{bank.DwyCCyd0.cjs → bank.CtnsGHM8.cjs} +128 -20
- package/dist/shared/{bank.62VzK9Aj.cjs → bank.DJnDSYqE.cjs} +1 -1
- package/dist/shared/{bank.BYRq3yJf.d.ts → bank.DRTuKO8S.d.ts} +1 -1
- package/dist/shared/{bank.Dm8GHThw.cjs → bank.DT6bg8k5.cjs} +2 -5
- package/dist/shared/{bank.BS7fFjGA.cjs → bank.JVlyPAAb.cjs} +0 -2
- package/dist/types.cjs +3 -3
- package/dist/types.d.cts +10 -6
- package/dist/types.d.mts +10 -6
- package/dist/types.d.ts +10 -6
- package/dist/types.mjs +3 -3
- package/package.json +1 -1
|
@@ -90,6 +90,12 @@ type ConnectedAccount = {
|
|
|
90
90
|
declare abstract class IBankConnector {
|
|
91
91
|
/** Unique identifier for this bank connector (e.g., 'ERSTE', 'FINBRICKS', 'MOCK') */
|
|
92
92
|
abstract connectorKey: ConnectorKey;
|
|
93
|
+
/**
|
|
94
|
+
* Lifecycle mode for payment status resolution:
|
|
95
|
+
* - 'batch': statuses are resolved via updateBatchStatuses (getBatchStatus polling)
|
|
96
|
+
* - 'per-payment': statuses are resolved via updatePaymentStatuses (getPaymentStatus polling per payment)
|
|
97
|
+
*/
|
|
98
|
+
abstract readonly lifecycleMode: 'batch' | 'per-payment';
|
|
93
99
|
/** List of bank accounts connected through this connector instance */
|
|
94
100
|
abstract connectedAccounts: ConnectedAccount[];
|
|
95
101
|
/** Optional resolver for loading credentials on demand */
|
|
@@ -2630,7 +2636,7 @@ declare const batch: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2630
2636
|
tableName: "batch";
|
|
2631
2637
|
dataType: "string";
|
|
2632
2638
|
columnType: "SQLiteText";
|
|
2633
|
-
data: "
|
|
2639
|
+
data: "OPEN" | "PROCESSING" | "READY_TO_SIGN" | "SIGNED" | "SIGNATURE_FAILED" | "FAILED" | "COMPLETED";
|
|
2634
2640
|
driverParam: string;
|
|
2635
2641
|
notNull: false;
|
|
2636
2642
|
hasDefault: false;
|
|
@@ -2643,7 +2649,7 @@ declare const batch: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2643
2649
|
generated: undefined;
|
|
2644
2650
|
}, {}, {
|
|
2645
2651
|
length: number | undefined;
|
|
2646
|
-
$type: "
|
|
2652
|
+
$type: "OPEN" | "PROCESSING" | "READY_TO_SIGN" | "SIGNED" | "SIGNATURE_FAILED" | "FAILED" | "COMPLETED";
|
|
2647
2653
|
}>;
|
|
2648
2654
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2649
2655
|
name: "status_reason";
|
|
@@ -2895,25 +2901,6 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2895
2901
|
}, {}, {
|
|
2896
2902
|
length: number | undefined;
|
|
2897
2903
|
}>;
|
|
2898
|
-
paymentRequestId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2899
|
-
name: "payment_request_id";
|
|
2900
|
-
tableName: "payment";
|
|
2901
|
-
dataType: "string";
|
|
2902
|
-
columnType: "SQLiteText";
|
|
2903
|
-
data: string;
|
|
2904
|
-
driverParam: string;
|
|
2905
|
-
notNull: false;
|
|
2906
|
-
hasDefault: false;
|
|
2907
|
-
isPrimaryKey: false;
|
|
2908
|
-
isAutoincrement: false;
|
|
2909
|
-
hasRuntimeDefault: false;
|
|
2910
|
-
enumValues: [string, ...string[]];
|
|
2911
|
-
baseColumn: never;
|
|
2912
|
-
identity: undefined;
|
|
2913
|
-
generated: undefined;
|
|
2914
|
-
}, {}, {
|
|
2915
|
-
length: number | undefined;
|
|
2916
|
-
}>;
|
|
2917
2904
|
refId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2918
2905
|
name: "ref_id";
|
|
2919
2906
|
tableName: "payment";
|
|
@@ -3073,7 +3060,7 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3073
3060
|
tableName: "payment";
|
|
3074
3061
|
dataType: "string";
|
|
3075
3062
|
columnType: "SQLiteText";
|
|
3076
|
-
data: "
|
|
3063
|
+
data: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3077
3064
|
driverParam: string;
|
|
3078
3065
|
notNull: true;
|
|
3079
3066
|
hasDefault: false;
|
|
@@ -3086,7 +3073,7 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3086
3073
|
generated: undefined;
|
|
3087
3074
|
}, {}, {
|
|
3088
3075
|
length: number | undefined;
|
|
3089
|
-
$type: "
|
|
3076
|
+
$type: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3090
3077
|
}>;
|
|
3091
3078
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
3092
3079
|
name: "status_reason";
|
|
@@ -3667,7 +3654,7 @@ declare const paymentRequest: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3667
3654
|
tableName: "payment_request";
|
|
3668
3655
|
dataType: "string";
|
|
3669
3656
|
columnType: "SQLiteText";
|
|
3670
|
-
data: "
|
|
3657
|
+
data: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3671
3658
|
driverParam: string;
|
|
3672
3659
|
notNull: true;
|
|
3673
3660
|
hasDefault: false;
|
|
@@ -3680,7 +3667,7 @@ declare const paymentRequest: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3680
3667
|
generated: undefined;
|
|
3681
3668
|
}, {}, {
|
|
3682
3669
|
length: number | undefined;
|
|
3683
|
-
$type: "
|
|
3670
|
+
$type: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3684
3671
|
}>;
|
|
3685
3672
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
3686
3673
|
name: "status_reason";
|
|
@@ -90,6 +90,12 @@ type ConnectedAccount = {
|
|
|
90
90
|
declare abstract class IBankConnector {
|
|
91
91
|
/** Unique identifier for this bank connector (e.g., 'ERSTE', 'FINBRICKS', 'MOCK') */
|
|
92
92
|
abstract connectorKey: ConnectorKey;
|
|
93
|
+
/**
|
|
94
|
+
* Lifecycle mode for payment status resolution:
|
|
95
|
+
* - 'batch': statuses are resolved via updateBatchStatuses (getBatchStatus polling)
|
|
96
|
+
* - 'per-payment': statuses are resolved via updatePaymentStatuses (getPaymentStatus polling per payment)
|
|
97
|
+
*/
|
|
98
|
+
abstract readonly lifecycleMode: 'batch' | 'per-payment';
|
|
93
99
|
/** List of bank accounts connected through this connector instance */
|
|
94
100
|
abstract connectedAccounts: ConnectedAccount[];
|
|
95
101
|
/** Optional resolver for loading credentials on demand */
|
|
@@ -2630,7 +2636,7 @@ declare const batch: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2630
2636
|
tableName: "batch";
|
|
2631
2637
|
dataType: "string";
|
|
2632
2638
|
columnType: "SQLiteText";
|
|
2633
|
-
data: "
|
|
2639
|
+
data: "OPEN" | "PROCESSING" | "READY_TO_SIGN" | "SIGNED" | "SIGNATURE_FAILED" | "FAILED" | "COMPLETED";
|
|
2634
2640
|
driverParam: string;
|
|
2635
2641
|
notNull: false;
|
|
2636
2642
|
hasDefault: false;
|
|
@@ -2643,7 +2649,7 @@ declare const batch: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2643
2649
|
generated: undefined;
|
|
2644
2650
|
}, {}, {
|
|
2645
2651
|
length: number | undefined;
|
|
2646
|
-
$type: "
|
|
2652
|
+
$type: "OPEN" | "PROCESSING" | "READY_TO_SIGN" | "SIGNED" | "SIGNATURE_FAILED" | "FAILED" | "COMPLETED";
|
|
2647
2653
|
}>;
|
|
2648
2654
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2649
2655
|
name: "status_reason";
|
|
@@ -2895,25 +2901,6 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2895
2901
|
}, {}, {
|
|
2896
2902
|
length: number | undefined;
|
|
2897
2903
|
}>;
|
|
2898
|
-
paymentRequestId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2899
|
-
name: "payment_request_id";
|
|
2900
|
-
tableName: "payment";
|
|
2901
|
-
dataType: "string";
|
|
2902
|
-
columnType: "SQLiteText";
|
|
2903
|
-
data: string;
|
|
2904
|
-
driverParam: string;
|
|
2905
|
-
notNull: false;
|
|
2906
|
-
hasDefault: false;
|
|
2907
|
-
isPrimaryKey: false;
|
|
2908
|
-
isAutoincrement: false;
|
|
2909
|
-
hasRuntimeDefault: false;
|
|
2910
|
-
enumValues: [string, ...string[]];
|
|
2911
|
-
baseColumn: never;
|
|
2912
|
-
identity: undefined;
|
|
2913
|
-
generated: undefined;
|
|
2914
|
-
}, {}, {
|
|
2915
|
-
length: number | undefined;
|
|
2916
|
-
}>;
|
|
2917
2904
|
refId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2918
2905
|
name: "ref_id";
|
|
2919
2906
|
tableName: "payment";
|
|
@@ -3073,7 +3060,7 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3073
3060
|
tableName: "payment";
|
|
3074
3061
|
dataType: "string";
|
|
3075
3062
|
columnType: "SQLiteText";
|
|
3076
|
-
data: "
|
|
3063
|
+
data: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3077
3064
|
driverParam: string;
|
|
3078
3065
|
notNull: true;
|
|
3079
3066
|
hasDefault: false;
|
|
@@ -3086,7 +3073,7 @@ declare const payment: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3086
3073
|
generated: undefined;
|
|
3087
3074
|
}, {}, {
|
|
3088
3075
|
length: number | undefined;
|
|
3089
|
-
$type: "
|
|
3076
|
+
$type: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3090
3077
|
}>;
|
|
3091
3078
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
3092
3079
|
name: "status_reason";
|
|
@@ -3667,7 +3654,7 @@ declare const paymentRequest: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3667
3654
|
tableName: "payment_request";
|
|
3668
3655
|
dataType: "string";
|
|
3669
3656
|
columnType: "SQLiteText";
|
|
3670
|
-
data: "
|
|
3657
|
+
data: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3671
3658
|
driverParam: string;
|
|
3672
3659
|
notNull: true;
|
|
3673
3660
|
hasDefault: false;
|
|
@@ -3680,7 +3667,7 @@ declare const paymentRequest: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
3680
3667
|
generated: undefined;
|
|
3681
3668
|
}, {}, {
|
|
3682
3669
|
length: number | undefined;
|
|
3683
|
-
$type: "
|
|
3670
|
+
$type: "SIGNED" | "FAILED" | "COMPLETED" | "CREATED" | "PREPARED" | "PENDING";
|
|
3684
3671
|
}>;
|
|
3685
3672
|
statusReason: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
3686
3673
|
name: "status_reason";
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { sql, and, eq, isNull } from 'drizzle-orm';
|
|
2
2
|
import { uuidv4 } from '@develit-io/backend-sdk';
|
|
3
|
-
import './bank.
|
|
3
|
+
import './bank.C6jjS1Pl.mjs';
|
|
4
4
|
import 'date-fns';
|
|
5
5
|
import 'jose';
|
|
6
6
|
import '@develit-io/general-codes';
|
|
7
7
|
import { createHash } from 'node:crypto';
|
|
8
|
-
import { s as schema } from './bank.
|
|
9
|
-
import 'drizzle-orm/sqlite-core';
|
|
8
|
+
import { s as schema } from './bank.BoZtXQpG.mjs';
|
|
10
9
|
|
|
11
10
|
const createPaymentCommand = (db, { payment }) => {
|
|
12
11
|
return {
|
|
@@ -22,8 +21,6 @@ const createPaymentCommand = (db, { payment }) => {
|
|
|
22
21
|
statusReason: sql`excluded.status_reason`,
|
|
23
22
|
processedAt: sql`excluded.processed_at`,
|
|
24
23
|
updatedAt: sql`excluded.updated_at`,
|
|
25
|
-
// Keep existing paymentRequestId if already set, otherwise use new value
|
|
26
|
-
paymentRequestId: sql`coalesce(payment.payment_request_id, excluded.payment_request_id)`,
|
|
27
24
|
// Keep existing refId if already set, otherwise use enriched value
|
|
28
25
|
refId: sql`coalesce(payment.ref_id, excluded.ref_id)`,
|
|
29
26
|
// Keep existing batchId if already set, otherwise use enriched value
|
|
@@ -27,6 +27,7 @@ interface BankServiceEnvironmentConfig {
|
|
|
27
27
|
FINBRICKS_BASE_URI: 'https://api.sandbox.finbricks.com';
|
|
28
28
|
FINBRICKS_MERCHANT_ID: string;
|
|
29
29
|
CRON_BATCH_STATUSES: string;
|
|
30
|
+
CRON_PAYMENT_STATUSES: string;
|
|
30
31
|
BANK_AUTH_RECIPIENT: string;
|
|
31
32
|
DBUCS_BASE_URI: string;
|
|
32
33
|
DBUCS_USERNAME: string;
|
|
@@ -27,6 +27,7 @@ interface BankServiceEnvironmentConfig {
|
|
|
27
27
|
FINBRICKS_BASE_URI: 'https://api.sandbox.finbricks.com';
|
|
28
28
|
FINBRICKS_MERCHANT_ID: string;
|
|
29
29
|
CRON_BATCH_STATUSES: string;
|
|
30
|
+
CRON_PAYMENT_STATUSES: string;
|
|
30
31
|
BANK_AUTH_RECIPIENT: string;
|
|
31
32
|
DBUCS_BASE_URI: string;
|
|
32
33
|
DBUCS_USERNAME: string;
|
|
@@ -27,6 +27,7 @@ interface BankServiceEnvironmentConfig {
|
|
|
27
27
|
FINBRICKS_BASE_URI: 'https://api.sandbox.finbricks.com';
|
|
28
28
|
FINBRICKS_MERCHANT_ID: string;
|
|
29
29
|
CRON_BATCH_STATUSES: string;
|
|
30
|
+
CRON_PAYMENT_STATUSES: string;
|
|
30
31
|
BANK_AUTH_RECIPIENT: string;
|
|
31
32
|
DBUCS_BASE_URI: string;
|
|
32
33
|
DBUCS_USERNAME: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations, u as paymentRequest, v as paymentRequestRelations } from './bank.
|
|
1
|
+
import { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations, u as paymentRequest, v as paymentRequestRelations } from './bank.C6jjS1Pl.mjs';
|
|
2
2
|
|
|
3
3
|
const schema = {
|
|
4
4
|
__proto__: null,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { uuidv4, createInternalError, useResult } from '@develit-io/backend-sdk';
|
|
2
2
|
import { format, parseISO } from 'date-fns';
|
|
3
3
|
import { CURRENCY_CODES } from '@develit-io/general-codes';
|
|
4
|
-
import './bank.
|
|
4
|
+
import './bank.C6jjS1Pl.mjs';
|
|
5
5
|
import 'drizzle-orm';
|
|
6
|
-
import 'drizzle-orm/sqlite-core';
|
|
7
6
|
import { importPKCS8, SignJWT } from 'jose';
|
|
8
7
|
import 'node:crypto';
|
|
9
8
|
|
|
@@ -206,6 +205,17 @@ class IBankConnector {
|
|
|
206
205
|
}
|
|
207
206
|
}
|
|
208
207
|
|
|
208
|
+
function buildEndToEndId(payment) {
|
|
209
|
+
const parts = [];
|
|
210
|
+
if (payment.vs) parts.push(`VS${payment.vs}`);
|
|
211
|
+
if (payment.ss) parts.push(`SS${payment.ss}`);
|
|
212
|
+
if (payment.ks) parts.push(`KS${payment.ks}`);
|
|
213
|
+
if (parts.length === 0) {
|
|
214
|
+
return payment.id.replace(/-/g, "");
|
|
215
|
+
}
|
|
216
|
+
return `/${parts.join("/")}`;
|
|
217
|
+
}
|
|
218
|
+
|
|
209
219
|
async function signFinbricksJws({
|
|
210
220
|
privateKeyPem,
|
|
211
221
|
merchantId,
|
|
@@ -262,6 +272,18 @@ const useFinbricksFetch = async (config, init) => {
|
|
|
262
272
|
if (correlationId) {
|
|
263
273
|
headers["Correlation-ID"] = correlationId;
|
|
264
274
|
}
|
|
275
|
+
console.log(
|
|
276
|
+
"[Finbricks] request",
|
|
277
|
+
JSON.stringify(
|
|
278
|
+
{
|
|
279
|
+
method,
|
|
280
|
+
url: url.toString(),
|
|
281
|
+
body: body ?? null
|
|
282
|
+
},
|
|
283
|
+
null,
|
|
284
|
+
2
|
|
285
|
+
)
|
|
286
|
+
);
|
|
265
287
|
const res = await fetch(url.toString(), {
|
|
266
288
|
method,
|
|
267
289
|
headers,
|
|
@@ -269,11 +291,30 @@ const useFinbricksFetch = async (config, init) => {
|
|
|
269
291
|
});
|
|
270
292
|
if (!res.ok) {
|
|
271
293
|
const text = await res.text().catch(() => "unknown error");
|
|
294
|
+
console.error("[Finbricks] error response", {
|
|
295
|
+
status: res.status,
|
|
296
|
+
statusText: res.statusText,
|
|
297
|
+
url: url.toString(),
|
|
298
|
+
body: text
|
|
299
|
+
});
|
|
272
300
|
throw new Error(
|
|
273
301
|
`Finbricks API error: ${res.status} ${res.statusText} \u2013 ${text}`
|
|
274
302
|
);
|
|
275
303
|
}
|
|
276
|
-
|
|
304
|
+
const json = await res.json();
|
|
305
|
+
console.log(
|
|
306
|
+
"[Finbricks] response",
|
|
307
|
+
JSON.stringify(
|
|
308
|
+
{
|
|
309
|
+
status: res.status,
|
|
310
|
+
url: url.toString(),
|
|
311
|
+
body: json
|
|
312
|
+
},
|
|
313
|
+
null,
|
|
314
|
+
2
|
|
315
|
+
)
|
|
316
|
+
);
|
|
317
|
+
return json;
|
|
277
318
|
};
|
|
278
319
|
class FinbricksClient {
|
|
279
320
|
constructor(baseUrl, merchantId, privateKeyPem, redirectUri) {
|
|
@@ -328,16 +369,16 @@ const mapFinbricksStatus = (status) => {
|
|
|
328
369
|
return "PENDING";
|
|
329
370
|
}
|
|
330
371
|
};
|
|
331
|
-
const mapFinbricksTransactionStatus = (status) => {
|
|
372
|
+
const mapFinbricksTransactionStatus = (status, finalBankStatus) => {
|
|
332
373
|
switch (status) {
|
|
333
374
|
case "OPENED":
|
|
334
|
-
return "
|
|
375
|
+
return "PREPARED";
|
|
335
376
|
case "AUTHORIZED":
|
|
336
|
-
return "PENDING";
|
|
377
|
+
return finalBankStatus ? "COMPLETED" : "PENDING";
|
|
337
378
|
case "COMPLETED":
|
|
338
|
-
return "COMPLETED";
|
|
379
|
+
return finalBankStatus ? "COMPLETED" : "PENDING";
|
|
339
380
|
case "BOOKED":
|
|
340
|
-
return "PENDING";
|
|
381
|
+
return finalBankStatus ? "COMPLETED" : "PENDING";
|
|
341
382
|
case "SETTLED":
|
|
342
383
|
return "COMPLETED";
|
|
343
384
|
case "REJECTED":
|
|
@@ -391,27 +432,81 @@ const mapReferencesToPayment = (reference) => {
|
|
|
391
432
|
return symbols;
|
|
392
433
|
};
|
|
393
434
|
|
|
435
|
+
const SEPA_COUNTRIES = /* @__PURE__ */ new Set([
|
|
436
|
+
"AT",
|
|
437
|
+
"BE",
|
|
438
|
+
"BG",
|
|
439
|
+
"CY",
|
|
440
|
+
"CZ",
|
|
441
|
+
"DE",
|
|
442
|
+
"DK",
|
|
443
|
+
"EE",
|
|
444
|
+
"ES",
|
|
445
|
+
"FI",
|
|
446
|
+
"FR",
|
|
447
|
+
"GR",
|
|
448
|
+
"HR",
|
|
449
|
+
"HU",
|
|
450
|
+
"IE",
|
|
451
|
+
"IT",
|
|
452
|
+
"LT",
|
|
453
|
+
"LU",
|
|
454
|
+
"LV",
|
|
455
|
+
"MT",
|
|
456
|
+
"NL",
|
|
457
|
+
"PL",
|
|
458
|
+
"PT",
|
|
459
|
+
"RO",
|
|
460
|
+
"SE",
|
|
461
|
+
"SI",
|
|
462
|
+
"SK",
|
|
463
|
+
"IS",
|
|
464
|
+
"LI",
|
|
465
|
+
"NO",
|
|
466
|
+
"CH",
|
|
467
|
+
"GB",
|
|
468
|
+
"MC",
|
|
469
|
+
"SM",
|
|
470
|
+
"VA",
|
|
471
|
+
"AD",
|
|
472
|
+
"GI",
|
|
473
|
+
"XK"
|
|
474
|
+
]);
|
|
475
|
+
function detectPaymentType(tx, isIncoming) {
|
|
476
|
+
const related = tx.entryDetails?.transactionDetails?.relatedParties;
|
|
477
|
+
const otherParty = isIncoming ? related?.debtorAccount : related?.creditorAccount;
|
|
478
|
+
if (otherParty?.identification?.other?.identification) return "DOMESTIC";
|
|
479
|
+
const otherIban = otherParty?.identification?.iban;
|
|
480
|
+
const otherCountry = otherIban?.slice(0, 2);
|
|
481
|
+
if (otherCountry === "CZ") return "DOMESTIC";
|
|
482
|
+
if (otherIban && otherCountry) {
|
|
483
|
+
if (SEPA_COUNTRIES.has(otherCountry) && tx.amount?.currency === "EUR")
|
|
484
|
+
return "SEPA";
|
|
485
|
+
return "SWIFT";
|
|
486
|
+
}
|
|
487
|
+
if (tx.amount?.currency === "EUR") return "SEPA";
|
|
488
|
+
if (tx.amount?.currency !== "CZK") return "SWIFT";
|
|
489
|
+
return "DOMESTIC";
|
|
490
|
+
}
|
|
394
491
|
const mapFinbricksTransactionToPayment = (tx, account) => {
|
|
395
492
|
const isIncoming = tx.creditDebitIndicator === "CRDT";
|
|
396
493
|
const related = tx.entryDetails?.transactionDetails?.relatedParties;
|
|
397
494
|
const endToEndId = tx.entryDetails.transactionDetails?.references?.endToEndIdentification;
|
|
398
|
-
const
|
|
399
|
-
const paymentRequestId = endToEndId && uuidRegex.test(endToEndId) ? endToEndId : null;
|
|
495
|
+
const symbolsRegex = /^\/VS\d+/;
|
|
400
496
|
const base = {
|
|
401
497
|
id: uuidv4(),
|
|
402
498
|
correlationId: uuidv4(),
|
|
403
|
-
paymentRequestId,
|
|
404
499
|
connectorKey: account.connectorKey,
|
|
405
500
|
accountId: account.id,
|
|
406
501
|
bankRefId: tx.fbxReference,
|
|
407
502
|
amount: tx.amount?.value || 0,
|
|
408
503
|
currency: tx.amount?.currency || "CZK",
|
|
409
|
-
paymentType:
|
|
504
|
+
paymentType: detectPaymentType(tx, isIncoming),
|
|
410
505
|
status: mapFinbricksStatus(tx.status),
|
|
411
506
|
message: tx.entryDetails.transactionDetails?.remittanceInformation?.unstructured || tx.entryDetails.transactionDetails?.additionalRemittanceInformation || tx.entryDetails.transactionDetails?.additionalTransactionInformation || null,
|
|
412
507
|
processedAt: new Date(tx.bookingDate.date),
|
|
413
508
|
...mapReferencesToPayment(
|
|
414
|
-
tx.entryDetails.transactionDetails?.remittanceInformation?.structured?.creditorReferenceInformation?.reference || (
|
|
509
|
+
tx.entryDetails.transactionDetails?.remittanceInformation?.structured?.creditorReferenceInformation?.reference || (endToEndId && symbolsRegex.test(endToEndId) ? endToEndId : void 0)
|
|
415
510
|
),
|
|
416
511
|
creditor: {
|
|
417
512
|
holderName: related?.creditorAccount?.name || related?.creditor?.name || "Unknown",
|
|
@@ -438,6 +533,13 @@ const mapFinbricksTransactionToPayment = (tx, account) => {
|
|
|
438
533
|
return base;
|
|
439
534
|
};
|
|
440
535
|
|
|
536
|
+
function autoVariableSymbol(paymentId) {
|
|
537
|
+
let hash = 0;
|
|
538
|
+
for (let i = 0; i < paymentId.length; i++) {
|
|
539
|
+
hash = (hash << 5) - hash + paymentId.charCodeAt(i) | 0;
|
|
540
|
+
}
|
|
541
|
+
return String(Math.abs(hash) % 1e10).padStart(10, "0");
|
|
542
|
+
}
|
|
441
543
|
class FinbricksConnector extends IBankConnector {
|
|
442
544
|
constructor(provider, {
|
|
443
545
|
BASE_URI,
|
|
@@ -449,6 +551,7 @@ class FinbricksConnector extends IBankConnector {
|
|
|
449
551
|
}) {
|
|
450
552
|
super();
|
|
451
553
|
this.connectorKey = "FINBRICKS";
|
|
554
|
+
this.lifecycleMode = "batch";
|
|
452
555
|
this.connectedAccounts = [];
|
|
453
556
|
this.PROVIDER = provider;
|
|
454
557
|
this.finbricks = new FinbricksClient(
|
|
@@ -652,7 +755,7 @@ class FinbricksConnector extends IBankConnector {
|
|
|
652
755
|
merchantTransactionId: p.id,
|
|
653
756
|
creditorAccountIban: p.creditor.iban,
|
|
654
757
|
amount: p.amount,
|
|
655
|
-
variableSymbol: p.vs,
|
|
758
|
+
variableSymbol: p.vs ?? (p.ss ? void 0 : autoVariableSymbol(p.id)),
|
|
656
759
|
specificSymbol: p.ss,
|
|
657
760
|
constantSymbol: p.ks,
|
|
658
761
|
description: p.message
|
|
@@ -760,7 +863,7 @@ class FinbricksConnector extends IBankConnector {
|
|
|
760
863
|
},
|
|
761
864
|
paymentIdentification: {
|
|
762
865
|
merchantTransactionId: bankRefId,
|
|
763
|
-
endToEndIdentification: payment
|
|
866
|
+
endToEndIdentification: buildEndToEndId(payment)
|
|
764
867
|
},
|
|
765
868
|
amount: payment.amount,
|
|
766
869
|
debtor: {
|
|
@@ -810,7 +913,7 @@ class FinbricksConnector extends IBankConnector {
|
|
|
810
913
|
creditorAccountIban: payment.creditor.iban,
|
|
811
914
|
creditorName: payment.creditor.holderName,
|
|
812
915
|
description: payment.message,
|
|
813
|
-
variableSymbol: payment.vs,
|
|
916
|
+
variableSymbol: payment.vs ?? (payment.ss ? void 0 : autoVariableSymbol(payment.id)),
|
|
814
917
|
callbackUrl: `${this.finbricks.REDIRECT_URI}?type=payment&paymentId=${payment.id}`,
|
|
815
918
|
paymentProvider: this.PROVIDER
|
|
816
919
|
}
|
|
@@ -901,7 +1004,10 @@ class FinbricksConnector extends IBankConnector {
|
|
|
901
1004
|
message: "Finbricks: failed to fetch payment status"
|
|
902
1005
|
});
|
|
903
1006
|
}
|
|
904
|
-
return mapFinbricksTransactionStatus(
|
|
1007
|
+
return mapFinbricksTransactionStatus(
|
|
1008
|
+
response.resultCode,
|
|
1009
|
+
response.finalBankStatus ?? false
|
|
1010
|
+
);
|
|
905
1011
|
}
|
|
906
1012
|
async getBatchStatus({
|
|
907
1013
|
batchId,
|
|
@@ -954,6 +1060,7 @@ class AirBankConnector extends FinbricksConnector {
|
|
|
954
1060
|
class CreditasConnector extends FinbricksConnector {
|
|
955
1061
|
constructor(config) {
|
|
956
1062
|
super("CREDITAS", config);
|
|
1063
|
+
this.lifecycleMode = "per-payment";
|
|
957
1064
|
}
|
|
958
1065
|
/**
|
|
959
1066
|
* Creditas bank doesn't support batch payments at all.
|
|
@@ -1223,6 +1330,7 @@ class DbuConnector extends IBankConnector {
|
|
|
1223
1330
|
}) {
|
|
1224
1331
|
super();
|
|
1225
1332
|
this.connectorKey = "DBU";
|
|
1333
|
+
this.lifecycleMode = "per-payment";
|
|
1226
1334
|
this.connectedAccounts = [];
|
|
1227
1335
|
this.baseUrl = BASE_URL;
|
|
1228
1336
|
this.username = USERNAME;
|
|
@@ -1306,7 +1414,6 @@ class DbuConnector extends IBankConnector {
|
|
|
1306
1414
|
const parsed = {
|
|
1307
1415
|
id: uuidv4(),
|
|
1308
1416
|
correlationId: uuidv4(),
|
|
1309
|
-
paymentRequestId: transaction.uniqueExternalId ?? null,
|
|
1310
1417
|
connectorKey: "DBU",
|
|
1311
1418
|
accountId: account.id,
|
|
1312
1419
|
bankRefId: transaction.idRequiredTransaction.toString(),
|
|
@@ -1680,6 +1787,7 @@ class ErsteConnector extends IBankConnector {
|
|
|
1680
1787
|
constructor(config) {
|
|
1681
1788
|
super();
|
|
1682
1789
|
this.connectorKey = "ERSTE";
|
|
1790
|
+
this.lifecycleMode = "batch";
|
|
1683
1791
|
this.accessToken = null;
|
|
1684
1792
|
this.API_KEY = config.API_KEY;
|
|
1685
1793
|
this.CLIENT_ID = config.CLIENT_ID;
|
|
@@ -1785,7 +1893,7 @@ class ErsteConnector extends IBankConnector {
|
|
|
1785
1893
|
}
|
|
1786
1894
|
const paymentBody = {
|
|
1787
1895
|
paymentIdentification: {
|
|
1788
|
-
endToEndIdentification: payment
|
|
1896
|
+
endToEndIdentification: buildEndToEndId(payment),
|
|
1789
1897
|
instructionIdentification: payment.id
|
|
1790
1898
|
},
|
|
1791
1899
|
paymentTypeInformation: { instructionPriority: "NORM" },
|
|
@@ -1945,7 +2053,6 @@ class ErsteConnector extends IBankConnector {
|
|
|
1945
2053
|
const paymentInsert = {
|
|
1946
2054
|
id: uuidv4(),
|
|
1947
2055
|
correlationId: uuidv4(),
|
|
1948
|
-
paymentRequestId: payment.entryDetails.transactionDetails.references.endToEndIdentification ?? null,
|
|
1949
2056
|
connectorKey: "ERSTE",
|
|
1950
2057
|
accountId: account.id,
|
|
1951
2058
|
bankRefId: payment.entryReference,
|
|
@@ -2012,6 +2119,7 @@ class MockConnector extends IBankConnector {
|
|
|
2012
2119
|
constructor() {
|
|
2013
2120
|
super();
|
|
2014
2121
|
this.connectorKey = "MOCK";
|
|
2122
|
+
this.lifecycleMode = "batch";
|
|
2015
2123
|
this.connectedAccounts = [];
|
|
2016
2124
|
}
|
|
2017
2125
|
supportsBatch(_paymentType) {
|
|
@@ -138,7 +138,6 @@ const payment = sqliteTable(
|
|
|
138
138
|
{
|
|
139
139
|
...base,
|
|
140
140
|
correlationId: text("correlation_id").notNull(),
|
|
141
|
-
paymentRequestId: text("payment_request_id"),
|
|
142
141
|
refId: text("ref_id"),
|
|
143
142
|
bankRefId: text("bank_ref_id").notNull(),
|
|
144
143
|
accountId: text("account_id").references(() => account.id, {
|
|
@@ -180,7 +179,6 @@ const payment = sqliteTable(
|
|
|
180
179
|
index("payment_account_id_status_idx").on(t.accountId, t.status),
|
|
181
180
|
index("payment_account_id_created_at_idx").on(t.accountId, t.createdAt),
|
|
182
181
|
index("payment_created_at_idx").on(t.createdAt),
|
|
183
|
-
index("payment_payment_request_id_idx").on(t.paymentRequestId),
|
|
184
182
|
index("payment_direction_idx").on(t.direction),
|
|
185
183
|
index("payment_batch_id_idx").on(t.batchId),
|
|
186
184
|
index("payment_creditor_iban_idx").on(t.creditorIban),
|