feat(customer-account): payment extension for order page (shares /api/public/payment-info; dual auth)

This commit is contained in:
Gerhard Scheikl
2026-05-09 21:45:27 +02:00
parent 5ac2e09f8c
commit ca769c49a4
6 changed files with 183 additions and 5 deletions
+22 -5
View File
@@ -6,10 +6,13 @@ import { getStrings, pickLanguage } from "../services/invoice/i18n";
import { signGiroCodeUrl } from "../services/invoice/signedUrl";
/**
* Public endpoint consumed by the checkout / thank-you UI extension to fetch
* payment instructions (GiroCode + bank details) for an order.
* Public endpoint consumed by the checkout / thank-you UI extension AND by
* the customer-account order page extension to fetch payment instructions
* (GiroCode + bank details) for an order.
*
* Auth: validated Shopify checkout session token (via `authenticate.public.checkout`).
* Auth: validated Shopify session token. The handler tries
* `authenticate.public.customerAccount` first and falls back to
* `authenticate.public.checkout` so a single endpoint serves both surfaces.
* The shop domain is derived from `sessionToken.dest`; the order id is read
* from the `?orderId=` query parameter (numeric or GID, both accepted).
*
@@ -22,8 +25,22 @@ import { signGiroCodeUrl } from "../services/invoice/signedUrl";
* - the shop has an IBAN configured.
*/
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { sessionToken, cors } = await authenticate.public.checkout(request);
const shop = (sessionToken.dest ?? "").toString().replace(/^https?:\/\//, "");
let sessionToken: { dest?: string } | null = null;
let cors: <T>(res: T) => T = (r) => r;
try {
const auth = await authenticate.public.customerAccount(request);
sessionToken = auth.sessionToken as { dest?: string };
cors = auth.cors;
} catch {
try {
const auth = await authenticate.public.checkout(request);
sessionToken = auth.sessionToken as { dest?: string };
cors = auth.cors;
} catch (err) {
throw err;
}
}
const shop = (sessionToken?.dest ?? "").toString().replace(/^https?:\/\//, "");
if (!shop) {
return cors(Response.json({ showPaymentInstructions: false, error: "no-shop" }, { status: 400 }));
}