fix(thank-you): serve GiroCode as signed PNG URL instead of data URL
This commit is contained in:
@@ -61,3 +61,15 @@ export async function buildGiroCodeDataUrl(
|
||||
width: 256,
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildGiroCodePngBuffer(
|
||||
input: GiroCodeInput,
|
||||
): Promise<Buffer> {
|
||||
const payload = buildGiroCodePayload(input);
|
||||
return QRCode.toBuffer(payload, {
|
||||
errorCorrectionLevel: "M",
|
||||
margin: 1,
|
||||
width: 256,
|
||||
type: "png",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import crypto from "node:crypto";
|
||||
|
||||
const SECRET = process.env.SHOPIFY_API_SECRET || "";
|
||||
|
||||
function hmac(payload: string): string {
|
||||
return crypto.createHmac("sha256", SECRET).update(payload).digest("hex");
|
||||
}
|
||||
|
||||
export interface GiroCodeUrlParams {
|
||||
shop: string;
|
||||
orderId: string;
|
||||
exp: number; // unix seconds
|
||||
}
|
||||
|
||||
export function signGiroCodeUrl(params: GiroCodeUrlParams): string {
|
||||
const base = `shop=${params.shop}&orderId=${params.orderId}&exp=${params.exp}`;
|
||||
const sig = hmac(base);
|
||||
return `${base}&sig=${sig}`;
|
||||
}
|
||||
|
||||
export function verifyGiroCodeUrl(query: URLSearchParams): { ok: boolean; shop?: string; orderId?: string; reason?: string } {
|
||||
const shop = query.get("shop") || "";
|
||||
const orderId = query.get("orderId") || "";
|
||||
const exp = parseInt(query.get("exp") || "0", 10);
|
||||
const sig = query.get("sig") || "";
|
||||
if (!shop || !orderId || !exp || !sig) return { ok: false, reason: "missing-params" };
|
||||
if (Date.now() / 1000 > exp) return { ok: false, reason: "expired" };
|
||||
const expected = hmac(`shop=${shop}&orderId=${orderId}&exp=${exp}`);
|
||||
// timing-safe compare
|
||||
const a = Buffer.from(sig);
|
||||
const b = Buffer.from(expected);
|
||||
if (a.length !== b.length) return { ok: false, reason: "bad-sig" };
|
||||
if (!crypto.timingSafeEqual(a, b)) return { ok: false, reason: "bad-sig" };
|
||||
return { ok: true, shop, orderId };
|
||||
}
|
||||
Reference in New Issue
Block a user