Migrate billing from Paddle to Lemon Squeezy
This commit is contained in:
@@ -557,7 +557,7 @@ export type DataExportSummary = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type PaddleTransactionSummary = {
|
||||
export type LemonSqueezyOrderSummary = {
|
||||
id: string | null;
|
||||
status: string | null;
|
||||
amount: number | null;
|
||||
@@ -1125,7 +1125,7 @@ export function normalizeTenantPackage(pkg: JsonValue): TenantPackageSummary {
|
||||
};
|
||||
}
|
||||
|
||||
function normalizePaddleTransaction(entry: JsonValue): PaddleTransactionSummary {
|
||||
function normalizeLemonSqueezyOrder(entry: JsonValue): LemonSqueezyOrderSummary {
|
||||
const amountValue = entry.amount ?? entry.grand_total ?? (entry.totals && entry.totals.grand_total);
|
||||
const taxValue = entry.tax ?? (entry.totals && entry.totals.tax_total);
|
||||
|
||||
@@ -2348,8 +2348,8 @@ export type Package = {
|
||||
gallery_days: number | null;
|
||||
max_events_per_year?: number | null;
|
||||
included_package_slug?: string | null;
|
||||
paddle_price_id?: string | null;
|
||||
paddle_product_id?: string | null;
|
||||
lemonsqueezy_variant_id?: string | null;
|
||||
lemonsqueezy_product_id?: string | null;
|
||||
branding_allowed?: boolean | null;
|
||||
watermark_allowed?: boolean | null;
|
||||
features: string[] | Record<string, boolean> | null;
|
||||
@@ -2731,8 +2731,8 @@ export async function downloadTenantDataExport(downloadUrl: string): Promise<Blo
|
||||
return response.blob();
|
||||
}
|
||||
|
||||
export async function getTenantPaddleTransactions(cursor?: string): Promise<{
|
||||
data: PaddleTransactionSummary[];
|
||||
export async function getTenantLemonSqueezyTransactions(cursor?: string): Promise<{
|
||||
data: LemonSqueezyOrderSummary[];
|
||||
nextCursor: string | null;
|
||||
hasMore: boolean;
|
||||
}> {
|
||||
@@ -2745,8 +2745,8 @@ export async function getTenantPaddleTransactions(cursor?: string): Promise<{
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await safeJson(response);
|
||||
console.error('[API] Failed to load Paddle transactions', response.status, payload);
|
||||
throw new Error('Failed to load Paddle transactions');
|
||||
console.error('[API] Failed to load Lemon Squeezy transactions', response.status, payload);
|
||||
throw new Error('Failed to load Lemon Squeezy transactions');
|
||||
}
|
||||
|
||||
const payload = await safeJson(response) ?? {};
|
||||
@@ -2754,17 +2754,17 @@ export async function getTenantPaddleTransactions(cursor?: string): Promise<{
|
||||
const meta = payload.meta ?? {};
|
||||
|
||||
return {
|
||||
data: entries.map(normalizePaddleTransaction),
|
||||
data: entries.map(normalizeLemonSqueezyOrder),
|
||||
nextCursor: typeof meta.next === 'string' ? meta.next : null,
|
||||
hasMore: Boolean(meta.has_more),
|
||||
};
|
||||
}
|
||||
|
||||
export async function createTenantPaddleCheckout(
|
||||
export async function createTenantLemonSqueezyCheckout(
|
||||
packageId: number,
|
||||
urls?: { success_url?: string; return_url?: string }
|
||||
): Promise<{ checkout_url: string; id: string; expires_at?: string; checkout_session_id?: string }> {
|
||||
const response = await authorizedFetch('/api/v1/tenant/packages/paddle-checkout', {
|
||||
const response = await authorizedFetch('/api/v1/tenant/packages/lemonsqueezy-checkout', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -2796,15 +2796,15 @@ export async function createTenantBillingPortalSession(): Promise<{ url: string
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await safeJson(response);
|
||||
console.error('[API] Failed to create Paddle portal session', response.status, payload);
|
||||
throw new Error('Failed to create Paddle portal session');
|
||||
console.error('[API] Failed to create Lemon Squeezy portal session', response.status, payload);
|
||||
throw new Error('Failed to create Lemon Squeezy portal session');
|
||||
}
|
||||
|
||||
const payload = await safeJson(response);
|
||||
const url = payload?.url;
|
||||
|
||||
if (typeof url !== 'string' || url.length === 0) {
|
||||
throw new Error('Paddle portal session missing URL');
|
||||
throw new Error('Lemon Squeezy portal session missing URL');
|
||||
}
|
||||
|
||||
return { url };
|
||||
@@ -2848,13 +2848,13 @@ export async function getTenantAddonHistory(page = 1, perPage = 25): Promise<{
|
||||
|
||||
export async function completeTenantPackagePurchase(params: {
|
||||
packageId: number;
|
||||
paddleTransactionId: string;
|
||||
orderId: string;
|
||||
}): Promise<void> {
|
||||
const { packageId, paddleTransactionId } = params;
|
||||
const { packageId, orderId } = params;
|
||||
const payload: Record<string, unknown> = { package_id: packageId };
|
||||
|
||||
if (paddleTransactionId) {
|
||||
payload.paddle_transaction_id = paddleTransactionId;
|
||||
if (orderId) {
|
||||
payload.lemonsqueezy_order_id = orderId;
|
||||
}
|
||||
|
||||
const response = await authorizedFetch('/api/v1/tenant/packages/complete', {
|
||||
|
||||
Reference in New Issue
Block a user