Add queryUsage method to billing services

A new method, queryUsage, has been added to the billing strategy classes and the gateway service to offer usage querying capabilities for Stripe and Lemon Squeezy. QueryBillingUsageSchema has also been introduced in the schema-related changes. Changes also include updates to the functions' comment descriptions. A minor tweak was made to the Button and Link components in the `faq/page.tsx' file.
This commit is contained in:
giancarlo
2024-04-25 11:34:47 +07:00
parent 19332d124d
commit 8d04624b1d
8 changed files with 278 additions and 14 deletions

View File

@@ -8,6 +8,7 @@ import {
CancelSubscriptionParamsSchema,
CreateBillingCheckoutSchema,
CreateBillingPortalSessionSchema,
QueryBillingUsageSchema,
ReportBillingUsageSchema,
RetrieveCheckoutSessionSchema,
UpdateSubscriptionParamsSchema,
@@ -23,6 +24,11 @@ export class StripeBillingStrategyService
{
private readonly namespace = 'billing.stripe';
/**
* @name createCheckoutSession
* @description Creates a checkout session for a customer
* @param params
*/
async createCheckoutSession(
params: z.infer<typeof CreateBillingCheckoutSchema>,
) {
@@ -50,6 +56,11 @@ export class StripeBillingStrategyService
return { checkoutToken: client_secret };
}
/**
* @name createBillingPortalSession
* @description Creates a billing portal session for a customer
* @param params
*/
async createBillingPortalSession(
params: z.infer<typeof CreateBillingPortalSessionSchema>,
) {
@@ -74,6 +85,11 @@ export class StripeBillingStrategyService
return session;
}
/**
* @name cancelSubscription
* @description Cancels a subscription
* @param params
*/
async cancelSubscription(
params: z.infer<typeof CancelSubscriptionParamsSchema>,
) {
@@ -108,6 +124,11 @@ export class StripeBillingStrategyService
}
}
/**
* @name retrieveCheckoutSession
* @description Retrieves a checkout session
* @param params
*/
async retrieveCheckoutSession(
params: z.infer<typeof RetrieveCheckoutSessionSchema>,
) {
@@ -148,26 +169,37 @@ export class StripeBillingStrategyService
}
}
/**
* @name reportUsage
* @description Reports usage for a subscription with the Metrics API
* @param params
*/
async reportUsage(params: z.infer<typeof ReportBillingUsageSchema>) {
const stripe = await this.stripeProvider();
const logger = await getLogger();
const ctx = {
name: this.namespace,
subscriptionItemId: params.subscriptionItemId,
subscriptionItemId: params.id,
usage: params.usage,
};
logger.info(ctx, 'Reporting usage...');
if (!params.eventName) {
logger.error(ctx, 'Event name is required');
throw new Error('Event name is required when reporting Metrics');
}
try {
await stripe.subscriptionItems.createUsageRecord(
params.subscriptionItemId,
{
quantity: params.usage.quantity,
action: params.usage.action,
await stripe.billing.meterEvents.create({
event_name: params.eventName,
payload: {
value: params.usage.quantity.toString(),
stripe_customer_id: params.id,
},
);
});
} catch (error) {
logger.error(
{
@@ -180,9 +212,71 @@ export class StripeBillingStrategyService
throw new Error('Failed to report usage');
}
return { success: true };
return {
success: true,
};
}
/**
* @name queryUsage
* @description Reports the total usage for a subscription with the Metrics API
*/
async queryUsage(params: z.infer<typeof QueryBillingUsageSchema>) {
const stripe = await this.stripeProvider();
const logger = await getLogger();
const ctx = {
name: this.namespace,
id: params.id,
customerId: params.customerId,
};
// validate shape of filters for Stripe
if (!('startTime' in params.filter)) {
logger.error(ctx, 'Start and end time are required for Stripe');
throw new Error('Start and end time are required when querying usage');
}
logger.info(ctx, 'Querying billing usage...');
try {
const summaries = await stripe.billing.meters.listEventSummaries(
params.id,
{
customer: params.customerId,
start_time: params.filter.startTime,
end_time: params.filter.endTime,
},
);
logger.info(ctx, 'Billing usage queried successfully');
const value = summaries.data.reduce((acc, summary) => {
return acc + Number(summary.aggregated_value);
}, 0);
return {
value,
};
} catch (error) {
logger.error(
{
...ctx,
error,
},
'Failed to report usage',
);
throw new Error('Failed to report usage');
}
}
/**
* @name updateSubscription
* @description Updates a subscription
* @param params
*/
async updateSubscription(
params: z.infer<typeof UpdateSubscriptionParamsSchema>,
) {
@@ -218,6 +312,11 @@ export class StripeBillingStrategyService
}
}
/**
* @name getPlanById
* @description Retrieves a plan by id
* @param planId
*/
async getPlanById(planId: string) {
const logger = await getLogger();