@forklaunch/implementation-billing-stripe 0.4.3 → 0.5.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.
@@ -89,12 +89,13 @@ var StripeBillingPortalService = class {
89
89
  });
90
90
  const session = await this.stripeClient.billingPortal.sessions.create({
91
91
  ...billingPortalDto.stripeFields,
92
- customer: existingSession.customerId
92
+ customer: billingPortalDto.customerId || existingSession.customerId
93
93
  });
94
94
  return await this.baseBillingPortalService.updateBillingPortalSession(
95
95
  {
96
96
  ...billingPortalDto,
97
- id: session.id,
97
+ id: existingSession.id,
98
+ // Use the original database ID, not the new Stripe session ID
98
99
  uri: session.url,
99
100
  expiresAt: new Date(
100
101
  Date.now() + this.billingPortalSessionExpiryDurationMs
@@ -137,6 +138,7 @@ var StripeCheckoutSessionService = class {
137
138
  async createCheckoutSession(checkoutSessionDto, ...args) {
138
139
  const session = await this.stripeClient.checkout.sessions.create({
139
140
  ...checkoutSessionDto.stripeFields,
141
+ mode: "subscription",
140
142
  payment_method_types: checkoutSessionDto.paymentMethods,
141
143
  currency: checkoutSessionDto.currency,
142
144
  success_url: checkoutSessionDto.successRedirectUri,
@@ -222,10 +224,10 @@ var StripePaymentLinkService = class {
222
224
  {
223
225
  ...paymentLinkDto,
224
226
  id: session.id,
225
- amount: session.line_items?.data.reduce(
227
+ amount: paymentLinkDto.amount ?? session.line_items?.data.reduce(
226
228
  (total, item) => total + item.amount_total,
227
229
  0
228
- ) ?? 0
230
+ )
229
231
  },
230
232
  this.em,
231
233
  session,
@@ -291,24 +293,21 @@ var StripePaymentLinkService = class {
291
293
  await this.basePaymentLinkService.handlePaymentFailure({ id });
292
294
  }
293
295
  async listPaymentLinks(idsDto) {
296
+ this.openTelemetryCollector.log("info", idsDto ?? "idsDto is undefined");
294
297
  const stripePaymentLinks = await this.stripeClient.paymentLinks.list({
295
298
  active: true
296
299
  });
297
300
  const databasePaymentLinks = await this.basePaymentLinkService.listPaymentLinks(idsDto);
298
- return await Promise.all(
299
- databasePaymentLinks.map(async (paymentLink) => {
300
- const stripePaymentLink = stripePaymentLinks.data.find(
301
- (sp) => sp.id === paymentLink.id
302
- );
303
- if (!stripePaymentLink) {
304
- throw new Error(
305
- `Stripe payment link not found for id: ${paymentLink.id}`
306
- );
307
- }
308
- paymentLink.stripeFields = stripePaymentLink;
309
- return paymentLink;
310
- })
311
- );
301
+ return databasePaymentLinks.map((paymentLink) => {
302
+ const stripePaymentLink = stripePaymentLinks.data.find(
303
+ (sp) => sp.id === paymentLink.id
304
+ );
305
+ if (!stripePaymentLink) {
306
+ return null;
307
+ }
308
+ paymentLink.stripeFields = stripePaymentLink;
309
+ return paymentLink;
310
+ }).filter((paymentLink) => paymentLink !== null);
312
311
  }
313
312
  };
314
313
 
@@ -339,6 +338,7 @@ var StripePlanService = class {
339
338
  async createPlan(planDto, em) {
340
339
  const stripePlan = await this.stripeClient.plans.create({
341
340
  ...planDto.stripeFields,
341
+ amount: planDto.price,
342
342
  interval: planDto.cadence,
343
343
  product: planDto.name,
344
344
  currency: planDto.currency
@@ -355,68 +355,76 @@ var StripePlanService = class {
355
355
  return plan;
356
356
  }
357
357
  async getPlan(idDto, em) {
358
- const plan = await this.stripeClient.plans.retrieve(idDto.id);
359
- const id = (await em?.findOne(
360
- this.options?.databaseTableName ?? "plan",
361
- { externalId: idDto.id }
362
- ))?.id;
363
- if (!id) {
358
+ const planEntity = await this.basePlanService.getPlan(idDto, em);
359
+ if (!planEntity.externalId) {
364
360
  throw new Error("Plan not found");
365
361
  }
366
- const planEntity = await this.basePlanService.getPlan({ id }, em);
362
+ const plan = await this.stripeClient.plans.retrieve(planEntity.externalId);
367
363
  planEntity.stripeFields = plan;
368
364
  return planEntity;
369
365
  }
370
366
  async updatePlan(planDto, em) {
371
- const existingPlan = await this.stripeClient.plans.retrieve(planDto.id);
372
- const plan = await this.stripeClient.plans.del(planDto.id).then(
373
- () => this.stripeClient.plans.create({
374
- ...planDto.stripeFields,
375
- interval: planDto.cadence ?? existingPlan.interval,
376
- product: planDto.name,
377
- currency: planDto.currency ?? existingPlan.currency
378
- })
379
- );
380
- const planEntity = await this.basePlanService.updatePlan(
381
- await this.mappers.UpdatePlanMapper.toEntity(
382
- {
383
- ...planDto,
384
- externalId: plan.id,
385
- billingProvider: "stripe"
386
- },
387
- em ?? this.em,
388
- plan
389
- ),
367
+ const planEntity = await this.basePlanService.getPlan(
368
+ {
369
+ id: planDto.id
370
+ },
390
371
  em
391
372
  );
392
- planEntity.stripeFields = plan;
393
- return planEntity;
373
+ const existingPlan = await this.stripeClient.plans.retrieve(
374
+ planEntity.externalId
375
+ );
376
+ const existingProduct = existingPlan.product;
377
+ if (!existingProduct) {
378
+ throw new Error("Plan product not found");
379
+ }
380
+ const productId = typeof existingProduct === "string" ? existingProduct : existingProduct.id;
381
+ await this.stripeClient.plans.del(planEntity.externalId);
382
+ const updatedPlan = await this.stripeClient.plans.create({
383
+ ...planDto.stripeFields,
384
+ interval: planDto.cadence ?? existingPlan.interval,
385
+ currency: planDto.currency ?? existingPlan.currency,
386
+ amount: planDto.price ?? existingPlan.amount ?? void 0,
387
+ product: productId
388
+ });
389
+ const updatedPlanEntity = await this.basePlanService.updatePlan(
390
+ {
391
+ ...planDto,
392
+ externalId: updatedPlan.id,
393
+ name: planDto.name,
394
+ billingProvider: "stripe"
395
+ },
396
+ em,
397
+ updatedPlan
398
+ );
399
+ updatedPlanEntity.stripeFields = updatedPlan;
400
+ return updatedPlanEntity;
394
401
  }
395
402
  async deletePlan(idDto, em) {
396
- await this.stripeClient.plans.del(idDto.id);
403
+ const plan = await this.basePlanService.getPlan(idDto, em);
404
+ if (!plan.externalId) {
405
+ throw new Error("Plan not found");
406
+ }
407
+ await this.stripeClient.plans.del(plan.externalId);
397
408
  await this.basePlanService.deletePlan(idDto, em);
398
409
  }
399
410
  async listPlans(idsDto, em) {
400
- const plans = await this.stripeClient.plans.list({
401
- active: true
402
- });
403
- const planIds = (await em?.findAll(
404
- this.options?.databaseTableName ?? "plan",
405
- { where: { externalId: { $in: plans.data.map((plan) => plan.id) } } }
406
- ))?.filter((s) => idsDto?.ids?.includes(s.id))?.map((s) => s.id);
407
- if (!planIds) {
408
- throw new Error("Plans not found");
411
+ const plans = await this.basePlanService.listPlans(idsDto, em);
412
+ if (!plans || plans.length === 0) {
413
+ return [];
409
414
  }
410
- return await Promise.all(
411
- (await this.basePlanService.listPlans({ ids: planIds }, em)).map(
412
- async (plan) => ({
413
- ...plan,
414
- stripeFields: plans.data.find(
415
- (stripePlan) => stripePlan.id === plan.externalId
416
- )
417
- })
418
- )
415
+ const stripePlans = await Promise.all(
416
+ plans.map(async (plan) => {
417
+ try {
418
+ return await this.stripeClient.plans.retrieve(plan.externalId);
419
+ } catch {
420
+ return null;
421
+ }
422
+ })
419
423
  );
424
+ return plans.map((plan, index) => ({
425
+ ...plan,
426
+ stripeFields: stripePlans[index]
427
+ })).filter((plan) => plan.stripeFields !== null);
420
428
  }
421
429
  };
422
430
 
@@ -466,94 +474,127 @@ var StripeSubscriptionService = class {
466
474
  }
467
475
  async getSubscription(idDto, em) {
468
476
  const subscriptionEntity = await this.baseSubscriptionService.getSubscription(idDto, em);
477
+ if (!subscriptionEntity.externalId) {
478
+ throw new Error("Subscription not found");
479
+ }
469
480
  const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
470
- idDto.id
481
+ subscriptionEntity.externalId
471
482
  );
472
483
  subscriptionEntity.stripeFields = stripeSubscription;
473
484
  return subscriptionEntity;
474
485
  }
475
486
  async getUserSubscription(idDto, em) {
476
487
  const subscriptionEntity = await this.baseSubscriptionService.getUserSubscription(idDto, em);
488
+ if (!subscriptionEntity.externalId) {
489
+ throw new Error("Subscription not found");
490
+ }
477
491
  const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
478
- idDto.id
492
+ subscriptionEntity.externalId
479
493
  );
480
494
  subscriptionEntity.stripeFields = stripeSubscription;
481
495
  return subscriptionEntity;
482
496
  }
483
497
  async getOrganizationSubscription(idDto, em) {
484
- const id = (await em?.findOne(
485
- this.options?.databaseTableName ?? "subscription",
486
- { externalId: idDto.id }
487
- ))?.id;
488
- if (!id) {
498
+ const subscriptionEntity = await this.baseSubscriptionService.getOrganizationSubscription(idDto, em);
499
+ if (!subscriptionEntity.externalId) {
489
500
  throw new Error("Subscription not found");
490
501
  }
491
- const subscriptionEntity = await this.baseSubscriptionService.getOrganizationSubscription(
492
- { id },
493
- em
494
- );
495
502
  const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
496
- idDto.id
503
+ subscriptionEntity.externalId
497
504
  );
498
505
  subscriptionEntity.stripeFields = stripeSubscription;
499
506
  return subscriptionEntity;
500
507
  }
501
508
  async updateSubscription(subscriptionDto, em) {
502
- const subscription = await this.stripeClient.subscriptions.update(
503
- subscriptionDto.id,
509
+ const subscriptionEntity = await this.baseSubscriptionService.getSubscription(
510
+ {
511
+ id: subscriptionDto.id
512
+ },
513
+ em
514
+ );
515
+ if (!subscriptionEntity.externalId) {
516
+ throw new Error("Subscription not found");
517
+ }
518
+ const existingStripeSubscription = await this.stripeClient.subscriptions.retrieve(
519
+ subscriptionEntity.externalId
520
+ );
521
+ const updatedSubscription = await this.stripeClient.subscriptions.update(
522
+ subscriptionEntity.externalId,
504
523
  {
505
524
  ...subscriptionDto.stripeFields,
506
- items: [
507
- {
508
- plan: subscriptionDto.productId
509
- }
510
- ]
525
+ items: existingStripeSubscription.items.data.map((item) => ({
526
+ id: item.id,
527
+ plan: subscriptionDto.productId || item.plan?.id
528
+ }))
511
529
  }
512
530
  );
513
- return await this.baseSubscriptionService.updateSubscription(
531
+ const updatedSubscriptionEntity = await this.baseSubscriptionService.updateSubscription(
514
532
  {
515
533
  ...subscriptionDto,
516
- externalId: subscription.id,
517
- billingProvider: "stripe",
518
- providerFields: subscription
534
+ externalId: updatedSubscription.id,
535
+ billingProvider: "stripe"
519
536
  },
520
537
  em ?? this.em,
521
- subscription
538
+ updatedSubscription
522
539
  );
540
+ updatedSubscriptionEntity.stripeFields = updatedSubscription;
541
+ return updatedSubscriptionEntity;
523
542
  }
524
543
  async deleteSubscription(idDto, em) {
525
- await this.stripeClient.subscriptions.cancel(idDto.id);
544
+ const subscription = await this.baseSubscriptionService.getSubscription(
545
+ idDto,
546
+ em
547
+ );
548
+ if (!subscription.externalId) {
549
+ throw new Error("Subscription not found");
550
+ }
551
+ await this.stripeClient.subscriptions.cancel(subscription.externalId);
526
552
  await this.baseSubscriptionService.deleteSubscription(idDto, em);
527
553
  }
528
554
  async listSubscriptions(idsDto, em) {
529
- const subscriptions = (await this.stripeClient.subscriptions.list({
530
- status: "active"
531
- })).data.filter((s) => idsDto.ids?.includes(s.id));
532
- const ids = (await em?.findAll(
533
- this.options?.databaseTableName ?? "subscription",
534
- { where: { externalId: { $in: subscriptions.map((s) => s.id) } } }
535
- ))?.map((s) => s.id);
536
- if (!ids) {
537
- throw new Error("Subscriptions not found");
555
+ const subscriptions = await this.baseSubscriptionService.listSubscriptions(
556
+ idsDto,
557
+ em
558
+ );
559
+ if (!subscriptions || subscriptions.length === 0) {
560
+ return [];
538
561
  }
539
- return await Promise.all(
540
- (await this.baseSubscriptionService.listSubscriptions({ ids }, em)).map(
541
- async (subscription) => {
542
- const stripeSubscription = subscriptions.find(
543
- (s) => s.id === subscription.externalId
562
+ const stripeSubscriptions = await Promise.all(
563
+ subscriptions.map(async (subscription) => {
564
+ try {
565
+ return await this.stripeClient.subscriptions.retrieve(
566
+ subscription.externalId
544
567
  );
545
- subscription.stripeFields = stripeSubscription;
546
- return subscription;
568
+ } catch {
569
+ return null;
547
570
  }
548
- )
571
+ })
549
572
  );
573
+ return subscriptions.map((subscription, index) => ({
574
+ ...subscription,
575
+ stripeFields: stripeSubscriptions[index]
576
+ })).filter((subscription) => subscription.stripeFields !== null);
550
577
  }
551
578
  async cancelSubscription(idDto, em) {
552
- await this.stripeClient.subscriptions.cancel(idDto.id);
579
+ const subscription = await this.baseSubscriptionService.getSubscription(
580
+ idDto,
581
+ em
582
+ );
583
+ if (!subscription.externalId) {
584
+ throw new Error("Subscription not found");
585
+ }
586
+ await this.stripeClient.subscriptions.cancel(subscription.externalId);
553
587
  await this.baseSubscriptionService.cancelSubscription(idDto, em);
554
588
  }
555
589
  async resumeSubscription(idDto, em) {
556
- await this.stripeClient.subscriptions.resume(idDto.id);
590
+ const subscription = await this.baseSubscriptionService.getSubscription(
591
+ idDto,
592
+ em
593
+ );
594
+ if (!subscription.externalId) {
595
+ throw new Error("Subscription not found");
596
+ }
597
+ await this.stripeClient.subscriptions.resume(subscription.externalId);
557
598
  await this.baseSubscriptionService.resumeSubscription(idDto, em);
558
599
  }
559
600
  };
@@ -759,6 +800,7 @@ var StripeWebhookService = class {
759
800
 
760
801
  // services/index.ts
761
802
  __reExport(services_exports, require("@forklaunch/interfaces-billing/interfaces"), module.exports);
803
+ __reExport(services_exports, require("@forklaunch/interfaces-billing/types"), module.exports);
762
804
  // Annotate the CommonJS export names for ESM import in node:
763
805
  0 && (module.exports = {
764
806
  StripeBillingPortalService,
@@ -767,5 +809,6 @@ __reExport(services_exports, require("@forklaunch/interfaces-billing/interfaces"
767
809
  StripePlanService,
768
810
  StripeSubscriptionService,
769
811
  StripeWebhookService,
770
- ...require("@forklaunch/interfaces-billing/interfaces")
812
+ ...require("@forklaunch/interfaces-billing/interfaces"),
813
+ ...require("@forklaunch/interfaces-billing/types")
771
814
  });