From 9192ee2dd2c3ed96c9db04c3d10864ad4d777755 Mon Sep 17 00:00:00 2001 From: Nyk <0xnykcd@googlemail.com> Date: Wed, 4 Mar 2026 07:55:26 +0700 Subject: [PATCH] fix: switch pro activation flow to license key only --- docs/commercial/checkout-migration.md | 4 +- landing/README.md | 2 +- landing/api/pro/verify.js | 21 ++----- landing/index.html | 5 +- src-tauri/src/commands/pro.rs | 44 ++++++------- src-tauri/src/settings.rs | 4 ++ .../settings/about/AboutSettings.tsx | 63 ++++--------------- src/i18n/locales/en/translation.json | 8 +-- src/stores/proEntitlementStore.ts | 8 +-- src/utils/proEntitlement.ts | 7 +-- 10 files changed, 58 insertions(+), 108 deletions(-) diff --git a/docs/commercial/checkout-migration.md b/docs/commercial/checkout-migration.md index e82864c..ebe3c3c 100644 --- a/docs/commercial/checkout-migration.md +++ b/docs/commercial/checkout-migration.md @@ -45,7 +45,7 @@ Entitlement grants: Activation flow in app: - User opens **Settings -> About -> Upgrade to Dictx Pro** -- User enters purchase email + Polar checkout ID (`polar_cl_...`) +- User enters license key (`polar_cl_...`) - App verifies against `https://dictx.splitlabs.io/api/pro/verify` - On success, app stores active entitlement and enables updater checks @@ -91,7 +91,7 @@ Before launch: - Checkout success flow creates receipt + customer record - Webhook signature validation works in production - `dictx_pro` entitlement is granted/revoked correctly -- `landing/api/pro/verify` returns `{ active: true }` only for valid paid checkout + matching email +- `landing/api/pro/verify` returns `{ active: true }` only for valid paid checkout key - Customer portal access works from receipt email - Purchase links from app + README resolve to `https://dictx.splitlabs.io/buy` diff --git a/landing/README.md b/landing/README.md index c7752d3..25f264d 100644 --- a/landing/README.md +++ b/landing/README.md @@ -17,7 +17,7 @@ Attach `dictx.splitlabs.io` to this Vercel project. - `/` serves `landing/index.html` - `/buy` redirects to Polar checkout -- `/api/pro/verify` validates a Polar checkout/email pair for in-app Pro activation +- `/api/pro/verify` validates a Polar license key (`polar_cl_...`) for in-app Pro activation ## Environment Variables (Vercel) diff --git a/landing/api/pro/verify.js b/landing/api/pro/verify.js index 5e684be..1469f2e 100644 --- a/landing/api/pro/verify.js +++ b/landing/api/pro/verify.js @@ -5,8 +5,6 @@ const ALLOWED_PRODUCT_IDS = (process.env.POLAR_DICTX_PRODUCT_IDS || "") .map((value) => value.trim()) .filter(Boolean); -const normalizeEmail = (value) => value.trim().toLowerCase(); - const readBody = (req) => { if (!req.body) return {}; if (typeof req.body === "string") { @@ -42,17 +40,16 @@ module.exports = async (req, res) => { } const body = readBody(req); - const checkoutId = (body.checkoutId || "").trim(); - const email = normalizeEmail(body.email || ""); + const licenseKey = (body.licenseKey || body.checkoutId || "").trim(); - if (!checkoutId || !email) { - res.status(400).json({ error: "checkoutId_and_email_required" }); + if (!licenseKey) { + res.status(400).json({ error: "licenseKey_required" }); return; } try { const response = await fetch( - `${POLAR_API_BASE}/checkouts/${encodeURIComponent(checkoutId)}`, + `${POLAR_API_BASE}/checkouts/${encodeURIComponent(licenseKey)}`, { method: "GET", headers: { @@ -74,21 +71,13 @@ module.exports = async (req, res) => { } const checkout = await response.json(); - const checkoutEmail = normalizeEmail( - checkout.customer_email || - checkout.customer?.email || - checkout.metadata?.customer_email || - "", - ); - const productId = checkout.product_id == null ? "" : String(checkout.product_id); const productAllowed = ALLOWED_PRODUCT_IDS.length === 0 || ALLOWED_PRODUCT_IDS.includes(productId); - const emailMatches = checkoutEmail !== "" && checkoutEmail === email; const paid = statusLooksPaid(checkout.status, checkout.paid); - res.status(200).json({ active: Boolean(productAllowed && emailMatches && paid) }); + res.status(200).json({ active: Boolean(productAllowed && paid) }); } catch (error) { res.status(500).json({ error: "internal_error", diff --git a/landing/index.html b/landing/index.html index 526fb91..387bf3c 100644 --- a/landing/index.html +++ b/landing/index.html @@ -201,8 +201,9 @@
- Open Settings, go to About, and enter your purchase email and
- Polar checkout ID (starts with polar_cl_).
+ Open Settings, go to About, and enter your Pro license key
+ (currently your Polar checkout key, starts with
+ polar_cl_).
- {t("settings.about.proActivation.email")}: {entitlement.email} -
- )} - {entitlement?.checkout_id && ( + {(entitlement?.license_key || entitlement?.checkout_id) && (- {t("settings.about.proActivation.checkoutId")}:{" "} - {entitlement.checkout_id} + {t("settings.about.proActivation.licenseKey")}:{" "} + {entitlement.license_key ?? entitlement.checkout_id}
)} -