Implement new billing-gateway and update related services

Created a new package named billing-gateway which implements interfaces for different billing providers and provides a centralized service for payments. This will potentially help to maintain cleaner code by reducing direct dependencies on specific payment providers in the core application code. Additionally, made adjustments in existing services, like Stripe, to comply with this change. The relevant interfaces and types have been exported and imported accordingly.
This commit is contained in:
giancarlo
2024-03-24 20:54:12 +08:00
parent 06156e980d
commit 78c704e54d
44 changed files with 1251 additions and 108 deletions

View File

@@ -2,7 +2,8 @@ import { z } from 'zod';
const Interval = z.enum(['month', 'year']);
const PaymentType = z.enum(['recurring', 'one-time']);
const BillingProvider = z.enum(['stripe']);
export const BillingProvider = z.enum(['stripe', 'paddle', 'lemon-squeezy']);
const PlanSchema = z.object({
id: z.string().min(1),
@@ -72,7 +73,6 @@ export function createBillingSchema(config: z.infer<typeof BillingSchema>) {
* Returns an array of billing plans based on the provided configuration.
*
* @param {Object} config - The configuration object containing product and plan information.
* @return {Array} - An array of billing plans.
*/
export function getBillingPlans(config: z.infer<typeof BillingSchema>) {
return config.products.flatMap((product) => product.plans);
@@ -82,7 +82,6 @@ export function getBillingPlans(config: z.infer<typeof BillingSchema>) {
* Retrieves the intervals of all plans specified in the given configuration.
*
* @param {Object} config - The billing configuration containing products and plans.
* @returns {Array} - An array of intervals.
*/
export function getPlanIntervals(config: z.infer<typeof BillingSchema>) {
return Array.from(
@@ -93,3 +92,18 @@ export function getPlanIntervals(config: z.infer<typeof BillingSchema>) {
),
);
}
export function getProductPlanPairFromId(
config: z.infer<typeof BillingSchema>,
planId: string,
) {
for (const product of config.products) {
const plan = product.plans.find((plan) => plan.id === planId);
if (plan) {
return { product, plan };
}
}
return undefined;
}

View File

@@ -0,0 +1,2 @@
export * from './create-billing-schema';
export * from './services/billing-strategy-provider.service';

View File

@@ -0,0 +1,6 @@
import { z } from 'zod';
export const CancelSubscriptionParamsSchema = z.object({
subscriptionId: z.string(),
invoiceNow: z.boolean().optional(),
});

View File

@@ -0,0 +1,6 @@
import { z } from 'zod';
export const CreateBillingPortalSessionSchema = z.object({
returnUrl: z.string().url(),
customerId: z.string().min(1),
});

View File

@@ -0,0 +1,13 @@
import { z } from 'zod';
export const CreateBillingCheckoutSchema = z.object({
returnUrl: z.string().url(),
accountId: z.string(),
planId: z.string(),
paymentType: z.enum(['recurring', 'one-time']),
trialPeriodDays: z.number().optional(),
customerId: z.string().optional(),
customerEmail: z.string().optional(),
});

View File

@@ -0,0 +1,4 @@
export * from './create-billing-checkout.schema';
export * from './create-biling-portal-session.schema';
export * from './retrieve-checkout-session.schema';
export * from './cancel-subscription-params.schema';

View File

@@ -0,0 +1,5 @@
import { z } from 'zod';
export const RetrieveCheckoutSessionSchema = z.object({
sessionId: z.string(),
});

View File

@@ -0,0 +1,32 @@
import { z } from 'zod';
import {
CancelSubscriptionParamsSchema,
CreateBillingCheckoutSchema,
CreateBillingPortalSessionSchema,
RetrieveCheckoutSessionSchema,
} from '../schema';
export abstract class BillingStrategyProviderService {
abstract createBillingPortalSession(
params: z.infer<typeof CreateBillingPortalSessionSchema>,
): Promise<{
url: string;
}>;
abstract retrieveCheckoutSession(
params: z.infer<typeof RetrieveCheckoutSessionSchema>,
): Promise<unknown>;
abstract createCheckoutSession(
params: z.infer<typeof CreateBillingCheckoutSchema>,
): Promise<{
checkoutToken: string;
}>;
abstract cancelSubscription(
params: z.infer<typeof CancelSubscriptionParamsSchema>,
): Promise<{
success: boolean;
}>;
}