import { afterEach, describe, expect, it, vi } from "vitest"; vi.mock("server-only", () => ({})); import { promptPayConfig, verifyCommissionSlip } from "./payment"; const names = ["SLIP2GO_VERIFY_URL", "SLIP2GO_API_SECRET", "COMMISSION_PROMPTPAY_TYPE", "COMMISSION_PROMPTPAY_VALUE", "COMMISSION_RECEIVER_ACCOUNT_NUMBER"] as const; const original = names.map((name) => process.env[name]); const checkoutDate = new Date("2026-09-01T12:00:00.000Z"); const validData = { code: "200200", data: { referenceId: "provider-ref", transRef: "bank-ref", amount: 100, dateTime: "2026-09-01T12:01:00.000Z" } }; afterEach(() => { names.forEach((name, index) => { if (original[index] === undefined) delete process.env[name]; else process.env[name] = original[index]; }); vi.unstubAllGlobals(); }); describe("commission slip verification", () => { it("rejects a non-mobile PromptPay value before checkout", () => { process.env.COMMISSION_PROMPTPAY_TYPE = "mobile"; process.env.COMMISSION_PROMPTPAY_VALUE = "123456789012345"; process.env.COMMISSION_RECEIVER_ACCOUNT_NUMBER = "0812345678"; expect(() => promptPayConfig()).toThrow("invalid-promptpay-value"); process.env.COMMISSION_PROMPTPAY_VALUE = "0812345678"; expect(promptPayConfig().identifier).toEqual({ type: "mobile", value: "0066812345678" }); }); async function check(response: unknown) { process.env.SLIP2GO_VERIFY_URL = "https://example.test/api/verify-slip/qr-image/info"; process.env.SLIP2GO_API_SECRET = "secret"; process.env.COMMISSION_PROMPTPAY_TYPE = "mobile"; process.env.COMMISSION_PROMPTPAY_VALUE = "0812345678"; process.env.COMMISSION_RECEIVER_ACCOUNT_NUMBER = "0812345678"; const fetch = vi.fn(async (_url: URL, init: RequestInit) => { expect(init.headers).toEqual({ Authorization: "Bearer secret" }); const payload = JSON.parse((init.body as FormData).get("payload") as string); expect(payload).toMatchObject({ checkReceiver: [{ accountType: "02001", accountNumber: "0812345678" }], checkAmount: { type: "eq", amount: "100.00" } }); expect(payload).not.toHaveProperty("checkDuplicate"); return Response.json(response); }); vi.stubGlobal("fetch", fetch); return verifyCommissionSlip(new File(["image"], "slip.png", { type: "image/png" }), 100, checkoutDate); } it("accepts a matching verified transfer", async () => { await expect(check(validData)).resolves.toMatchObject({ referenceId: "provider-ref", transRef: "bank-ref", amountBaht: 100 }); }); it("rejects duplicate and amount mismatch results", async () => { await expect(check({ code: "200501" })).rejects.toMatchObject({ status: 422 }); await expect(check({ code: "200401", data: { referenceId: "provider-ref" } })) .rejects.toMatchObject({ status: 422, message: "slip-rejected:200401" }); await expect(check({ ...validData, code: "200000" })).rejects.toMatchObject({ status: 422 }); await expect(check({ ...validData, data: { ...validData.data, amount: 80 } })) .rejects.toMatchObject({ status: 422 }); }); it("treats a rejected API secret as a service error, not an invalid slip", async () => { await expect(check({ code: "401001", message: "Authentication Token Mismatch", data: { referenceId: "provider-ref" } })) .rejects.toMatchObject({ status: 503, message: "slip2go-service:401001" }); }); it("reports which required field is missing from a successful provider response", async () => { await expect(check({ code: "200200", data: { referenceId: "provider-ref" } })) .rejects.toMatchObject({ status: 503, message: "invalid-slip-verification-response:transRef" }); }); });