/** API client — mock adapters when EXPO_PUBLIC_API_URL is unset. */ export const BASE_URLS = { core: process.env.EXPO_PUBLIC_API_URL ?? "https://api.gishen.example/v1", } as const; export const USE_MOCKS = !process.env.EXPO_PUBLIC_API_URL; export type ApiError = { message: string; code?: string }; export type PaymentIntent = { id: string; provider: string; status: "requires_action" | "succeeded" | "pending"; amountEtb: number; checkoutUrl?: string; }; export async function initiatePayment(input: { provider: string; amountEtb: number; orderId: string; }): Promise { if (USE_MOCKS) { await delay(450); return { id: `pay_${Date.now()}`, provider: input.provider, status: input.provider === "bank" || input.provider === "cod" || input.provider === "pay_at_branch" ? "pending" : "succeeded", amountEtb: input.amountEtb, checkoutUrl: input.provider === "chapa" || input.provider === "arifpay" ? `https://checkout.mock.gishen/${input.provider}` : undefined, }; } return callEndpoint("/payments/intent", { method: "POST", body: JSON.stringify(input), }); } export async function callEndpoint( path: string, init?: RequestInit & { locale?: string } ): Promise { const headers: Record = { "Content-Type": "application/json", Accept: "application/json", ...(init?.locale ? { "Accept-Language": init.locale } : {}), ...(init?.headers as Record), }; if (USE_MOCKS) { throw new Error(`No mock for ${path} — pass EXPO_PUBLIC_API_URL or add an adapter`); } const res = await fetch(`${BASE_URLS.core}${path}`, { ...init, headers, }); if (!res.ok) { const body = (await res.json().catch(() => ({}))) as ApiError; throw new Error(body.message || res.statusText); } return res.json() as Promise; } function delay(ms: number) { return new Promise((r) => setTimeout(r, ms)); }