@skillsmith/core 0.6.3 → 0.7.2

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.
Files changed (130) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +18 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/api/client.d.ts.map +1 -1
  5. package/dist/src/api/client.events.d.ts.map +1 -1
  6. package/dist/src/api/client.events.js +10 -1
  7. package/dist/src/api/client.events.js.map +1 -1
  8. package/dist/src/api/client.health.d.ts.map +1 -1
  9. package/dist/src/api/client.health.js +7 -1
  10. package/dist/src/api/client.health.js.map +1 -1
  11. package/dist/src/api/client.js +11 -1
  12. package/dist/src/api/client.js.map +1 -1
  13. package/dist/src/api/utils.d.ts +14 -3
  14. package/dist/src/api/utils.d.ts.map +1 -1
  15. package/dist/src/api/utils.js +14 -4
  16. package/dist/src/api/utils.js.map +1 -1
  17. package/dist/src/exports/services.d.ts +0 -1
  18. package/dist/src/exports/services.d.ts.map +1 -1
  19. package/dist/src/exports/services.js +14 -3
  20. package/dist/src/exports/services.js.map +1 -1
  21. package/dist/src/index.d.ts +2 -1
  22. package/dist/src/index.d.ts.map +1 -1
  23. package/dist/src/index.js +4 -1
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/types.d.ts +12 -0
  26. package/dist/src/types.d.ts.map +1 -1
  27. package/dist/tests/api/client.auth.test.js +50 -0
  28. package/dist/tests/api/client.auth.test.js.map +1 -1
  29. package/dist/tests/api/utils.test.js +7 -3
  30. package/dist/tests/api/utils.test.js.map +1 -1
  31. package/dist/tests/{billing/stripe-validators.test.d.ts → security/sanitization-stripe-ids.test.d.ts} +1 -1
  32. package/dist/tests/security/sanitization-stripe-ids.test.d.ts.map +1 -0
  33. package/dist/tests/{billing/stripe-validators.test.js → security/sanitization-stripe-ids.test.js} +1 -1
  34. package/dist/tests/security/sanitization-stripe-ids.test.js.map +1 -0
  35. package/dist/tests/shared.test.js.map +1 -1
  36. package/package.json +2 -8
  37. package/dist/src/billing/BillingService.d.ts +0 -101
  38. package/dist/src/billing/BillingService.d.ts.map +0 -1
  39. package/dist/src/billing/BillingService.helpers.d.ts +0 -15
  40. package/dist/src/billing/BillingService.helpers.d.ts.map +0 -1
  41. package/dist/src/billing/BillingService.helpers.js +0 -45
  42. package/dist/src/billing/BillingService.helpers.js.map +0 -1
  43. package/dist/src/billing/BillingService.js +0 -263
  44. package/dist/src/billing/BillingService.js.map +0 -1
  45. package/dist/src/billing/BillingService.types.d.ts +0 -52
  46. package/dist/src/billing/BillingService.types.d.ts.map +0 -1
  47. package/dist/src/billing/BillingService.types.js +0 -6
  48. package/dist/src/billing/BillingService.types.js.map +0 -1
  49. package/dist/src/billing/GDPRComplianceService.d.ts +0 -81
  50. package/dist/src/billing/GDPRComplianceService.d.ts.map +0 -1
  51. package/dist/src/billing/GDPRComplianceService.js +0 -361
  52. package/dist/src/billing/GDPRComplianceService.js.map +0 -1
  53. package/dist/src/billing/StripeClient.d.ts +0 -119
  54. package/dist/src/billing/StripeClient.d.ts.map +0 -1
  55. package/dist/src/billing/StripeClient.js +0 -405
  56. package/dist/src/billing/StripeClient.js.map +0 -1
  57. package/dist/src/billing/StripeReconciliationJob.d.ts +0 -50
  58. package/dist/src/billing/StripeReconciliationJob.d.ts.map +0 -1
  59. package/dist/src/billing/StripeReconciliationJob.js +0 -365
  60. package/dist/src/billing/StripeReconciliationJob.js.map +0 -1
  61. package/dist/src/billing/StripeWebhookHandler.d.ts +0 -49
  62. package/dist/src/billing/StripeWebhookHandler.d.ts.map +0 -1
  63. package/dist/src/billing/StripeWebhookHandler.js +0 -162
  64. package/dist/src/billing/StripeWebhookHandler.js.map +0 -1
  65. package/dist/src/billing/gdpr-types.d.ts +0 -103
  66. package/dist/src/billing/gdpr-types.d.ts.map +0 -1
  67. package/dist/src/billing/gdpr-types.js +0 -7
  68. package/dist/src/billing/gdpr-types.js.map +0 -1
  69. package/dist/src/billing/index.d.ts +0 -18
  70. package/dist/src/billing/index.d.ts.map +0 -1
  71. package/dist/src/billing/index.js +0 -19
  72. package/dist/src/billing/index.js.map +0 -1
  73. package/dist/src/billing/reconciliation-helpers.d.ts +0 -16
  74. package/dist/src/billing/reconciliation-helpers.d.ts.map +0 -1
  75. package/dist/src/billing/reconciliation-helpers.js +0 -53
  76. package/dist/src/billing/reconciliation-helpers.js.map +0 -1
  77. package/dist/src/billing/reconciliation-types.d.ts +0 -71
  78. package/dist/src/billing/reconciliation-types.d.ts.map +0 -1
  79. package/dist/src/billing/reconciliation-types.js +0 -7
  80. package/dist/src/billing/reconciliation-types.js.map +0 -1
  81. package/dist/src/billing/stripe-client-types.d.ts +0 -45
  82. package/dist/src/billing/stripe-client-types.d.ts.map +0 -1
  83. package/dist/src/billing/stripe-client-types.js +0 -7
  84. package/dist/src/billing/stripe-client-types.js.map +0 -1
  85. package/dist/src/billing/stripe-helpers.d.ts +0 -17
  86. package/dist/src/billing/stripe-helpers.d.ts.map +0 -1
  87. package/dist/src/billing/stripe-helpers.js +0 -50
  88. package/dist/src/billing/stripe-helpers.js.map +0 -1
  89. package/dist/src/billing/types.d.ts +0 -266
  90. package/dist/src/billing/types.d.ts.map +0 -1
  91. package/dist/src/billing/types.js +0 -23
  92. package/dist/src/billing/types.js.map +0 -1
  93. package/dist/src/billing/webhook-handlers.d.ts +0 -56
  94. package/dist/src/billing/webhook-handlers.d.ts.map +0 -1
  95. package/dist/src/billing/webhook-handlers.js +0 -303
  96. package/dist/src/billing/webhook-handlers.js.map +0 -1
  97. package/dist/src/billing/webhook-types.d.ts +0 -42
  98. package/dist/src/billing/webhook-types.d.ts.map +0 -1
  99. package/dist/src/billing/webhook-types.js +0 -7
  100. package/dist/src/billing/webhook-types.js.map +0 -1
  101. package/dist/tests/billing/BillingService.test.d.ts +0 -7
  102. package/dist/tests/billing/BillingService.test.d.ts.map +0 -1
  103. package/dist/tests/billing/BillingService.test.js +0 -168
  104. package/dist/tests/billing/BillingService.test.js.map +0 -1
  105. package/dist/tests/billing/GDPRCompliance.test.d.ts +0 -7
  106. package/dist/tests/billing/GDPRCompliance.test.d.ts.map +0 -1
  107. package/dist/tests/billing/GDPRCompliance.test.js +0 -380
  108. package/dist/tests/billing/GDPRCompliance.test.js.map +0 -1
  109. package/dist/tests/billing/StripeClient.test.d.ts +0 -18
  110. package/dist/tests/billing/StripeClient.test.d.ts.map +0 -1
  111. package/dist/tests/billing/StripeClient.test.js +0 -566
  112. package/dist/tests/billing/StripeClient.test.js.map +0 -1
  113. package/dist/tests/billing/StripeReconciliation.test.d.ts +0 -7
  114. package/dist/tests/billing/StripeReconciliation.test.d.ts.map +0 -1
  115. package/dist/tests/billing/StripeReconciliation.test.js +0 -266
  116. package/dist/tests/billing/StripeReconciliation.test.js.map +0 -1
  117. package/dist/tests/billing/StripeWebhookHandler.test.d.ts +0 -16
  118. package/dist/tests/billing/StripeWebhookHandler.test.d.ts.map +0 -1
  119. package/dist/tests/billing/StripeWebhookHandler.test.js +0 -240
  120. package/dist/tests/billing/StripeWebhookHandler.test.js.map +0 -1
  121. package/dist/tests/billing/stripe-helpers.test.d.ts +0 -7
  122. package/dist/tests/billing/stripe-helpers.test.d.ts.map +0 -1
  123. package/dist/tests/billing/stripe-helpers.test.js +0 -91
  124. package/dist/tests/billing/stripe-helpers.test.js.map +0 -1
  125. package/dist/tests/billing/stripe-validators.test.d.ts.map +0 -1
  126. package/dist/tests/billing/stripe-validators.test.js.map +0 -1
  127. package/dist/tests/billing/webhook-handlers.test.d.ts +0 -16
  128. package/dist/tests/billing/webhook-handlers.test.d.ts.map +0 -1
  129. package/dist/tests/billing/webhook-handlers.test.js +0 -519
  130. package/dist/tests/billing/webhook-handlers.test.js.map +0 -1
