116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { getApiUrlFromRequest, getPaymentConfig } from "@/config/services.config";
|
|
import {
|
|
findAnonymousUserIdForUser,
|
|
findLinkedMemberFromOrder,
|
|
findVipEmailLinkByAnonymousUserId,
|
|
findVipEmailLinkByUserId,
|
|
getAdminToken,
|
|
isAnonymousUserId,
|
|
upsertVipEmailLink,
|
|
} from "@/app/api/vip/_helpers";
|
|
|
|
function resolvePayApiUrl(request: NextRequest): string {
|
|
const payConfig = getPaymentConfig();
|
|
const hostHeader = request.headers.get("host") || request.headers.get("x-forwarded-host");
|
|
return (
|
|
(hostHeader ? getApiUrlFromRequest(hostHeader) : null) ||
|
|
payConfig.apiUrl
|
|
).replace(/\/$/, "");
|
|
}
|
|
|
|
async function getLinkedEmailFromPayjsapi(
|
|
request: NextRequest,
|
|
userId: string
|
|
): Promise<string | null> {
|
|
try {
|
|
const apiUrl = resolvePayApiUrl(request);
|
|
const res = await fetch(
|
|
`${apiUrl}/nomadvip/check_vip?user_id=${encodeURIComponent(userId)}`,
|
|
{ cache: "no-store", signal: AbortSignal.timeout(5000) }
|
|
);
|
|
if (!res.ok) {
|
|
return null;
|
|
}
|
|
|
|
const data = await res.json().catch(() => ({}));
|
|
const email =
|
|
typeof data?.email === "string" ? data.email.trim().toLowerCase() : "";
|
|
return data?.vip && email ? email : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const userId = request.nextUrl.searchParams.get("user_id")?.trim() || "";
|
|
if (!userId) {
|
|
return NextResponse.json(
|
|
{ email: null, error: "缺少 user_id" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
try {
|
|
const adminToken = await getAdminToken();
|
|
if (!adminToken) {
|
|
return NextResponse.json({ email: null }, { status: 500 });
|
|
}
|
|
|
|
const linkRecord = isAnonymousUserId(userId)
|
|
? await findVipEmailLinkByAnonymousUserId(adminToken, userId)
|
|
: await findVipEmailLinkByUserId(adminToken, userId);
|
|
const linkedEmail =
|
|
typeof linkRecord?.email === "string"
|
|
? linkRecord.email.trim().toLowerCase()
|
|
: "";
|
|
const anonymousUserId =
|
|
typeof linkRecord?.anonymous_user_id === "string" &&
|
|
isAnonymousUserId(linkRecord.anonymous_user_id.trim())
|
|
? linkRecord.anonymous_user_id.trim()
|
|
: !isAnonymousUserId(userId)
|
|
? await findAnonymousUserIdForUser(adminToken, userId)
|
|
: isAnonymousUserId(userId)
|
|
? userId
|
|
: null;
|
|
if (linkedEmail) {
|
|
return NextResponse.json({
|
|
email: linkedEmail,
|
|
anonymousUserId,
|
|
});
|
|
}
|
|
|
|
if (isAnonymousUserId(userId)) {
|
|
const linkedMember = await findLinkedMemberFromOrder(adminToken, userId);
|
|
if (linkedMember) {
|
|
await upsertVipEmailLink(
|
|
adminToken,
|
|
linkedMember.email,
|
|
linkedMember.userId,
|
|
userId
|
|
);
|
|
return NextResponse.json({
|
|
email: linkedMember.email,
|
|
anonymousUserId: userId,
|
|
});
|
|
}
|
|
}
|
|
|
|
const payjsEmail = await getLinkedEmailFromPayjsapi(request, userId);
|
|
if (payjsEmail) {
|
|
if (anonymousUserId && !isAnonymousUserId(userId)) {
|
|
await upsertVipEmailLink(adminToken, payjsEmail, userId, anonymousUserId);
|
|
}
|
|
return NextResponse.json({
|
|
email: payjsEmail,
|
|
anonymousUserId: anonymousUserId ?? (isAnonymousUserId(userId) ? userId : null),
|
|
});
|
|
}
|
|
|
|
return NextResponse.json({ email: null, anonymousUserId: anonymousUserId ?? null });
|
|
} catch (error) {
|
|
console.error("[linked-email] failed:", error);
|
|
return NextResponse.json({ email: null, anonymousUserId: null }, { status: 500 });
|
|
}
|
|
}
|