feat(payment): share payment method selector

This commit is contained in:
2026-07-17 18:27:24 +08:00
parent 66445a9972
commit b22db6d147
13 changed files with 386 additions and 173 deletions
@@ -0,0 +1,65 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { getDefaultPayChannelForCountryCode } from "../default_pay_channel";
import {
canChoosePayChannel,
getPaymentMethodConfig,
resolvePayChannel,
} from "../payment_method";
describe("payment method rules", () => {
afterEach(() => {
vi.unstubAllEnvs();
});
it("defaults Philippines users to GCash and other countries to Stripe", () => {
expect(getDefaultPayChannelForCountryCode("PH")).toBe("ezpay");
expect(getDefaultPayChannelForCountryCode("ph")).toBe("ezpay");
expect(getDefaultPayChannelForCountryCode("HK")).toBe("stripe");
expect(getDefaultPayChannelForCountryCode(null)).toBe("stripe");
});
it("only allows Philippines users to choose in production", () => {
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
expect(canChoosePayChannel("PH")).toBe(true);
expect(canChoosePayChannel("ph")).toBe(true);
expect(canChoosePayChannel("HK")).toBe(false);
expect(canChoosePayChannel(null)).toBe(false);
expect(
getPaymentMethodConfig({
countryCode: null,
requestedPayChannel: "ezpay",
}),
).toEqual({
canChoosePaymentMethod: false,
initialPayChannel: "stripe",
});
});
it("resolves requested and default channels for Philippines", () => {
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "production");
expect(
resolvePayChannel({ countryCode: "PH", requestedPayChannel: null }),
).toBe("ezpay");
expect(
resolvePayChannel({
countryCode: "PH",
requestedPayChannel: "stripe",
}),
).toBe("stripe");
});
it("allows every user and keeps the requested channel outside production", () => {
vi.stubEnv("NEXT_PUBLIC_APP_ENV", "test");
expect(canChoosePayChannel(null)).toBe(true);
expect(
resolvePayChannel({
countryCode: "HK",
requestedPayChannel: "ezpay",
}),
).toBe("ezpay");
});
});
+37
View File
@@ -0,0 +1,37 @@
import type { PayChannel } from "@/data/schemas/payment";
import { AppEnvUtil } from "@/utils/app-env";
import { getDefaultPayChannelForCountryCode } from "./default_pay_channel";
export interface PaymentMethodConfig {
canChoosePaymentMethod: boolean;
initialPayChannel: PayChannel;
}
export function canChoosePayChannel(
countryCode: string | null | undefined,
): boolean {
if (!AppEnvUtil.isProduction()) return true;
return countryCode?.trim().toUpperCase() === "PH";
}
export function resolvePayChannel(input: {
countryCode: string | null | undefined;
requestedPayChannel: PayChannel | null | undefined;
}): PayChannel {
if (!canChoosePayChannel(input.countryCode)) return "stripe";
return (
input.requestedPayChannel ??
getDefaultPayChannelForCountryCode(input.countryCode)
);
}
export function getPaymentMethodConfig(input: {
countryCode: string | null | undefined;
requestedPayChannel: PayChannel | null | undefined;
}): PaymentMethodConfig {
return {
canChoosePaymentMethod: canChoosePayChannel(input.countryCode),
initialPayChannel: resolvePayChannel(input),
};
}