@@ -1,365 +0,0 @@
1
- /**
2
- * SMI-1069: Stripe Reconciliation Job
3
- *
4
- * Periodically reconciles local subscription and invoice data with Stripe.
5
- * Identifies and reports discrepancies to ensure data consistency.
6
- *
7
- * Features:
8
- * - Subscription status sync
9
- * - Invoice status verification
10
- * - Missing data detection
11
- * - Automatic correction (optional)
12
- * - Detailed reporting
13
- */
14
- import { createLogger } from '../utils/logger.js';
15
- import { mapStripeStatus, mapInvoiceStatus } from './reconciliation-helpers.js';
16
- const logger = createLogger('StripeReconciliation');
17
- // ============================================================================
18
- // StripeReconciliationJob Class
19
- // ============================================================================
20
- /**
21
- * Stripe Reconciliation Job
22
- *
23
- * @example
24
- * ```typescript
25
- * const job = new StripeReconciliationJob({
26
- * stripeClient,
27
- * db,
28
- * autoFix: true,
29
- * });
30
- *
31
- * // Run reconciliation
32
- * const result = await job.run();
33
- * console.log(`Found ${result.discrepancies.length} discrepancies`);
34
- * ```
35
- */
36
- export class StripeReconciliationJob {
37
- stripe;
38
- db;
39
- autoFix;
40
- batchSize;
41
- constructor(config) {
42
- this.stripe = config.stripeClient;
43
- this.db = config.db;
44
- this.autoFix = config.autoFix ?? false;
45
- this.batchSize = config.batchSize ?? 100;
46
- logger.info('Stripe reconciliation job initialized', {
47
- autoFix: this.autoFix,
48
- batchSize: this.batchSize,
49
- });
50
- }
51
- // ==========================================================================
52
- // Main Entry Point
53
- // ==========================================================================
54
- /**
55
- * Run the reconciliation job
56
- */
57
- async run() {
58
- const startedAt = new Date();
59
- const discrepancies = [];
60
- const errors = [];
61
- let subscriptionsChecked = 0;
62
- let invoicesChecked = 0;
63
- let discrepanciesFixed = 0;
64
- logger.info('Starting Stripe reconciliation job');
65
- try {
66
- // 1. Get all local subscriptions with Stripe IDs
67
- const localSubscriptions = this.getLocalSubscriptions();
68
- subscriptionsChecked = localSubscriptions.length;
69
- // 2. Reconcile each subscription
70
- for (const local of localSubscriptions) {
71
- try {
72
- const subDiscrepancies = await this.reconcileSubscription(local);
73
- discrepancies.push(...subDiscrepancies);
74
- }
75
- catch (error) {
76
- const errorMsg = error instanceof Error ? error.message : String(error);
77
- errors.push(`Subscription ${local.stripeSubscriptionId}: ${errorMsg}`);
78
- }
79
- }
80
- // 3. Reconcile invoices
81
- const localInvoices = this.getLocalInvoices();
82
- invoicesChecked = localInvoices.length;
83
- for (const invoice of localInvoices) {
84
- try {
85
- const invDiscrepancies = await this.reconcileInvoice(invoice);
86
- discrepancies.push(...invDiscrepancies);
87
- }
88
- catch (error) {
89
- const errorMsg = error instanceof Error ? error.message : String(error);
90
- errors.push(`Invoice ${invoice.stripeInvoiceId}: ${errorMsg}`);
91
- }
92
- }
93
- // 4. Apply fixes if autoFix is enabled
94
- if (this.autoFix) {
95
- for (const discrepancy of discrepancies) {
96
- if (this.fixDiscrepancy(discrepancy)) {
97
- discrepancy.fixed = true;
98
- discrepanciesFixed++;
99
- }
100
- }
101
- }
102
- }
103
- catch (error) {
104
- const errorMsg = error instanceof Error ? error.message : String(error);
105
- errors.push(`Job failed: ${errorMsg}`);
106
- logger.error('Reconciliation job failed', undefined, { error: errorMsg });
107
- }
108
- const completedAt = new Date();
109
- const result = {
110
- success: errors.length === 0,
111
- startedAt: startedAt.toISOString(),
112
- completedAt: completedAt.toISOString(),
113
- durationMs: completedAt.getTime() - startedAt.getTime(),
114
- stats: {
115
- subscriptionsChecked,
116
- invoicesChecked,
117
- discrepanciesFound: discrepancies.length,
118
- discrepanciesFixed,
119
- },
120
- discrepancies,
121
- errors,
122
- };
123
- logger.info('Stripe reconciliation job completed', {
124
- success: result.success,
125
- subscriptionsChecked,
126
- invoicesChecked,
127
- discrepanciesFound: discrepancies.length,
128
- discrepanciesFixed,
129
- durationMs: result.durationMs,
130
- });
131
- return result;
132
- }
133
- // ==========================================================================
134
- // Subscription Reconciliation
135
- // ==========================================================================
136
- getLocalSubscriptions() {
137
- return this.db
138
- .prepare(`SELECT
139
- id,
140
- customer_id as customerId,
141
- stripe_subscription_id as stripeSubscriptionId,
142
- stripe_customer_id as stripeCustomerId,
143
- tier,
144
- status,
145
- seat_count as seatCount,
146
- current_period_start as currentPeriodStart,
147
- current_period_end as currentPeriodEnd
148
- FROM user_subscriptions
149
- WHERE stripe_subscription_id IS NOT NULL
150
- LIMIT ?`)
151
- .all(this.batchSize);
152
- }
153
- async reconcileSubscription(local) {
154
- const discrepancies = [];
155
- // Fetch from Stripe
156
- const stripeSubscription = await this.stripe.getSubscription(local.stripeSubscriptionId);
157
- if (!stripeSubscription) {
158
- discrepancies.push({
159
- type: 'missing_stripe',
160
- entityType: 'subscription',
161
- entityId: local.id,
162
- stripeId: local.stripeSubscriptionId,
163
- localValue: local.status,
164
- stripeValue: null,
165
- description: 'Subscription exists locally but not in Stripe',
166
- fixed: false,
167
- });
168
- return discrepancies;
169
- }
170
- // Compare status
171
- const stripeStatus = mapStripeStatus(stripeSubscription.status);
172
- if (local.status !== stripeStatus) {
173
- discrepancies.push({
174
- type: 'status_mismatch',
175
- entityType: 'subscription',
176
- entityId: local.id,
177
- stripeId: local.stripeSubscriptionId,
178
- localValue: local.status,
179
- stripeValue: stripeStatus,
180
- description: `Status mismatch: local=${local.status}, stripe=${stripeStatus}`,
181
- fixed: false,
182
- });
183
- }
184
- // Compare tier (from metadata)
185
- const stripeTier = stripeSubscription.metadata?.tier;
186
- if (stripeTier && local.tier !== stripeTier) {
187
- discrepancies.push({
188
- type: 'tier_mismatch',
189
- entityType: 'subscription',
190
- entityId: local.id,
191
- stripeId: local.stripeSubscriptionId,
192
- localValue: local.tier,
193
- stripeValue: stripeTier,
194
- description: `Tier mismatch: local=${local.tier}, stripe=${stripeTier}`,
195
- fixed: false,
196
- });
197
- }
198
- // Compare seat count
199
- const stripeQuantity = stripeSubscription.items.data[0]?.quantity ?? 1;
200
- if (local.seatCount !== stripeQuantity) {
201
- discrepancies.push({
202
- type: 'seat_count_mismatch',
203
- entityType: 'subscription',
204
- entityId: local.id,
205
- stripeId: local.stripeSubscriptionId,
206
- localValue: local.seatCount,
207
- stripeValue: stripeQuantity,
208
- description: `Seat count mismatch: local=${local.seatCount}, stripe=${stripeQuantity}`,
209
- fixed: false,
210
- });
211
- }
212
- return discrepancies;
213
- }
214
- // ==========================================================================
215
- // Invoice Reconciliation
216
- // ==========================================================================
217
- getLocalInvoices() {
218
- return this.db
219
- .prepare(`SELECT
220
- id,
221
- customer_id as customerId,
222
- stripe_invoice_id as stripeInvoiceId,
223
- amount_cents as amountCents,
224
- status
225
- FROM invoices
226
- WHERE stripe_invoice_id IS NOT NULL
227
- LIMIT ?`)
228
- .all(this.batchSize);
229
- }
230
- async reconcileInvoice(local) {
231
- const discrepancies = [];
232
- // Fetch from Stripe
233
- const stripeInvoice = await this.stripe.getInvoice(local.stripeInvoiceId);
234
- if (!stripeInvoice) {
235
- discrepancies.push({
236
- type: 'missing_stripe',
237
- entityType: 'invoice',
238
- entityId: local.id,
239
- stripeId: local.stripeInvoiceId,
240
- localValue: local.status,
241
- stripeValue: null,
242
- description: 'Invoice exists locally but not in Stripe',
243
- fixed: false,
244
- });
245
- return discrepancies;
246
- }
247
- // Compare status
248
- const stripeStatus = mapInvoiceStatus(stripeInvoice.status);
249
- if (local.status !== stripeStatus) {
250
- discrepancies.push({
251
- type: 'invoice_status_mismatch',
252
- entityType: 'invoice',
253
- entityId: local.id,
254
- stripeId: local.stripeInvoiceId,
255
- localValue: local.status,
256
- stripeValue: stripeStatus,
257
- description: `Invoice status mismatch: local=${local.status}, stripe=${stripeStatus}`,
258
- fixed: false,
259
- });
260
- }
261
- // Compare amount
262
- const stripeAmount = stripeInvoice.amount_paid ?? stripeInvoice.amount_due;
263
- if (local.amountCents !== stripeAmount) {
264
- discrepancies.push({
265
- type: 'invoice_amount_mismatch',
266
- entityType: 'invoice',
267
- entityId: local.id,
268
- stripeId: local.stripeInvoiceId,
269
- localValue: local.amountCents,
270
- stripeValue: stripeAmount,
271
- description: `Invoice amount mismatch: local=${local.amountCents}, stripe=${stripeAmount}`,
272
- fixed: false,
273
- });
274
- }
275
- return discrepancies;
276
- }
277
- // ==========================================================================
278
- // Fix Discrepancies
279
- // ==========================================================================
280
- fixDiscrepancy(discrepancy) {
281
- try {
282
- if (discrepancy.entityType === 'subscription') {
283
- return this.fixSubscriptionDiscrepancy(discrepancy);
284
- }
285
- else if (discrepancy.entityType === 'invoice') {
286
- return this.fixInvoiceDiscrepancy(discrepancy);
287
- }
288
- return false;
289
- }
290
- catch (error) {
291
- const errorMsg = error instanceof Error ? error.message : String(error);
292
- logger.error('Failed to fix discrepancy', undefined, {
293
- type: discrepancy.type,
294
- entityId: discrepancy.entityId,
295
- error: errorMsg,
296
- });
297
- return false;
298
- }
299
- }
300
- fixSubscriptionDiscrepancy(discrepancy) {
301
- switch (discrepancy.type) {
302
- case 'status_mismatch':
303
- this.db
304
- .prepare(`UPDATE user_subscriptions SET status = ?, updated_at = ? WHERE id = ?`)
305
- .run(discrepancy.stripeValue, new Date().toISOString(), discrepancy.entityId);
306
- logger.info('Fixed subscription status', {
307
- entityId: discrepancy.entityId,
308
- newStatus: discrepancy.stripeValue,
309
- });
310
- return true;
311
- case 'tier_mismatch':
312
- this.db
313
- .prepare(`UPDATE user_subscriptions SET tier = ?, updated_at = ? WHERE id = ?`)
314
- .run(discrepancy.stripeValue, new Date().toISOString(), discrepancy.entityId);
315
- logger.info('Fixed subscription tier', {
316
- entityId: discrepancy.entityId,
317
- newTier: discrepancy.stripeValue,
318
- });
319
- return true;
320
- case 'seat_count_mismatch':
321
- this.db
322
- .prepare(`UPDATE user_subscriptions SET seat_count = ?, updated_at = ? WHERE id = ?`)
323
- .run(discrepancy.stripeValue, new Date().toISOString(), discrepancy.entityId);
324
- logger.info('Fixed subscription seat count', {
325
- entityId: discrepancy.entityId,
326
- newSeatCount: discrepancy.stripeValue,
327
- });
328
- return true;
329
- case 'missing_stripe':
330
- // Mark local subscription as canceled if missing in Stripe
331
- this.db
332
- .prepare(`UPDATE user_subscriptions SET status = 'canceled', canceled_at = ?, updated_at = ? WHERE id = ?`)
333
- .run(new Date().toISOString(), new Date().toISOString(), discrepancy.entityId);
334
- logger.info('Marked missing subscription as canceled', { entityId: discrepancy.entityId });
335
- return true;
336
- default:
337
- return false;
338
- }
339
- }
340
- fixInvoiceDiscrepancy(discrepancy) {
341
- switch (discrepancy.type) {
342
- case 'invoice_status_mismatch':
343
- this.db
344
- .prepare(`UPDATE invoices SET status = ? WHERE id = ?`)
345
- .run(discrepancy.stripeValue, discrepancy.entityId);
346
- logger.info('Fixed invoice status', {
347
- entityId: discrepancy.entityId,
348
- newStatus: discrepancy.stripeValue,
349
- });
350
- return true;
351
- case 'invoice_amount_mismatch':
352
- this.db
353
- .prepare(`UPDATE invoices SET amount_cents = ? WHERE id = ?`)
354
- .run(discrepancy.stripeValue, discrepancy.entityId);
355
- logger.info('Fixed invoice amount', {
356
- entityId: discrepancy.entityId,
357
- newAmount: discrepancy.stripeValue,
358
- });
359
- return true;
360
- default:
361
- return false;
362
- }
363
- }
364
- }
365
- //# sourceMappingURL=StripeReconciliationJob.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StripeReconciliationJob.js","sourceRoot":"","sources":["../../../src/billing/StripeReconciliationJob.ts"],"names":[],"mappings":"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"}
@@ -1,49 +0,0 @@
1
- /**
2
- * SMI-1070: Stripe Webhook Handler
3
- *
4
- * Processes Stripe webhook events for:
5
- * - Subscription lifecycle (created, updated, deleted)
6
- * - Invoice events (payment succeeded, payment failed)
7
- * - Checkout session completion
8
- *
9
- * Features:
10
- * - Idempotent event processing
11
- * - Signature verification
12
- * - License key generation on subscription creation
13
- * - Status synchronization
14
- */
15
- import type { WebhookProcessResult } from './types.js';
16
- import type { StripeWebhookHandlerConfig } from './webhook-types.js';
17
- export type { StripeWebhookHandlerConfig } from './webhook-types.js';
18
- /**
19
- * Handles Stripe webhook events
20
- *
21
- * @example
22
- * ```typescript
23
- * const handler = new StripeWebhookHandler({
24
- * stripeClient,
25
- * billingService,
26
- * db,
27
- * onLicenseKeyNeeded: async (params) => {
28
- * return licenseGenerator.createLicense(params);
29
- * },
30
- * });
31
- *
32
- * // In webhook endpoint:
33
- * const result = await handler.handleWebhook(payload, signature);
34
- * ```
35
- */
36
- export declare class StripeWebhookHandler {
37
- private readonly stripe;
38
- private readonly billing;
39
- private readonly db;
40
- private readonly onLicenseKeyNeeded?;
41
- private readonly onEmailNeeded?;
42
- constructor(config: StripeWebhookHandlerConfig);
43
- /**
44
- * Handle an incoming Stripe webhook
45
- */
46
- handleWebhook(payload: string, signature: string): Promise<WebhookProcessResult>;
47
- private routeEvent;
48
- }
49
- //# sourceMappingURL=StripeWebhookHandler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StripeWebhookHandler.d.ts","sourceRoot":"","sources":["../../../src/billing/StripeWebhookHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EAAiB,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACrE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAYpE,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAQpE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAkD;IACtF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA6C;gBAEhE,MAAM,EAAE,0BAA0B;IAc9C;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAgFxE,UAAU;CAsCzB"}
@@ -1,162 +0,0 @@
1
- /**
2
- * SMI-1070: Stripe Webhook Handler
3
- *
4
- * Processes Stripe webhook events for:
5
- * - Subscription lifecycle (created, updated, deleted)
6
- * - Invoice events (payment succeeded, payment failed)
7
- * - Checkout session completion
8
- *
9
- * Features:
10
- * - Idempotent event processing
11
- * - Signature verification
12
- * - License key generation on subscription creation
13
- * - Status synchronization
14
- */
15
- import { createLogger } from '../utils/logger.js';
16
- import { handleSubscriptionCreated, handleSubscriptionUpdated, handleSubscriptionDeleted, handleInvoicePaymentSucceeded, handleInvoicePaymentFailed, handleCheckoutSessionCompleted, } from './webhook-handlers.js';
17
- const logger = createLogger('StripeWebhookHandler');
18
- // ============================================================================
19
- // StripeWebhookHandler Class
20
- // ============================================================================
21
- /**
22
- * Handles Stripe webhook events
23
- *
24
- * @example
25
- * ```typescript
26
- * const handler = new StripeWebhookHandler({
27
- * stripeClient,
28
- * billingService,
29
- * db,
30
- * onLicenseKeyNeeded: async (params) => {
31
- * return licenseGenerator.createLicense(params);
32
- * },
33
- * });
34
- *
35
- * // In webhook endpoint:
36
- * const result = await handler.handleWebhook(payload, signature);
37
- * ```
38
- */
39
- export class StripeWebhookHandler {
40
- stripe;
41
- billing;
42
- db;
43
- onLicenseKeyNeeded;
44
- onEmailNeeded;
45
- constructor(config) {
46
- this.stripe = config.stripeClient;
47
- this.billing = config.billingService;
48
- this.db = config.db;
49
- this.onLicenseKeyNeeded = config.onLicenseKeyNeeded;
50
- this.onEmailNeeded = config.onEmailNeeded;
51
- logger.info('Stripe webhook handler initialized');
52
- }
53
- // ==========================================================================
54
- // Main Entry Point
55
- // ==========================================================================
56
- /**
57
- * Handle an incoming Stripe webhook
58
- */
59
- async handleWebhook(payload, signature) {
60
- // 1. Verify signature
61
- let event;
62
- try {
63
- event = this.stripe.verifyWebhookSignature(payload, signature);
64
- }
65
- catch (error) {
66
- return {
67
- success: false,
68
- message: 'Signature verification failed',
69
- eventId: '',
70
- processed: false,
71
- error: error instanceof Error ? error.message : 'Invalid signature',
72
- };
73
- }
74
- const eventId = event.id;
75
- // 2. Check for duplicate (idempotency)
76
- if (this.billing.isEventProcessed(eventId)) {
77
- logger.info('Duplicate webhook event', { eventId, type: event.type });
78
- return {
79
- success: true,
80
- message: 'Event already processed',
81
- eventId,
82
- processed: false,
83
- };
84
- }
85
- // 3. Route to appropriate handler
86
- try {
87
- await this.routeEvent(event);
88
- // 4. Record successful processing
89
- this.billing.recordWebhookEvent({
90
- stripeEventId: eventId,
91
- eventType: event.type,
92
- payload,
93
- success: true,
94
- });
95
- logger.info('Webhook event processed', { eventId, type: event.type });
96
- return {
97
- success: true,
98
- message: `Processed ${event.type}`,
99
- eventId,
100
- processed: true,
101
- };
102
- }
103
- catch (error) {
104
- const errorMessage = error instanceof Error ? error.message : String(error);
105
- // Record failed processing
106
- this.billing.recordWebhookEvent({
107
- stripeEventId: eventId,
108
- eventType: event.type,
109
- payload,
110
- success: false,
111
- errorMessage,
112
- });
113
- logger.error('Webhook processing failed', undefined, {
114
- eventId,
115
- eventType: event.type,
116
- errorDetails: errorMessage,
117
- });
118
- return {
119
- success: false,
120
- message: 'Processing failed',
121
- eventId,
122
- processed: false,
123
- error: errorMessage,
124
- };
125
- }
126
- }
127
- // ==========================================================================
128
- // Event Routing
129
- // ==========================================================================
130
- async routeEvent(event) {
131
- const ctx = {
132
- stripe: this.stripe,
133
- billing: this.billing,
134
- db: this.db,
135
- onLicenseKeyNeeded: this.onLicenseKeyNeeded,
136
- onEmailNeeded: this.onEmailNeeded,
137
- };
138
- switch (event.type) {
139
- case 'customer.subscription.created':
140
- await handleSubscriptionCreated(ctx, event.data.object);
141
- break;
142
- case 'customer.subscription.updated':
143
- await handleSubscriptionUpdated(ctx, event.data.object);
144
- break;
145
- case 'customer.subscription.deleted':
146
- await handleSubscriptionDeleted(ctx, event.data.object);
147
- break;
148
- case 'invoice.payment_succeeded':
149
- await handleInvoicePaymentSucceeded(ctx, event.data.object);
150
- break;
151
- case 'invoice.payment_failed':
152
- await handleInvoicePaymentFailed(ctx, event.data.object);
153
- break;
154
- case 'checkout.session.completed':
155
- handleCheckoutSessionCompleted(event.data.object);
156
- break;
157
- default:
158
- logger.debug('Unhandled webhook event type', { type: event.type });
159
- }
160
- }
161
- }
162
- //# sourceMappingURL=StripeWebhookHandler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StripeWebhookHandler.js","sourceRoot":"","sources":["../../../src/billing/StripeWebhookHandler.ts"],"names":[],"mappings":"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"}