This commit is contained in:
eric
2026-03-26 11:08:35 -05:00
parent eaa92ddf36
commit db65182dc1
3 changed files with 67 additions and 43 deletions

View File

@@ -3,6 +3,8 @@
# ========== PocketBase ==========
NEXT_PUBLIC_POCKETBASE_URL=https://pocketbase.hackrobot.cn
# 服务端 API 可优先走内网/本机,避免公网超时
# POCKETBASE_INTERNAL_URL=http://127.0.0.1:8090
POCKETBASE_EMAIL=xiaoshuang.eric@gmail.com
POCKETBASE_PASSWORD=Xiao4669805@
@@ -15,6 +17,8 @@ NEXT_PUBLIC_API_URL=http://127.0.0.1:8007
# PAYMENT_API_INTERNAL_URL=http://127.0.0.1:8007
# 内网/慢网络可适当提高超时毫秒check_vip 默认 15spayh5/redirect 默认 60s
# PAYJSAPI_CHECK_TIMEOUT=15000
# PAYJSAPI_CHECK_BY_EMAIL_TIMEOUT=15000
# PAYJSAPI_CHECK_BY_EMAIL_RETRIES=1
# PAYJSAPI_PAYH5_TIMEOUT=60000
# PAYJSAPI_REDIRECT_TIMEOUT=60000
PAYMENT_PROVIDER=zpay

View File

@@ -37,6 +37,8 @@ type RecoveryResult = {
const PAYJS_CHECK_BY_EMAIL_TIMEOUT =
Number(process.env.PAYJSAPI_CHECK_BY_EMAIL_TIMEOUT) || 5000;
const PAYJS_CHECK_BY_EMAIL_RETRIES =
Math.max(0, Number(process.env.PAYJSAPI_CHECK_BY_EMAIL_RETRIES) || 1);
function resolvePayApiUrl(request: NextRequest): string {
const payConfig = getPaymentConfig();
@@ -53,51 +55,64 @@ async function checkVipByEmailFromPayjsapi(
password: string,
userId?: string
): Promise<PayjsVipEmailResult | null> {
try {
const apiUrl = resolvePayApiUrl(request);
const res = await fetch(`${apiUrl}/nomadvip/check_vip_by_email`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email,
password,
...(userId ? { user_id: userId } : {}),
}),
cache: "no-store",
signal: AbortSignal.timeout(PAYJS_CHECK_BY_EMAIL_TIMEOUT),
});
if (!res.ok) {
return null;
}
const payConfig = getPaymentConfig();
const primaryUrl = resolvePayApiUrl(request);
const candidates = Array.from(
new Set([primaryUrl, payConfig.apiUrl].map((x) => (x || "").trim().replace(/\/$/, "")).filter(Boolean))
);
const data = await res.json().catch(() => ({}));
if (!data?.vip) {
return {
vip: false,
error:
typeof data?.error === "string" && data.error.trim()
? data.error.trim()
: undefined,
};
}
for (const apiUrl of candidates) {
for (let i = 0; i <= PAYJS_CHECK_BY_EMAIL_RETRIES; i += 1) {
try {
const res = await fetch(`${apiUrl}/nomadvip/check_vip_by_email`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email,
password,
...(userId ? { user_id: userId } : {}),
}),
cache: "no-store",
signal: AbortSignal.timeout(PAYJS_CHECK_BY_EMAIL_TIMEOUT),
});
if (!res.ok) {
continue;
}
return {
vip: true,
effectiveUserId:
typeof data?.effectiveUserId === "string"
? data.effectiveUserId.trim()
: undefined,
anonymousUserId:
typeof data?.anonymousUserId === "string"
? data.anonymousUserId.trim()
: undefined,
token: typeof data?.token === "string" ? data.token : undefined,
record: data?.record?.id ? data.record : undefined,
};
} catch (error) {
console.log("[check-by-email] payjsapi request failed:", error);
return null;
const data = await res.json().catch(() => ({}));
if (!data?.vip) {
return {
vip: false,
error:
typeof data?.error === "string" && data.error.trim()
? data.error.trim()
: undefined,
};
}
return {
vip: true,
effectiveUserId:
typeof data?.effectiveUserId === "string"
? data.effectiveUserId.trim()
: undefined,
anonymousUserId:
typeof data?.anonymousUserId === "string"
? data.anonymousUserId.trim()
: undefined,
token: typeof data?.token === "string" ? data.token : undefined,
record: data?.record?.id ? data.record : undefined,
};
} catch (error) {
if (i >= PAYJS_CHECK_BY_EMAIL_RETRIES) {
console.log("[check-by-email] payjsapi request failed url=%s error=%o", apiUrl, error);
} else {
await new Promise((resolve) => setTimeout(resolve, 250 * (i + 1)));
}
}
}
}
return null;
}
async function loginPocketBaseUser(

View File

@@ -31,10 +31,15 @@ export interface MinioConfig {
}
export function getPocketBaseConfig(): PocketBaseConfig {
const serverSide = typeof window === "undefined";
const internal = process.env.POCKETBASE_INTERNAL_URL?.trim();
if (serverSide && internal) {
return { url: internal.replace(/\/$/, "") };
}
return {
url:
process.env.NEXT_PUBLIC_POCKETBASE_URL ||
process.env.POCKETBASE_URL ||
process.env.NEXT_PUBLIC_POCKETBASE_URL ||
"https://pocketbase.hackrobot.cn",
};
}