App Store review 1.2.2: the reviewer's store got a test charge, but billing.check ran with isTest:false and ignored it, so the approved plan never registered. Checks now count test subscriptions too, and cancel uses each subscription's own test flag. Uninstall resets the stored plan to free (Shopify cancels the subscription), so a reinstall asks for approval again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
24 lines
1.3 KiB
TypeScript
24 lines
1.3 KiB
TypeScript
import type { ActionFunctionArgs } from "react-router";
|
|
import prisma from "../db.server";
|
|
import { authenticate } from "../shopify.server";
|
|
|
|
/**
|
|
* app/uninstalled: storefront behaviour stops immediately (proxy calls fail without a
|
|
* session and the theme extension is removed by Shopify). Data is kept for 48 hours so a
|
|
* quick reinstall keeps bookings; Shopify's shop/redact webhook then deletes everything.
|
|
*/
|
|
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(), 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" } });
|
|
}
|
|
if (topic === "APP_SCOPES_UPDATE" && session) {
|
|
const current = (payload as { current?: string[] }).current;
|
|
if (current) await prisma.session.update({ where: { id: session.id }, data: { scope: current.toString() } });
|
|
}
|
|
return new Response();
|
|
};
|