@zendfi/sdk 0.1.2 → 0.2.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/index.d.ts CHANGED
@@ -1,328 +1,9 @@
1
- /**
2
- * ZendFi SDK Types
3
- * Complete type definitions for the ZendFi API
4
- */
5
- type Environment = 'development' | 'staging' | 'production';
6
- type Currency = 'USD' | 'EUR' | 'GBP';
7
- type PaymentToken = 'SOL' | 'USDC' | 'USDT';
8
- type PaymentStatus = 'pending' | 'confirmed' | 'failed' | 'expired';
9
- type SubscriptionStatus = 'active' | 'canceled' | 'past_due' | 'paused';
10
- type InstallmentPlanStatus = 'active' | 'completed' | 'defaulted' | 'cancelled';
11
- type EscrowStatus = 'pending' | 'funded' | 'released' | 'refunded' | 'disputed' | 'cancelled';
12
- type InvoiceStatus = 'draft' | 'sent' | 'paid';
13
- type SplitStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'refunded';
14
- type WebhookEvent = 'payment.created' | 'payment.confirmed' | 'payment.failed' | 'payment.expired' | 'subscription.created' | 'subscription.activated' | 'subscription.canceled' | 'subscription.payment_failed' | 'split.completed' | 'split.failed' | 'installment.due' | 'installment.paid' | 'installment.late' | 'escrow.funded' | 'escrow.released' | 'escrow.refunded' | 'escrow.disputed' | 'invoice.sent' | 'invoice.paid';
15
- interface ZendFiConfig {
16
- apiKey?: string;
17
- baseURL?: string;
18
- environment?: Environment;
19
- timeout?: number;
20
- retries?: number;
21
- idempotencyEnabled?: boolean;
22
- }
23
- interface SplitRecipient {
24
- recipient_wallet: string;
25
- recipient_name?: string;
26
- percentage?: number;
27
- fixed_amount_usd?: number;
28
- split_order?: number;
29
- }
30
- interface CreatePaymentRequest {
31
- amount: number;
32
- currency?: Currency;
33
- token?: PaymentToken;
34
- description?: string;
35
- customer_email?: string;
36
- redirect_url?: string;
37
- metadata?: Record<string, any>;
38
- split_recipients?: SplitRecipient[];
39
- }
40
- /**
41
- * Payment Link - Shareable checkout links
42
- */
43
- interface CreatePaymentLinkRequest {
44
- amount: number;
45
- currency?: string;
46
- token?: string;
47
- description?: string;
48
- max_uses?: number;
49
- expires_at?: string;
50
- metadata?: Record<string, any>;
51
- }
52
- interface PaymentLink {
53
- id: string;
54
- link_code: string;
55
- payment_url: string;
56
- hosted_page_url: string;
57
- amount: number;
58
- currency: string;
59
- token: string;
60
- max_uses?: number;
61
- uses_count: number;
62
- expires_at?: string;
63
- is_active: boolean;
64
- created_at: string;
65
- url: string;
66
- }
67
- interface Payment {
68
- id: string;
69
- merchant_id: string;
70
- amount_usd?: number;
71
- amount?: number;
72
- currency?: string;
73
- payment_token?: PaymentToken;
74
- status: PaymentStatus;
75
- customer_wallet?: string;
76
- customer_email?: string;
77
- description?: string;
78
- checkout_url?: string;
79
- payment_url?: string;
80
- qr_code?: string;
81
- expires_at: string;
82
- confirmed_at?: string;
83
- transaction_signature?: string;
84
- metadata?: Record<string, any>;
85
- split_ids?: string[];
86
- created_at?: string;
87
- updated_at?: string;
88
- }
89
- interface ListPaymentsRequest {
90
- page?: number;
91
- limit?: number;
92
- status?: PaymentStatus;
93
- from_date?: string;
94
- to_date?: string;
95
- }
96
- interface PaginatedResponse<T> {
97
- data: T[];
98
- pagination: {
99
- page: number;
100
- limit: number;
101
- total: number;
102
- total_pages: number;
103
- };
104
- }
105
- interface CreateSubscriptionPlanRequest {
106
- name: string;
107
- description?: string;
108
- amount: number;
109
- currency?: Currency;
110
- interval: 'daily' | 'weekly' | 'monthly' | 'yearly';
111
- interval_count?: number;
112
- trial_days?: number;
113
- metadata?: Record<string, any>;
114
- }
115
- interface SubscriptionPlan {
116
- id: string;
117
- merchant_id: string;
118
- name: string;
119
- description?: string;
120
- amount: number;
121
- currency: Currency;
122
- interval: string;
123
- interval_count: number;
124
- trial_days: number;
125
- is_active: boolean;
126
- metadata?: Record<string, any>;
127
- created_at: string;
128
- updated_at: string;
129
- }
130
- interface CreateSubscriptionRequest {
131
- plan_id: string;
132
- customer_email: string;
133
- customer_wallet?: string;
134
- metadata?: Record<string, any>;
135
- }
136
- interface Subscription {
137
- id: string;
138
- plan_id: string;
139
- merchant_id: string;
140
- customer_email: string;
141
- customer_wallet?: string;
142
- status: SubscriptionStatus;
143
- current_period_start: string;
144
- current_period_end: string;
145
- trial_end?: string;
146
- canceled_at?: string;
147
- metadata?: Record<string, any>;
148
- created_at: string;
149
- updated_at: string;
150
- }
151
- interface WebhookPayload {
152
- event: WebhookEvent;
153
- timestamp: string;
154
- merchant_id: string;
155
- data: Payment | Subscription;
156
- }
157
- interface VerifyWebhookRequest {
158
- payload: string | object;
159
- signature: string;
160
- secret: string;
161
- }
162
- declare class ZendFiError extends Error {
163
- statusCode?: number | undefined;
164
- code?: string | undefined;
165
- details?: any | undefined;
166
- constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: any | undefined);
167
- }
168
- declare class AuthenticationError extends ZendFiError {
169
- constructor(message?: string);
170
- }
171
- declare class ValidationError extends ZendFiError {
172
- constructor(message: string, details?: any);
173
- }
174
- declare class NetworkError extends ZendFiError {
175
- constructor(message: string);
176
- }
177
- declare class RateLimitError extends ZendFiError {
178
- constructor(message?: string);
179
- }
180
- /**
181
- * Installment Plans - Pay over time
182
- */
183
- interface InstallmentScheduleItem {
184
- installment_number: number;
185
- due_date: string;
186
- amount: string;
187
- status: string;
188
- payment_id?: string;
189
- paid_at?: string;
190
- }
191
- interface CreateInstallmentPlanRequest {
192
- customer_wallet: string;
193
- customer_email?: string;
194
- total_amount: number;
195
- installment_count: number;
196
- first_payment_date?: string;
197
- payment_frequency_days: number;
198
- description?: string;
199
- late_fee_amount?: number;
200
- grace_period_days?: number;
201
- metadata?: Record<string, any>;
202
- }
203
- interface CreateInstallmentPlanResponse {
204
- plan_id: string;
205
- status: string;
206
- }
207
- interface InstallmentPlan {
208
- id?: string;
209
- plan_id?: string;
210
- merchant_id?: string;
211
- customer_wallet?: string;
212
- customer_email?: string;
213
- total_amount?: string;
214
- installment_count?: number;
215
- amount_per_installment?: string;
216
- payment_schedule?: InstallmentScheduleItem[];
217
- paid_count?: number;
218
- status: InstallmentPlanStatus | string;
219
- description?: string;
220
- late_fee_amount?: string;
221
- grace_period_days?: number;
222
- metadata?: Record<string, any>;
223
- created_at?: string;
224
- updated_at?: string;
225
- completed_at?: string;
226
- defaulted_at?: string;
227
- }
228
- /**
229
- * Escrow - Secure fund holding
230
- */
231
- interface ReleaseCondition {
232
- type: 'manual_approval' | 'time_based' | 'confirmation_required' | 'milestone';
233
- approver?: string;
234
- approved?: boolean;
235
- release_after?: string;
236
- confirmations_needed?: number;
237
- confirmed_by?: string[];
238
- description?: string;
239
- approved_by?: string;
240
- }
241
- interface CreateEscrowRequest {
242
- buyer_wallet: string;
243
- seller_wallet: string;
244
- amount: number;
245
- currency?: Currency;
246
- token?: PaymentToken;
247
- description?: string;
248
- release_conditions: ReleaseCondition;
249
- metadata?: Record<string, any>;
250
- }
251
- interface Escrow {
252
- id: string;
253
- payment_id: string;
254
- merchant_id: string;
255
- buyer_wallet: string;
256
- seller_wallet: string;
257
- escrow_wallet: string;
258
- amount: number;
259
- currency: Currency;
260
- token: PaymentToken;
261
- release_conditions: ReleaseCondition;
262
- status: EscrowStatus;
263
- payment_url?: string;
264
- qr_code?: string;
265
- funded_at?: string;
266
- released_at?: string;
267
- refunded_at?: string;
268
- disputed_at?: string;
269
- dispute_reason?: string;
270
- release_transaction_signature?: string;
271
- refund_transaction_signature?: string;
272
- metadata?: Record<string, any>;
273
- created_at: string;
274
- updated_at: string;
275
- }
276
- interface ApproveEscrowRequest {
277
- approver_wallet: string;
278
- }
279
- interface RefundEscrowRequest {
280
- reason: string;
281
- }
282
- interface DisputeEscrowRequest {
283
- reason: string;
284
- }
285
- /**
286
- * Invoices - Professional billing
287
- */
288
- interface InvoiceLineItem {
289
- description: string;
290
- quantity: number;
291
- unit_price: number;
292
- }
293
- interface CreateInvoiceRequest {
294
- customer_email: string;
295
- customer_name?: string;
296
- amount: number;
297
- token?: PaymentToken;
298
- description: string;
299
- line_items?: InvoiceLineItem[];
300
- due_date?: string;
301
- metadata?: Record<string, any>;
302
- }
303
- interface Invoice {
304
- id: string;
305
- invoice_number: string;
306
- merchant_id: string;
307
- customer_email: string;
308
- customer_name?: string;
309
- amount_usd: number;
310
- token: PaymentToken;
311
- description: string;
312
- line_items?: InvoiceLineItem[];
313
- status: InvoiceStatus;
314
- payment_url?: string;
315
- due_date?: string;
316
- sent_at?: string;
317
- paid_at?: string;
318
- metadata?: Record<string, any>;
319
- created_at: string;
320
- updated_at: string;
321
- }
1
+ import { Z as ZendFiConfig, C as CreatePaymentRequest, P as Payment, L as ListPaymentsRequest, b as PaginatedResponse, c as CreateSubscriptionPlanRequest, S as SubscriptionPlan, d as CreateSubscriptionRequest, e as Subscription, f as CreatePaymentLinkRequest, g as PaymentLink, h as CreateInstallmentPlanRequest, I as InstallmentPlan, i as CreateEscrowRequest, E as Escrow, A as ApproveEscrowRequest, R as RefundEscrowRequest, D as DisputeEscrowRequest, j as CreateInvoiceRequest, k as Invoice, V as VerifyWebhookRequest, l as WebhookPayload } from './webhook-handler-BIze3Qop.js';
2
+ export { F as AuthenticationError, K as CreateInstallmentPlanResponse, q as Currency, o as Environment, v as EscrowStatus, u as InstallmentPlanStatus, J as InstallmentScheduleItem, O as InvoiceLineItem, w as InvoiceStatus, N as NetworkError, s as PaymentStatus, r as PaymentToken, H as RateLimitError, M as ReleaseCondition, z as SplitRecipient, x as SplitStatus, t as SubscriptionStatus, G as ValidationError, y as WebhookEvent, n as WebhookEventHandler, W as WebhookHandlerConfig, a as WebhookHandlers, m as WebhookResult, B as ZendFiError, p as processWebhook } from './webhook-handler-BIze3Qop.js';
322
3
 
