's'
This commit is contained in:
@@ -15,6 +15,12 @@ function escapeAttr(s: string): string {
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
function buildErrorHtml(errorMsg: string): string {
|
||||
const esc = (s: string) =>
|
||||
s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c] || c);
|
||||
return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>支付失败</title><style>body{font-family:system-ui;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#f0f4f8;}h2{color:#dc2626;margin-bottom:12px;}p{color:#64748b;margin-bottom:20px;text-align:center;padding:0 20px;}a{color:#2563eb;text-decoration:none;font-weight:500;}a:hover{text-decoration:underline;}</style></head><body><h2>支付发起失败</h2><p>${esc(errorMsg)}</p><p><a href="/">返回首页重试</a></p></body></html>`;
|
||||
}
|
||||
|
||||
function buildPayHtml(
|
||||
payUrl: string,
|
||||
params: Record<string, unknown>,
|
||||
@@ -31,8 +37,9 @@ function buildPayHtml(
|
||||
.map(([k, v]) => `<input type="hidden" name="${escapeAttr(k)}" value="${escapeAttr(v)}" />`)
|
||||
.join("\n");
|
||||
const direct = options?.directToCashier;
|
||||
// 微信内:显示加载提示,避免 visibility:hidden 导致部分 WebView 表单提交异常
|
||||
return direct
|
||||
? `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>支付</title><style>body{margin:0;overflow:hidden;visibility:hidden}</style></head><body><form id="f" action="${escapeAttr(payUrl)}" method="POST" enctype="application/x-www-form-urlencoded">${inputs}</form><script>document.getElementById("f").submit()</script></body></html>`
|
||||
? `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>支付</title><style>body{font-family:system-ui;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0;background:#f0f4f8;}p{color:#64748b;}</style></head><body><p>正在跳转至微信支付...</p><form id="f" action="${escapeAttr(payUrl)}" method="POST" enctype="application/x-www-form-urlencoded">${inputs}</form><script>document.getElementById("f").submit()</script></body></html>`
|
||||
: `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -120,6 +127,12 @@ export async function POST(request: NextRequest) {
|
||||
const device = String(body?.device || "pc");
|
||||
|
||||
if (!user_id) {
|
||||
if (wantHtml) {
|
||||
return new NextResponse(buildErrorHtml("缺少 user_id"), {
|
||||
status: 400,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
return NextResponse.json({ ok: false, error: "缺少 user_id" }, { status: 400 });
|
||||
}
|
||||
|
||||
@@ -152,6 +165,12 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
|
||||
if (!params || Object.keys(params).length === 0) {
|
||||
if (wantHtml) {
|
||||
return new NextResponse(buildErrorHtml("支付参数为空"), {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
return NextResponse.json({ ok: false, error: "支付参数为空" }, { status: 500 });
|
||||
}
|
||||
|
||||
@@ -262,13 +281,24 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
if (redirectRes.status === 400 || redirectRes.status === 500) {
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: resData?.detail || resData?.msg || "支付跳转失败" },
|
||||
{ status: redirectRes.status }
|
||||
);
|
||||
const errMsg = resData?.detail || resData?.msg || "支付跳转失败";
|
||||
if (wantHtml) {
|
||||
return new NextResponse(buildErrorHtml(errMsg), {
|
||||
status: redirectRes.status,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
return NextResponse.json({ ok: false, error: errMsg }, { status: redirectRes.status });
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: false, error: "支付创建失败" }, { status: 500 });
|
||||
const createFailMsg = "支付创建失败";
|
||||
if (wantHtml) {
|
||||
return new NextResponse(buildErrorHtml(createFailMsg), {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
return NextResponse.json({ ok: false, error: createFailMsg }, { status: 500 });
|
||||
} catch (e) {
|
||||
const err = e instanceof Error ? e : new Error(String(e));
|
||||
const msg = err.message || "";
|
||||
@@ -279,6 +309,15 @@ export async function POST(request: NextRequest) {
|
||||
? "请求超时"
|
||||
: msg;
|
||||
console.error("Pay API error:", err);
|
||||
return NextResponse.json({ ok: false, error: `支付请求失败: ${hint}` }, { status: 500 });
|
||||
const errorMsg = `支付请求失败: ${hint}`;
|
||||
const ct = request.headers.get("content-type") || "";
|
||||
const isForm = ct.includes("form") || ct.includes("x-www-form-urlencoded");
|
||||
if (isForm) {
|
||||
return new NextResponse(buildErrorHtml(errorMsg), {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "text/html; charset=utf-8" },
|
||||
});
|
||||
}
|
||||
return NextResponse.json({ ok: false, error: errorMsg }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user