/** * 服务配置 - 参考 desktop digital 项目 * PocketBase、支付(ZPAY)、MinIO 可通过环境变量覆盖 */ const isDev = process.env.NODE_ENV === "development"; /** 站点标识,用于 VIP 按站点隔离 */ export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "vip"; export interface PocketBaseConfig { url: string; } export interface PaymentConfig { apiUrl: string; provider: "zpay" | "xorpay"; zpaySubmitUrl: string; /** 默认金额(分),88元=8800分 */ defaultAmount?: number; /** nomadvip 专用接口路径 */ nomadvipPayPath: string; } export interface MinioConfig { endPoint: string; port: number; useSSL: boolean; bucket: string; publicUrl: string; } /** * 服务端 PocketBase 基址: * - 生产(next start):只认 `POCKETBASE_URL`,否则本机 8090。忽略 `POCKETBASE_INTERNAL_URL`,避免误配公网域名把同机 API 拖慢。 * - 本地 next dev:可用 `POCKETBASE_INTERNAL_URL` 指向远程 PB(本机未起 8090)。 */ export function getPocketBaseConfig(): PocketBaseConfig { const serverSide = typeof window === "undefined"; if (serverSide) { if (isDev) { const devServerUrl = process.env.POCKETBASE_INTERNAL_URL?.trim() || process.env.POCKETBASE_URL?.trim(); if (devServerUrl) { return { url: devServerUrl.replace(/\/$/, "") }; } return { url: "http://127.0.0.1:8090" }; } return { url: (process.env.POCKETBASE_URL || "http://127.0.0.1:8090").replace( /\/$/, "" ), }; } return { url: ( process.env.NEXT_PUBLIC_POCKETBASE_URL || process.env.POCKETBASE_URL || "https://pocketbase.hackrobot.cn" ).replace(/\/$/, ""), }; } const PAYJSAPI_PORT = process.env.PAYJSAPI_PORT || "8007"; /** * 根据请求 Host 推断 payjsapi 地址。同机部署时优先用 PAYMENT_API_INTERNAL_URL。 * 访问 192.168.41.222:3000 时自动用 192.168.41.222:8007 */ export function getApiUrlFromRequest(hostHeader: string | null): string { const internal = process.env.PAYMENT_API_INTERNAL_URL?.trim(); if (internal) return internal.replace(/\/$/, ""); if (!hostHeader) return `http://127.0.0.1:${PAYJSAPI_PORT}`; const hostname = hostHeader.split(":")[0]; if (!isDev && /^(vip\.hackrobot\.cn|www\.vip\.hackrobot\.cn)$/i.test(hostname)) { return `http://127.0.0.1:${PAYJSAPI_PORT}`; } return isDev ? `http://${hostname}:${PAYJSAPI_PORT}` : "https://api.hackrobot.cn"; } /** * 支付 API 地址。同机部署时优先用 PAYMENT_API_INTERNAL_URL 避免 hairpin NAT 问题。 * 生产环境若 PAYMENT_API_URL 指向 localhost 且未设 INTERNAL,则用 api 域名。 */ function resolvePaymentApiUrl(): string { const internal = process.env.PAYMENT_API_INTERNAL_URL?.trim(); if (internal) return internal.replace(/\/$/, ""); const url = process.env.PAYMENT_API_URL || process.env.NEXT_PUBLIC_API_URL || `http://127.0.0.1:${PAYJSAPI_PORT}`; if (!isDev && /^(https?:\/\/)?(127\.0\.0\.1|localhost)(:\d+)?(\/|$)/i.test(url)) { return `http://127.0.0.1:${PAYJSAPI_PORT}`; } return url; } export function getPaymentConfig(): PaymentConfig { const apiUrl = resolvePaymentApiUrl(); return { apiUrl, provider: (process.env.PAYMENT_PROVIDER as "zpay" | "xorpay") || "zpay", zpaySubmitUrl: process.env.ZPAY_SUBMIT_URL || "https://zpayz.cn/submit.php", /** 支付价格 188 元=18800 分 */ defaultAmount: Number(process.env.PAYMENT_DEFAULT_AMOUNT) || 28800, nomadvipPayPath: "/nomadvip/payh5", }; } export function getMinioConfig(): MinioConfig { const endPoint = process.env.MINIO_ENDPOINT || "minioweb.hackrobot.cn"; const port = parseInt(process.env.MINIO_PORT || "9035", 10); const useSSL = process.env.MINIO_USE_SSL === "true"; const bucket = process.env.MINIO_BUCKET || "hackrobot"; const publicUrl = process.env.MINIO_PUBLIC_URL || `https://${endPoint}/${bucket}`; return { endPoint, port, useSSL, bucket, publicUrl: publicUrl.replace(/\/$/, ""), }; }