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