diff --git a/app/routes/api.public.payment-info.tsx b/app/routes/api.public.payment-info.tsx index 90e7bb9..638dedd 100644 --- a/app/routes/api.public.payment-info.tsx +++ b/app/routes/api.public.payment-info.tsx @@ -33,9 +33,14 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { if (!orderIdRaw) { return cors(Response.json({ showPaymentInstructions: false, error: "no-order-id" }, { status: 400 })); } - const orderGid = orderIdRaw.startsWith("gid://") - ? orderIdRaw - : `gid://shopify/Order/${orderIdRaw.replace(/[^0-9]/g, "")}`; + // The thank-you page exposes the order id as an `OrderIdentity` GID + // (e.g. `gid://shopify/OrderIdentity/123`). For the Admin API we need an + // `Order` GID. The numeric id is the same — just rewrite the type segment. + const numericId = orderIdRaw.replace(/^gid:\/\/shopify\/[^/]+\//, "").replace(/[^0-9]/g, ""); + if (!numericId) { + return cors(Response.json({ showPaymentInstructions: false, error: "bad-order-id" }, { status: 400 })); + } + const orderGid = `gid://shopify/Order/${numericId}`; const settings = await db.shopSettings.findUnique({ where: { shopDomain: shop } }); if (!settings?.iban || !settings.giroCodeEnabled) { @@ -46,7 +51,18 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { let orderInfo: OrderInfo | null = null; try { const { admin } = await unauthenticated.admin(shop); - orderInfo = await fetchOrderInfo(admin, orderGid); + // Brief retry: the Order may not be queryable for a moment after creation. + let lastErr: unknown = null; + for (let attempt = 0; attempt < 3; attempt++) { + try { + orderInfo = await fetchOrderInfo(admin, orderGid); + if (orderInfo) break; + } catch (e) { + lastErr = e; + } + await new Promise((r) => setTimeout(r, 500 * (attempt + 1))); + } + if (!orderInfo && lastErr) throw lastErr; } catch (err) { const msg = (err as Error)?.message ?? String(err); console.warn(`payment-info: failed to load order ${orderGid} for ${shop}:`, err);