323
4
  /**
324
- * ZendFi SDK Client
325
- * Zero-config TypeScript SDK for crypto payments
5
+ * ZendFi SDK Client.
6
+ * AZero-config TypeScript SDK for crypto payments
326
7
  */
327
8
  declare class ZendFiClient {
328
9
  private config;
@@ -368,7 +49,7 @@ declare class ZendFiClient {
368
49
  */
369
50
  getPaymentLink(linkCode: string): Promise<PaymentLink>;
370
51
  /**
371
- * List all payment links
52
+ * List all payment links for the authenticated merchant
372
53
  */
373
54
  listPaymentLinks(): Promise<PaymentLink[]>;
374
55
  /**
@@ -608,64 +289,4 @@ declare function verifyExpressWebhook(request: any, secret?: string): Promise<We
608
289
  */
609
290
  declare function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean;
610
291
 
611
- /**
612
- * ZendFi Webhook Handlers
613
- * Type-safe webhook handlers with automatic verification and deduplication
614
- */
615
-
616
- /**
617
- * Webhook handler configuration
618
- */
619
- interface WebhookHandlerConfig {
620
- /** Your webhook secret from ZendFi dashboard */
621
- secret: string;
622
- /** Optional: Path to store processed webhook IDs (for deduplication) */
623
- onProcessed?: (webhookId: string) => Promise<void>;
624
- /** Optional: Check if webhook was already processed */
625
- isProcessed?: (webhookId: string) => Promise<boolean>;
626
- /** Optional: Custom error handler */
627
- onError?: (error: Error, event?: WebhookEvent) => void | Promise<void>;
628
- }
629
- /**
630
- * Event handler function type
631
- */
632
- type WebhookEventHandler<T = any> = (data: T, event: WebhookPayload) => void | Promise<void>;
633
- /**
634
- * Webhook handlers map - type-safe event handlers
635
- */
636
- type WebhookHandlers = Partial<{
637
- 'payment.created': WebhookEventHandler;
638
- 'payment.confirmed': WebhookEventHandler;
639
- 'payment.failed': WebhookEventHandler;
640
- 'payment.expired': WebhookEventHandler;
641
- 'subscription.created': WebhookEventHandler;
642
- 'subscription.activated': WebhookEventHandler;
643
- 'subscription.canceled': WebhookEventHandler;
644
- 'subscription.payment_failed': WebhookEventHandler;
645
- 'split.completed': WebhookEventHandler;
646
- 'split.failed': WebhookEventHandler;
647
- 'installment.due': WebhookEventHandler;
648
- 'installment.paid': WebhookEventHandler;
649
- 'installment.late': WebhookEventHandler;
650
- 'escrow.funded': WebhookEventHandler;
651
- 'escrow.released': WebhookEventHandler;
652
- 'escrow.refunded': WebhookEventHandler;
653
- 'escrow.disputed': WebhookEventHandler;
654
- 'invoice.sent': WebhookEventHandler;
655
- 'invoice.paid': WebhookEventHandler;
656
- }>;
657
- /**
658
- * Webhook processing result
659
- */
660
- interface WebhookResult {
661
- success: boolean;
662
- processed: boolean;
663
- error?: string;
664
- event?: WebhookEvent;
665
- }
666
- /**
667
- * Process webhook with handlers
668
- */
669
- declare function processWebhook(payload: WebhookPayload, handlers: WebhookHandlers, config: WebhookHandlerConfig): Promise<WebhookResult>;
670
-
671
- export { type ApproveEscrowRequest, AuthenticationError, ConfigLoader, type CreateEscrowRequest, type CreateInstallmentPlanRequest, type CreateInstallmentPlanResponse, type CreateInvoiceRequest, type CreatePaymentLinkRequest, type CreatePaymentRequest, type CreateSubscriptionPlanRequest, type CreateSubscriptionRequest, type Currency, type DisputeEscrowRequest, type Environment, type Escrow, type EscrowStatus, type InstallmentPlan, type InstallmentPlanStatus, type InstallmentScheduleItem, type Invoice, type InvoiceLineItem, type InvoiceStatus, type ListPaymentsRequest, NetworkError, type PaginatedResponse, type Payment, type PaymentLink, type PaymentStatus, type PaymentToken, RateLimitError, type RefundEscrowRequest, type ReleaseCondition, type SplitRecipient, type SplitStatus, type Subscription, type SubscriptionPlan, type SubscriptionStatus, ValidationError, type VerifyWebhookRequest, type WebhookEvent, type WebhookEventHandler, type WebhookHandlerConfig, type WebhookHandlers, type WebhookPayload, type WebhookResult, ZendFiClient, type ZendFiConfig, ZendFiError, processWebhook, verifyExpressWebhook, verifyNextWebhook, verifyWebhookSignature, zendfi };
292
+ export { ApproveEscrowRequest, ConfigLoader, CreateEscrowRequest, CreateInstallmentPlanRequest, CreateInvoiceRequest, CreatePaymentLinkRequest, CreatePaymentRequest, CreateSubscriptionPlanRequest, CreateSubscriptionRequest, DisputeEscrowRequest, Escrow, InstallmentPlan, Invoice, ListPaymentsRequest, PaginatedResponse, Payment, PaymentLink, RefundEscrowRequest, Subscription, SubscriptionPlan, VerifyWebhookRequest, WebhookPayload, ZendFiClient, ZendFiConfig, verifyExpressWebhook, verifyNextWebhook, verifyWebhookSignature, zendfi };
package/dist/index.js CHANGED
@@ -323,10 +323,14 @@ var ZendFiClient = class {
323
323
  };
324
324
  }
325
325
  /**
326
- * List all payment links
326
+ * List all payment links for the authenticated merchant
327
327
  */
328
328
  async listPaymentLinks() {
329
- return [];
329
+ const response = await this.request("GET", "/api/v1/payment-links");
330
+ return response.map((link) => ({
331
+ ...link,
332
+ url: link.hosted_page_url
333
+ }));
330
334
  }
331
335
  /**
332
336
  * Create an installment plan
@@ -677,6 +681,7 @@ function verifyWebhookSignature(payload, signature, secret) {
677
681
  }
678
682
 
679
683
  // src/webhook-handler.ts
684
+ var import_crypto2 = require("crypto");
680
685
  var processedWebhooks = /* @__PURE__ */ new Set();
681
686
  var defaultIsProcessed = async (webhookId) => {
682
687
  return processedWebhooks.has(webhookId);
@@ -694,16 +699,19 @@ var defaultOnProcessed = async (webhookId) => {
694
699
  function generateWebhookId(payload) {
695
700
  return `${payload.merchant_id}:${payload.event}:${payload.timestamp}`;
696
701
  }
697
- async function processWebhook(payload, handlers, config) {
702
+ async function processPayload(payload, handlers, config) {
698
703
  try {
699
704
  const webhookId = generateWebhookId(payload);
700
- const isProcessed = config.isProcessed || defaultIsProcessed;
701
- const onProcessed = config.onProcessed || defaultOnProcessed;
702
- if (await isProcessed(webhookId)) {
705
+ const isProcessed = config.isProcessed || config.checkDuplicate || defaultIsProcessed;
706
+ const onProcessed = config.onProcessed || config.markProcessed || defaultOnProcessed;
707
+ const dedupEnabled = !!(config.enableDeduplication || config.isProcessed || config.checkDuplicate);
708
+ if (dedupEnabled && await isProcessed(webhookId)) {
703
709
  return {
704
- success: true,
710
+ success: false,
705
711
  processed: false,
706
- event: payload.event
712
+ event: payload.event,
713
+ error: "Duplicate webhook",
714
+ statusCode: 409
707
715
  };
708
716
  }
709
717
  const handler = handlers[payload.event];
@@ -711,7 +719,8 @@ async function processWebhook(payload, handlers, config) {
711
719
  return {
712
720
  success: true,
713
721
  processed: false,
714
- event: payload.event
722
+ event: payload.event,
723
+ statusCode: 200
715
724
  };
716
725
  }
717
726
  await handler(payload.data, payload);
@@ -723,14 +732,91 @@ async function processWebhook(payload, handlers, config) {
723
732
  };
724
733
  } catch (error) {
725
734
  const err = error;
726
- if (config.onError) {
727
- await config.onError(err, payload?.event);
735
+ if (config?.onError) {
736
+ await config.onError(err, error?.event);
728
737
  }
729
738
  return {
730
739
  success: false,
731
740
  processed: false,
732
741
  error: err.message,
733
- event: payload?.event
742
+ event: error?.event,
743
+ statusCode: 500
744
+ };
745
+ }
746
+ }
747
+ async function processWebhook(a, b, c) {
748
+ if (a && typeof a === "object" && a.event && b && c) {
749
+ return processPayload(a, b, c);
750
+ }
751
+ const opts = a;
752
+ if (!opts || !opts.signature && !opts.body && !opts.handlers) {
753
+ return {
754
+ success: false,
755
+ processed: false,
756
+ error: "Invalid arguments to processWebhook",
757
+ statusCode: 400
758
+ };
759
+ }
760
+ const signature = opts.signature;
761
+ const body = opts.body;
762
+ const handlers = opts.handlers || {};
763
+ const cfg = opts.config || {};
764
+ const secret = cfg.webhookSecret || cfg.secret;
765
+ if (!secret) {
766
+ return {
767
+ success: false,
768
+ processed: false,
769
+ error: "Webhook secret not provided",
770
+ statusCode: 400
771
+ };
772
+ }
773
+ if (!signature || !body) {
774
+ return {
775
+ success: false,
776
+ processed: false,
777
+ error: "Missing signature or body",
778
+ statusCode: 400
779
+ };
780
+ }
781
+ try {
782
+ const sig = typeof signature === "string" && signature.startsWith("sha256=") ? signature.slice("sha256=".length) : String(signature);
783
+ const hmac = (0, import_crypto2.createHmac)("sha256", secret).update(body, "utf8").digest("hex");
784
+ let ok = false;
785
+ try {
786
+ const sigBuf = Buffer.from(sig, "hex");
787
+ const hmacBuf = Buffer.from(hmac, "hex");
788
+ if (sigBuf.length === hmacBuf.length) {
789
+ ok = (0, import_crypto2.timingSafeEqual)(sigBuf, hmacBuf);
790
+ }
791
+ } catch (e) {
792
+ ok = (0, import_crypto2.timingSafeEqual)(Buffer.from(String(sig), "utf8"), Buffer.from(hmac, "utf8"));
793
+ }
794
+ if (!ok) {
795
+ return {
796
+ success: false,
797
+ processed: false,
798
+ error: "Invalid signature",
799
+ statusCode: 401
800
+ };
801
+ }
802
+ const payload = JSON.parse(body);
803
+ const fullConfig = {
804
+ secret,
805
+ isProcessed: cfg.isProcessed,
806
+ onProcessed: cfg.onProcessed,
807
+ onError: cfg.onError,
808
+ // Forward compatibility for alternate names and flags
809
+ enableDeduplication: cfg.enableDeduplication,
810
+ checkDuplicate: cfg.checkDuplicate,
811
+ markProcessed: cfg.markProcessed
812
+ };
813
+ return await processPayload(payload, handlers, fullConfig);
814
+ } catch (err) {
815
+ return {
816
+ success: false,
817
+ processed: false,
818
+ error: err.message,
819
+ statusCode: 500
734
820
  };
735
821
  }
736
822
  }
package/dist/index.mjs CHANGED
@@ -1,9 +1,7 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
1
+ import {
2
+ __require,
3
+ processWebhook
4
+ } from "./chunk-YFOBPGQE.mjs";
7
5
 
8
6
  // src/client.ts
9
7
  import fetch from "cross-fetch";
@@ -283,10 +281,14 @@ var ZendFiClient = class {
283
281
  };
284
282
  }
285
283
  /**
286
- * List all payment links
284
+ * List all payment links for the authenticated merchant
287
285
  */
288
286
  async listPaymentLinks() {
289
- return [];
287
+ const response = await this.request("GET", "/api/v1/payment-links");
288
+ return response.map((link) => ({
289
+ ...link,
290
+ url: link.hosted_page_url
291
+ }));
290
292
  }
291
293
  /**
292
294
  * Create an installment plan
@@ -635,65 +637,6 @@ function verifyWebhookSignature(payload, signature, secret) {
635
637
  secret
636
638
  });
637
639
  }
638
-
639
- // src/webhook-handler.ts
640
- var processedWebhooks = /* @__PURE__ */ new Set();
641
- var defaultIsProcessed = async (webhookId) => {
642
- return processedWebhooks.has(webhookId);
643
- };
644
- var defaultOnProcessed = async (webhookId) => {
645
- processedWebhooks.add(webhookId);
646
- if (processedWebhooks.size > 1e4) {
647
- const iterator = processedWebhooks.values();
648
- for (let i = 0; i < 1e3; i++) {
649
- const { value } = iterator.next();
650
- if (value) processedWebhooks.delete(value);
651
- }
652
- }
653
- };
654
- function generateWebhookId(payload) {
655
- return `${payload.merchant_id}:${payload.event}:${payload.timestamp}`;
656
- }
657
- async function processWebhook(payload, handlers, config) {
658
- try {
659
- const webhookId = generateWebhookId(payload);
660
- const isProcessed = config.isProcessed || defaultIsProcessed;
661
- const onProcessed = config.onProcessed || defaultOnProcessed;
662
- if (await isProcessed(webhookId)) {
663
- return {
664
- success: true,
665
- processed: false,
666
- event: payload.event
667
- };
668
- }
669
- const handler = handlers[payload.event];
670
- if (!handler) {
671
- return {
672
- success: true,
673
- processed: false,
674
- event: payload.event
675
- };
676
- }
677
- await handler(payload.data, payload);
678
- await onProcessed(webhookId);
679
- return {
680
- success: true,
681
- processed: true,
682
- event: payload.event
683
- };
684
- } catch (error) {
685
- const err = error;
686
- if (config.onError) {
687
- await config.onError(err, payload?.event);
688
- }
689
- return {
690
- success: false,
691
- processed: false,
692
- error: err.message,
693
- event: payload?.event
694
- };
695
- }
696
- }
697
640
  export {
698
641
  AuthenticationError,
699
642
  ConfigLoader,
@@ -0,0 +1,37 @@
1
+ import { W as WebhookHandlerConfig, a as WebhookHandlers } from './webhook-handler-BIze3Qop.mjs';
2
+
3
+ /**
4
+ * Next.js Webhook Handler for App Router
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // app/api/webhooks/zendfi/route.ts
9
+ * import { createNextWebhookHandler } from '@zendfi/sdk/nextjs';
10
+ *
11
+ * export const POST = createNextWebhookHandler({
12
+ * secret: process.env.ZENDFI_WEBHOOK_SECRET!,
13
+ * handlers: {
14
+ * 'payment.confirmed': async (payment) => {
15
+ * await db.orders.update({
16
+ * where: { id: payment.metadata.orderId },
17
+ * data: { status: 'paid' },
18
+ * });
19
+ * },
20
+ * 'payment.failed': async (payment) => {
21
+ * await sendFailureEmail(payment);
22
+ * },
23
+ * },
24
+ * });
25
+ * ```
26
+ */
27
+
28
+ type NextRequest = any;
29
+ interface NextWebhookHandlerConfig extends WebhookHandlerConfig {
30
+ handlers: WebhookHandlers;
31
+ }
32
+ /**
33
+ * Create a Next.js App Router webhook handler
34
+ */
35
+ declare function createNextWebhookHandler(config: NextWebhookHandlerConfig): (request: NextRequest) => Promise<Response>;
36
+
37
+ export { type NextWebhookHandlerConfig, createNextWebhookHandler };