@payloops/processor-core 0.0.1 → 0.0.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.
@@ -1,297 +0,0 @@
1
- import {
2
- __export
3
- } from "./chunk-MLKGABMK.js";
4
-
5
- // src/activities/index.ts
6
- var activities_exports = {};
7
- __export(activities_exports, {
8
- capturePayment: () => capturePayment,
9
- deliverWebhook: () => deliverWebhook,
10
- getMerchantWebhookUrl: () => getMerchantWebhookUrl,
11
- getProcessorConfig: () => getProcessorConfig,
12
- processPayment: () => processPayment,
13
- refundPayment: () => refundPayment,
14
- updateOrderStatus: () => updateOrderStatus
15
- });
16
- import { eq, and } from "drizzle-orm";
17
-
18
- // src/lib/db.ts
19
- import { drizzle } from "drizzle-orm/node-postgres";
20
- import { Pool } from "pg";
21
- import {
22
- pgTable,
23
- text,
24
- timestamp,
25
- integer,
26
- boolean,
27
- jsonb,
28
- varchar,
29
- uuid
30
- } from "drizzle-orm/pg-core";
31
- var orders = pgTable("orders", {
32
- id: uuid("id").primaryKey().defaultRandom(),
33
- merchantId: uuid("merchant_id").notNull(),
34
- externalId: varchar("external_id", { length: 255 }).notNull(),
35
- amount: integer("amount").notNull(),
36
- currency: varchar("currency", { length: 3 }).notNull().default("USD"),
37
- status: varchar("status", { length: 50 }).notNull().default("pending"),
38
- processor: varchar("processor", { length: 50 }),
39
- processorOrderId: varchar("processor_order_id", { length: 255 }),
40
- metadata: jsonb("metadata").default({}),
41
- workflowId: varchar("workflow_id", { length: 255 }),
42
- createdAt: timestamp("created_at").defaultNow().notNull(),
43
- updatedAt: timestamp("updated_at").defaultNow().notNull()
44
- });
45
- var transactions = pgTable("transactions", {
46
- id: uuid("id").primaryKey().defaultRandom(),
47
- orderId: uuid("order_id").notNull(),
48
- type: varchar("type", { length: 50 }).notNull(),
49
- amount: integer("amount").notNull(),
50
- status: varchar("status", { length: 50 }).notNull().default("pending"),
51
- processorTransactionId: varchar("processor_transaction_id", { length: 255 }),
52
- processorResponse: jsonb("processor_response"),
53
- errorCode: varchar("error_code", { length: 100 }),
54
- errorMessage: text("error_message"),
55
- createdAt: timestamp("created_at").defaultNow().notNull()
56
- });
57
- var processorConfigs = pgTable("processor_configs", {
58
- id: uuid("id").primaryKey().defaultRandom(),
59
- merchantId: uuid("merchant_id").notNull(),
60
- processor: varchar("processor", { length: 50 }).notNull(),
61
- credentialsEncrypted: text("credentials_encrypted").notNull(),
62
- priority: integer("priority").notNull().default(1),
63
- enabled: boolean("enabled").notNull().default(true),
64
- testMode: boolean("test_mode").notNull().default(true),
65
- createdAt: timestamp("created_at").defaultNow().notNull(),
66
- updatedAt: timestamp("updated_at").defaultNow().notNull()
67
- });
68
- var webhookEvents = pgTable("webhook_events", {
69
- id: uuid("id").primaryKey().defaultRandom(),
70
- merchantId: uuid("merchant_id").notNull(),
71
- orderId: uuid("order_id"),
72
- eventType: varchar("event_type", { length: 100 }).notNull(),
73
- payload: jsonb("payload").notNull(),
74
- status: varchar("status", { length: 50 }).notNull().default("pending"),
75
- attempts: integer("attempts").notNull().default(0),
76
- lastAttemptAt: timestamp("last_attempt_at"),
77
- nextRetryAt: timestamp("next_retry_at"),
78
- deliveredAt: timestamp("delivered_at"),
79
- workflowId: varchar("workflow_id", { length: 255 }),
80
- createdAt: timestamp("created_at").defaultNow().notNull()
81
- });
82
- var merchants = pgTable("merchants", {
83
- id: uuid("id").primaryKey().defaultRandom(),
84
- name: varchar("name", { length: 255 }).notNull(),
85
- email: varchar("email", { length: 255 }).notNull().unique(),
86
- webhookUrl: text("webhook_url"),
87
- webhookSecret: text("webhook_secret")
88
- });
89
- var dbInstance = null;
90
- function getDb() {
91
- if (!dbInstance) {
92
- const pool = new Pool({
93
- connectionString: process.env.DATABASE_URL
94
- });
95
- dbInstance = drizzle(pool);
96
- }
97
- return dbInstance;
98
- }
99
-
100
- // src/lib/crypto.ts
101
- import { createDecipheriv, createHash } from "crypto";
102
- var ALGORITHM = "aes-256-gcm";
103
- function getKey() {
104
- const key = process.env.ENCRYPTION_KEY;
105
- if (!key) throw new Error("ENCRYPTION_KEY not set");
106
- return createHash("sha256").update(key).digest();
107
- }
108
- function decrypt(encryptedText) {
109
- const [ivHex, authTagHex, encrypted] = encryptedText.split(":");
110
- const iv = Buffer.from(ivHex, "hex");
111
- const authTag = Buffer.from(authTagHex, "hex");
112
- const decipher = createDecipheriv(ALGORITHM, getKey(), iv);
113
- decipher.setAuthTag(authTag);
114
- let decrypted = decipher.update(encrypted, "hex", "utf8");
115
- decrypted += decipher.final("utf8");
116
- return decrypted;
117
- }
118
-
119
- // src/lib/registry.ts
120
- var processors = /* @__PURE__ */ new Map();
121
- function registerProcessor(processor) {
122
- if (processors.has(processor.name)) {
123
- throw new Error(`Processor ${processor.name} is already registered`);
124
- }
125
- processors.set(processor.name, processor);
126
- console.log(`Registered processor: ${processor.name}`);
127
- }
128
- function getProcessor(name) {
129
- const processor = processors.get(name);
130
- if (!processor) {
131
- throw new Error(`Processor ${name} not found. Available: ${Array.from(processors.keys()).join(", ")}`);
132
- }
133
- return processor;
134
- }
135
- function getRegisteredProcessors() {
136
- return Array.from(processors.keys());
137
- }
138
- function hasProcessor(name) {
139
- return processors.has(name);
140
- }
141
-
142
- // src/activities/index.ts
143
- import crypto from "crypto";
144
- async function getProcessorConfig(merchantId, processor) {
145
- const db = getDb();
146
- const config = await db.select().from(processorConfigs).where(and(eq(processorConfigs.merchantId, merchantId), eq(processorConfigs.processor, processor))).limit(1);
147
- if (config.length === 0) return null;
148
- const credentials = JSON.parse(decrypt(config[0].credentialsEncrypted));
149
- return {
150
- merchantId,
151
- processor,
152
- testMode: config[0].testMode,
153
- credentials
154
- };
155
- }
156
- async function updateOrderStatus(orderId, status, processorOrderId, processorTransactionId) {
157
- const db = getDb();
158
- await db.update(orders).set({
159
- status,
160
- processorOrderId: processorOrderId || void 0,
161
- updatedAt: /* @__PURE__ */ new Date()
162
- }).where(eq(orders.id, orderId));
163
- if (processorTransactionId) {
164
- const order = await db.select().from(orders).where(eq(orders.id, orderId)).limit(1);
165
- if (order.length > 0) {
166
- await db.insert(transactions).values({
167
- orderId,
168
- type: status === "captured" ? "capture" : status === "authorized" ? "authorization" : "authorization",
169
- amount: order[0].amount,
170
- status: status === "failed" ? "failed" : "success",
171
- processorTransactionId
172
- });
173
- }
174
- }
175
- }
176
- async function processPayment(input) {
177
- const config = await getProcessorConfig(input.merchantId, input.processor);
178
- if (!config) {
179
- return {
180
- success: false,
181
- status: "failed",
182
- errorCode: "no_processor_config",
183
- errorMessage: `Processor ${input.processor} not configured for merchant`
184
- };
185
- }
186
- const processor = getProcessor(input.processor);
187
- return processor.createPayment(input, config);
188
- }
189
- async function capturePayment(processorOrderId, amount, merchantId, processor) {
190
- const config = await getProcessorConfig(merchantId, processor);
191
- if (!config) {
192
- return {
193
- success: false,
194
- status: "failed",
195
- errorCode: "no_processor_config",
196
- errorMessage: `Processor ${processor} not configured`
197
- };
198
- }
199
- const processorInstance = getProcessor(processor);
200
- return processorInstance.capturePayment(processorOrderId, amount, config);
201
- }
202
- async function refundPayment(processorTransactionId, amount, merchantId, processor) {
203
- const config = await getProcessorConfig(merchantId, processor);
204
- if (!config) {
205
- return {
206
- success: false,
207
- status: "failed",
208
- errorCode: "no_processor_config",
209
- errorMessage: `Processor ${processor} not configured`
210
- };
211
- }
212
- const processorInstance = getProcessor(processor);
213
- return processorInstance.refundPayment(processorTransactionId, amount, config);
214
- }
215
- async function deliverWebhook(webhookEventId, webhookUrl, webhookSecret, payload) {
216
- const db = getDb();
217
- const event = await db.select().from(webhookEvents).where(eq(webhookEvents.id, webhookEventId)).limit(1);
218
- const attempts = (event[0]?.attempts || 0) + 1;
219
- try {
220
- const body = JSON.stringify(payload);
221
- const headers = {
222
- "Content-Type": "application/json",
223
- "X-Loop-Event-Id": webhookEventId,
224
- "X-Loop-Timestamp": String(Date.now())
225
- };
226
- if (webhookSecret) {
227
- const timestamp2 = headers["X-Loop-Timestamp"];
228
- const signaturePayload = `${timestamp2}.${body}`;
229
- const signature = crypto.createHmac("sha256", webhookSecret).update(signaturePayload).digest("hex");
230
- headers["X-Loop-Signature"] = `v1=${signature}`;
231
- }
232
- const response = await fetch(webhookUrl, {
233
- method: "POST",
234
- headers,
235
- body,
236
- signal: AbortSignal.timeout(3e4)
237
- // 30 second timeout
238
- });
239
- const success = response.ok;
240
- await db.update(webhookEvents).set({
241
- status: success ? "delivered" : "pending",
242
- attempts,
243
- lastAttemptAt: /* @__PURE__ */ new Date(),
244
- deliveredAt: success ? /* @__PURE__ */ new Date() : void 0,
245
- nextRetryAt: success ? void 0 : new Date(Date.now() + getRetryDelay(attempts))
246
- }).where(eq(webhookEvents.id, webhookEventId));
247
- return {
248
- success,
249
- statusCode: response.status,
250
- attempts,
251
- deliveredAt: success ? /* @__PURE__ */ new Date() : void 0,
252
- errorMessage: success ? void 0 : `HTTP ${response.status}`
253
- };
254
- } catch (error) {
255
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
256
- await db.update(webhookEvents).set({
257
- status: attempts >= 5 ? "failed" : "pending",
258
- attempts,
259
- lastAttemptAt: /* @__PURE__ */ new Date(),
260
- nextRetryAt: attempts >= 5 ? void 0 : new Date(Date.now() + getRetryDelay(attempts))
261
- }).where(eq(webhookEvents.id, webhookEventId));
262
- return {
263
- success: false,
264
- attempts,
265
- errorMessage
266
- };
267
- }
268
- }
269
- async function getMerchantWebhookUrl(merchantId) {
270
- const db = getDb();
271
- const merchant = await db.select().from(merchants).where(eq(merchants.id, merchantId)).limit(1);
272
- return {
273
- url: merchant[0]?.webhookUrl || null,
274
- secret: merchant[0]?.webhookSecret || null
275
- };
276
- }
277
- function getRetryDelay(attempt) {
278
- const baseDelay = 60 * 1e3;
279
- const maxDelay = 24 * 60 * 60 * 1e3;
280
- const delay = baseDelay * Math.pow(2, attempt - 1);
281
- return Math.min(delay, maxDelay);
282
- }
283
-
284
- export {
285
- registerProcessor,
286
- getProcessor,
287
- getRegisteredProcessors,
288
- hasProcessor,
289
- getProcessorConfig,
290
- updateOrderStatus,
291
- processPayment,
292
- capturePayment,
293
- refundPayment,
294
- deliverWebhook,
295
- getMerchantWebhookUrl,
296
- activities_exports
297
- };
@@ -1,25 +0,0 @@
1
- import { a as PaymentConfig, b as PaymentInput, c as PaymentResult, d as RefundResult, e as WebhookDeliveryResult } from './index-CsnpS83V.js';
2
-
3
- declare function getProcessorConfig(merchantId: string, processor: string): Promise<PaymentConfig | null>;
4
- declare function updateOrderStatus(orderId: string, status: string, processorOrderId?: string, processorTransactionId?: string): Promise<void>;
5
- declare function processPayment(input: PaymentInput): Promise<PaymentResult>;
6
- declare function capturePayment(processorOrderId: string, amount: number, merchantId: string, processor: string): Promise<PaymentResult>;
7
- declare function refundPayment(processorTransactionId: string, amount: number, merchantId: string, processor: string): Promise<RefundResult>;
8
- declare function deliverWebhook(webhookEventId: string, webhookUrl: string, webhookSecret: string | undefined, payload: Record<string, unknown>): Promise<WebhookDeliveryResult>;
9
- declare function getMerchantWebhookUrl(merchantId: string): Promise<{
10
- url: string | null;
11
- secret: string | null;
12
- }>;
13
-
14
- declare const index_capturePayment: typeof capturePayment;
15
- declare const index_deliverWebhook: typeof deliverWebhook;
16
- declare const index_getMerchantWebhookUrl: typeof getMerchantWebhookUrl;
17
- declare const index_getProcessorConfig: typeof getProcessorConfig;
18
- declare const index_processPayment: typeof processPayment;
19
- declare const index_refundPayment: typeof refundPayment;
20
- declare const index_updateOrderStatus: typeof updateOrderStatus;
21
- declare namespace index {
22
- export { index_capturePayment as capturePayment, index_deliverWebhook as deliverWebhook, index_getMerchantWebhookUrl as getMerchantWebhookUrl, index_getProcessorConfig as getProcessorConfig, index_processPayment as processPayment, index_refundPayment as refundPayment, index_updateOrderStatus as updateOrderStatus };
23
- }
24
-
25
- export { getMerchantWebhookUrl as a, capturePayment as c, deliverWebhook as d, getProcessorConfig as g, index as i, processPayment as p, refundPayment as r, updateOrderStatus as u };
@@ -1,72 +0,0 @@
1
- interface PaymentConfig {
2
- merchantId: string;
3
- processor: string;
4
- testMode: boolean;
5
- credentials: Record<string, string>;
6
- }
7
- interface PaymentInput {
8
- orderId: string;
9
- merchantId: string;
10
- amount: number;
11
- currency: string;
12
- processor: string;
13
- returnUrl?: string;
14
- cancelUrl?: string;
15
- metadata?: Record<string, unknown>;
16
- customer?: {
17
- id?: string;
18
- email?: string;
19
- name?: string;
20
- };
21
- paymentMethod?: {
22
- type: 'card' | 'upi' | 'netbanking' | 'wallet';
23
- token?: string;
24
- };
25
- }
26
- interface PaymentResult {
27
- success: boolean;
28
- status: 'authorized' | 'captured' | 'failed' | 'pending' | 'requires_action';
29
- processorOrderId?: string;
30
- processorTransactionId?: string;
31
- redirectUrl?: string;
32
- errorCode?: string;
33
- errorMessage?: string;
34
- metadata?: Record<string, unknown>;
35
- }
36
- interface RefundInput {
37
- orderId: string;
38
- transactionId: string;
39
- amount: number;
40
- reason?: string;
41
- }
42
- interface RefundResult {
43
- success: boolean;
44
- refundId?: string;
45
- status: 'pending' | 'success' | 'failed';
46
- errorCode?: string;
47
- errorMessage?: string;
48
- }
49
- interface WebhookDeliveryInput {
50
- webhookEventId: string;
51
- merchantId: string;
52
- webhookUrl: string;
53
- webhookSecret?: string;
54
- payload: Record<string, unknown>;
55
- }
56
- interface WebhookDeliveryResult {
57
- success: boolean;
58
- statusCode?: number;
59
- attempts: number;
60
- deliveredAt?: Date;
61
- errorMessage?: string;
62
- }
63
- interface PaymentProcessor {
64
- name: string;
65
- createPayment(input: PaymentInput, config: PaymentConfig): Promise<PaymentResult>;
66
- capturePayment(processorOrderId: string, amount: number, config: PaymentConfig): Promise<PaymentResult>;
67
- refundPayment(processorTransactionId: string, amount: number, config: PaymentConfig): Promise<RefundResult>;
68
- getPaymentStatus(processorOrderId: string, config: PaymentConfig): Promise<PaymentResult>;
69
- }
70
- type ProcessorRegistry = Map<string, PaymentProcessor>;
71
-
72
- export type { PaymentProcessor as P, RefundInput as R, WebhookDeliveryInput as W, PaymentConfig as a, PaymentInput as b, PaymentResult as c, RefundResult as d, WebhookDeliveryResult as e, ProcessorRegistry as f };
@@ -1,27 +0,0 @@
1
- import * as _temporalio_common from '@temporalio/common';
2
- import { c as PaymentResult, e as WebhookDeliveryResult } from '../index-CsnpS83V.js';
3
-
4
- interface PaymentWorkflowInput {
5
- orderId: string;
6
- merchantId: string;
7
- amount: number;
8
- currency: string;
9
- processor: string;
10
- returnUrl?: string;
11
- }
12
- declare const completePaymentSignal: _temporalio_common.SignalDefinition<[{
13
- success: boolean;
14
- processorTransactionId?: string;
15
- }], string>;
16
- declare const cancelPaymentSignal: _temporalio_common.SignalDefinition<[], "cancelPayment">;
17
- declare function PaymentWorkflow(input: PaymentWorkflowInput): Promise<PaymentResult>;
18
-
19
- interface WebhookDeliveryWorkflowInput {
20
- webhookEventId: string;
21
- merchantId: string;
22
- webhookUrl: string;
23
- payload: Record<string, unknown>;
24
- }
25
- declare function WebhookDeliveryWorkflow(input: WebhookDeliveryWorkflowInput): Promise<WebhookDeliveryResult>;
26
-
27
- export { PaymentWorkflow, type PaymentWorkflowInput, WebhookDeliveryWorkflow, type WebhookDeliveryWorkflowInput, cancelPaymentSignal, completePaymentSignal };
@@ -1,13 +0,0 @@
1
- import {
2
- PaymentWorkflow,
3
- WebhookDeliveryWorkflow,
4
- cancelPaymentSignal,
5
- completePaymentSignal
6
- } from "../chunk-CZTZBCNV.js";
7
- import "../chunk-MLKGABMK.js";
8
- export {
9
- PaymentWorkflow,
10
- WebhookDeliveryWorkflow,
11
- cancelPaymentSignal,
12
- completePaymentSignal
13
- };
@@ -1,224 +0,0 @@
1
- import { eq, and } from 'drizzle-orm';
2
- import { getDb, orders, transactions, processorConfigs, webhookEvents, merchants } from '../lib/db';
3
- import { decrypt } from '../lib/crypto';
4
- import { getProcessor } from '../lib/registry';
5
- import type { PaymentInput, PaymentResult, PaymentConfig, RefundResult, WebhookDeliveryResult } from '../types';
6
- import crypto from 'crypto';
7
-
8
- // Get processor config for a merchant
9
- export async function getProcessorConfig(
10
- merchantId: string,
11
- processor: string
12
- ): Promise<PaymentConfig | null> {
13
- const db = getDb();
14
-
15
- const config = await db
16
- .select()
17
- .from(processorConfigs)
18
- .where(and(eq(processorConfigs.merchantId, merchantId), eq(processorConfigs.processor, processor)))
19
- .limit(1);
20
-
21
- if (config.length === 0) return null;
22
-
23
- const credentials = JSON.parse(decrypt(config[0].credentialsEncrypted));
24
-
25
- return {
26
- merchantId,
27
- processor,
28
- testMode: config[0].testMode,
29
- credentials
30
- };
31
- }
32
-
33
- // Update order status
34
- export async function updateOrderStatus(
35
- orderId: string,
36
- status: string,
37
- processorOrderId?: string,
38
- processorTransactionId?: string
39
- ): Promise<void> {
40
- const db = getDb();
41
-
42
- await db
43
- .update(orders)
44
- .set({
45
- status,
46
- processorOrderId: processorOrderId || undefined,
47
- updatedAt: new Date()
48
- })
49
- .where(eq(orders.id, orderId));
50
-
51
- // Create transaction record if we have a transaction id
52
- if (processorTransactionId) {
53
- const order = await db.select().from(orders).where(eq(orders.id, orderId)).limit(1);
54
-
55
- if (order.length > 0) {
56
- await db.insert(transactions).values({
57
- orderId,
58
- type: status === 'captured' ? 'capture' : status === 'authorized' ? 'authorization' : 'authorization',
59
- amount: order[0].amount,
60
- status: status === 'failed' ? 'failed' : 'success',
61
- processorTransactionId
62
- });
63
- }
64
- }
65
- }
66
-
67
- // Process payment using the appropriate processor
68
- export async function processPayment(input: PaymentInput): Promise<PaymentResult> {
69
- const config = await getProcessorConfig(input.merchantId, input.processor);
70
-
71
- if (!config) {
72
- return {
73
- success: false,
74
- status: 'failed',
75
- errorCode: 'no_processor_config',
76
- errorMessage: `Processor ${input.processor} not configured for merchant`
77
- };
78
- }
79
-
80
- const processor = getProcessor(input.processor);
81
- return processor.createPayment(input, config);
82
- }
83
-
84
- // Capture a payment
85
- export async function capturePayment(
86
- processorOrderId: string,
87
- amount: number,
88
- merchantId: string,
89
- processor: string
90
- ): Promise<PaymentResult> {
91
- const config = await getProcessorConfig(merchantId, processor);
92
-
93
- if (!config) {
94
- return {
95
- success: false,
96
- status: 'failed',
97
- errorCode: 'no_processor_config',
98
- errorMessage: `Processor ${processor} not configured`
99
- };
100
- }
101
-
102
- const processorInstance = getProcessor(processor);
103
- return processorInstance.capturePayment(processorOrderId, amount, config);
104
- }
105
-
106
- // Refund a payment
107
- export async function refundPayment(
108
- processorTransactionId: string,
109
- amount: number,
110
- merchantId: string,
111
- processor: string
112
- ): Promise<RefundResult> {
113
- const config = await getProcessorConfig(merchantId, processor);
114
-
115
- if (!config) {
116
- return {
117
- success: false,
118
- status: 'failed',
119
- errorCode: 'no_processor_config',
120
- errorMessage: `Processor ${processor} not configured`
121
- };
122
- }
123
-
124
- const processorInstance = getProcessor(processor);
125
- return processorInstance.refundPayment(processorTransactionId, amount, config);
126
- }
127
-
128
- // Deliver webhook to merchant
129
- export async function deliverWebhook(
130
- webhookEventId: string,
131
- webhookUrl: string,
132
- webhookSecret: string | undefined,
133
- payload: Record<string, unknown>
134
- ): Promise<WebhookDeliveryResult> {
135
- const db = getDb();
136
-
137
- // Get current attempt count
138
- const event = await db.select().from(webhookEvents).where(eq(webhookEvents.id, webhookEventId)).limit(1);
139
-
140
- const attempts = (event[0]?.attempts || 0) + 1;
141
-
142
- try {
143
- const body = JSON.stringify(payload);
144
- const headers: Record<string, string> = {
145
- 'Content-Type': 'application/json',
146
- 'X-Loop-Event-Id': webhookEventId,
147
- 'X-Loop-Timestamp': String(Date.now())
148
- };
149
-
150
- // Sign the webhook if secret is provided
151
- if (webhookSecret) {
152
- const timestamp = headers['X-Loop-Timestamp'];
153
- const signaturePayload = `${timestamp}.${body}`;
154
- const signature = crypto.createHmac('sha256', webhookSecret).update(signaturePayload).digest('hex');
155
- headers['X-Loop-Signature'] = `v1=${signature}`;
156
- }
157
-
158
- const response = await fetch(webhookUrl, {
159
- method: 'POST',
160
- headers,
161
- body,
162
- signal: AbortSignal.timeout(30000) // 30 second timeout
163
- });
164
-
165
- const success = response.ok;
166
-
167
- await db
168
- .update(webhookEvents)
169
- .set({
170
- status: success ? 'delivered' : 'pending',
171
- attempts,
172
- lastAttemptAt: new Date(),
173
- deliveredAt: success ? new Date() : undefined,
174
- nextRetryAt: success ? undefined : new Date(Date.now() + getRetryDelay(attempts))
175
- })
176
- .where(eq(webhookEvents.id, webhookEventId));
177
-
178
- return {
179
- success,
180
- statusCode: response.status,
181
- attempts,
182
- deliveredAt: success ? new Date() : undefined,
183
- errorMessage: success ? undefined : `HTTP ${response.status}`
184
- };
185
- } catch (error) {
186
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
187
-
188
- await db
189
- .update(webhookEvents)
190
- .set({
191
- status: attempts >= 5 ? 'failed' : 'pending',
192
- attempts,
193
- lastAttemptAt: new Date(),
194
- nextRetryAt: attempts >= 5 ? undefined : new Date(Date.now() + getRetryDelay(attempts))
195
- })
196
- .where(eq(webhookEvents.id, webhookEventId));
197
-
198
- return {
199
- success: false,
200
- attempts,
201
- errorMessage
202
- };
203
- }
204
- }
205
-
206
- // Get merchant webhook URL
207
- export async function getMerchantWebhookUrl(merchantId: string): Promise<{ url: string | null; secret: string | null }> {
208
- const db = getDb();
209
-
210
- const merchant = await db.select().from(merchants).where(eq(merchants.id, merchantId)).limit(1);
211
-
212
- return {
213
- url: merchant[0]?.webhookUrl || null,
214
- secret: merchant[0]?.webhookSecret || null
215
- };
216
- }
217
-
218
- // Exponential backoff for retries
219
- function getRetryDelay(attempt: number): number {
220
- const baseDelay = 60 * 1000; // 1 minute
221
- const maxDelay = 24 * 60 * 60 * 1000; // 24 hours
222
- const delay = baseDelay * Math.pow(2, attempt - 1);
223
- return Math.min(delay, maxDelay);
224
- }
package/src/index.ts DELETED
@@ -1,22 +0,0 @@
1
- // Core types
2
- export type {
3
- PaymentConfig,
4
- PaymentInput,
5
- PaymentResult,
6
- RefundInput,
7
- RefundResult,
8
- WebhookDeliveryInput,
9
- WebhookDeliveryResult,
10
- PaymentProcessor,
11
- ProcessorRegistry
12
- } from './types';
13
-
14
- // Processor registry
15
- export { registerProcessor, getProcessor, getRegisteredProcessors, hasProcessor } from './lib/registry';
16
-
17
- // Activities (for worker registration)
18
- export * as activities from './activities';
19
-
20
- // Workflows
21
- export { PaymentWorkflow, WebhookDeliveryWorkflow } from './workflows';
22
- export type { PaymentWorkflowInput, WebhookDeliveryWorkflowInput } from './workflows';