@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.
- package/lib/eject/services/billingPortal.service.ts +2 -2
- package/lib/eject/services/checkoutSession.service.ts +1 -0
- package/lib/eject/services/index.ts +1 -0
- package/lib/eject/services/paymentLink.service.ts +7 -7
- package/lib/eject/services/plan.service.ts +70 -55
- package/lib/eject/services/subscription.service.ts +96 -64
- package/lib/services/index.d.mts +5 -9
- package/lib/services/index.d.ts +5 -9
- package/lib/services/index.js +153 -110
- package/lib/services/index.mjs +151 -109
- package/package.json +11 -11
package/lib/services/index.js
CHANGED
|
@@ -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:
|
|
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
|
-
)
|
|
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
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
|
359
|
-
|
|
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
|
|
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
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
|
|
393
|
-
|
|
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.
|
|
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.
|
|
401
|
-
|
|
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
|
-
|
|
411
|
-
(
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
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
|
-
|
|
492
|
+
subscriptionEntity.externalId
|
|
479
493
|
);
|
|
480
494
|
subscriptionEntity.stripeFields = stripeSubscription;
|
|
481
495
|
return subscriptionEntity;
|
|
482
496
|
}
|
|
483
497
|
async getOrganizationSubscription(idDto, em) {
|
|
484
|
-
const
|
|
485
|
-
|
|
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
|
-
|
|
503
|
+
subscriptionEntity.externalId
|
|
497
504
|
);
|
|
498
505
|
subscriptionEntity.stripeFields = stripeSubscription;
|
|
499
506
|
return subscriptionEntity;
|
|
500
507
|
}
|
|
501
508
|
async updateSubscription(subscriptionDto, em) {
|
|
502
|
-
const
|
|
503
|
-
|
|
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
|
-
|
|
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
|
-
|
|
531
|
+
const updatedSubscriptionEntity = await this.baseSubscriptionService.updateSubscription(
|
|
514
532
|
{
|
|
515
533
|
...subscriptionDto,
|
|
516
|
-
externalId:
|
|
517
|
-
billingProvider: "stripe"
|
|
518
|
-
providerFields: subscription
|
|
534
|
+
externalId: updatedSubscription.id,
|
|
535
|
+
billingProvider: "stripe"
|
|
519
536
|
},
|
|
520
537
|
em ?? this.em,
|
|
521
|
-
|
|
538
|
+
updatedSubscription
|
|
522
539
|
);
|
|
540
|
+
updatedSubscriptionEntity.stripeFields = updatedSubscription;
|
|
541
|
+
return updatedSubscriptionEntity;
|
|
523
542
|
}
|
|
524
543
|
async deleteSubscription(idDto, em) {
|
|
525
|
-
await this.
|
|
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 =
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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
|
-
|
|
540
|
-
(
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
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
|
-
|
|
546
|
-
return
|
|
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.
|
|
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.
|
|
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
|
});
|