@forklaunch/implementation-billing-stripe 0.0.1

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 (34) hide show
  1. package/LICENSE +21 -0
  2. package/lib/domain/index.d.mts +189 -0
  3. package/lib/domain/index.d.ts +189 -0
  4. package/lib/domain/index.js +231 -0
  5. package/lib/domain/index.mjs +201 -0
  6. package/lib/eject/domain/schemas/billingPortal.schema.ts +37 -0
  7. package/lib/eject/domain/schemas/checkoutSession.schema.ts +74 -0
  8. package/lib/eject/domain/schemas/index.ts +5 -0
  9. package/lib/eject/domain/schemas/paymentLink.schema.ts +62 -0
  10. package/lib/eject/domain/schemas/plan.schema.ts +68 -0
  11. package/lib/eject/domain/schemas/subscription.schema.ts +78 -0
  12. package/lib/eject/services/billingPortal.service.ts +185 -0
  13. package/lib/eject/services/checkoutSession.service.ts +179 -0
  14. package/lib/eject/services/index.ts +6 -0
  15. package/lib/eject/services/paymentLink.service.ts +239 -0
  16. package/lib/eject/services/plan.service.ts +219 -0
  17. package/lib/eject/services/subscription.service.ts +285 -0
  18. package/lib/eject/services/webhook.service.ts +272 -0
  19. package/lib/eject/types/index.ts +2 -0
  20. package/lib/eject/types/stripe.dto.types.ts +214 -0
  21. package/lib/eject/types/stripe.entity.types.ts +83 -0
  22. package/lib/schemas/index.d.mts +376 -0
  23. package/lib/schemas/index.d.ts +376 -0
  24. package/lib/schemas/index.js +704 -0
  25. package/lib/schemas/index.mjs +737 -0
  26. package/lib/services/index.d.mts +223 -0
  27. package/lib/services/index.d.ts +223 -0
  28. package/lib/services/index.js +788 -0
  29. package/lib/services/index.mjs +776 -0
  30. package/lib/types/index.d.mts +121 -0
  31. package/lib/types/index.d.ts +121 -0
  32. package/lib/types/index.js +18 -0
  33. package/lib/types/index.mjs +0 -0
  34. package/package.json +74 -0
