@develit-services/bank 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -6
- package/dist/database/schema.cjs +9 -7
- 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 +221 -43
- package/dist/export/worker.d.cts +24 -8
- package/dist/export/worker.d.mts +24 -8
- package/dist/export/worker.d.ts +24 -8
- package/dist/export/worker.mjs +212 -34
- package/dist/export/workflows.cjs +71 -52
- package/dist/export/workflows.mjs +71 -52
- package/dist/export/wrangler.d.cts +1 -2
- package/dist/export/wrangler.d.mts +1 -2
- package/dist/export/wrangler.d.ts +1 -2
- package/dist/shared/{bank.Du70-Kk_.d.ts → bank.6faPHUEY.d.ts} +211 -1
- package/dist/shared/{bank.Bs7mkXbR.cjs → bank.BOnP9p9Y.cjs} +15 -2
- package/dist/shared/{bank.BJ7LqYtJ.d.cts → bank.BaMRCHk-.d.cts} +707 -126
- package/dist/shared/{bank.BJ7LqYtJ.d.mts → bank.BaMRCHk-.d.mts} +707 -126
- package/dist/shared/{bank.BJ7LqYtJ.d.ts → bank.BaMRCHk-.d.ts} +707 -126
- package/dist/shared/{bank.Du70-Kk_.d.cts → bank.BoWCMu5n.d.cts} +211 -1
- package/dist/shared/bank.C-T1FQxg.cjs +17 -0
- package/dist/shared/{bank.993UA65l.mjs → bank.C4VOdIx1.mjs} +57 -5
- package/dist/shared/{bank.BC06Rbrx.d.cts → bank.CQBfbG8u.d.cts} +0 -1
- package/dist/shared/{bank.BC06Rbrx.d.mts → bank.CQBfbG8u.d.mts} +0 -1
- package/dist/shared/{bank.BC06Rbrx.d.ts → bank.CQBfbG8u.d.ts} +0 -1
- package/dist/shared/{bank.Ce-NBBw1.cjs → bank.CQURey1E.cjs} +64 -7
- package/dist/shared/{bank.CGIeLo8U.mjs → bank.Cpy9PULF.mjs} +14 -3
- package/dist/shared/bank.DDHrdFgy.mjs +15 -0
- package/dist/shared/{bank.Du70-Kk_.d.mts → bank.DOL1uM4n.d.mts} +211 -1
- package/dist/shared/{bank.CeRbuycV.mjs → bank.DRrBrAdI.mjs} +62 -8
- package/dist/shared/{bank.IVhZ_RlH.cjs → bank.SQ4Mmr8u.cjs} +57 -3
- package/dist/types.cjs +25 -23
- package/dist/types.d.cts +29 -180
- package/dist/types.d.mts +29 -180
- package/dist/types.d.ts +29 -180
- package/dist/types.mjs +2 -2
- package/package.json +1 -1
- package/dist/shared/bank.Cp0yvOdq.cjs +0 -15
- package/dist/shared/bank.fIGTiPnp.mjs +0 -13
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Sluzba se sklada z:
|
|
|
24
24
|
|
|
25
25
|
## Zivotni cyklus platby
|
|
26
26
|
|
|
27
|
-
Platba prochazi
|
|
27
|
+
Platba prochazi 6 fazemi s explicitnimi typy:
|
|
28
28
|
|
|
29
29
|
```
|
|
30
30
|
SendPaymentInput (API vstup)
|
|
@@ -55,10 +55,17 @@ SendPaymentInput (API vstup)
|
|
|
55
55
|
│ Odeslana do banky, ceka na autorizaci │
|
|
56
56
|
│ (muze jiz mit bankRefId) │
|
|
57
57
|
└──────────────────┬──────────────────────────┘
|
|
58
|
-
│
|
|
58
|
+
│ uzivatel autorizuje (callback)
|
|
59
59
|
▼
|
|
60
60
|
┌─────────────────────────────────────────────┐
|
|
61
|
-
│ 5.
|
|
61
|
+
│ 5. SignedPayment status: SIGNED │
|
|
62
|
+
│ Autorizovana uzivatelem, banka │
|
|
63
|
+
│ zpracovava │
|
|
64
|
+
└──────────────────┬──────────────────────────┘
|
|
65
|
+
│ banka dokonci zpracovani
|
|
66
|
+
▼
|
|
67
|
+
┌─────────────────────────────────────────────┐
|
|
68
|
+
│ 6. CompletedPayment status: COMPLETED│
|
|
62
69
|
│ Zpracovana bankou, ma bankRefId │
|
|
63
70
|
│ a processedAt timestamp │
|
|
64
71
|
│ (pripadne FAILED / PENDING) │
|
|
@@ -71,6 +78,7 @@ SendPaymentInput (API vstup)
|
|
|
71
78
|
|--------|-------|
|
|
72
79
|
| `CREATED` | Platba vytvorena, ceka na zpracovani |
|
|
73
80
|
| `PREPARED` | Odeslana do banky, ceka na autorizaci |
|
|
81
|
+
| `SIGNED` | Autorizovana uzivatelem, banka zpracovava |
|
|
74
82
|
| `PENDING` | Banka zpracovava |
|
|
75
83
|
| `COMPLETED` | Uspesne dokoncena |
|
|
76
84
|
| `FAILED` | Selhala |
|
|
@@ -146,11 +154,14 @@ Kazdy batch obsahuje pouze platby **jednoho typu** (SEPA, DOMESTIC nebo SWIFT).
|
|
|
146
154
|
Workflow (Cloudflare Durable Object) ridi zpracovani batche:
|
|
147
155
|
|
|
148
156
|
1. Nacte a validuje batch (nesmi byt SIGNED/PROCESSING)
|
|
157
|
+
1b. Nacte payment requesty pro batch z `payment_request` tabulky
|
|
149
158
|
2. Zamkne batch (nastavi PROCESSING, overi checksum)
|
|
150
159
|
3. Iniciuje batch u banky pres konektor podle typu platby (`connector.initiateDomesticBatch()` / `initiateSEPABatch()` / `initiateForeignBatch()`)
|
|
160
|
+
3b. Aktualizuje singlePayments na PREPARED (bankRefId, initiatedAt, authorizationUrl)
|
|
151
161
|
4. Aktualizuje batch na READY_TO_SIGN s autorizacnimi URL
|
|
162
|
+
4a. MOCK konektor: preskoci autorizaci, rovnou oznaci singlePayments jako COMPLETED a batch jako SIGNED
|
|
152
163
|
5. Odesle email s odkazem na autorizaci
|
|
153
|
-
6. Ceka na autorizaci uzivatelem
|
|
164
|
+
6. (TBD) Ceka na autorizaci uzivatelem (waitForEvent)
|
|
154
165
|
|
|
155
166
|
### CRON kontrola stavu
|
|
156
167
|
|
|
@@ -241,6 +252,64 @@ Vsechny konektory dedi z abstraktni tridy `IBankConnector`, ktera poskytuje spol
|
|
|
241
252
|
| Mock | `MOCK` | Vsechny typy | Testovaci, automaticky dokoncuje platby |
|
|
242
253
|
| Mock COBS | `MOCK_COBS` | Vsechny typy | Testovaci COBS konektor |
|
|
243
254
|
|
|
255
|
+
### Podporovane sluzby dle bank (Finbricks, CZ)
|
|
256
|
+
|
|
257
|
+
> Data ze sandbox prostredi Finbricks (`/status/bankInfo`). Aktualizovano: 2026-02-23.
|
|
258
|
+
|
|
259
|
+
#### Platby
|
|
260
|
+
|
|
261
|
+
| Banka | Provider | Domestic | SEPA | Foreign | Batch | Recurring | Pairing | Settled |
|
|
262
|
+
|-------|----------|:--------:|:----:|:-------:|:-----:|:---------:|:-------:|:-------:|
|
|
263
|
+
| MONETA Money Bank | `MONETA` | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
|
|
264
|
+
| Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
|
265
|
+
| Air Bank | `AIRBANK` | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
266
|
+
| J&T Banka | `JTB` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
267
|
+
| mBank | `MBANK` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
268
|
+
| Raiffeisen | `RAIFFEISEN` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
269
|
+
| Fio banka | `FIO` | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
|
|
270
|
+
| CSOB | `CSOB` | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
|
|
271
|
+
| Komercni banka | `KB` | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ |
|
|
272
|
+
| UniCredit | `UNICREDIT` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
273
|
+
| Ceska sporitelna | `CSAS` | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
|
|
274
|
+
| Partners Banka | `PARTNERS` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
275
|
+
| Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
|
|
276
|
+
|
|
277
|
+
#### Ucty (informace)
|
|
278
|
+
|
|
279
|
+
| Banka | Provider | Info | Zustatek | Transakce |
|
|
280
|
+
|-------|----------|:----:|:--------:|:---------:|
|
|
281
|
+
| MONETA Money Bank | `MONETA` | ✅ | ✅ | ✅ |
|
|
282
|
+
| Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ✅ |
|
|
283
|
+
| Air Bank | `AIRBANK` | ✅ | ✅ | ✅ |
|
|
284
|
+
| J&T Banka | `JTB` | ✅ | ✅ | ✅ |
|
|
285
|
+
| mBank | `MBANK` | ✅ | ✅ | ✅ |
|
|
286
|
+
| Raiffeisen | `RAIFFEISEN` | ✅ | ✅ | ✅ |
|
|
287
|
+
| Fio banka | `FIO` | ✅ | ✅ | ✅ |
|
|
288
|
+
| CSOB | `CSOB` | ✅ | ✅ | ✅ |
|
|
289
|
+
| Komercni banka | `KB` | ✅ | ✅ | ✅ |
|
|
290
|
+
| UniCredit | `UNICREDIT` | ✅ | ✅ | ✅ |
|
|
291
|
+
| Ceska sporitelna | `CSAS` | ✅ | ✅ | ✅ |
|
|
292
|
+
| Partners Banka | `PARTNERS` | ✅ | ✅ | ✅ |
|
|
293
|
+
| Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ✅ |
|
|
294
|
+
|
|
295
|
+
#### Instant platby
|
|
296
|
+
|
|
297
|
+
| Banka | Provider | Domestic Creditor | Domestic Debtor | SEPA Creditor | SEPA Debtor |
|
|
298
|
+
|-------|----------|:-----------------:|:---------------:|:-------------:|:-----------:|
|
|
299
|
+
| MONETA Money Bank | `MONETA` | ✅ | ✅ | ❌ | ❌ |
|
|
300
|
+
| Mock Cobs banka | `MOCK_COBS` | ✅ | ✅ | ✅ | ❌ |
|
|
301
|
+
| Air Bank | `AIRBANK` | ✅ | ✅ | ✅ | ✅ |
|
|
302
|
+
| J&T Banka | `JTB` | ✅ | ✅ | ✅ | ✅ |
|
|
303
|
+
| mBank | `MBANK` | ✅ | ✅ | ❌ | ❌ |
|
|
304
|
+
| Raiffeisen | `RAIFFEISEN` | ✅ | ✅ | ❌ | ❌ |
|
|
305
|
+
| Fio banka | `FIO` | ✅ | ✅ | ❌ | ✅ |
|
|
306
|
+
| CSOB | `CSOB` | ✅ | ✅ | ❌ | ❌ |
|
|
307
|
+
| Komercni banka | `KB` | ✅ | ✅ | ❌ | ❌ |
|
|
308
|
+
| UniCredit | `UNICREDIT` | ✅ | ✅ | ❌ | ❌ |
|
|
309
|
+
| Ceska sporitelna | `CSAS` | ✅ | ✅ | ❌ | ❌ |
|
|
310
|
+
| Partners Banka | `PARTNERS` | ✅ | ✅ | ❌ | ❌ |
|
|
311
|
+
| Banka CREDITAS | `CREDITAS` | ✅ | ✅ | ❌ | ❌ |
|
|
312
|
+
|
|
244
313
|
### Metody konektoru
|
|
245
314
|
|
|
246
315
|
Kazdy konektor implementuje nasledujici metody (nebo vraci `Not implemented`):
|
|
@@ -319,6 +388,7 @@ Bank service je **RPC worker** - nema vlastni verejne HTTP endpointy. Vsechny ak
|
|
|
319
388
|
| `send-payment` | Odesle platbu (vlozi do fronty pro batchovani) |
|
|
320
389
|
| `send-payment-sync` | Odesle platbu synchronne primo do banky, vrati `authorizationUrl` (bez queue/batch/DB) |
|
|
321
390
|
| `get-payments` | Seznam plateb s paginaci a filtry (ucet, castka, mena, smer, datum, stav) |
|
|
391
|
+
| `handle-authorization-callback` | Zpracuje callback po autorizaci platby/batche (aktualizuje singlePayment + batch status) |
|
|
322
392
|
| `simulate-deposit` | Testovaci: vytvori prichozi platbu ve stavu COMPLETED |
|
|
323
393
|
|
|
324
394
|
### Batch operace
|
|
@@ -374,11 +444,17 @@ Klicove sloupce: `correlationId`, `refId`, `bankRefId`, `amount`, `currency`, `d
|
|
|
374
444
|
|
|
375
445
|
Unikatni omezeni: `(connectorKey, bankRefId)`.
|
|
376
446
|
|
|
447
|
+
### payment_request
|
|
448
|
+
|
|
449
|
+
Odchozi platby v prubehu zpracovani (in-flight). Kazda platba v batchi ma vlastni radek se stavem.
|
|
450
|
+
|
|
451
|
+
Klicove sloupce: `batchId`, `status`, `bankRefId`, `amount`, `currency`, `paymentType`, `creditorIban`, `debtorIban`, `accountId`, `connectorKey`, `authorizationUrl`, `initiatedAt`, `processedAt`, `statusReason`.
|
|
452
|
+
|
|
377
453
|
### batch
|
|
378
454
|
|
|
379
|
-
Batch plateb
|
|
455
|
+
Batch plateb se stavovymi informacemi. Platby jsou v tabulce `payment_request` (vazba pres `batchId`).
|
|
380
456
|
|
|
381
|
-
Klicove sloupce: `status`, `
|
|
457
|
+
Klicove sloupce: `status`, `authorizationUrls`, `paymentsChecksum`, `metadata`, `sizeLimit`, `accountId`, `paymentType`.
|
|
382
458
|
|
|
383
459
|
### account
|
|
384
460
|
|
package/dist/database/schema.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const paymentRequest_schema = require('../shared/bank.SQ4Mmr8u.cjs');
|
|
4
4
|
require('@develit-io/backend-sdk');
|
|
5
5
|
require('drizzle-orm/relations');
|
|
6
6
|
require('drizzle-orm/sqlite-core');
|
|
@@ -13,9 +13,11 @@ require('drizzle-zod');
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
exports.account =
|
|
17
|
-
exports.accountCredentials =
|
|
18
|
-
exports.batch =
|
|
19
|
-
exports.ott =
|
|
20
|
-
exports.payment =
|
|
21
|
-
exports.paymentRelations =
|
|
16
|
+
exports.account = paymentRequest_schema.account;
|
|
17
|
+
exports.accountCredentials = paymentRequest_schema.accountCredentials;
|
|
18
|
+
exports.batch = paymentRequest_schema.batch;
|
|
19
|
+
exports.ott = paymentRequest_schema.ott;
|
|
20
|
+
exports.payment = paymentRequest_schema.payment;
|
|
21
|
+
exports.paymentRelations = paymentRequest_schema.paymentRelations;
|
|
22
|
+
exports.paymentRequest = paymentRequest_schema.paymentRequest;
|
|
23
|
+
exports.paymentRequestRelations = paymentRequest_schema.paymentRequestRelations;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.cjs';
|
|
2
2
|
import 'drizzle-orm/sqlite-core';
|
|
3
3
|
import 'drizzle-orm';
|
|
4
4
|
import '@develit-io/backend-sdk';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.mjs';
|
|
2
2
|
import 'drizzle-orm/sqlite-core';
|
|
3
3
|
import 'drizzle-orm';
|
|
4
4
|
import '@develit-io/backend-sdk';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { as as account, at as accountCredentials, au as batch, av as ott, aw as payment, ax as paymentRelations, ay as paymentRequest, az as paymentRequestRelations } from '../shared/bank.BaMRCHk-.js';
|
|
2
2
|
import 'drizzle-orm/sqlite-core';
|
|
3
3
|
import 'drizzle-orm';
|
|
4
4
|
import '@develit-io/backend-sdk';
|
package/dist/database/schema.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { n as account, p as accountCredentials, q as batch, r as ott, s as payment, t as paymentRelations } from '../shared/bank.
|
|
1
|
+
export { 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 '../shared/bank.C4VOdIx1.mjs';
|
|
2
2
|
import '@develit-io/backend-sdk';
|
|
3
3
|
import 'drizzle-orm/relations';
|
|
4
4
|
import 'drizzle-orm/sqlite-core';
|
package/dist/export/worker.cjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const backendSdk = require('@develit-io/backend-sdk');
|
|
4
|
-
const drizzle = require('../shared/bank.
|
|
4
|
+
const drizzle = require('../shared/bank.BOnP9p9Y.cjs');
|
|
5
5
|
const cloudflare_workers = require('cloudflare:workers');
|
|
6
6
|
const d1 = require('drizzle-orm/d1');
|
|
7
|
+
const mock_connector = require('../shared/bank.CQURey1E.cjs');
|
|
8
|
+
require('jose');
|
|
7
9
|
const zod = require('zod');
|
|
8
|
-
const
|
|
10
|
+
const paymentRequest_schema = require('../shared/bank.SQ4Mmr8u.cjs');
|
|
9
11
|
const generalCodes = require('@develit-io/general-codes');
|
|
10
12
|
require('date-fns');
|
|
11
|
-
require('jose');
|
|
12
13
|
const drizzleOrm = require('drizzle-orm');
|
|
13
14
|
require('node:crypto');
|
|
14
|
-
|
|
15
|
-
require('../shared/bank.Cp0yvOdq.cjs');
|
|
15
|
+
require('../shared/bank.C-T1FQxg.cjs');
|
|
16
16
|
require('drizzle-orm/relations');
|
|
17
17
|
require('drizzle-orm/sqlite-core');
|
|
18
18
|
require('drizzle-zod');
|
|
@@ -94,6 +94,16 @@ const deletePaymentsByAccountCommand = (db, { accountId }) => {
|
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
+
const createPaymentRequestCommand = (db, { paymentRequest }) => {
|
|
98
|
+
return {
|
|
99
|
+
command: db.insert(drizzle.tables.paymentRequest).values({
|
|
100
|
+
...paymentRequest,
|
|
101
|
+
creditorIban: paymentRequest.creditor.iban,
|
|
102
|
+
debtorIban: paymentRequest.debtor.iban
|
|
103
|
+
}).returning()
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
|
|
97
107
|
const getAccountBatchCountsQuery = async (db, { accountId }) => {
|
|
98
108
|
const result = await db.select({
|
|
99
109
|
totalCount: drizzleOrm.sql`COUNT(*)`.as("totalCount"),
|
|
@@ -144,7 +154,7 @@ const getAllAccountsQuery = async (db, filters) => {
|
|
|
144
154
|
};
|
|
145
155
|
|
|
146
156
|
const getAllPendingBatchesQuery = (db) => {
|
|
147
|
-
return db.select().from(drizzle.tables.batch).where(drizzleOrm.inArray(drizzle.tables.batch.status, ["READY_TO_SIGN"]));
|
|
157
|
+
return db.select().from(drizzle.tables.batch).where(drizzleOrm.inArray(drizzle.tables.batch.status, ["READY_TO_SIGN", "SIGNED"]));
|
|
148
158
|
};
|
|
149
159
|
|
|
150
160
|
const buildMultiFilterConditions = (column, value) => {
|
|
@@ -229,8 +239,18 @@ const getBatchesQuery = async (db, {
|
|
|
229
239
|
totalCount: drizzleOrm.sql`count(*)`
|
|
230
240
|
}).from(drizzle.tables.batch).where(whereConditions);
|
|
231
241
|
const batches = await db.select().from(drizzle.tables.batch).where(whereConditions).limit(limit).offset((page - 1) * limit).orderBy(sort.direction === "asc" ? drizzleOrm.asc(sortColumn) : drizzleOrm.desc(sortColumn));
|
|
242
|
+
const batchIds = batches.map((b) => b.id);
|
|
243
|
+
const paymentRequests = batchIds.length > 0 ? await db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.inArray(drizzle.tables.paymentRequest.batchId, batchIds)) : [];
|
|
244
|
+
const paymentRequestsByBatchId = Map.groupBy(
|
|
245
|
+
paymentRequests,
|
|
246
|
+
(pr) => pr.batchId
|
|
247
|
+
);
|
|
248
|
+
const batchesWithPaymentRequests = batches.map((batch) => ({
|
|
249
|
+
...batch,
|
|
250
|
+
paymentRequests: paymentRequestsByBatchId.get(batch.id) ?? []
|
|
251
|
+
}));
|
|
232
252
|
return {
|
|
233
|
-
batches,
|
|
253
|
+
batches: batchesWithPaymentRequests,
|
|
234
254
|
totalCount
|
|
235
255
|
};
|
|
236
256
|
};
|
|
@@ -249,6 +269,11 @@ const getOttQuery = async (db, { ott }) => {
|
|
|
249
269
|
return await db.select().from(drizzle.tables.ott).where(drizzleOrm.eq(drizzle.tables.ott.oneTimeToken, ott)).get();
|
|
250
270
|
};
|
|
251
271
|
|
|
272
|
+
const getPaymentRequestByIdQuery = async (db, { paymentId }) => {
|
|
273
|
+
const results = await db.select().from(drizzle.tables.paymentRequest).where(drizzleOrm.eq(drizzle.tables.paymentRequest.id, paymentId)).limit(1);
|
|
274
|
+
return results[0] ?? null;
|
|
275
|
+
};
|
|
276
|
+
|
|
252
277
|
const seperateSupportedPayments = (incomingPayments, accounts) => {
|
|
253
278
|
const [supportedPayments, unsupportedPayments] = incomingPayments.reduce(
|
|
254
279
|
([valid, invalid], payment) => {
|
|
@@ -274,10 +299,10 @@ const sendPaymentInputSchema = zod.z.object({
|
|
|
274
299
|
correlationId: zod.z.string().min(1),
|
|
275
300
|
refId: zod.z.string().optional(),
|
|
276
301
|
amount: zod.z.number().positive(),
|
|
277
|
-
paymentType: zod.z.enum(
|
|
278
|
-
chargeBearer: zod.z.enum(
|
|
302
|
+
paymentType: zod.z.enum(paymentRequest_schema.PAYMENT_TYPES),
|
|
303
|
+
chargeBearer: zod.z.enum(paymentRequest_schema.CHARGE_BEARERS).optional(),
|
|
279
304
|
executionDate: zod.z.string().optional(),
|
|
280
|
-
instructionPriority: zod.z.enum(
|
|
305
|
+
instructionPriority: zod.z.enum(paymentRequest_schema.INSTRUCTION_PRIORITIES).optional(),
|
|
281
306
|
currency: zod.z.enum(generalCodes.CURRENCY_CODES),
|
|
282
307
|
vs: zod.z.string().optional(),
|
|
283
308
|
ss: zod.z.string().optional(),
|
|
@@ -290,7 +315,7 @@ const sendPaymentInputSchema = zod.z.object({
|
|
|
290
315
|
});
|
|
291
316
|
|
|
292
317
|
const getAuthUriInputSchema = zod.z.object({
|
|
293
|
-
connectorKey: zod.z.enum(
|
|
318
|
+
connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
|
|
294
319
|
});
|
|
295
320
|
|
|
296
321
|
const authorizeAccountInputSchema = zod.z.object({
|
|
@@ -311,7 +336,7 @@ const simulateDepositInputSchema = zod.z.object({
|
|
|
311
336
|
message: zod.z.string(),
|
|
312
337
|
creditor: backendSdk.bankAccountMetadataSchema,
|
|
313
338
|
debtor: backendSdk.bankAccountMetadataSchema,
|
|
314
|
-
connectorKey: zod.z.enum(
|
|
339
|
+
connectorKey: zod.z.enum(paymentRequest_schema.CONNECTOR_KEYS)
|
|
315
340
|
});
|
|
316
341
|
|
|
317
342
|
const ALLOWED_BATCH_FILTERS = {
|
|
@@ -326,7 +351,7 @@ const getBatchesInputSchema = zod.z.object({
|
|
|
326
351
|
direction: zod.z.enum(["asc", "desc"])
|
|
327
352
|
}),
|
|
328
353
|
[ALLOWED_BATCH_FILTERS.ACCOUNT_ID]: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
|
|
329
|
-
[ALLOWED_BATCH_FILTERS.STATUS]: zod.z.union([zod.z.enum(
|
|
354
|
+
[ALLOWED_BATCH_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.BATCH_STATUSES), zod.z.enum(paymentRequest_schema.BATCH_STATUSES).array()]).optional()
|
|
330
355
|
});
|
|
331
356
|
|
|
332
357
|
const processBatchInputSchema = zod.z.object({
|
|
@@ -381,10 +406,10 @@ const getPaymentsInputSchema = zod.z.object({
|
|
|
381
406
|
[ALLOWED_PAYMENT_FILTERS.ACCOUNT_ID]: zod.z.union([zod.z.uuid(), zod.z.uuid().array()]).optional(),
|
|
382
407
|
[ALLOWED_PAYMENT_FILTERS.AMOUNT]: zod.z.union([zod.z.number(), zod.z.number().array()]).optional(),
|
|
383
408
|
[ALLOWED_PAYMENT_FILTERS.CURRENCY]: zod.z.union([zod.z.enum(generalCodes.CURRENCY_CODES), zod.z.enum(generalCodes.CURRENCY_CODES).array()]).optional(),
|
|
384
|
-
[ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(
|
|
409
|
+
[ALLOWED_PAYMENT_FILTERS.DIRECTION]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS), zod.z.enum(paymentRequest_schema.PAYMENT_DIRECTIONS).array()]).optional(),
|
|
385
410
|
[ALLOWED_PAYMENT_FILTERS.FROM]: zod.z.date().optional(),
|
|
386
411
|
[ALLOWED_PAYMENT_FILTERS.TO]: zod.z.date().optional(),
|
|
387
|
-
[ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(
|
|
412
|
+
[ALLOWED_PAYMENT_FILTERS.STATUS]: zod.z.union([zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES), zod.z.enum(paymentRequest_schema.PAYMENT_STATUSES).array()]).optional()
|
|
388
413
|
});
|
|
389
414
|
|
|
390
415
|
const syncAccountInputSchema = zod.z.object({
|
|
@@ -419,7 +444,7 @@ zod.z.object({
|
|
|
419
444
|
});
|
|
420
445
|
|
|
421
446
|
const updateAccountInputSchema = zod.z.object({
|
|
422
|
-
account:
|
|
447
|
+
account: paymentRequest_schema.accountInsertSchema
|
|
423
448
|
});
|
|
424
449
|
|
|
425
450
|
const getBankAccountsInputSchema = zod.z.object({
|
|
@@ -434,6 +459,13 @@ const disconnectAccountInputSchema = zod.z.object({
|
|
|
434
459
|
accountId: zod.z.uuid()
|
|
435
460
|
});
|
|
436
461
|
|
|
462
|
+
const handleAuthorizationCallbackInputSchema = zod.z.object({
|
|
463
|
+
paymentId: zod.z.string().uuid().optional(),
|
|
464
|
+
batchId: zod.z.string().uuid().optional()
|
|
465
|
+
}).refine((data) => data.paymentId || data.batchId, {
|
|
466
|
+
message: "Either paymentId or batchId is required"
|
|
467
|
+
});
|
|
468
|
+
|
|
437
469
|
const sendPaymentSyncInputSchema = sendPaymentInputSchema;
|
|
438
470
|
|
|
439
471
|
var __defProp = Object.defineProperty;
|
|
@@ -593,12 +625,45 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
593
625
|
}).command.execute();
|
|
594
626
|
statusChanged = true;
|
|
595
627
|
}
|
|
628
|
+
if (statusChanged) {
|
|
629
|
+
const paymentRequests = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
|
|
630
|
+
batchId: batch.id
|
|
631
|
+
});
|
|
632
|
+
const perPaymentStatuses = "payments" in apiResponse ? apiResponse.payments : null;
|
|
633
|
+
const batchStatusToPaymentStatus = {
|
|
634
|
+
SIGNED: "SIGNED",
|
|
635
|
+
COMPLETED: "COMPLETED",
|
|
636
|
+
FAILED: "FAILED",
|
|
637
|
+
SIGNATURE_FAILED: "FAILED"
|
|
638
|
+
};
|
|
639
|
+
for (const pr of paymentRequests) {
|
|
640
|
+
let newStatus = pr.status;
|
|
641
|
+
if (perPaymentStatuses) {
|
|
642
|
+
const match = perPaymentStatuses.find(
|
|
643
|
+
(p) => p.merchantTransactionId === pr.id
|
|
644
|
+
);
|
|
645
|
+
if (match) {
|
|
646
|
+
newStatus = mock_connector.mapFinbricksTransactionStatus(
|
|
647
|
+
match.resultCode
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
} else {
|
|
651
|
+
newStatus = batchStatusToPaymentStatus[currentStatus] ?? pr.status;
|
|
652
|
+
}
|
|
653
|
+
if (newStatus !== pr.status) {
|
|
654
|
+
await drizzle.updatePaymentRequestStatusCommand(this.db, {
|
|
655
|
+
id: pr.id,
|
|
656
|
+
status: newStatus,
|
|
657
|
+
processedAt: newStatus === "COMPLETED" || newStatus === "FAILED" ? /* @__PURE__ */ new Date() : void 0
|
|
658
|
+
}).command.execute();
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
596
662
|
return {
|
|
597
663
|
batchId: batch.id,
|
|
598
664
|
previousStatus,
|
|
599
665
|
currentStatus,
|
|
600
666
|
statusChanged
|
|
601
|
-
// eventSent,
|
|
602
667
|
};
|
|
603
668
|
}
|
|
604
669
|
async updateBatchStatuses(input) {
|
|
@@ -670,6 +735,77 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
670
735
|
}
|
|
671
736
|
);
|
|
672
737
|
}
|
|
738
|
+
async handleAuthorizationCallback(input) {
|
|
739
|
+
return this.handleAction(
|
|
740
|
+
{ data: input, schema: handleAuthorizationCallbackInputSchema },
|
|
741
|
+
{ successMessage: "Authorization callback processed" },
|
|
742
|
+
async ({ paymentId, batchId }) => {
|
|
743
|
+
let targetBatchId = null;
|
|
744
|
+
let paymentsUpdated = 0;
|
|
745
|
+
if (paymentId) {
|
|
746
|
+
const pr = await getPaymentRequestByIdQuery(this.db, { paymentId });
|
|
747
|
+
if (!pr) {
|
|
748
|
+
throw backendSdk.createInternalError(null, {
|
|
749
|
+
message: `Payment request not found: ${paymentId}`,
|
|
750
|
+
code: "DB-B-008",
|
|
751
|
+
status: 404
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
|
|
755
|
+
await drizzle.updatePaymentRequestStatusCommand(this.db, {
|
|
756
|
+
id: paymentId,
|
|
757
|
+
status: "SIGNED"
|
|
758
|
+
}).command.execute();
|
|
759
|
+
paymentsUpdated = 1;
|
|
760
|
+
}
|
|
761
|
+
targetBatchId = pr.batchId;
|
|
762
|
+
}
|
|
763
|
+
if (batchId) {
|
|
764
|
+
targetBatchId = batchId;
|
|
765
|
+
const batchPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
|
|
766
|
+
this.db,
|
|
767
|
+
{
|
|
768
|
+
batchId
|
|
769
|
+
}
|
|
770
|
+
);
|
|
771
|
+
for (const pr of batchPayments) {
|
|
772
|
+
if (pr.status !== "SIGNED" && pr.status !== "COMPLETED") {
|
|
773
|
+
await drizzle.updatePaymentRequestStatusCommand(this.db, {
|
|
774
|
+
id: pr.id,
|
|
775
|
+
status: "SIGNED"
|
|
776
|
+
}).command.execute();
|
|
777
|
+
paymentsUpdated++;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
let batchSigned = false;
|
|
782
|
+
if (targetBatchId) {
|
|
783
|
+
const allPayments = await drizzle.getPaymentRequestsByBatchIdQuery(this.db, {
|
|
784
|
+
batchId: targetBatchId
|
|
785
|
+
});
|
|
786
|
+
const allDone = allPayments.every(
|
|
787
|
+
(p) => p.status === "SIGNED" || p.status === "COMPLETED"
|
|
788
|
+
);
|
|
789
|
+
if (allDone) {
|
|
790
|
+
const batch = await drizzle.getBatchByIdQuery(this.db, {
|
|
791
|
+
batchId: targetBatchId
|
|
792
|
+
});
|
|
793
|
+
if (batch && batch.status !== "SIGNED") {
|
|
794
|
+
await drizzle.upsertBatchCommand(this.db, {
|
|
795
|
+
batch: { ...batch, status: "SIGNED" }
|
|
796
|
+
}).command.execute();
|
|
797
|
+
batchSigned = true;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return {
|
|
802
|
+
paymentsUpdated,
|
|
803
|
+
batchId: targetBatchId,
|
|
804
|
+
batchSigned
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
);
|
|
808
|
+
}
|
|
673
809
|
async addPaymentsToBatch({
|
|
674
810
|
paymentsToBatch
|
|
675
811
|
}) {
|
|
@@ -715,21 +851,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
715
851
|
(p) => p.sendAsSinglePayment !== true
|
|
716
852
|
);
|
|
717
853
|
for (const singlePayment of singlePayments) {
|
|
718
|
-
const
|
|
719
|
-
const { command } = drizzle.upsertBatchCommand(this.db, {
|
|
854
|
+
const batchId = backendSdk.uuidv4();
|
|
855
|
+
const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
|
|
720
856
|
batch: {
|
|
721
|
-
id:
|
|
857
|
+
id: batchId,
|
|
722
858
|
authorizationUrls: [],
|
|
723
859
|
accountId: acc.id,
|
|
724
860
|
paymentType: singlePayment.paymentType,
|
|
725
|
-
payments: [batchedPayment],
|
|
726
861
|
status: "OPEN",
|
|
727
|
-
metadata: {
|
|
728
|
-
sizeLimit: 1
|
|
729
|
-
}
|
|
862
|
+
metadata: { sizeLimit: 1 }
|
|
730
863
|
}
|
|
731
864
|
});
|
|
732
|
-
|
|
865
|
+
const { command: insertPaymentRequest } = createPaymentRequestCommand(
|
|
866
|
+
this.db,
|
|
867
|
+
{
|
|
868
|
+
paymentRequest: mock_connector.toPaymentRequestInsert(singlePayment, batchId)
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
await this.db.batch([upsertBatch, insertPaymentRequest]);
|
|
733
872
|
this.log({
|
|
734
873
|
message: `\u2728 Created single payment batch (${singlePayment.paymentType}) for account ${acc.id}`
|
|
735
874
|
});
|
|
@@ -744,30 +883,48 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
744
883
|
accountId: acc.id,
|
|
745
884
|
paymentType
|
|
746
885
|
});
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
886
|
+
let batchId;
|
|
887
|
+
let availableCount = 0;
|
|
888
|
+
let availableBatch;
|
|
889
|
+
for (const ob of openBatches) {
|
|
890
|
+
const existingPayments = await drizzle.getPaymentRequestsByBatchIdQuery(
|
|
891
|
+
this.db,
|
|
892
|
+
{ batchId: ob.id }
|
|
893
|
+
);
|
|
894
|
+
const limit = ob.metadata?.sizeLimit ?? acc.batchSizeLimit;
|
|
895
|
+
if (existingPayments.length < limit) {
|
|
896
|
+
availableBatch = ob;
|
|
897
|
+
availableCount = existingPayments.length;
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
if (availableBatch) {
|
|
902
|
+
batchId = availableBatch.id;
|
|
903
|
+
this.log({
|
|
904
|
+
message: `\u{1F504} Found existing OPEN batch (${paymentType}) for account ${acc.id}, merging ${availableCount} existing + ${paymentsOfType.length} new payments`
|
|
905
|
+
});
|
|
906
|
+
} else {
|
|
907
|
+
batchId = backendSdk.uuidv4();
|
|
908
|
+
this.log({
|
|
909
|
+
message: `\u2728 Creating new batch (${paymentType}) for account ${acc.id} with ${paymentsOfType.length} payments`
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const { command: upsertBatch } = drizzle.upsertBatchCommand(this.db, {
|
|
913
|
+
batch: availableBatch ? { ...availableBatch } : {
|
|
914
|
+
id: batchId,
|
|
760
915
|
authorizationUrls: [],
|
|
761
916
|
accountId: acc.id,
|
|
762
917
|
paymentType,
|
|
763
|
-
payments: batchedPayments,
|
|
764
918
|
status: "OPEN",
|
|
765
|
-
metadata: {
|
|
766
|
-
sizeLimit: acc.batchSizeLimit
|
|
767
|
-
}
|
|
919
|
+
metadata: { sizeLimit: acc.batchSizeLimit }
|
|
768
920
|
}
|
|
769
921
|
});
|
|
770
|
-
|
|
922
|
+
const paymentRequestCommands = paymentsOfType.map(
|
|
923
|
+
(p) => createPaymentRequestCommand(this.db, {
|
|
924
|
+
paymentRequest: mock_connector.toPaymentRequestInsert(p, batchId)
|
|
925
|
+
}).command
|
|
926
|
+
);
|
|
927
|
+
await this.db.batch([upsertBatch, ...paymentRequestCommands]);
|
|
771
928
|
this.log({
|
|
772
929
|
message: `\u2705 Batch (${paymentType}) upserted successfully for account ${acc.id}`
|
|
773
930
|
});
|
|
@@ -1256,6 +1413,24 @@ let BankServiceBase = class extends backendSdk.develitWorker(cloudflare_workers.
|
|
|
1256
1413
|
}
|
|
1257
1414
|
);
|
|
1258
1415
|
}
|
|
1416
|
+
async getFinbricksSupportedBanks() {
|
|
1417
|
+
const privateKeyPem = (await this.env.SECRETS_STORE.get({
|
|
1418
|
+
secretName: "BANK_SERVICE_FINBRICKS_PRIVATE_KEY_PEM"
|
|
1419
|
+
})).data?.secretValue || "";
|
|
1420
|
+
const client = new mock_connector.FinbricksClient(
|
|
1421
|
+
this.env.FINBRICKS_BASE_URI,
|
|
1422
|
+
this.env.FINBRICKS_MERCHANT_ID,
|
|
1423
|
+
privateKeyPem,
|
|
1424
|
+
this.env.REDIRECT_URI
|
|
1425
|
+
);
|
|
1426
|
+
return client.request({
|
|
1427
|
+
endpoint: mock_connector.FINBRICKS_ENDPOINTS.BANK_INFO,
|
|
1428
|
+
method: "GET",
|
|
1429
|
+
query: {
|
|
1430
|
+
merchantId: this.env.FINBRICKS_MERCHANT_ID
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1259
1434
|
};
|
|
1260
1435
|
__decorateClass([
|
|
1261
1436
|
backendSdk.action("get-payments")
|
|
@@ -1272,6 +1447,9 @@ __decorateClass([
|
|
|
1272
1447
|
__decorateClass([
|
|
1273
1448
|
backendSdk.action("update-batch-statuses")
|
|
1274
1449
|
], BankServiceBase.prototype, "updateBatchStatuses", 1);
|
|
1450
|
+
__decorateClass([
|
|
1451
|
+
backendSdk.action("handle-authorization-callback")
|
|
1452
|
+
], BankServiceBase.prototype, "handleAuthorizationCallback", 1);
|
|
1275
1453
|
__decorateClass([
|
|
1276
1454
|
backendSdk.action("add-payments-to-batch")
|
|
1277
1455
|
], BankServiceBase.prototype, "addPaymentsToBatch", 1);
|