@develit-services/bank 0.3.59 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/schema.cjs +9 -9
- package/dist/database/schema.d.cts +4 -5
- package/dist/database/schema.d.mts +4 -5
- package/dist/database/schema.d.ts +4 -5
- package/dist/database/schema.mjs +3 -3
- package/dist/export/worker.cjs +91 -85
- package/dist/export/worker.d.cts +32 -771
- package/dist/export/worker.d.mts +32 -771
- package/dist/export/worker.d.ts +32 -771
- package/dist/export/worker.mjs +72 -66
- package/dist/export/workflows.cjs +215 -211
- package/dist/export/workflows.d.cts +4 -4
- package/dist/export/workflows.d.mts +4 -4
- package/dist/export/workflows.d.ts +4 -4
- package/dist/export/workflows.mjs +210 -206
- package/dist/export/wrangler.d.cts +3 -1
- package/dist/export/wrangler.d.mts +3 -1
- package/dist/export/wrangler.d.ts +3 -1
- package/dist/shared/{bank.CXcZewU9.mjs → bank.B51e8oDT.mjs} +6 -76
- package/dist/shared/{bank.Dh_H_5rC.d.cts → bank.BJvgLwyZ.d.cts} +2 -0
- package/dist/shared/{bank.Dh_H_5rC.d.mts → bank.BJvgLwyZ.d.mts} +2 -0
- package/dist/shared/{bank.Dh_H_5rC.d.ts → bank.BJvgLwyZ.d.ts} +2 -0
- package/dist/shared/bank.BUSlmr6r.mjs +13 -0
- package/dist/shared/{bank.BnDb4liE.cjs → bank.BeIpkWR-.cjs} +6 -15
- package/dist/shared/bank.Bg3Pdwm4.cjs +44 -0
- package/dist/shared/bank.CDoYUKBx.d.cts +748 -0
- package/dist/shared/bank.CDoYUKBx.d.mts +748 -0
- package/dist/shared/bank.CDoYUKBx.d.ts +748 -0
- package/dist/shared/{bank.0IwqmnZ7.cjs → bank.CfSZTfWS.cjs} +634 -179
- package/dist/shared/{bank.BwXpqjVU.d.mts → bank.CsJuzqZH.d.cts} +2400 -2116
- package/dist/shared/{bank.BwXpqjVU.d.ts → bank.CsJuzqZH.d.mts} +2400 -2116
- package/dist/shared/{bank.BwXpqjVU.d.cts → bank.CsJuzqZH.d.ts} +2400 -2116
- package/dist/shared/{bank.Cg05BigT.cjs → bank.DEvSNsEs.cjs} +12 -82
- package/dist/shared/{bank.Dh6IUoHL.mjs → bank.DinCwx0P.mjs} +627 -179
- package/dist/shared/bank.Dpx6PvkA.mjs +33 -0
- package/dist/shared/bank.c38V_FCq.cjs +15 -0
- package/dist/shared/{bank.BPxg79Tw.mjs → bank.qc8ALZwm.mjs} +7 -15
- package/dist/types.cjs +51 -33
- package/dist/types.d.cts +165 -40
- package/dist/types.d.mts +165 -40
- package/dist/types.d.ts +165 -40
- package/dist/types.mjs +4 -3
- package/package.json +7 -10
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
2
|
|
|
3
3
|
type Params$1 = {
|
|
4
|
-
|
|
4
|
+
batchId: string;
|
|
5
5
|
};
|
|
6
|
-
declare class
|
|
6
|
+
declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
7
7
|
run(event: WorkflowEvent<Params$1>, step: WorkflowStep): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
|
-
|
|
11
|
+
accountId: string;
|
|
12
12
|
};
|
|
13
|
-
declare class
|
|
13
|
+
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
14
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
2
|
|
|
3
3
|
type Params$1 = {
|
|
4
|
-
|
|
4
|
+
batchId: string;
|
|
5
5
|
};
|
|
6
|
-
declare class
|
|
6
|
+
declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
7
7
|
run(event: WorkflowEvent<Params$1>, step: WorkflowStep): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
|
-
|
|
11
|
+
accountId: string;
|
|
12
12
|
};
|
|
13
|
-
declare class
|
|
13
|
+
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
14
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
2
|
|
|
3
3
|
type Params$1 = {
|
|
4
|
-
|
|
4
|
+
batchId: string;
|
|
5
5
|
};
|
|
6
|
-
declare class
|
|
6
|
+
declare class BankProcessBatch extends WorkflowEntrypoint<BankEnv, Params$1> {
|
|
7
7
|
run(event: WorkflowEvent<Params$1>, step: WorkflowStep): Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
type Params = {
|
|
11
|
-
|
|
11
|
+
accountId: string;
|
|
12
12
|
};
|
|
13
|
-
declare class
|
|
13
|
+
declare class BankSyncAccountPayments extends WorkflowEntrypoint<BankEnv, Params> {
|
|
14
14
|
run(event: WorkflowEvent<Params>, step: WorkflowStep): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { first, uuidv4, asNonEmpty } from '@develit-io/backend-sdk';
|
|
1
2
|
import { WorkflowEntrypoint } from 'cloudflare:workers';
|
|
2
3
|
import { NonRetryableError } from 'cloudflare:workflows';
|
|
3
4
|
import { drizzle } from 'drizzle-orm/d1';
|
|
4
|
-
import { t as tables } from '../shared/bank.
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { t as tables, g as getBatchByIdQuery, c as checksum, u as upsertBatchCommand, a as getAccountByIdQuery, i as importAesKey, b as getCredentialsByAccountId, d as createPaymentCommand } from '../shared/bank.B51e8oDT.mjs';
|
|
6
|
+
import { d as isBatchSigned, j as isBatchFailed, g as isBatchOpen, a as isPaymentCompleted } from '../shared/bank.Dpx6PvkA.mjs';
|
|
7
|
+
import { f as toPreparedPayment, i as initiateConnector, g as toCompletedPayment } from '../shared/bank.DinCwx0P.mjs';
|
|
7
8
|
import { eq } from 'drizzle-orm';
|
|
8
|
-
import '
|
|
9
|
-
import '../shared/bank.
|
|
10
|
-
import 'drizzle-orm/sqlite-core';
|
|
9
|
+
import '../shared/bank.BUSlmr6r.mjs';
|
|
10
|
+
import '../shared/bank.qc8ALZwm.mjs';
|
|
11
11
|
import 'drizzle-orm/relations';
|
|
12
|
+
import 'drizzle-orm/sqlite-core';
|
|
13
|
+
import 'date-fns';
|
|
12
14
|
import '@develit-io/general-codes';
|
|
13
15
|
import 'jose';
|
|
14
16
|
import 'node:crypto';
|
|
@@ -37,6 +39,206 @@ function pushToQueue$1(queue, message) {
|
|
|
37
39
|
}))
|
|
38
40
|
);
|
|
39
41
|
}
|
|
42
|
+
class BankProcessBatch extends WorkflowEntrypoint {
|
|
43
|
+
async run(event, step) {
|
|
44
|
+
const { batchId } = event.payload;
|
|
45
|
+
const db = drizzle(this.env.BANK_D1, { schema: tables });
|
|
46
|
+
const batch = await step.do("load batch", async () => {
|
|
47
|
+
const batch2 = await getBatchByIdQuery(db, { batchId });
|
|
48
|
+
if (!batch2) {
|
|
49
|
+
throw new NonRetryableError(`Batch not found`);
|
|
50
|
+
}
|
|
51
|
+
if (isBatchSigned(batch2))
|
|
52
|
+
throw new NonRetryableError(`Batch already signed`);
|
|
53
|
+
return batch2;
|
|
54
|
+
});
|
|
55
|
+
await step.do("lock batch", async () => {
|
|
56
|
+
const paymentsChecksum = checksum(batch.payments);
|
|
57
|
+
if (batch.paymentsChecksum && batch.paymentsChecksum !== paymentsChecksum)
|
|
58
|
+
throw new NonRetryableError(
|
|
59
|
+
`Batch payments have been modified externally, manual review needed`
|
|
60
|
+
);
|
|
61
|
+
if (isBatchFailed(batch))
|
|
62
|
+
throw new NonRetryableError(
|
|
63
|
+
`Batch is in FAILED status and cannot be processed, manual review needed`
|
|
64
|
+
);
|
|
65
|
+
if (isBatchOpen(batch)) {
|
|
66
|
+
const updatedBatch = await upsertBatchCommand(db, {
|
|
67
|
+
batch: {
|
|
68
|
+
...batch,
|
|
69
|
+
status: "PROCESSING",
|
|
70
|
+
paymentsChecksum
|
|
71
|
+
}
|
|
72
|
+
}).command.execute().then(first);
|
|
73
|
+
return { status: updatedBatch.status };
|
|
74
|
+
}
|
|
75
|
+
return { status: batch.status };
|
|
76
|
+
});
|
|
77
|
+
const batchResult = await step.do(
|
|
78
|
+
"initiate batch with payments",
|
|
79
|
+
{
|
|
80
|
+
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
81
|
+
timeout: "30 seconds"
|
|
82
|
+
},
|
|
83
|
+
async () => {
|
|
84
|
+
if (batch.batchPaymentInitiatedAt) {
|
|
85
|
+
return {
|
|
86
|
+
authorizationUrls: batch.authorizationUrls,
|
|
87
|
+
preparedPayments: batch.payments.map(
|
|
88
|
+
(p) => toPreparedPayment(p, void 0, batch.batchPaymentInitiatedAt)
|
|
89
|
+
),
|
|
90
|
+
metadata: batch.metadata
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const account = await getAccountByIdQuery(db, {
|
|
94
|
+
accountId: batch.accountId
|
|
95
|
+
});
|
|
96
|
+
if (!account) {
|
|
97
|
+
throw new NonRetryableError(`Account not found: ${batch.accountId}`);
|
|
98
|
+
}
|
|
99
|
+
const encryptionKey = await importAesKey(this.env.ENCRYPTION_KEY);
|
|
100
|
+
const credentials = await getCredentialsByAccountId(db, encryptionKey, {
|
|
101
|
+
accountId: account.id
|
|
102
|
+
});
|
|
103
|
+
if (!credentials) {
|
|
104
|
+
throw new NonRetryableError(
|
|
105
|
+
`No credentials found for account: ${account.id}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (credentials.expiresAt < /* @__PURE__ */ new Date()) {
|
|
109
|
+
throw new NonRetryableError(
|
|
110
|
+
`Credentials have expired for account: ${account.id}`
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const connector = initiateConnector({
|
|
114
|
+
env: this.env,
|
|
115
|
+
bank: account.connectorKey,
|
|
116
|
+
connectedAccounts: [
|
|
117
|
+
{
|
|
118
|
+
...account,
|
|
119
|
+
iban: account.iban,
|
|
120
|
+
token: credentials.value
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
});
|
|
124
|
+
const result = await connector.initiateBatch({
|
|
125
|
+
batchId: batch.id,
|
|
126
|
+
payments: batch.payments
|
|
127
|
+
});
|
|
128
|
+
const {
|
|
129
|
+
authorizationUrls,
|
|
130
|
+
payments: preparedPayments,
|
|
131
|
+
metadata
|
|
132
|
+
} = result;
|
|
133
|
+
if (!authorizationUrls || authorizationUrls.length === 0) {
|
|
134
|
+
throw new Error("Failed to retrieve authorization URLs");
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
authorizationUrls,
|
|
138
|
+
preparedPayments,
|
|
139
|
+
metadata
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
await step.do("update batch to ready to sign", async () => {
|
|
144
|
+
const upsertBatch = upsertBatchCommand(db, {
|
|
145
|
+
batch: {
|
|
146
|
+
...batch,
|
|
147
|
+
authorizationUrls: batchResult.authorizationUrls,
|
|
148
|
+
metadata: batchResult.metadata,
|
|
149
|
+
status: "READY_TO_SIGN",
|
|
150
|
+
batchPaymentInitiatedAt: /* @__PURE__ */ new Date()
|
|
151
|
+
}
|
|
152
|
+
}).command;
|
|
153
|
+
await upsertBatch.execute();
|
|
154
|
+
return {
|
|
155
|
+
status: "READY_TO_SIGN",
|
|
156
|
+
paymentsPrepared: batchResult.preparedPayments.length
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
const isMockConnector = batchResult.preparedPayments.some(
|
|
160
|
+
(p) => p.connectorKey === "MOCK"
|
|
161
|
+
);
|
|
162
|
+
if (isMockConnector) {
|
|
163
|
+
await step.do(
|
|
164
|
+
"mock: create completed payments and update batch",
|
|
165
|
+
async () => {
|
|
166
|
+
const processedAt = /* @__PURE__ */ new Date();
|
|
167
|
+
const completedPayments = batchResult.preparedPayments.map(
|
|
168
|
+
(p) => toCompletedPayment(p, "COMPLETED", `MOCK-${uuidv4()}`, processedAt)
|
|
169
|
+
);
|
|
170
|
+
const createCommands = completedPayments.map(
|
|
171
|
+
(payment) => createPaymentCommand(db, { payment }).command
|
|
172
|
+
);
|
|
173
|
+
const updateBatchCommand = upsertBatchCommand(db, {
|
|
174
|
+
batch: {
|
|
175
|
+
...batch,
|
|
176
|
+
status: "SIGNED",
|
|
177
|
+
authorizationUrls: batchResult.authorizationUrls,
|
|
178
|
+
metadata: batchResult.metadata,
|
|
179
|
+
batchPaymentInitiatedAt: /* @__PURE__ */ new Date()
|
|
180
|
+
}
|
|
181
|
+
}).command;
|
|
182
|
+
if (createCommands.length > 0) {
|
|
183
|
+
await db.batch([updateBatchCommand, ...createCommands]);
|
|
184
|
+
} else {
|
|
185
|
+
await updateBatchCommand.execute();
|
|
186
|
+
}
|
|
187
|
+
const eventsToEmit = completedPayments.map(
|
|
188
|
+
(payment) => ({
|
|
189
|
+
eventType: "BANK_PAYMENT",
|
|
190
|
+
eventSignal: "paymentCompleted",
|
|
191
|
+
bankPayment: payment,
|
|
192
|
+
metadata: {
|
|
193
|
+
correlationId: uuidv4(),
|
|
194
|
+
entityId: payment.id,
|
|
195
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
);
|
|
199
|
+
await pushToQueue$1(
|
|
200
|
+
this.env.QUEUE_BUS_QUEUE,
|
|
201
|
+
eventsToEmit
|
|
202
|
+
);
|
|
203
|
+
return {
|
|
204
|
+
paymentsCreated: completedPayments.length,
|
|
205
|
+
eventsEmitted: completedPayments.length
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
if (!isMockConnector) {
|
|
211
|
+
await step.do("enqueue authorization email", async () => {
|
|
212
|
+
await pushToQueue$1(this.env.NOTIFICATIONS_QUEUE, {
|
|
213
|
+
type: "email",
|
|
214
|
+
payload: {
|
|
215
|
+
email: {
|
|
216
|
+
to: [this.env.BANK_AUTH_RECIPIENT],
|
|
217
|
+
subject: "Payment Authorization",
|
|
218
|
+
text: Array.isArray(batchResult.authorizationUrls) ? batchResult.authorizationUrls[0] || "No Authorization URL" : batchResult.authorizationUrls || "No Authorization URL"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
metadata: {
|
|
222
|
+
initiator: {
|
|
223
|
+
service: "bank"
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return { emailSent: true };
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function pushToQueue(queue, message) {
|
|
234
|
+
if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
|
|
235
|
+
return queue.sendBatch(
|
|
236
|
+
message.map((m) => ({
|
|
237
|
+
body: m,
|
|
238
|
+
contentType: "v8"
|
|
239
|
+
}))
|
|
240
|
+
);
|
|
241
|
+
}
|
|
40
242
|
class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
41
243
|
async run(event, step) {
|
|
42
244
|
const { accountId } = event.payload;
|
|
@@ -89,15 +291,13 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
89
291
|
]
|
|
90
292
|
});
|
|
91
293
|
return await connector.getAllAccountPayments({
|
|
92
|
-
environment: this.env.ENVIRONMENT,
|
|
93
|
-
db,
|
|
94
294
|
account,
|
|
95
295
|
filter: { dateFrom: account.lastSyncAt }
|
|
96
296
|
});
|
|
97
297
|
}
|
|
98
298
|
);
|
|
99
299
|
const paymentsToProcess = payments.filter(
|
|
100
|
-
(p) => p.parsed
|
|
300
|
+
(p) => isPaymentCompleted(p.parsed)
|
|
101
301
|
);
|
|
102
302
|
if (paymentsToProcess.length) {
|
|
103
303
|
const lastSyncBankRefIds = account.lastSyncMetadata?.lastSyncBankRefIds || [];
|
|
@@ -142,7 +342,7 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
142
342
|
await db.batch(
|
|
143
343
|
asNonEmpty([updateLastSyncCommand, ...createCommands])
|
|
144
344
|
);
|
|
145
|
-
await pushToQueue
|
|
345
|
+
await pushToQueue(
|
|
146
346
|
this.env.QUEUE_BUS_QUEUE,
|
|
147
347
|
eventsToEmit
|
|
148
348
|
);
|
|
@@ -162,200 +362,4 @@ class BankSyncAccountPayments extends WorkflowEntrypoint {
|
|
|
162
362
|
}
|
|
163
363
|
}
|
|
164
364
|
|
|
165
|
-
function pushToQueue(queue, message) {
|
|
166
|
-
if (!Array.isArray(message)) return queue.send(message, { contentType: "v8" });
|
|
167
|
-
return queue.sendBatch(
|
|
168
|
-
message.map((m) => ({
|
|
169
|
-
body: m,
|
|
170
|
-
contentType: "v8"
|
|
171
|
-
}))
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
class BankProcessBatch extends WorkflowEntrypoint {
|
|
175
|
-
async run(event, step) {
|
|
176
|
-
const { batchId } = event.payload;
|
|
177
|
-
const db = drizzle(this.env.BANK_D1, { schema: tables });
|
|
178
|
-
const batch = await step.do("load batch", async () => {
|
|
179
|
-
const batch2 = await getBatchByIdQuery(db, { batchId });
|
|
180
|
-
if (!batch2) {
|
|
181
|
-
throw new NonRetryableError(`Batch not found`);
|
|
182
|
-
}
|
|
183
|
-
if (batch2.status === "SIGNED")
|
|
184
|
-
throw new NonRetryableError(`Batch already signed`);
|
|
185
|
-
return batch2;
|
|
186
|
-
});
|
|
187
|
-
await step.do("lock batch", async () => {
|
|
188
|
-
const paymentsChecksum = checksum(batch.payments);
|
|
189
|
-
if (batch.paymentsChecksum && batch.paymentsChecksum !== paymentsChecksum)
|
|
190
|
-
throw new NonRetryableError(
|
|
191
|
-
`Batch payments have been modified externally, manual review needed`
|
|
192
|
-
);
|
|
193
|
-
if (batch.status === "FAILED")
|
|
194
|
-
throw new NonRetryableError(
|
|
195
|
-
`Batch is in FAILED status and cannot be processed, manual review needed`
|
|
196
|
-
);
|
|
197
|
-
if (batch.status === "OPEN") {
|
|
198
|
-
const updatedBatch = await upsertBatchCommand(db, {
|
|
199
|
-
batch: {
|
|
200
|
-
...batch,
|
|
201
|
-
status: "PROCESSING",
|
|
202
|
-
paymentsChecksum
|
|
203
|
-
}
|
|
204
|
-
}).command.execute().then(first);
|
|
205
|
-
return { status: updatedBatch.status };
|
|
206
|
-
}
|
|
207
|
-
return { status: batch.status };
|
|
208
|
-
});
|
|
209
|
-
const preparedPayments = await step.do(
|
|
210
|
-
"prepare payments",
|
|
211
|
-
{
|
|
212
|
-
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
213
|
-
timeout: "30 seconds"
|
|
214
|
-
},
|
|
215
|
-
async () => {
|
|
216
|
-
const account = await getAccountByIdQuery(db, {
|
|
217
|
-
accountId: batch.accountId
|
|
218
|
-
});
|
|
219
|
-
if (!account) {
|
|
220
|
-
throw new NonRetryableError(`Account not found: ${batch.accountId}`);
|
|
221
|
-
}
|
|
222
|
-
const encryptionKey = await importAesKey(this.env.ENCRYPTION_KEY);
|
|
223
|
-
const credentials = await getCredentialsByAccountId(db, encryptionKey, {
|
|
224
|
-
accountId: account.id
|
|
225
|
-
});
|
|
226
|
-
if (!credentials) {
|
|
227
|
-
throw new NonRetryableError(
|
|
228
|
-
`No credentials found for account: ${account.id}`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
if (credentials.expiresAt < /* @__PURE__ */ new Date()) {
|
|
232
|
-
throw new NonRetryableError(
|
|
233
|
-
`Credentials have expired for account: ${account.id}`
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
const connector = initiateConnector({
|
|
237
|
-
env: this.env,
|
|
238
|
-
bank: account.connectorKey,
|
|
239
|
-
connectedAccounts: [
|
|
240
|
-
{
|
|
241
|
-
...account,
|
|
242
|
-
iban: account.iban,
|
|
243
|
-
token: credentials.value
|
|
244
|
-
}
|
|
245
|
-
]
|
|
246
|
-
});
|
|
247
|
-
const preparedPayments2 = [];
|
|
248
|
-
for (const payment of batch.payments) {
|
|
249
|
-
const prepared = await connector.preparePayment(payment);
|
|
250
|
-
if (prepared) {
|
|
251
|
-
preparedPayments2.push(prepared);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return preparedPayments2;
|
|
255
|
-
}
|
|
256
|
-
);
|
|
257
|
-
const batchResult = await step.do(
|
|
258
|
-
"initiate batch from payments",
|
|
259
|
-
{
|
|
260
|
-
retries: { limit: 5, delay: 2e3, backoff: "constant" },
|
|
261
|
-
timeout: "30 seconds"
|
|
262
|
-
},
|
|
263
|
-
async () => {
|
|
264
|
-
if (batch.batchPaymentInitiatedAt) {
|
|
265
|
-
return {
|
|
266
|
-
authorizationUrls: batch.authorizationUrls,
|
|
267
|
-
initializedPayments: preparedPayments.map((p) => ({
|
|
268
|
-
...p,
|
|
269
|
-
status: "INITIALIZED"
|
|
270
|
-
})),
|
|
271
|
-
metadata: batch.metadata
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
const account = await getAccountByIdQuery(db, {
|
|
275
|
-
accountId: batch.accountId
|
|
276
|
-
});
|
|
277
|
-
if (!account) {
|
|
278
|
-
throw new NonRetryableError(`Account not found: ${batch.accountId}`);
|
|
279
|
-
}
|
|
280
|
-
const encryptionKey = await importAesKey(this.env.ENCRYPTION_KEY);
|
|
281
|
-
const credentials = await getCredentialsByAccountId(db, encryptionKey, {
|
|
282
|
-
accountId: account.id
|
|
283
|
-
});
|
|
284
|
-
if (!credentials) {
|
|
285
|
-
throw new NonRetryableError(
|
|
286
|
-
`No credentials found for account: ${account.id}`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
if (credentials.expiresAt < /* @__PURE__ */ new Date()) {
|
|
290
|
-
throw new NonRetryableError(
|
|
291
|
-
`Credentials have expired for account: ${account.id}`
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
const connector = initiateConnector({
|
|
295
|
-
env: this.env,
|
|
296
|
-
bank: account.connectorKey,
|
|
297
|
-
connectedAccounts: [
|
|
298
|
-
{
|
|
299
|
-
...account,
|
|
300
|
-
iban: account.iban,
|
|
301
|
-
token: credentials.value
|
|
302
|
-
}
|
|
303
|
-
]
|
|
304
|
-
});
|
|
305
|
-
const result = await connector.initiateBatchFromPayments({
|
|
306
|
-
batchId: batch.id,
|
|
307
|
-
payments: preparedPayments
|
|
308
|
-
});
|
|
309
|
-
const {
|
|
310
|
-
authorizationUrls,
|
|
311
|
-
payments: initializedPayments,
|
|
312
|
-
metadata
|
|
313
|
-
} = result;
|
|
314
|
-
if (!authorizationUrls || authorizationUrls.length === 0) {
|
|
315
|
-
throw new Error("Failed to retrieve authorization URLs");
|
|
316
|
-
}
|
|
317
|
-
return {
|
|
318
|
-
authorizationUrls,
|
|
319
|
-
initializedPayments,
|
|
320
|
-
metadata
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
);
|
|
324
|
-
await step.do("update batch and payments to initialized", async () => {
|
|
325
|
-
const upsertBatch = upsertBatchCommand(db, {
|
|
326
|
-
batch: {
|
|
327
|
-
...batch,
|
|
328
|
-
authorizationUrls: batchResult.authorizationUrls,
|
|
329
|
-
metadata: batchResult.metadata,
|
|
330
|
-
status: "READY_TO_SIGN",
|
|
331
|
-
batchPaymentInitiatedAt: /* @__PURE__ */ new Date()
|
|
332
|
-
}
|
|
333
|
-
}).command;
|
|
334
|
-
await upsertBatch.execute();
|
|
335
|
-
return {
|
|
336
|
-
status: "READY_TO_SIGN",
|
|
337
|
-
paymentsInitialized: batchResult.initializedPayments.length
|
|
338
|
-
};
|
|
339
|
-
});
|
|
340
|
-
await step.do("enqueue authorization email", async () => {
|
|
341
|
-
await pushToQueue(this.env.NOTIFICATIONS_QUEUE, {
|
|
342
|
-
type: "email",
|
|
343
|
-
payload: {
|
|
344
|
-
email: {
|
|
345
|
-
to: [this.env.BANK_AUTH_RECIPIENT],
|
|
346
|
-
subject: "Payment Authorization",
|
|
347
|
-
text: Array.isArray(batchResult.authorizationUrls) ? batchResult.authorizationUrls[0] || "No Authorization URL" : batchResult.authorizationUrls || "No Authorization URL"
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
metadata: {
|
|
351
|
-
initiator: {
|
|
352
|
-
service: "bank"
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
return { emailSent: true };
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
365
|
export { BankProcessBatch, BankSyncAccountPayments };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BankServiceWranglerConfig } from '../shared/bank.
|
|
1
|
+
import { B as BankServiceWranglerConfig } from '../shared/bank.BJvgLwyZ.cjs';
|
|
2
2
|
|
|
3
3
|
declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -11,6 +11,8 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
|
11
11
|
CRON_BATCH_STATUSES: string;
|
|
12
12
|
CRON_PAYMENTS_PROCESSING: string;
|
|
13
13
|
BANK_AUTH_RECIPIENT: string;
|
|
14
|
+
DBUCS_BASE_URI: string;
|
|
15
|
+
DBUCS_USERNAME: string;
|
|
14
16
|
REDIRECT_URI: string;
|
|
15
17
|
ENCRYPTION_KEY: string;
|
|
16
18
|
FINBRICKS_PRIVATE_KEY_PEM: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BankServiceWranglerConfig } from '../shared/bank.
|
|
1
|
+
import { B as BankServiceWranglerConfig } from '../shared/bank.BJvgLwyZ.mjs';
|
|
2
2
|
|
|
3
3
|
declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -11,6 +11,8 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
|
11
11
|
CRON_BATCH_STATUSES: string;
|
|
12
12
|
CRON_PAYMENTS_PROCESSING: string;
|
|
13
13
|
BANK_AUTH_RECIPIENT: string;
|
|
14
|
+
DBUCS_BASE_URI: string;
|
|
15
|
+
DBUCS_USERNAME: string;
|
|
14
16
|
REDIRECT_URI: string;
|
|
15
17
|
ENCRYPTION_KEY: string;
|
|
16
18
|
FINBRICKS_PRIVATE_KEY_PEM: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BankServiceWranglerConfig } from '../shared/bank.
|
|
1
|
+
import { B as BankServiceWranglerConfig } from '../shared/bank.BJvgLwyZ.js';
|
|
2
2
|
|
|
3
3
|
declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -11,6 +11,8 @@ declare function defineBankServiceWrangler(config: BankServiceWranglerConfig): {
|
|
|
11
11
|
CRON_BATCH_STATUSES: string;
|
|
12
12
|
CRON_PAYMENTS_PROCESSING: string;
|
|
13
13
|
BANK_AUTH_RECIPIENT: string;
|
|
14
|
+
DBUCS_BASE_URI: string;
|
|
15
|
+
DBUCS_USERNAME: string;
|
|
14
16
|
REDIRECT_URI: string;
|
|
15
17
|
ENCRYPTION_KEY: string;
|
|
16
18
|
FINBRICKS_PRIVATE_KEY_PEM: string;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { t as tables, F as FinbricksConnector, M as MockConnector, a as MockCobsConnector, E as ErsteConnector } from './bank.Dh6IUoHL.mjs';
|
|
2
1
|
import { uuidv4 } from '@develit-io/backend-sdk';
|
|
3
2
|
import { eq } from 'drizzle-orm';
|
|
3
|
+
import { s as schema } from './bank.BUSlmr6r.mjs';
|
|
4
4
|
import 'date-fns';
|
|
5
|
-
import 'jose';
|
|
6
5
|
import '@develit-io/general-codes';
|
|
7
|
-
import '
|
|
6
|
+
import 'jose';
|
|
7
|
+
import './bank.qc8ALZwm.mjs';
|
|
8
8
|
import { createHash } from 'node:crypto';
|
|
9
9
|
|
|
10
10
|
const createPaymentCommand = (db, { payment }) => {
|
|
@@ -50,78 +50,6 @@ const getCredentialsByAccountId = async (db, encryptionKey, { accountId }) => {
|
|
|
50
50
|
} : void 0;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
class CreditasConnector extends FinbricksConnector {
|
|
54
|
-
constructor(config) {
|
|
55
|
-
super("CREDITAS", config);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
class FioConnector extends FinbricksConnector {
|
|
60
|
-
constructor(config) {
|
|
61
|
-
super("FIO", config);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
class MonetaConnector extends FinbricksConnector {
|
|
66
|
-
constructor(config) {
|
|
67
|
-
super("MONETA", config);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const initiateConnector = ({
|
|
72
|
-
bank,
|
|
73
|
-
env,
|
|
74
|
-
connectedAccounts
|
|
75
|
-
}) => {
|
|
76
|
-
switch (bank) {
|
|
77
|
-
case "ERSTE":
|
|
78
|
-
return new ErsteConnector({
|
|
79
|
-
API_KEY: env.ERSTE_API_KEY,
|
|
80
|
-
CLIENT_ID: env.ERSTE_CLIENT_ID,
|
|
81
|
-
CLIENT_SECRET: env.ERSTE_CLIENT_SECRET,
|
|
82
|
-
REDIRECT_URI: env.REDIRECT_URI,
|
|
83
|
-
AUTH_URI: env.ERSTE_AUTH_URI,
|
|
84
|
-
PAYMENTS_URI: env.ERSTE_PAYMENTS_URI,
|
|
85
|
-
ACCOUNTS_URI: env.ERSTE_ACCOUNTS_URI,
|
|
86
|
-
connectedAccounts
|
|
87
|
-
});
|
|
88
|
-
case "CREDITAS":
|
|
89
|
-
return new CreditasConnector({
|
|
90
|
-
BASE_URI: env.FINBRICKS_BASE_URI,
|
|
91
|
-
MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
|
|
92
|
-
PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
|
|
93
|
-
REDIRECT_URI: env.REDIRECT_URI,
|
|
94
|
-
connectedAccounts
|
|
95
|
-
});
|
|
96
|
-
case "MOCK_COBS":
|
|
97
|
-
return new MockCobsConnector({
|
|
98
|
-
BASE_URI: env.FINBRICKS_BASE_URI,
|
|
99
|
-
MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
|
|
100
|
-
PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
|
|
101
|
-
REDIRECT_URI: env.REDIRECT_URI,
|
|
102
|
-
connectedAccounts
|
|
103
|
-
});
|
|
104
|
-
case "FIO":
|
|
105
|
-
return new FioConnector({
|
|
106
|
-
BASE_URI: env.FINBRICKS_BASE_URI,
|
|
107
|
-
MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
|
|
108
|
-
PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
|
|
109
|
-
REDIRECT_URI: env.REDIRECT_URI,
|
|
110
|
-
connectedAccounts
|
|
111
|
-
});
|
|
112
|
-
case "MONETA":
|
|
113
|
-
return new MonetaConnector({
|
|
114
|
-
BASE_URI: env.FINBRICKS_BASE_URI,
|
|
115
|
-
MERCHANT_ID: env.FINBRICKS_MERCHANT_ID,
|
|
116
|
-
PRIVATE_KEY_PEM: env.FINBRICKS_PRIVATE_KEY_PEM,
|
|
117
|
-
REDIRECT_URI: env.REDIRECT_URI,
|
|
118
|
-
connectedAccounts
|
|
119
|
-
});
|
|
120
|
-
default:
|
|
121
|
-
return new MockConnector();
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
53
|
async function importAesKey(base64Key) {
|
|
126
54
|
const raw = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
|
|
127
55
|
return await crypto.subtle.importKey("raw", raw, { name: "AES-GCM" }, false, [
|
|
@@ -171,4 +99,6 @@ function checksum(input) {
|
|
|
171
99
|
return createHash("sha256").update(json).digest("hex");
|
|
172
100
|
}
|
|
173
101
|
|
|
174
|
-
|
|
102
|
+
const tables = schema;
|
|
103
|
+
|
|
104
|
+
export { getAccountByIdQuery as a, getCredentialsByAccountId as b, checksum as c, createPaymentCommand as d, encrypt as e, getBatchByIdQuery as g, importAesKey as i, tables as t, upsertBatchCommand as u };
|