fix(billing): open Shopify's plan approval page instead of showing 401
billing.request throws a 401 with the approval URL in X-Shopify-API-Request-Failure-Reauthorize-Url for App Bridge to follow, but a React Router form submission rendered it as an error page. The action now returns the URL and the page opens it at the top level. Invalid-session retries are still rethrown for App Bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6061877ca1
commit
3f1a07382b
@ -1,4 +1,5 @@
|
||||
import type { ActionFunctionArgs, LoaderFunctionArgs } from "react-router";
|
||||
import { useEffect } from "react";
|
||||
import { Form, useActionData, useLoaderData, useNavigation } from "react-router";
|
||||
import prisma from "../db.server";
|
||||
import type { ReminderPolicy } from "../engine/types";
|
||||
@ -61,8 +62,17 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
await prisma.shop.update({ where: { id: cfg.shop.id }, data: { plan: "free" } });
|
||||
return { ok: true, message: "Switched to Starter" };
|
||||
}
|
||||
// Redirects the merchant to Shopify's approval page.
|
||||
await billing.request({ plan: plan as typeof PLAN_GROWTH, isTest, returnUrl: `https://${cfg.shop.domain}/admin/apps/${process.env.SHOPIFY_API_KEY}/app/settings` });
|
||||
// billing.request throws a 401 carrying Shopify's approval URL for App Bridge to follow. A React Router
|
||||
// form submission surfaces that 401 as an error page instead, so hand the URL to the page to open.
|
||||
try {
|
||||
await billing.request({ plan: plan as typeof PLAN_GROWTH, isTest, returnUrl: `https://${cfg.shop.domain}/admin/apps/${process.env.SHOPIFY_API_KEY}/app/settings` });
|
||||
} catch (e) {
|
||||
if (!(e instanceof Response) || e.headers.has("X-Shopify-Retry-Invalid-Session-Request")) throw e;
|
||||
const confirmationUrl = e.headers.get("X-Shopify-API-Request-Failure-Reauthorize-Url");
|
||||
if (confirmationUrl) return { ok: true, message: "Opening Shopify to approve the plan…", confirmationUrl };
|
||||
console.error(`[datewise] billing request failed: ${e.status} ${[...e.headers.keys()].join(",")}`);
|
||||
return { ok: false, message: "Shopify couldn't start the plan change. Reload the page and try again." };
|
||||
}
|
||||
}
|
||||
|
||||
if (intent === "guard") {
|
||||
@ -170,6 +180,10 @@ export default function Settings() {
|
||||
const { plan, s, guard, custom } = useLoaderData<typeof loader>();
|
||||
const result = useActionData<typeof action>();
|
||||
const busy = useNavigation().state !== "idle";
|
||||
const confirmationUrl = result && "confirmationUrl" in result ? result.confirmationUrl : null;
|
||||
useEffect(() => {
|
||||
if (confirmationUrl) window.open(confirmationUrl, "_top");
|
||||
}, [confirmationUrl]);
|
||||
return (
|
||||
<s-page heading="Settings">
|
||||
{result && <s-banner tone={result.ok ? "success" : "critical"}>{result.message}</s-banner>}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user