diff --git a/app/routes/app.settings.tsx b/app/routes/app.settings.tsx index 64e9e85..5ba42f1 100644 --- a/app/routes/app.settings.tsx +++ b/app/routes/app.settings.tsx @@ -16,7 +16,9 @@ import { type CustomizationKind, findCustomizations, findGuard, gql, setCustomiz export const loader = async ({ request }: LoaderFunctionArgs) => { const { cfg, admin, billing } = await adminContext(request); // Keep the stored plan in sync with Shopify billing. - const check = await billing.check({ plans: [PLAN_GROWTH, PLAN_PRO], isTest: await billingIsTest(admin) }); + // isTest: true counts test subscriptions too. Shopify makes the charge a test on stores that can't be billed + // (including App Store review stores), and those must still unlock the plan. + const check = await billing.check({ plans: [PLAN_GROWTH, PLAN_PRO], isTest: true }); const plan = check.appSubscriptions.find((s) => s.status === "ACTIVE")?.name ?? "free"; if (plan !== cfg.shop.plan) await prisma.shop.update({ where: { id: cfg.shop.id }, data: { plan } }); const guard = await findGuard(admin).catch(() => null); @@ -57,8 +59,8 @@ export const action = async ({ request }: ActionFunctionArgs) => { const plan = intent.slice(5); const isTest = await billingIsTest(admin); if (plan === "free") { - const check = await billing.check({ plans: [PLAN_GROWTH, PLAN_PRO], isTest }); - for (const sub of check.appSubscriptions) await billing.cancel({ subscriptionId: sub.id, isTest, prorate: true }); + const check = await billing.check({ plans: [PLAN_GROWTH, PLAN_PRO], isTest: true }); + for (const sub of check.appSubscriptions) await billing.cancel({ subscriptionId: sub.id, isTest: sub.test, prorate: true }); await prisma.shop.update({ where: { id: cfg.shop.id }, data: { plan: "free" } }); return { ok: true, message: "Switched to Starter" }; } diff --git a/app/routes/webhooks.app.tsx b/app/routes/webhooks.app.tsx index 66c55a3..aba53ed 100644 --- a/app/routes/webhooks.app.tsx +++ b/app/routes/webhooks.app.tsx @@ -11,7 +11,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { const { shop, topic, session, payload } = await authenticate.webhook(request); if (topic === "APP_UNINSTALLED") { if (session) await prisma.session.deleteMany({ where: { shop } }); - await prisma.shop.updateMany({ where: { domain: shop }, data: { uninstalledAt: new Date() } }); + await prisma.shop.updateMany({ where: { domain: shop }, data: { uninstalledAt: new Date(), plan: "free" } }); // Shopify cancels app subscriptions on uninstall await prisma.hold.deleteMany({ where: { shop: { domain: shop } } }); await prisma.reminderJob.updateMany({ where: { shop: { domain: shop }, status: "pending" }, data: { status: "cancelled" } }); }