diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json
index 23609e33..d200149f 100644
--- a/apps/dashboard/package.json
+++ b/apps/dashboard/package.json
@@ -21,6 +21,7 @@
},
"dependencies": {
"@carbon/charts-svelte": "^1.13.6",
+ "@lemonsqueezy/lemonsqueezy.js": "^4.0.0",
"@polar-sh/sveltekit": "^0.2.1",
"@sentry/browser": "^7.61.0",
"@sentry/integrations": "^7.61.0",
diff --git a/apps/dashboard/src/hooks.server.ts b/apps/dashboard/src/hooks.server.ts
index d438bdd7..782f55e5 100644
--- a/apps/dashboard/src/hooks.server.ts
+++ b/apps/dashboard/src/hooks.server.ts
@@ -5,7 +5,8 @@ const PUBLIC_ROUTES = [
'/api/completion',
'student_prove_payment',
'teacher_student_buycourse',
- '/api/polar'
+ '/api/polar',
+ '/api/lmz'
];
function isPublicRoute(pathname: string) {
diff --git a/apps/dashboard/src/lib/components/Org/Settings/Billing.svelte b/apps/dashboard/src/lib/components/Org/Settings/Billing.svelte
index 006f68e5..a35db44d 100644
--- a/apps/dashboard/src/lib/components/Org/Settings/Billing.svelte
+++ b/apps/dashboard/src/lib/components/Org/Settings/Billing.svelte
@@ -1,21 +1,44 @@
@@ -36,7 +59,7 @@
label={$t('settings.billing.open_billing')}
variant={VARIANTS.CONTAINED_DARK}
onClick={onOpenBilling}
- isDisabled={!$currentOrgPlan?.customerId}
+ isLoading={isRedirecting}
/>
{/if}
diff --git a/apps/dashboard/src/lib/utils/services/lemonsqueezy/index.ts b/apps/dashboard/src/lib/utils/services/lemonsqueezy/index.ts
new file mode 100644
index 00000000..358e4d88
--- /dev/null
+++ b/apps/dashboard/src/lib/utils/services/lemonsqueezy/index.ts
@@ -0,0 +1,11 @@
+import { env } from '$env/dynamic/private';
+import { lemonSqueezySetup } from '@lemonsqueezy/lemonsqueezy.js';
+
+export function configureLemonSqueezy() {
+ return lemonSqueezySetup({
+ apiKey: env.LEMON_SQUEEZY_API_KEY,
+ onError: (error) => {
+ throw new Error(`Lemon Squeezy API error: ${error.message}`);
+ }
+ });
+}
diff --git a/apps/dashboard/src/lib/utils/services/lemonsqueezy/subscribe.ts b/apps/dashboard/src/lib/utils/services/lemonsqueezy/subscribe.ts
new file mode 100644
index 00000000..59a824c8
--- /dev/null
+++ b/apps/dashboard/src/lib/utils/services/lemonsqueezy/subscribe.ts
@@ -0,0 +1,30 @@
+import { getAccessToken } from '$lib/utils/functions/supabase';
+import axios from 'axios';
+
+interface SubscriptionData {
+ productId: string;
+ email: string;
+ name: string;
+ triggeredBy: string;
+ orgId: string;
+}
+
+interface SubscriptionResponse {
+ success: boolean;
+ checkoutURL: string;
+}
+
+export async function subscribeToProduct(data: SubscriptionData): Promise {
+ const accessToken = await getAccessToken();
+
+ const response = await axios({
+ method: 'POST',
+ url: '/api/lmz/subscribe',
+ data,
+ headers: {
+ Authorization: `Bearer ${accessToken}`
+ }
+ });
+
+ return response.data;
+}
diff --git a/apps/dashboard/src/lib/utils/services/org/index.ts b/apps/dashboard/src/lib/utils/services/org/index.ts
index 25901342..32b9b620 100644
--- a/apps/dashboard/src/lib/utils/services/org/index.ts
+++ b/apps/dashboard/src/lib/utils/services/org/index.ts
@@ -77,6 +77,8 @@ export async function getOrganizations(userId: string, isOrgSite?: boolean, orgS
organization_plan(
plan_name,
is_active,
+ provider,
+ subscriptionId:payload->id,
customerId:payload->customerId
)
)
diff --git a/apps/dashboard/src/lib/utils/translations/de.json b/apps/dashboard/src/lib/utils/translations/de.json
index 69e43ea7..623cd236 100644
--- a/apps/dashboard/src/lib/utils/translations/de.json
+++ b/apps/dashboard/src/lib/utils/translations/de.json
@@ -1148,7 +1148,8 @@
"manage": "Verwalten Sie Ihre Abrechnung",
"active": "Sie haben keine aktive Abrechnung",
"open_billing": "Abrechnung öffnen",
- "provider": "Wir verwenden Polar, um Ihre Abrechnung zu verwalten"
+ "provider": "Wir verwenden Polar, um Ihre Abrechnung zu verwalten",
+ "error": "Beim Öffnen der Abrechnung ist ein Fehler aufgetreten"
},
"integrations": {
"heading": "Telegramm",
diff --git a/apps/dashboard/src/lib/utils/translations/en.json b/apps/dashboard/src/lib/utils/translations/en.json
index 3088d1f3..a82a9f9e 100644
--- a/apps/dashboard/src/lib/utils/translations/en.json
+++ b/apps/dashboard/src/lib/utils/translations/en.json
@@ -243,7 +243,8 @@
"manage": "Manage your billing",
"active": "You don't have any active billing",
"provider": "We use Polar to help manage your billing",
- "open_billing": "Open billing"
+ "open_billing": "Open billing",
+ "error": "An error occurred while opening billing"
}
},
diff --git a/apps/dashboard/src/lib/utils/translations/es.json b/apps/dashboard/src/lib/utils/translations/es.json
index 6a639a83..3a15e91f 100644
--- a/apps/dashboard/src/lib/utils/translations/es.json
+++ b/apps/dashboard/src/lib/utils/translations/es.json
@@ -1148,7 +1148,8 @@
"manage": "Gestiona tu facturación",
"active": "No tienes ninguna facturación activa",
"open_billing": "Facturación abierta",
- "provider": "Usamos Polar para ayudarte a gestionar tu facturación"
+ "provider": "Usamos Polar para ayudarte a gestionar tu facturación",
+ "error": "Se produjo un error al abrir la facturación."
},
"integrations": {
"heading": "Telegrama",
diff --git a/apps/dashboard/src/lib/utils/translations/fr.json b/apps/dashboard/src/lib/utils/translations/fr.json
index 99b920b1..b2e3dafd 100644
--- a/apps/dashboard/src/lib/utils/translations/fr.json
+++ b/apps/dashboard/src/lib/utils/translations/fr.json
@@ -1148,7 +1148,8 @@
"manage": "Gérez votre facturation",
"active": "Vous n'avez aucune facturation active",
"open_billing": "Facturation ouverte",
- "provider": "Nous utilisons Polar pour vous aider à gérer votre facturation"
+ "provider": "Nous utilisons Polar pour vous aider à gérer votre facturation",
+ "error": "Une erreur s'est produite lors de l'ouverture de la facturation"
},
"integrations": {
"heading": "Télégramme",
diff --git a/apps/dashboard/src/lib/utils/translations/hi.json b/apps/dashboard/src/lib/utils/translations/hi.json
index 83d4d4ee..4fc70327 100644
--- a/apps/dashboard/src/lib/utils/translations/hi.json
+++ b/apps/dashboard/src/lib/utils/translations/hi.json
@@ -1148,7 +1148,8 @@
"manage": "अपनी बिलिंग प्रबंधित करें",
"active": "आपके पास कोई सक्रिय बिलिंग नहीं है",
"open_billing": "बिलिंग खोलें",
- "provider": "हम आपकी बिलिंग प्रबंधित करने में सहायता के लिए पोलर का उपयोग करते हैं"
+ "provider": "हम आपकी बिलिंग प्रबंधित करने में सहायता के लिए पोलर का उपयोग करते हैं",
+ "error": "बिलिंग खोलते समय एक त्रुटि उत्पन्न हुई"
},
"integrations": {
"heading": "तार",
diff --git a/apps/dashboard/src/lib/utils/translations/pt.json b/apps/dashboard/src/lib/utils/translations/pt.json
index 65d1bc45..12ed3d16 100644
--- a/apps/dashboard/src/lib/utils/translations/pt.json
+++ b/apps/dashboard/src/lib/utils/translations/pt.json
@@ -1148,7 +1148,8 @@
"manage": "Gerencie seu faturamento",
"active": "Você não tem nenhum faturamento ativo",
"open_billing": "Faturamento aberto",
- "provider": "Usamos a Polar para ajudar a gerenciar seu faturamento"
+ "provider": "Usamos a Polar para ajudar a gerenciar seu faturamento",
+ "error": "Ocorreu um erro ao abrir o faturamento"
},
"integrations": {
"heading": "Telegrama",
diff --git a/apps/dashboard/src/lib/utils/translations/ru.json b/apps/dashboard/src/lib/utils/translations/ru.json
index 18b15a9a..da23c8d9 100644
--- a/apps/dashboard/src/lib/utils/translations/ru.json
+++ b/apps/dashboard/src/lib/utils/translations/ru.json
@@ -1148,7 +1148,8 @@
"manage": "Управляйте своим биллингом",
"active": "У вас нет активных платежных данных.",
"open_billing": "Открыть биллинг",
- "provider": "Мы используем Polar, чтобы управлять вашими платежами."
+ "provider": "Мы используем Polar, чтобы управлять вашими платежами.",
+ "error": "Произошла ошибка при открытии счета."
},
"integrations": {
"heading": "Телеграмма",
diff --git a/apps/dashboard/src/lib/utils/translations/vi.json b/apps/dashboard/src/lib/utils/translations/vi.json
index 0639d8b9..3f77fb58 100644
--- a/apps/dashboard/src/lib/utils/translations/vi.json
+++ b/apps/dashboard/src/lib/utils/translations/vi.json
@@ -1148,7 +1148,8 @@
"manage": "Quản lý thanh toán của bạn",
"active": "Bạn không có bất kỳ thanh toán nào đang hoạt động",
"open_billing": "Thanh toán mở",
- "provider": "Chúng tôi sử dụng Polar để giúp quản lý việc thanh toán của bạn"
+ "provider": "Chúng tôi sử dụng Polar để giúp quản lý việc thanh toán của bạn",
+ "error": "Đã xảy ra lỗi khi mở thanh toán"
},
"integrations": {
"heading": "điện tín",
diff --git a/apps/dashboard/src/lib/utils/types/org.ts b/apps/dashboard/src/lib/utils/types/org.ts
index 178c1f02..7f9fa426 100644
--- a/apps/dashboard/src/lib/utils/types/org.ts
+++ b/apps/dashboard/src/lib/utils/types/org.ts
@@ -29,6 +29,8 @@ export interface CurrentOrg {
customization: OrgCustomization;
theme: string;
organization_plan: {
+ provider: 'polar' | 'lmz';
+ subscriptionId: string;
customerId: string;
plan_name: string;
is_active: boolean;
diff --git a/apps/dashboard/src/routes/api/analytics/dash/+server.ts b/apps/dashboard/src/routes/api/analytics/dash/+server.ts
index d0adca59..7a024b4d 100644
--- a/apps/dashboard/src/routes/api/analytics/dash/+server.ts
+++ b/apps/dashboard/src/routes/api/analytics/dash/+server.ts
@@ -37,7 +37,7 @@ async function getOrganisationAnalytics(orgId: string): Promise ({
id: course.course_id,
diff --git a/apps/dashboard/src/routes/api/lmz/subscription/+server.ts b/apps/dashboard/src/routes/api/lmz/subscription/+server.ts
new file mode 100644
index 00000000..dac1d73a
--- /dev/null
+++ b/apps/dashboard/src/routes/api/lmz/subscription/+server.ts
@@ -0,0 +1,23 @@
+import { configureLemonSqueezy } from '$lib/utils/services/lemonsqueezy';
+import { getSubscription } from '@lemonsqueezy/lemonsqueezy.js';
+import { json } from '@sveltejs/kit';
+
+export async function GET({ url }) {
+ const subscriptionId = url.searchParams.get('subscriptionId');
+
+ await configureLemonSqueezy();
+
+ if (!subscriptionId) {
+ return json({ success: false, message: 'Subscription id is required' }, { status: 400 });
+ }
+
+ const response = await getSubscription(subscriptionId);
+ const customerPortal = response?.data?.data?.attributes?.urls?.customer_portal;
+
+ console.log({ customerPortal });
+
+ return json({
+ success: true,
+ customerPortal
+ });
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0ead4040..20091654 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -266,6 +266,9 @@ importers:
'@carbon/charts-svelte':
specifier: ^1.13.6
version: 1.13.6(d3-cloud@1.2.7)(d3-sankey@0.12.3)(d3@7.8.5)(svelte@4.1.2)
+ '@lemonsqueezy/lemonsqueezy.js':
+ specifier: ^4.0.0
+ version: 4.0.0
'@polar-sh/sveltekit':
specifier: ^0.2.1
version: 0.2.1(@sveltejs/kit@1.29.0(svelte@4.1.2)(vite@4.4.8(@types/node@22.10.1)(sass@1.64.2)))(zod@3.21.4)
@@ -2460,6 +2463,10 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@lemonsqueezy/lemonsqueezy.js@4.0.0':
+ resolution: {integrity: sha512-xcY1/lDrY7CpIF98WKiL1ElsfoVhddP7FT0fw7ssOzrFqQsr44HgolKrQZxd9SywsCPn12OTOUieqDIokI3mFg==}
+ engines: {node: '>=20'}
+
'@mapbox/node-pre-gyp@1.0.11':
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
hasBin: true
@@ -10508,7 +10515,7 @@ snapshots:
'@babel/traverse': 7.23.4
'@babel/types': 7.23.4
convert-source-map: 1.9.0
- debug: 4.3.4
+ debug: 4.3.4(supports-color@5.5.0)
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
@@ -10528,7 +10535,7 @@ snapshots:
'@babel/traverse': 7.23.4
'@babel/types': 7.23.4
convert-source-map: 2.0.0
- debug: 4.3.4
+ debug: 4.3.4(supports-color@5.5.0)
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
@@ -12248,6 +12255,8 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@lemonsqueezy/lemonsqueezy.js@4.0.0': {}
+
'@mapbox/node-pre-gyp@1.0.11':
dependencies:
detect-libc: 2.0.2
@@ -15321,10 +15330,6 @@ snapshots:
dependencies:
ms: 2.1.3
- debug@4.3.4:
- dependencies:
- ms: 2.1.2
-
debug@4.3.4(supports-color@5.5.0):
dependencies:
ms: 2.1.2