This commit is contained in:
eric
2026-03-13 05:14:28 -05:00
parent f66859c032
commit 8a095f7d45
13 changed files with 820 additions and 132 deletions

View File

@@ -1,6 +1,13 @@
import { NextRequest, NextResponse } from "next/server";
import { getPocketBaseConfig, getPaymentConfig, SITE_ID } from "@/config/services.config";
import {
getApiUrlFromRequest,
getPocketBaseConfig,
getPaymentConfig,
SITE_ID,
} from "@/config/services.config";
import { getAdminToken } from "@/app/lib/pocketbase/admin";
import { queryXorPayOrderStatus } from "@/app/lib/payment/xorpayStatus";
import { queryZPayOrderStatus } from "@/app/lib/payment/zpayStatus";
const DEFAULT_PASSWORD = "12345678";
@@ -26,27 +33,44 @@ function decodePendingEmail(userId: string): string | null {
}
}
async function queryZpayPaid(orderId: string): Promise<boolean> {
async function verifyOrderPaid(request: NextRequest, orderId: string): Promise<boolean> {
const config = getPaymentConfig();
if (!config.apiUrl) {
console.error("queryZpayPaid: PAYMENT_API_URL not configured");
return false;
}
const hostHeader =
request.headers.get("host") || request.headers.get("x-forwarded-host");
const apiUrl = (
getApiUrlFromRequest(hostHeader) ||
process.env.PAYMENT_API_URL ||
config.apiUrl
).replace(/\/$/, "");
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
const url = `${config.apiUrl}/cnomadcna/zpay_order_status?out_trade_no=${encodeURIComponent(orderId)}`;
const res = await fetch(url, { cache: "no-store", signal: controller.signal })
.finally(() => clearTimeout(timeout));
const timeout = setTimeout(() => controller.abort(), 3000);
const url = `${apiUrl}/cnomadcna/order_status?order_id=${encodeURIComponent(orderId)}`;
console.log(`complete-order: check payjsapi order_id=${orderId} url=${url}`);
const res = await fetch(url, { cache: "no-store", signal: controller.signal }).finally(() =>
clearTimeout(timeout)
);
const data = await res.json().catch(() => ({}));
if (!data?.paid) {
console.warn(`queryZpayPaid: not paid yet, order_id=${orderId}, response=`, JSON.stringify(data));
if (data?.paid) {
console.log(`complete-order: payjsapi paid order_id=${orderId}`);
return true;
}
return !!data?.paid;
} catch (e) {
console.error(`queryZpayPaid: fetch error, order_id=${orderId}`, e);
return false;
console.error(`complete-order: payjsapi fetch error order_id=${orderId}`, e);
}
const xorpay = await queryXorPayOrderStatus(orderId, 5000);
console.log(
`complete-order: xorpay fallback order_id=${orderId} paid=${!!xorpay?.paid} status=${xorpay?.status || ""} error=${xorpay?.error || ""}`
);
if (xorpay?.paid) return true;
const zpay = await queryZPayOrderStatus(orderId, 5000);
console.log(
`complete-order: zpay fallback order_id=${orderId} paid=${!!zpay?.paid} status=${zpay?.status || ""} error=${zpay?.error || ""}`
);
return !!zpay?.paid;
}
async function ensureSiteVip(
@@ -145,8 +169,8 @@ export async function POST(request: NextRequest) {
// 2. 没找到 → 查 ZPAY 确认是否已支付,已支付则直接创建 site_vip
if (!found) {
const zpayPaid = await queryZpayPaid(orderId);
if (!zpayPaid) {
const paid = await verifyOrderPaid(request, orderId);
if (!paid) {
console.error(`complete-order: ZPAY 未确认支付 order_id=${orderId}`);
return NextResponse.json({ ok: false, error: "订单不存在或未支付成功" }, { status: 400 });
}