Add logging and error-handling to billing service

Enhanced the TeamBillingService class by including several logging statements and added error-handling surrounding the creation of a checkout session and a billing portal session. The logging statements provide more context about the processes such as the associated user and account, adding a layer of transparency and traceability.
This commit is contained in:
giancarlo
2024-04-06 14:44:35 +08:00
parent 67e9c8b676
commit 36bcf64f52

View File

@@ -16,6 +16,8 @@ import billingConfig from '~/config/billing.config';
import pathsConfig from '~/config/paths.config'; import pathsConfig from '~/config/paths.config';
export class TeamBillingService { export class TeamBillingService {
private readonly namespace = 'billing.team-account';
constructor(private readonly client: SupabaseClient<Database>) {} constructor(private readonly client: SupabaseClient<Database>) {}
async createCheckout(params: z.infer<typeof TeamCheckoutSchema>) { async createCheckout(params: z.infer<typeof TeamCheckoutSchema>) {
@@ -29,6 +31,15 @@ export class TeamBillingService {
const userId = user.id; const userId = user.id;
const accountId = params.accountId; const accountId = params.accountId;
Logger.info(
{
userId,
accountId,
name: this.namespace,
},
`Requested checkout session. Processing...`,
);
// verify permissions to manage billing // verify permissions to manage billing
const hasPermission = await getBillingPermissionsForAccountId( const hasPermission = await getBillingPermissionsForAccountId(
userId, userId,
@@ -38,6 +49,15 @@ export class TeamBillingService {
// if the user does not have permission to manage billing for the account // if the user does not have permission to manage billing for the account
// then we should not proceed // then we should not proceed
if (!hasPermission) { if (!hasPermission) {
Logger.warn(
{
userId,
accountId,
name: this.namespace,
},
`User without permissions attempted to create checkout.`,
);
throw new Error('Permission denied'); throw new Error('Permission denied');
} }
@@ -65,21 +85,45 @@ export class TeamBillingService {
accountId, accountId,
); );
// call the payment gateway to create the checkout session Logger.info(
const { checkoutToken } = await service.createCheckoutSession({ {
accountId, userId,
plan, accountId,
returnUrl, planId: plan.id,
customerEmail, namespace: this.namespace,
customerId, },
variantQuantities, `Creating checkout session...`,
}); );
// return the checkout token to the client try {
// so we can call the payment gateway to complete the checkout // call the payment gateway to create the checkout session
return { const { checkoutToken } = await service.createCheckoutSession({
checkoutToken, accountId,
}; plan,
returnUrl,
customerEmail,
customerId,
variantQuantities,
});
// return the checkout token to the client
// so we can call the payment gateway to complete the checkout
return {
checkoutToken,
};
} catch (error) {
Logger.error(
{
name: this.namespace,
error,
accountId,
planId: plan.id,
},
`Error creating the checkout session`,
);
throw new Error(`Checkout not created`);
}
} }
async createBillingPortalSession({ async createBillingPortalSession({
@@ -91,6 +135,14 @@ export class TeamBillingService {
}) { }) {
const client = getSupabaseServerActionClient(); const client = getSupabaseServerActionClient();
Logger.info(
{
accountId,
name: this.namespace,
},
`Billing portal session requested. Processing...`,
);
const { data: user, error } = await requireUser(client); const { data: user, error } = await requireUser(client);
if (error ?? !user) { if (error ?? !user) {
@@ -108,24 +160,58 @@ export class TeamBillingService {
// if the user does not have permission to manage billing for the account // if the user does not have permission to manage billing for the account
// then we should not proceed // then we should not proceed
if (!hasPermission) { if (!hasPermission) {
Logger.warn(
{
userId,
accountId,
name: this.namespace,
},
`User without permissions attempted to create billing portal session.`,
);
throw new Error('Permission denied'); throw new Error('Permission denied');
} }
const service = await getBillingGatewayProvider(client); const service = await getBillingGatewayProvider(client);
const customerId = await getCustomerIdFromAccountId(client, accountId); const customerId = await getCustomerIdFromAccountId(client, accountId);
const returnUrl = getBillingPortalReturnUrl(slug);
if (!customerId) { if (!customerId) {
throw new Error('Customer not found'); throw new Error('Customer not found');
} }
const { url } = await service.createBillingPortalSession({ Logger.info(
customerId, {
returnUrl, userId,
}); customerId,
accountId,
name: this.namespace,
},
`Creating billing portal session...`,
);
// redirect the user to the billing portal try {
return url; const returnUrl = getBillingPortalReturnUrl(slug);
const { url } = await service.createBillingPortalSession({
customerId,
returnUrl,
});
// redirect the user to the billing portal
return url;
} catch (error) {
Logger.error(
{
userId,
customerId,
accountId,
name: this.namespace,
},
`Billing Portal session was not created`,
);
throw new Error(`Error creating Billing Portal`);
}
} }
/** /**