's'
This commit is contained in:
@@ -35,6 +35,8 @@ type RecoveryResult = {
|
||||
source?: string;
|
||||
};
|
||||
|
||||
const inflightEmailChecks = new Map<string, Promise<PayjsVipEmailResult | null>>();
|
||||
|
||||
const PAYJS_CHECK_BY_EMAIL_TIMEOUT =
|
||||
Number(process.env.PAYJSAPI_CHECK_BY_EMAIL_TIMEOUT) || 20000;
|
||||
const PAYJS_CHECK_BY_EMAIL_RETRIES =
|
||||
@@ -62,6 +64,13 @@ async function checkVipByEmailFromPayjsapi(
|
||||
password: string,
|
||||
userId?: string
|
||||
): Promise<PayjsVipEmailResult | null> {
|
||||
const inflightKey = `${email}::${userId || ""}`;
|
||||
const existed = inflightEmailChecks.get(inflightKey);
|
||||
if (existed) {
|
||||
return existed;
|
||||
}
|
||||
|
||||
const task = (async () => {
|
||||
const payConfig = getPaymentConfig();
|
||||
const primaryUrl = resolvePayApiUrl(request);
|
||||
const localUrl = getLocalPayApiUrl();
|
||||
@@ -125,6 +134,14 @@ async function checkVipByEmailFromPayjsapi(
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
|
||||
inflightEmailChecks.set(inflightKey, task);
|
||||
try {
|
||||
return await task;
|
||||
} finally {
|
||||
inflightEmailChecks.delete(inflightKey);
|
||||
}
|
||||
}
|
||||
|
||||
async function loginPocketBaseUser(
|
||||
|
||||
@@ -15,6 +15,8 @@ type PayjsVipResult = {
|
||||
email?: string;
|
||||
};
|
||||
|
||||
const inflightUserChecks = new Map<string, Promise<PayjsVipResult | null>>();
|
||||
|
||||
async function fetchPayjsVipWithRetry(
|
||||
url: string,
|
||||
timeoutMs: number,
|
||||
@@ -51,6 +53,12 @@ async function checkVipFromPayjsapi(
|
||||
request: NextRequest,
|
||||
userId: string
|
||||
): Promise<PayjsVipResult | null> {
|
||||
const existed = inflightUserChecks.get(userId);
|
||||
if (existed) {
|
||||
return existed;
|
||||
}
|
||||
|
||||
const task = (async () => {
|
||||
try {
|
||||
const apiUrl = resolvePayApiUrl(request);
|
||||
const url = `${apiUrl}/nomadvip/check_vip?user_id=${encodeURIComponent(
|
||||
@@ -95,6 +103,14 @@ async function checkVipFromPayjsapi(
|
||||
);
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
inflightUserChecks.set(userId, task);
|
||||
try {
|
||||
return await task;
|
||||
} finally {
|
||||
inflightUserChecks.delete(userId);
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
|
||||
@@ -15,6 +15,8 @@ const ANONYMOUS_USER_COOKIE = "nomadvip_anon_uid";
|
||||
const ANONYMOUS_USER_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
||||
const PAY_ORDER_COOKIE = "nomadvip_pay_order";
|
||||
const PAY_ORDER_MAX_AGE = 60 * 15;
|
||||
const EMAIL_VERIFY_TS_KEY = "emailVerifyAt";
|
||||
const EMAIL_VERIFY_COOLDOWN_MS = 60 * 1000;
|
||||
|
||||
function getStorage(key: string): string | null {
|
||||
if (typeof window === "undefined") return null;
|
||||
@@ -174,6 +176,7 @@ export default function Home() {
|
||||
savePaidType("vip");
|
||||
setUserEmail(normalizedEmail);
|
||||
saveUserName(normalizedEmail);
|
||||
setStorage(EMAIL_VERIFY_TS_KEY, String(Date.now()));
|
||||
return true;
|
||||
},
|
||||
[savePaidType, saveUserName]
|
||||
@@ -485,7 +488,10 @@ export default function Home() {
|
||||
// 校验逻辑:有本地存储(登录资料+VIP)时优先使用并校验;无身份/VIP 时点击按钮直接进入支付,不校验
|
||||
const anonymousCandidate = getStoredAnonymousUserId();
|
||||
const hadStoredUserId = !!anonymousCandidate;
|
||||
if (anonymousCandidate) {
|
||||
const emailVerifiedAt = Number(getStorage(EMAIL_VERIFY_TS_KEY) || "0");
|
||||
const skipAnonymousRecover =
|
||||
!!(getStorage("emailLinked") === "1" && Date.now() - emailVerifiedAt < EMAIL_VERIFY_COOLDOWN_MS);
|
||||
if (anonymousCandidate && !skipAnonymousRecover) {
|
||||
const recovered = await tryRecoverByAnonymousUserId(anonymousCandidate);
|
||||
if (recovered) {
|
||||
setStorage("userId", anonymousCandidate);
|
||||
|
||||
Reference in New Issue
Block a user