@@ -0,0 +1,788 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // services/index.ts
21
+ var services_exports = {};
22
+ __export(services_exports, {
23
+ StripeBillingPortalService: () => StripeBillingPortalService,
24
+ StripeCheckoutSessionService: () => StripeCheckoutSessionService,
25
+ StripePaymentLinkService: () => StripePaymentLinkService,
26
+ StripePlanService: () => StripePlanService,
27
+ StripeSubscriptionService: () => StripeSubscriptionService,
28
+ StripeWebhookService: () => StripeWebhookService
29
+ });
30
+ module.exports = __toCommonJS(services_exports);
31
+
32
+ // services/billingPortal.service.ts
33
+ var import_services = require("@forklaunch/implementation-billing-base/services");
34
+ var import_internal = require("@forklaunch/internal");
35
+ var StripeBillingPortalService = class {
36
+ constructor(stripeClient, em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
37
+ this.stripeClient = stripeClient;
38
+ this.em = em;
39
+ this.cache = cache;
40
+ this.openTelemetryCollector = openTelemetryCollector;
41
+ this.schemaValidator = schemaValidator;
42
+ this.mappers = mappers;
43
+ this.options = options;
44
+ this._mappers = (0, import_internal.transformIntoInternalMapper)(mappers, schemaValidator);
45
+ this.baseBillingPortalService = new import_services.BaseBillingPortalService(
46
+ em,
47
+ cache,
48
+ openTelemetryCollector,
49
+ schemaValidator,
50
+ {
51
+ BillingPortalMapper: import_internal.IdentityResponseMapper,
52
+ CreateBillingPortalMapper: import_internal.IdentityRequestMapper,
53
+ UpdateBillingPortalMapper: import_internal.IdentityRequestMapper
54
+ },
55
+ options
56
+ );
57
+ }
58
+ billingPortalSessionExpiryDurationMs = 5 * 60 * 1e3;
59
+ baseBillingPortalService;
60
+ _mappers;
61
+ async createBillingPortalSession(billingPortalDto) {
62
+ const session = await this.stripeClient.billingPortal.sessions.create({
63
+ ...billingPortalDto.stripeFields,
64
+ customer: billingPortalDto.customerId
65
+ });
66
+ const billingPortalEntity = await this.baseBillingPortalService.createBillingPortalSession(
67
+ await this._mappers.CreateBillingPortalMapper.deserializeDtoToEntity(
68
+ {
69
+ ...billingPortalDto,
70
+ id: session.id,
71
+ uri: session.url,
72
+ expiresAt: new Date(
73
+ Date.now() + this.billingPortalSessionExpiryDurationMs
74
+ )
75
+ },
76
+ this.em,
77
+ session
78
+ )
79
+ );
80
+ return this._mappers.BillingPortalMapper.serializeEntityToDto(
81
+ billingPortalEntity
82
+ );
83
+ }
84
+ async getBillingPortalSession(idDto) {
85
+ const billingPortalEntity = await this.baseBillingPortalService.getBillingPortalSession(idDto);
86
+ return this._mappers.BillingPortalMapper.serializeEntityToDto(
87
+ billingPortalEntity
88
+ );
89
+ }
90
+ async expireBillingPortalSession(idDto) {
91
+ return this.baseBillingPortalService.expireBillingPortalSession(idDto);
92
+ }
93
+ async updateBillingPortalSession(billingPortalDto) {
94
+ const existingSession = await this.baseBillingPortalService.getBillingPortalSession({
95
+ id: billingPortalDto.id
96
+ });
97
+ const session = await this.stripeClient.billingPortal.sessions.create({
98
+ ...billingPortalDto.stripeFields,
99
+ customer: existingSession.customerId
100
+ });
101
+ const baseBillingPortalDto = await this.baseBillingPortalService.updateBillingPortalSession(
102
+ await this._mappers.UpdateBillingPortalMapper.deserializeDtoToEntity(
103
+ {
104
+ ...billingPortalDto,
105
+ id: session.id,
106
+ uri: session.url,
107
+ expiresAt: new Date(
108
+ Date.now() + this.billingPortalSessionExpiryDurationMs
109
+ )
110
+ },
111
+ this.em,
112
+ session
113
+ )
114
+ );
115
+ return this._mappers.BillingPortalMapper.serializeEntityToDto(
116
+ baseBillingPortalDto
117
+ );
118
+ }
119
+ };
120
+
121
+ // services/checkoutSession.service.ts
122
+ var import_services2 = require("@forklaunch/implementation-billing-base/services");
123
+ var import_internal2 = require("@forklaunch/internal");
124
+ var StripeCheckoutSessionService = class {
125
+ constructor(stripeClient, em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
126
+ this.stripeClient = stripeClient;
127
+ this.em = em;
128
+ this.cache = cache;
129
+ this.openTelemetryCollector = openTelemetryCollector;
130
+ this.schemaValidator = schemaValidator;
131
+ this.mappers = mappers;
132
+ this.options = options;
133
+ this._mappers = (0, import_internal2.transformIntoInternalMapper)(mappers, schemaValidator);
134
+ this.baseCheckoutSessionService = new import_services2.BaseCheckoutSessionService(
135
+ em,
136
+ cache,
137
+ openTelemetryCollector,
138
+ schemaValidator,
139
+ {
140
+ CheckoutSessionMapper: import_internal2.IdentityResponseMapper,
141
+ CreateCheckoutSessionMapper: import_internal2.IdentityRequestMapper,
142
+ UpdateCheckoutSessionMapper: import_internal2.IdentityRequestMapper
143
+ },
144
+ options
145
+ );
146
+ }
147
+ baseCheckoutSessionService;
148
+ _mappers;
149
+ async createCheckoutSession(checkoutSessionDto) {
150
+ const session = await this.stripeClient.checkout.sessions.create({
151
+ ...checkoutSessionDto.stripeFields,
152
+ payment_method_types: checkoutSessionDto.paymentMethods,
153
+ currency: checkoutSessionDto.currency,
154
+ success_url: checkoutSessionDto.successRedirectUri,
155
+ cancel_url: checkoutSessionDto.cancelRedirectUri
156
+ });
157
+ const checkoutSessionEntity = await this.baseCheckoutSessionService.createCheckoutSession(
158
+ await this._mappers.CreateCheckoutSessionMapper.deserializeDtoToEntity(
159
+ {
160
+ ...checkoutSessionDto,
161
+ id: session.id,
162
+ uri: session.url,
163
+ expiresAt: new Date(Date.now() + 5 * 60 * 1e3),
164
+ providerFields: session
165
+ },
166
+ this.em,
167
+ session
168
+ )
169
+ );
170
+ return this._mappers.CheckoutSessionMapper.serializeEntityToDto(
171
+ checkoutSessionEntity
172
+ );
173
+ }
174
+ async getCheckoutSession({
175
+ id
176
+ }) {
177
+ const databaseCheckoutSession = await this.baseCheckoutSessionService.getCheckoutSession({ id });
178
+ return {
179
+ ...this._mappers.CheckoutSessionMapper.serializeEntityToDto(
180
+ databaseCheckoutSession
181
+ ),
182
+ stripeFields: await this.stripeClient.checkout.sessions.retrieve(id)
183
+ };
184
+ }
185
+ async expireCheckoutSession({ id }) {
186
+ await this.stripeClient.checkout.sessions.expire(id);
187
+ await this.baseCheckoutSessionService.expireCheckoutSession({ id });
188
+ }
189
+ async handleCheckoutSuccess({ id }) {
190
+ await this.stripeClient.checkout.sessions.update(id, {
191
+ metadata: {
192
+ status: "SUCCESS"
193
+ }
194
+ });
195
+ await this.baseCheckoutSessionService.handleCheckoutSuccess({ id });
196
+ }
197
+ async handleCheckoutFailure({ id }) {
198
+ await this.stripeClient.checkout.sessions.update(id, {
199
+ metadata: {
200
+ status: "FAILED"
201
+ }
202
+ });
203
+ await this.baseCheckoutSessionService.handleCheckoutFailure({ id });
204
+ }
205
+ };
206
+
207
+ // services/paymentLink.service.ts
208
+ var import_services3 = require("@forklaunch/implementation-billing-base/services");
209
+ var import_internal3 = require("@forklaunch/internal");
210
+ var StripePaymentLinkService = class {
211
+ constructor(stripeClient, em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
212
+ this.stripeClient = stripeClient;
213
+ this.em = em;
214
+ this.cache = cache;
215
+ this.openTelemetryCollector = openTelemetryCollector;
216
+ this.schemaValidator = schemaValidator;
217
+ this.mappers = mappers;
218
+ this.options = options;
219
+ this._mappers = (0, import_internal3.transformIntoInternalMapper)(mappers, schemaValidator);
220
+ this.basePaymentLinkService = new import_services3.BasePaymentLinkService(
221
+ em,
222
+ cache,
223
+ openTelemetryCollector,
224
+ schemaValidator,
225
+ {
226
+ PaymentLinkMapper: import_internal3.IdentityResponseMapper,
227
+ CreatePaymentLinkMapper: import_internal3.IdentityRequestMapper,
228
+ UpdatePaymentLinkMapper: import_internal3.IdentityRequestMapper
229
+ },
230
+ options
231
+ );
232
+ }
233
+ basePaymentLinkService;
234
+ _mappers;
235
+ async createPaymentLink(paymentLinkDto) {
236
+ const session = await this.stripeClient.paymentLinks.create({
237
+ ...paymentLinkDto.stripeFields,
238
+ payment_method_types: paymentLinkDto.paymentMethods,
239
+ currency: paymentLinkDto.currency
240
+ });
241
+ const paymentLinkEntity = await this.basePaymentLinkService.createPaymentLink(
242
+ await this._mappers.CreatePaymentLinkMapper.deserializeDtoToEntity(
243
+ {
244
+ ...paymentLinkDto,
245
+ id: session.id,
246
+ amount: session.line_items?.data.reduce(
247
+ (total, item) => total + item.amount_total,
248
+ 0
249
+ ) ?? 0
250
+ },
251
+ this.em,
252
+ session
253
+ )
254
+ );
255
+ return this._mappers.PaymentLinkMapper.serializeEntityToDto(
256
+ paymentLinkEntity
257
+ );
258
+ }
259
+ async updatePaymentLink(paymentLinkDto) {
260
+ const session = await this.stripeClient.paymentLinks.update(
261
+ paymentLinkDto.id,
262
+ {
263
+ ...paymentLinkDto.stripeFields,
264
+ payment_method_types: paymentLinkDto.paymentMethods
265
+ }
266
+ );
267
+ const paymentLinkEntity = await this.basePaymentLinkService.updatePaymentLink(
268
+ await this._mappers.UpdatePaymentLinkMapper.deserializeDtoToEntity(
269
+ {
270
+ ...paymentLinkDto,
271
+ id: session.id,
272
+ amount: session.line_items?.data.reduce(
273
+ (total, item) => total + item.amount_total,
274
+ 0
275
+ ) ?? 0
276
+ },
277
+ this.em,
278
+ session
279
+ )
280
+ );
281
+ return this._mappers.PaymentLinkMapper.serializeEntityToDto(
282
+ paymentLinkEntity
283
+ );
284
+ }
285
+ async getPaymentLink({ id }) {
286
+ const databasePaymentLink = await this.basePaymentLinkService.getPaymentLink({ id });
287
+ return {
288
+ ...this._mappers.PaymentLinkMapper.serializeEntityToDto(
289
+ databasePaymentLink
290
+ ),
291
+ stripeFields: await this.stripeClient.paymentLinks.retrieve(id)
292
+ };
293
+ }
294
+ async expirePaymentLink({ id }) {
295
+ await this.stripeClient.paymentLinks.update(id, {
296
+ metadata: {
297
+ status: "EXPIRED"
298
+ }
299
+ });
300
+ await this.basePaymentLinkService.expirePaymentLink({ id });
301
+ }
302
+ async handlePaymentSuccess({ id }) {
303
+ await this.stripeClient.paymentLinks.update(id, {
304
+ metadata: {
305
+ status: "COMPLETED"
306
+ }
307
+ });
308
+ await this.basePaymentLinkService.handlePaymentSuccess({ id });
309
+ }
310
+ async handlePaymentFailure({ id }) {
311
+ await this.stripeClient.paymentLinks.update(id, {
312
+ metadata: {
313
+ status: "FAILED"
314
+ }
315
+ });
316
+ await this.basePaymentLinkService.handlePaymentFailure({ id });
317
+ }
318
+ async listPaymentLinks(idsDto) {
319
+ const paymentLinks = await this.stripeClient.paymentLinks.list({
320
+ active: true
321
+ });
322
+ return await Promise.all(
323
+ (await this.basePaymentLinkService.listPaymentLinks(idsDto)).map(
324
+ async (paymentLink) => ({
325
+ ...await this._mappers.PaymentLinkMapper.serializeEntityToDto(
326
+ paymentLink
327
+ ),
328
+ stripeFields: paymentLinks.data.find(
329
+ (paymentLink2) => paymentLink2.id === paymentLink2.id
330
+ )
331
+ })
332
+ )
333
+ );
334
+ }
335
+ };
336
+
337
+ // services/plan.service.ts
338
+ var import_services4 = require("@forklaunch/implementation-billing-base/services");
339
+ var import_internal4 = require("@forklaunch/internal");
340
+ var StripePlanService = class {
341
+ constructor(stripeClient, em, openTelemetryCollector, schemaValidator, mappers, options) {
342
+ this.stripeClient = stripeClient;
343
+ this.em = em;
344
+ this.openTelemetryCollector = openTelemetryCollector;
345
+ this.schemaValidator = schemaValidator;
346
+ this.mappers = mappers;
347
+ this.options = options;
348
+ this._mappers = (0, import_internal4.transformIntoInternalMapper)(mappers, schemaValidator);
349
+ this.basePlanService = new import_services4.BasePlanService(
350
+ em,
351
+ openTelemetryCollector,
352
+ schemaValidator,
353
+ {
354
+ PlanMapper: import_internal4.IdentityResponseMapper,
355
+ CreatePlanMapper: import_internal4.IdentityRequestMapper,
356
+ UpdatePlanMapper: import_internal4.IdentityRequestMapper
357
+ },
358
+ options
359
+ );
360
+ }
361
+ basePlanService;
362
+ _mappers;
363
+ async createPlan(planDto, em) {
364
+ const plan = await this.stripeClient.plans.create({
365
+ ...planDto.stripeFields,
366
+ interval: planDto.cadence,
367
+ product: planDto.name,
368
+ currency: planDto.currency
369
+ });
370
+ const planEntity = await this.basePlanService.createPlan(
371
+ await this._mappers.CreatePlanMapper.deserializeDtoToEntity(
372
+ {
373
+ ...planDto,
374
+ externalId: plan.id,
375
+ billingProvider: "stripe"
376
+ },
377
+ em ?? this.em,
378
+ plan
379
+ ),
380
+ em
381
+ );
382
+ return this._mappers.PlanMapper.serializeEntityToDto(planEntity);
383
+ }
384
+ async getPlan(idDto, em) {
385
+ const plan = await this.stripeClient.plans.retrieve(idDto.id);
386
+ const id = (await em?.findOne(
387
+ this.options?.databaseTableName ?? "plan",
388
+ { externalId: idDto.id }
389
+ ))?.id;
390
+ if (!id) {
391
+ throw new Error("Plan not found");
392
+ }
393
+ return {
394
+ ...await this._mappers.PlanMapper.serializeEntityToDto(
395
+ await this.basePlanService.getPlan({ id }, em)
396
+ ),
397
+ stripeFields: plan
398
+ };
399
+ }
400
+ async updatePlan(planDto, em) {
401
+ const existingPlan = await this.stripeClient.plans.retrieve(planDto.id);
402
+ const plan = await this.stripeClient.plans.del(planDto.id).then(
403
+ () => this.stripeClient.plans.create({
404
+ ...planDto.stripeFields,
405
+ interval: planDto.cadence ?? existingPlan.interval,
406
+ product: planDto.name,
407
+ currency: planDto.currency ?? existingPlan.currency
408
+ })
409
+ );
410
+ const planEntity = await this.basePlanService.updatePlan(
411
+ await this._mappers.UpdatePlanMapper.deserializeDtoToEntity(
412
+ {
413
+ ...planDto,
414
+ externalId: plan.id,
415
+ billingProvider: "stripe"
416
+ },
417
+ em ?? this.em,
418
+ plan
419
+ ),
420
+ em
421
+ );
422
+ return this._mappers.PlanMapper.serializeEntityToDto(planEntity);
423
+ }
424
+ async deletePlan(idDto, em) {
425
+ await this.stripeClient.plans.del(idDto.id);
426
+ await this.basePlanService.deletePlan(idDto, em);
427
+ }
428
+ async listPlans(idsDto, em) {
429
+ const plans = await this.stripeClient.plans.list({
430
+ active: true
431
+ });
432
+ const ids = (await em?.findAll(
433
+ this.options?.databaseTableName ?? "plan",
434
+ { where: { externalId: { $in: plans.data.map((plan) => plan.id) } } }
435
+ ))?.filter((s) => idsDto?.ids?.includes(s.id))?.map((s) => s.id);
436
+ if (!ids) {
437
+ throw new Error("Plans not found");
438
+ }
439
+ return await Promise.all(
440
+ (await this.basePlanService.listPlans({ ids }, em)).map(async (plan) => ({
441
+ ...await this._mappers.PlanMapper.serializeEntityToDto(plan),
442
+ stripeFields: plans.data.find(
443
+ (stripePlan) => stripePlan.id === plan.externalId
444
+ )
445
+ }))
446
+ );
447
+ }
448
+ };
449
+
450
+ // services/subscription.service.ts
451
+ var import_services5 = require("@forklaunch/implementation-billing-base/services");
452
+ var import_internal5 = require("@forklaunch/internal");
453
+ var StripeSubscriptionService = class {
454
+ constructor(stripe, em, openTelemetryCollector, schemaValidator, mappers, options) {
455
+ this.stripe = stripe;
456
+ this.em = em;
457
+ this.openTelemetryCollector = openTelemetryCollector;
458
+ this.schemaValidator = schemaValidator;
459
+ this.mappers = mappers;
460
+ this.options = options;
461
+ this._mappers = (0, import_internal5.transformIntoInternalMapper)(mappers, schemaValidator);
462
+ this.baseSubscriptionService = new import_services5.BaseSubscriptionService(
463
+ em,
464
+ openTelemetryCollector,
465
+ schemaValidator,
466
+ {
467
+ SubscriptionMapper: import_internal5.IdentityResponseMapper,
468
+ CreateSubscriptionMapper: import_internal5.IdentityRequestMapper,
469
+ UpdateSubscriptionMapper: import_internal5.IdentityRequestMapper
470
+ },
471
+ options
472
+ );
473
+ }
474
+ baseSubscriptionService;
475
+ _mappers;
476
+ async createSubscription(subscriptionDto, em) {
477
+ const subscription = await this.stripe.subscriptions.create({
478
+ ...subscriptionDto.stripeFields,
479
+ customer: subscriptionDto.partyId,
480
+ items: [
481
+ {
482
+ plan: subscriptionDto.productId
483
+ }
484
+ ]
485
+ });
486
+ const subscriptionEntity = await this.baseSubscriptionService.createSubscription(
487
+ await this._mappers.CreateSubscriptionMapper.deserializeDtoToEntity(
488
+ {
489
+ ...subscriptionDto,
490
+ externalId: subscription.id,
491
+ billingProvider: "stripe"
492
+ },
493
+ em ?? this.em,
494
+ subscription
495
+ ),
496
+ em
497
+ );
498
+ return this._mappers.SubscriptionMapper.serializeEntityToDto(
499
+ subscriptionEntity
500
+ );
501
+ }
502
+ async getSubscription(idDto, em) {
503
+ return {
504
+ ...await this._mappers.SubscriptionMapper.serializeEntityToDto(
505
+ await this.baseSubscriptionService.getSubscription(idDto, em)
506
+ ),
507
+ stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
508
+ };
509
+ }
510
+ async getUserSubscription(idDto, em) {
511
+ return {
512
+ ...await this._mappers.SubscriptionMapper.serializeEntityToDto(
513
+ await this.baseSubscriptionService.getUserSubscription(idDto, em)
514
+ ),
515
+ stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
516
+ };
517
+ }
518
+ async getOrganizationSubscription(idDto, em) {
519
+ const id = (await em?.findOne(
520
+ this.options?.databaseTableName ?? "subscription",
521
+ { externalId: idDto.id }
522
+ ))?.id;
523
+ if (!id) {
524
+ throw new Error("Subscription not found");
525
+ }
526
+ return {
527
+ ...await this._mappers.SubscriptionMapper.serializeEntityToDto(
528
+ await this.baseSubscriptionService.getOrganizationSubscription(
529
+ { id },
530
+ em
531
+ )
532
+ ),
533
+ stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
534
+ };
535
+ }
536
+ async updateSubscription(subscriptionDto, em) {
537
+ const subscription = await this.stripe.subscriptions.update(
538
+ subscriptionDto.id,
539
+ {
540
+ ...subscriptionDto.stripeFields,
541
+ items: [
542
+ {
543
+ plan: subscriptionDto.productId
544
+ }
545
+ ]
546
+ }
547
+ );
548
+ const subscriptionEntity = await this.baseSubscriptionService.updateSubscription(
549
+ await this._mappers.UpdateSubscriptionMapper.deserializeDtoToEntity(
550
+ {
551
+ ...subscriptionDto,
552
+ externalId: subscription.id,
553
+ billingProvider: "stripe",
554
+ providerFields: subscription
555
+ },
556
+ em ?? this.em,
557
+ subscription
558
+ ),
559
+ em
560
+ );
561
+ return this._mappers.SubscriptionMapper.serializeEntityToDto(
562
+ subscriptionEntity
563
+ );
564
+ }
565
+ async deleteSubscription(idDto, em) {
566
+ await this.stripe.subscriptions.cancel(idDto.id);
567
+ await this.baseSubscriptionService.deleteSubscription(idDto, em);
568
+ }
569
+ async listSubscriptions(idsDto, em) {
570
+ const subscriptions = (await this.stripe.subscriptions.list({
571
+ status: "active"
572
+ })).data.filter((s) => idsDto.ids?.includes(s.id));
573
+ const ids = (await em?.findAll(
574
+ this.options?.databaseTableName ?? "subscription",
575
+ { where: { externalId: { $in: subscriptions.map((s) => s.id) } } }
576
+ ))?.map((s) => s.id);
577
+ if (!ids) {
578
+ throw new Error("Subscriptions not found");
579
+ }
580
+ return await Promise.all(
581
+ (await this.baseSubscriptionService.listSubscriptions({ ids }, em)).map(
582
+ async (subscription) => {
583
+ return {
584
+ ...await this._mappers.SubscriptionMapper.serializeEntityToDto(
585
+ subscription
586
+ ),
587
+ stripeFields: subscriptions.find(
588
+ (s) => s.id === subscription.externalId
589
+ )
590
+ };
591
+ }
592
+ )
593
+ );
594
+ }
595
+ async cancelSubscription(idDto, em) {
596
+ await this.stripe.subscriptions.cancel(idDto.id);
597
+ await this.baseSubscriptionService.cancelSubscription(idDto, em);
598
+ }
599
+ async resumeSubscription(idDto, em) {
600
+ await this.stripe.subscriptions.resume(idDto.id);
601
+ await this.baseSubscriptionService.resumeSubscription(idDto, em);
602
+ }
603
+ };
604
+
605
+ // services/webhook.service.ts
606
+ var StripeWebhookService = class {
607
+ constructor(stripeClient, em, schemaValidator, openTelemetryCollector, billingPortalService, checkoutSessionService, paymentLinkService, planService, subscriptionService) {
608
+ this.stripeClient = stripeClient;
609
+ this.em = em;
610
+ this.schemaValidator = schemaValidator;
611
+ this.openTelemetryCollector = openTelemetryCollector;
612
+ this.billingPortalService = billingPortalService;
613
+ this.checkoutSessionService = checkoutSessionService;
614
+ this.paymentLinkService = paymentLinkService;
615
+ this.planService = planService;
616
+ this.subscriptionService = subscriptionService;
617
+ }
618
+ async handleWebhookEvent(event) {
619
+ if (this.openTelemetryCollector) {
620
+ this.openTelemetryCollector.info("Handling webhook event", event);
621
+ }
622
+ const eventType = event.type;
623
+ switch (eventType) {
624
+ case "billing_portal.session.created": {
625
+ this.billingPortalService.baseBillingPortalService.createBillingPortalSession(
626
+ {
627
+ id: event.data.object.id,
628
+ customerId: event.data.object.customer,
629
+ expiresAt: new Date(event.data.object.created + 5 * 60 * 1e3),
630
+ uri: event.data.object.url,
631
+ providerFields: event.data.object
632
+ }
633
+ );
634
+ break;
635
+ }
636
+ case "checkout.session.expired": {
637
+ this.checkoutSessionService.handleCheckoutFailure({
638
+ id: event.data.object.id
639
+ });
640
+ break;
641
+ }
642
+ case "checkout.session.completed": {
643
+ this.checkoutSessionService.handleCheckoutSuccess({
644
+ id: event.data.object.id
645
+ });
646
+ break;
647
+ }
648
+ case "payment_link.created":
649
+ {
650
+ this.paymentLinkService.basePaymentLinkService.createPaymentLink({
651
+ id: event.data.object.id,
652
+ amount: event.data.object.line_items?.data.reduce(
653
+ (total, item) => total + item.amount_total,
654
+ 0
655
+ ) ?? 0,
656
+ paymentMethods: event.data.object.payment_method_types,
657
+ status: "CREATED",
658
+ currency: event.data.object.currency,
659
+ providerFields: event.data.object
660
+ });
661
+ }
662
+ break;
663
+ case "payment_link.updated": {
664
+ this.paymentLinkService.basePaymentLinkService.updatePaymentLink({
665
+ id: event.data.object.id,
666
+ amount: event.data.object.line_items?.data.reduce(
667
+ (total, item) => total + item.amount_total,
668
+ 0
669
+ ) ?? 0,
670
+ paymentMethods: event.data.object.payment_method_types,
671
+ status: "UPDATED",
672
+ currency: event.data.object.currency,
673
+ providerFields: event.data.object
674
+ });
675
+ break;
676
+ }
677
+ case "plan.created": {
678
+ if (typeof event.data.object.product === "object" && event.data.object.product != null && event.data.object.amount != null) {
679
+ this.planService.basePlanService.createPlan({
680
+ id: event.data.object.id,
681
+ billingProvider: "stripe" /* STRIPE */,
682
+ cadence: event.data.object.interval,
683
+ currency: event.data.object.currency,
684
+ active: true,
685
+ name: typeof event.data.object.product === "string" ? event.data.object.product : event.data.object.product?.id,
686
+ price: event.data.object.amount,
687
+ externalId: event.data.object.id,
688
+ providerFields: event.data.object
689
+ });
690
+ } else {
691
+ throw new Error("Invalid plan");
692
+ }
693
+ break;
694
+ }
695
+ case "plan.updated": {
696
+ if (typeof event.data.object.product === "object" && event.data.object.product != null && event.data.object.amount != null) {
697
+ this.planService.basePlanService.updatePlan({
698
+ id: event.data.object.id,
699
+ billingProvider: "stripe" /* STRIPE */,
700
+ cadence: event.data.object.interval,
701
+ currency: event.data.object.currency,
702
+ active: true,
703
+ name: typeof event.data.object.product === "string" ? event.data.object.product : event.data.object.product?.id,
704
+ price: event.data.object.amount,
705
+ externalId: event.data.object.id,
706
+ providerFields: event.data.object
707
+ });
708
+ } else {
709
+ throw new Error("Invalid plan");
710
+ }
711
+ break;
712
+ }
713
+ case "plan.deleted": {
714
+ this.planService.deletePlan({
715
+ id: event.data.object.id
716
+ });
717
+ break;
718
+ }
719
+ case "customer.subscription.created": {
720
+ this.subscriptionService.baseSubscriptionService.createSubscription({
721
+ id: event.data.object.id,
722
+ partyId: typeof event.data.object.customer === "string" ? event.data.object.customer : event.data.object.customer.id,
723
+ partyType: "USER",
724
+ description: event.data.object.description ?? void 0,
725
+ active: true,
726
+ productId: event.data.object.items.data[0].plan.id,
727
+ providerFields: event.data.object,
728
+ externalId: event.data.object.id,
729
+ billingProvider: "stripe" /* STRIPE */,
730
+ startDate: new Date(event.data.object.created),
731
+ endDate: event.data.object.cancel_at ? new Date(event.data.object.cancel_at) : /* @__PURE__ */ new Date(Infinity),
732
+ status: event.data.object.status
733
+ });
734
+ break;
735
+ }
736
+ case "customer.subscription.updated": {
737
+ this.subscriptionService.baseSubscriptionService.updateSubscription({
738
+ id: event.data.object.id,
739
+ partyId: typeof event.data.object.customer === "string" ? event.data.object.customer : event.data.object.customer.id,
740
+ partyType: "USER",
741
+ description: event.data.object.description ?? void 0,
742
+ active: true,
743
+ providerFields: event.data.object,
744
+ externalId: event.data.object.id,
745
+ billingProvider: "stripe" /* STRIPE */,
746
+ startDate: new Date(event.data.object.created),
747
+ endDate: event.data.object.cancel_at ? new Date(event.data.object.cancel_at) : /* @__PURE__ */ new Date(Infinity),
748
+ productId: event.data.object.items.data[0].plan.id,
749
+ status: event.data.object.status
750
+ });
751
+ break;
752
+ }
753
+ case "customer.subscription.deleted": {
754
+ this.subscriptionService.deleteSubscription({
755
+ id: event.data.object.id
756
+ });
757
+ break;
758
+ }
759
+ case "customer.subscription.paused": {
760
+ this.subscriptionService.cancelSubscription({
761
+ id: event.data.object.id
762
+ });
763
+ break;
764
+ }
765
+ case "customer.subscription.resumed": {
766
+ this.subscriptionService.resumeSubscription({
767
+ id: event.data.object.id
768
+ });
769
+ break;
770
+ }
771
+ default:
772
+ this.openTelemetryCollector.info(
773
+ "Unprocessed stripe event type",
774
+ eventType
775
+ );
776
+ break;
777
+ }
778
+ }
779
+ };
780
+ // Annotate the CommonJS export names for ESM import in node:
781
+ 0 && (module.exports = {
782
+ StripeBillingPortalService,
783
+ StripeCheckoutSessionService,
784
+ StripePaymentLinkService,
785
+ StripePlanService,
786
+ StripeSubscriptionService,
787
+ StripeWebhookService
788
+ });