's'
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { AUTH_COOKIE_DOMAIN } from "@/config/domain.config";
|
import { getAuthCookieDomain } from "@/config/domain.config";
|
||||||
|
|
||||||
const COOKIE_NAME = "pb_session";
|
const COOKIE_NAME = "pb_session";
|
||||||
|
|
||||||
export async function POST() {
|
export async function POST(request: NextRequest) {
|
||||||
|
const domain = getAuthCookieDomain(request);
|
||||||
const res = NextResponse.json({ ok: true });
|
const res = NextResponse.json({ ok: true });
|
||||||
res.cookies.set(COOKIE_NAME, "", { domain: AUTH_COOKIE_DOMAIN, path: "/", maxAge: 0 });
|
res.cookies.set(COOKIE_NAME, "", {
|
||||||
|
...(domain && { domain }),
|
||||||
|
path: "/",
|
||||||
|
maxAge: 0,
|
||||||
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { getPocketBaseConfig } from "@/config/services.config";
|
import { getPocketBaseConfig } from "@/config/services.config";
|
||||||
import { AUTH_COOKIE_DOMAIN } from "@/config/domain.config";
|
import { getAuthCookieDomain } from "@/config/domain.config";
|
||||||
|
|
||||||
const COOKIE_NAME = "pb_session";
|
const COOKIE_NAME = "pb_session";
|
||||||
const COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
const cookie = request.cookies.get(COOKIE_NAME)?.value;
|
const cookie = request.cookies.get(COOKIE_NAME)?.value;
|
||||||
|
const domain = getAuthCookieDomain(request);
|
||||||
if (!cookie) {
|
if (!cookie) {
|
||||||
return NextResponse.json({ ok: true, user: null });
|
return NextResponse.json({ ok: true, user: null });
|
||||||
}
|
}
|
||||||
@@ -21,7 +22,7 @@ export async function GET(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const r = NextResponse.json({ ok: true, user: null });
|
const r = NextResponse.json({ ok: true, user: null });
|
||||||
r.cookies.set(COOKIE_NAME, "", { domain: AUTH_COOKIE_DOMAIN, path: "/", maxAge: 0 });
|
r.cookies.set(COOKIE_NAME, "", { ...(domain && { domain }), path: "/", maxAge: 0 });
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
@@ -40,7 +41,7 @@ export async function GET(request: NextRequest) {
|
|||||||
token: newToken,
|
token: newToken,
|
||||||
});
|
});
|
||||||
r.cookies.set(COOKIE_NAME, encoded, {
|
r.cookies.set(COOKIE_NAME, encoded, {
|
||||||
domain: AUTH_COOKIE_DOMAIN,
|
...(domain && { domain }),
|
||||||
path: "/",
|
path: "/",
|
||||||
maxAge: COOKIE_MAX_AGE,
|
maxAge: COOKIE_MAX_AGE,
|
||||||
secure: process.env.NODE_ENV === "production",
|
secure: process.env.NODE_ENV === "production",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { AUTH_COOKIE_DOMAIN } from "@/config/domain.config";
|
import { getAuthCookieDomain } from "@/config/domain.config";
|
||||||
|
|
||||||
const COOKIE_NAME = "pb_session";
|
const COOKIE_NAME = "pb_session";
|
||||||
const COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 365 天,登录态持续有效直至用户主动退出
|
const COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 365 天,登录态持续有效直至用户主动退出
|
||||||
@@ -19,9 +19,10 @@ export async function POST(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
const encoded = Buffer.from(payload, "utf-8").toString("base64url");
|
const encoded = Buffer.from(payload, "utf-8").toString("base64url");
|
||||||
|
|
||||||
|
const domain = getAuthCookieDomain(request);
|
||||||
const res = NextResponse.json({ ok: true });
|
const res = NextResponse.json({ ok: true });
|
||||||
res.cookies.set(COOKIE_NAME, encoded, {
|
res.cookies.set(COOKIE_NAME, encoded, {
|
||||||
domain: AUTH_COOKIE_DOMAIN,
|
...(domain && { domain }),
|
||||||
path: "/",
|
path: "/",
|
||||||
maxAge: COOKIE_MAX_AGE,
|
maxAge: COOKIE_MAX_AGE,
|
||||||
secure: process.env.NODE_ENV === "production",
|
secure: process.env.NODE_ENV === "production",
|
||||||
|
|||||||
@@ -3,14 +3,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link, useLocale } from "@/i18n/navigation";
|
import { Link, useLocale } from "@/i18n/navigation";
|
||||||
import { useTranslation } from "@/i18n/navigation";
|
import { useTranslation } from "@/i18n/navigation";
|
||||||
import {
|
import JoinModal from "./JoinModal";
|
||||||
getPayEnv,
|
|
||||||
getRecommendedChannel,
|
|
||||||
mustUseWxPay,
|
|
||||||
redirectToPay,
|
|
||||||
getDeviceFromEnv,
|
|
||||||
} from "@/app/lib/payment";
|
|
||||||
import type { PayChannel, PayEnv } from "@/app/lib/payment";
|
|
||||||
|
|
||||||
const MEDIA_NAMES_ZH = ["36氪", "少数派", "极客公园", "虎嗅", "创业邦", "澎湃新闻"];
|
const MEDIA_NAMES_ZH = ["36氪", "少数派", "极客公园", "虎嗅", "创业邦", "澎湃新闻"];
|
||||||
const MEDIA_NAMES_EN = ["36Kr", "sspai", "GeekPark", "Huxiu", "Cyzone", "The Paper"];
|
const MEDIA_NAMES_EN = ["36Kr", "sspai", "GeekPark", "Huxiu", "Cyzone", "The Paper"];
|
||||||
@@ -38,54 +31,14 @@ const features = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function HeroSection() {
|
export default function HeroSection() {
|
||||||
const { t } = useTranslation("common");
|
|
||||||
const { t: tHero } = useTranslation("hero");
|
const { t: tHero } = useTranslation("hero");
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [joinModalOpen, setJoinModalOpen] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const handleJoin = async (e: React.FormEvent) => {
|
const handleJoinClick = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const em = email.trim();
|
setJoinModalOpen(true);
|
||||||
if (!em) {
|
|
||||||
setError(locale === "zh" ? "请输入邮箱" : "Please enter your email");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setError(null);
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
const res = await fetch("/api/meetup/ensure-user", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ email: em, password: password || undefined }),
|
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
const data = await res.json();
|
|
||||||
if (!res.ok || !data?.ok) {
|
|
||||||
throw new Error(data?.error || (locale === "zh" ? "操作失败" : "Operation failed"));
|
|
||||||
}
|
|
||||||
await fetch("/api/auth/sync-session", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({ token: data.token, record: data.record }),
|
|
||||||
});
|
|
||||||
const returnUrl = typeof window !== "undefined" ? `${window.location.origin}/${locale}/join/paid` : "/zh/join/paid";
|
|
||||||
const env: PayEnv = typeof window !== "undefined" ? (navigator.userAgent.includes("MicroMessenger") ? "wechat" : "pc") : "pc";
|
|
||||||
const channel: PayChannel = mustUseWxPay(env) ? "wxpay" : getRecommendedChannel(env);
|
|
||||||
redirectToPay({
|
|
||||||
user_id: data.user_id,
|
|
||||||
return_url: returnUrl,
|
|
||||||
channel,
|
|
||||||
device: getDeviceFromEnv(env),
|
|
||||||
useJoinConfig: true,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
setError(err instanceof Error ? err.message : "操作失败");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -193,36 +146,30 @@ export default function HeroSection() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleJoin} className="p-4 sm:p-5">
|
<form onSubmit={handleJoinClick} className="p-4 sm:p-5">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => { setEmail(e.target.value); setError(null); }}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
placeholder={tHero("emailPlaceholder")}
|
placeholder={tHero("emailPlaceholder")}
|
||||||
className="w-full border border-gray-200 dark:border-gray-700 rounded-lg px-4 py-3 text-sm placeholder-gray-400 dark:placeholder-gray-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f] transition-colors mb-3"
|
className="w-full border border-gray-200 dark:border-gray-700 rounded-lg px-4 py-3 text-sm placeholder-gray-400 dark:placeholder-gray-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f] transition-colors mb-3"
|
||||||
/>
|
/>
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
value={password}
|
|
||||||
onChange={(e) => { setPassword(e.target.value); setError(null); }}
|
|
||||||
placeholder={locale === "zh" ? "密码(老用户必填)" : "Password (required for existing users)"}
|
|
||||||
className="w-full border border-gray-200 dark:border-gray-700 rounded-lg px-4 py-3 text-sm placeholder-gray-400 dark:placeholder-gray-500 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f] transition-colors mb-3"
|
|
||||||
/>
|
|
||||||
{error && (
|
|
||||||
<p className="mb-2 text-sm text-red-600 dark:text-red-400">{error}</p>
|
|
||||||
)}
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
className="w-full bg-[#ff4d4f] hover:bg-[#ff3333] dark:hover:bg-[#ff5c5e] text-white py-3 rounded-lg text-sm font-semibold transition-colors active:scale-[0.98]"
|
||||||
className="w-full bg-[#ff4d4f] hover:bg-[#ff3333] dark:hover:bg-[#ff5c5e] text-white py-3 rounded-lg text-sm font-semibold transition-colors active:scale-[0.98] disabled:opacity-70"
|
|
||||||
>
|
>
|
||||||
{loading ? (locale === "zh" ? "处理中…" : "Processing…") : tHero("ctaJoin")}
|
{tHero("ctaJoin")}
|
||||||
</button>
|
</button>
|
||||||
<p className="text-xs text-gray-400 dark:text-gray-500 text-center mt-3">
|
<p className="text-xs text-gray-400 dark:text-gray-500 text-center mt-3">
|
||||||
{locale === "zh" ? "新用户将自动注册,支付成功后需修改默认密码" : "New users auto-register; change default password after payment"}
|
{locale === "zh" ? "新用户将自动注册,支付成功后需修改默认密码" : "New users auto-register; change default password after payment"}
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<JoinModal
|
||||||
|
isOpen={joinModalOpen}
|
||||||
|
onClose={() => setJoinModalOpen(false)}
|
||||||
|
initialEmail={email.trim()}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="mt-4 flex flex-wrap gap-2 justify-center">
|
<div className="mt-4 flex flex-wrap gap-2 justify-center">
|
||||||
<Link href="/dashboard" className="text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 bg-white dark:bg-gray-800 rounded-full px-3 py-1.5 border border-gray-100 dark:border-gray-700 transition-colors min-h-[2rem] inline-flex items-center">
|
<Link href="/dashboard" className="text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 bg-white dark:bg-gray-800 rounded-full px-3 py-1.5 border border-gray-100 dark:border-gray-700 transition-colors min-h-[2rem] inline-flex items-center">
|
||||||
|
|||||||
152
app/components/JoinModal.tsx
Normal file
152
app/components/JoinModal.tsx
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState, useEffect, type FormEvent } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
|
import { useLocale } from "@/i18n/navigation";
|
||||||
|
import {
|
||||||
|
getRecommendedChannel,
|
||||||
|
mustUseWxPay,
|
||||||
|
redirectToPay,
|
||||||
|
getDeviceFromEnv,
|
||||||
|
} from "@/app/lib/payment";
|
||||||
|
import type { PayChannel, PayEnv } from "@/app/lib/payment";
|
||||||
|
|
||||||
|
interface JoinModalProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
initialEmail?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function JoinModal({ isOpen, onClose, initialEmail = "" }: JoinModalProps) {
|
||||||
|
const locale = useLocale();
|
||||||
|
const [email, setEmail] = useState(initialEmail);
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
setEmail(initialEmail);
|
||||||
|
setPassword("");
|
||||||
|
setError(null);
|
||||||
|
}
|
||||||
|
}, [isOpen, initialEmail]);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const em = email.trim();
|
||||||
|
if (!em) {
|
||||||
|
setError(locale === "zh" ? "请输入邮箱" : "Please enter your email");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setError(null);
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await fetch("/api/meetup/ensure-user", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ email: em, password: password || undefined }),
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (!res.ok || !data?.ok) {
|
||||||
|
throw new Error(data?.error || (locale === "zh" ? "操作失败" : "Operation failed"));
|
||||||
|
}
|
||||||
|
await fetch("/api/auth/sync-session", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ token: data.token, record: data.record }),
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const returnUrl = typeof window !== "undefined" ? `${window.location.origin}/${locale}/join/paid` : "/zh/join/paid";
|
||||||
|
const env: PayEnv = typeof window !== "undefined" ? (navigator.userAgent.includes("MicroMessenger") ? "wechat" : "pc") : "pc";
|
||||||
|
const channel: PayChannel = mustUseWxPay(env) ? "wxpay" : getRecommendedChannel(env);
|
||||||
|
redirectToPay({
|
||||||
|
user_id: data.user_id,
|
||||||
|
return_url: returnUrl,
|
||||||
|
channel,
|
||||||
|
device: getDeviceFromEnv(env),
|
||||||
|
useJoinConfig: true,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : "操作失败");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
useEffect(() => setMounted(true), []);
|
||||||
|
|
||||||
|
if (!isOpen || !mounted) return null;
|
||||||
|
|
||||||
|
const modalContent = (
|
||||||
|
<div className="fixed inset-0 z-[9999] overflow-y-auto">
|
||||||
|
<div className="fixed inset-0 bg-black/50" onClick={onClose} aria-hidden />
|
||||||
|
<div className="flex min-h-svh items-center justify-center p-4 py-8">
|
||||||
|
<div className="relative w-full max-w-sm rounded-2xl bg-white p-6 shadow-xl dark:bg-gray-900 dark:border dark:border-gray-700 shrink-0">
|
||||||
|
<button
|
||||||
|
onClick={onClose}
|
||||||
|
className="absolute right-4 top-4 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
||||||
|
aria-label="关闭"
|
||||||
|
>
|
||||||
|
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h2 className="text-xl font-bold text-gray-800 dark:text-gray-100">
|
||||||
|
{locale === "zh" ? "加入游牧中国" : "Join Nomad China"}
|
||||||
|
</h2>
|
||||||
|
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{locale === "zh" ? "新用户将自动注册,老用户请输入密码" : "New users auto-register; existing users enter password"}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit} className="mt-6 space-y-4">
|
||||||
|
<div>
|
||||||
|
<label className="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
{locale === "zh" ? "邮箱" : "Email"}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => { setEmail(e.target.value); setError(null); }}
|
||||||
|
placeholder={locale === "zh" ? "输入你的邮箱..." : "Enter your email..."}
|
||||||
|
required
|
||||||
|
className="w-full rounded-lg border border-gray-200 px-4 py-2.5 text-gray-800 placeholder-gray-400 focus:border-[#ff4d4f] focus:outline-none focus:ring-1 focus:ring-[#ff4d4f] dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
{locale === "zh" ? "密码(老用户必填)" : "Password (required for existing users)"}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => { setPassword(e.target.value); setError(null); }}
|
||||||
|
placeholder={locale === "zh" ? "新用户可留空" : "Leave empty for new users"}
|
||||||
|
className="w-full rounded-lg border border-gray-200 px-4 py-2.5 text-gray-800 placeholder-gray-400 focus:border-[#ff4d4f] focus:outline-none focus:ring-1 focus:ring-[#ff4d4f] dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error && (
|
||||||
|
<p className="rounded-lg bg-red-50 px-3 py-2 text-sm text-red-600 dark:bg-red-900/30 dark:text-red-400">{error}</p>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full rounded-lg bg-[#ff4d4f] py-3 font-semibold text-white transition-colors hover:bg-[#ff3333] disabled:opacity-70"
|
||||||
|
>
|
||||||
|
{loading ? (locale === "zh" ? "处理中…" : "Processing…") : (locale === "zh" ? "加入游牧中国 →" : "Join Nomad China →")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p className="text-xs text-gray-400 dark:text-gray-500 text-center mt-3">
|
||||||
|
{locale === "zh" ? "新用户将自动注册,支付成功后需修改默认密码" : "New users auto-register; change default password after payment"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return createPortal(modalContent, document.body);
|
||||||
|
}
|
||||||
@@ -11,6 +11,15 @@ export const ROOT_DOMAIN =
|
|||||||
export const AUTH_COOKIE_DOMAIN =
|
export const AUTH_COOKIE_DOMAIN =
|
||||||
process.env.AUTH_COOKIE_DOMAIN || `.${ROOT_DOMAIN}`;
|
process.env.AUTH_COOKIE_DOMAIN || `.${ROOT_DOMAIN}`;
|
||||||
|
|
||||||
|
/** 根据请求 host 返回 Cookie domain。localhost 时不设 domain,生产环境用根域实现跨站 SSO */
|
||||||
|
export function getAuthCookieDomain(request: { headers: { get: (name: string) => string | null } }): string | undefined {
|
||||||
|
const envDomain = process.env.AUTH_COOKIE_DOMAIN;
|
||||||
|
if (envDomain) return envDomain;
|
||||||
|
const host = request.headers.get("host") ?? "";
|
||||||
|
if (host.includes("localhost") || host.startsWith("127.0.0.1")) return undefined;
|
||||||
|
return AUTH_COOKIE_DOMAIN;
|
||||||
|
}
|
||||||
|
|
||||||
export const DEFAULT_PAYMENT_API_URL = isDev
|
export const DEFAULT_PAYMENT_API_URL = isDev
|
||||||
? "http://127.0.0.1:8700"
|
? "http://127.0.0.1:8700"
|
||||||
: `https://api.${ROOT_DOMAIN}`;
|
: `https://api.${ROOT_DOMAIN}`;
|
||||||
|
|||||||
Reference in New Issue
Block a user