Billing get subscription enhancement (#36)

* Filter out metered line items from billing schema

This update refines the process of creating a billing schema by filtering out metered line items. The change is necessary as metered line items can be shared across different plans, potentially causing conflicts or duplicates in the schema.

* Update packages to newer versions

This update upgrades several packages across multiple project files to their latest version. These packages include "supabase-js", "react-query", "react-hook-form", and "pnpm". The commit ensures the project is up-to-date with recent package versions, potentially benefiting from bug fixes, new features, and performance improvements.

* Add subscription retrieval in billing services

Added a function to retrieve subscription info in both Stripe and LemonSqueezy billing services. To accomplish this, new methods were added to related services and types. This allows querying specific subscription data based on its id, and throws an error if it fails. Furthermore, PayloadBuilder classes were created to systematically build the subscription payload.

* Remove account ID retrieval from Lemon Squeezy billing service

The code that was querying the database to fetch the accountId has been removed from lemon-squeezy-billing-strategy.service.ts. It was unnecessary as the Lemon Squeezy API does not provide account ID and therefore it is always left empty. Also, adjustments have been made in billing-strategy-provider.service.ts to reflect that the target account ID can be optional.

* Extract 'next' parameter from callback URL

The update allows for the extraction of the 'next' parameter from the callback URL. If such a parameter is available, it is subsequently added to the search parameters. The enhancement improves URL parameter handling in the authentication callback service.

* Refactor URL redirection in auth-callback service

The update simplifies the redirection logic in the authentication callback service. This is achieved by setting the url pathname directly to the redirect path, instead of first setting it to the callback parameter. Moreover, the code handling the 'next' path has also been streamlined, setting the url pathname to the next path when available.
This commit is contained in:
Giancarlo Buomprisco
2024-06-19 23:00:00 +08:00
committed by GitHub
parent fbe7ca4c9e
commit 6a339a4b02
30 changed files with 738 additions and 456 deletions

View File

@@ -173,7 +173,12 @@ export const PlanSchema = z
)
.refine(
(item) => {
const ids = item.lineItems.map((item) => item.id);
// metered line items can be shared across plans
const lineItems = item.lineItems.filter(
(item) => item.type !== LineItemType.Metered,
);
const ids = lineItems.map((item) => item.id);
return ids.length === new Set(ids).size;
},

View File

@@ -9,6 +9,7 @@ import {
RetrieveCheckoutSessionSchema,
UpdateSubscriptionParamsSchema,
} from '../schema';
import { UpsertSubscriptionParams } from '../types';
export abstract class BillingStrategyProviderService {
abstract createBillingPortalSession(
@@ -65,4 +66,12 @@ export abstract class BillingStrategyProviderService {
interval: string;
amount: number;
}>;
abstract getSubscription(
subscriptionId: string,
): Promise<UpsertSubscriptionParams & {
// we can't always guarantee that the target account id will be present
// so we need to make it optional and let the consumer handle it
target_account_id: string | undefined;
}>;
}

View File

@@ -43,7 +43,7 @@ export abstract class BillingWebhookHandlerService {
onPaymentFailed: (sessionId: string) => Promise<unknown>;
// generic handler for any event
onEvent?: <Data>(data: Data) => Promise<unknown>;
onEvent?: (data: unknown) => Promise<unknown>;
},
): Promise<unknown>;
}

View File

@@ -1,7 +1,22 @@
import { Database } from '@kit/supabase/database';
export type UpsertSubscriptionParams =
Database['public']['Functions']['upsert_subscription']['Args'];
Database['public']['Functions']['upsert_subscription']['Args'] & {
line_items: Array<LineItem>;
};
interface LineItem {
id: string;
quantity: number;
subscription_id: string;
subscription_item_id: string;
product_id: string;
variant_id: string;
price_amount: number | null | undefined;
interval: string;
interval_count: number;
type: 'flat' | 'metered' | 'per_seat' | undefined;
}
export type UpsertOrderParams =
Database['public']['Functions']['upsert_order']['Args'];