添加next-intl后调用Stripe现有接口返回404求助
可能的原因及解决方案
1. API路由误用客户端hooks导致加载失败
你提到仅修改了success_url和failure_url,如果在修改时错误地在checkout/route.ts中使用了客户端专属hooks(比如useLocale),会导致服务器端加载该文件失败,Next.js无法注册这个API路由,从而返回404。
解决方法:
在API路由中用服务器端方法获取locale,比如next-intl/server提供的getLocale:
// checkout/route.ts import { getLocale } from 'next-intl/server'; import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); export async function POST(request: Request) { // 服务器端安全获取locale const locale = await getLocale(); const { products } = await request.json(); const session = await stripe.checkout.sessions.create({ success_url: `${process.env.NEXT_PUBLIC_APP_URL}/${locale}/success?session_id={CHECKOUT_SESSION_ID}`, failure_url: `${process.env.NEXT_PUBLIC_APP_URL}/${locale}/failure`, line_items: products.map((product: any) => ({ price: product.priceId, quantity: product.quantity })), mode: 'payment' }); return Response.json({ url: session.url }); }
2. Middleware未排除API路径,请求被错误重写
如果你的middleware.ts没有排除/api开头的路径,next-intl会把API请求也重写成带语言前缀的路径(比如/en/api/checkout),但你的实际API路由在/api/checkout,因此返回404。
解决方法:
修改middleware.ts的匹配规则,跳过API、静态资源和Next.js内部路径:
// middleware.ts import createMiddleware from 'next-intl/middleware'; export default createMiddleware({ locales: ['en', 'zh'], // 替换为你的语言列表 defaultLocale: 'en' }); export const config = { // 仅处理页面路由,排除非页面路径 matcher: ['/((?!api|_next|.*\\..*).*)'] };
3. API路由文件存在语法错误
如果checkout/route.ts有语法问题(比如字符串拼接错误、缺失括号、导入错误),会导致Next.js无法正确加载该路由,返回404。
解决方法:
查看终端的服务器日志,检查是否有checkout/route.ts相关的报错,修复对应的语法问题。
4. 前端fetch路径的隐性错误(低概率)
如果订单页位于带语言前缀的路由下(比如/en/checkout),若fetch使用了不带开头/的相对路径(如fetch("api/checkout")),会请求/en/api/checkout导致404。不过你的代码用了/api/checkout绝对路径,这种情况概率较低,但仍需确认请求的实际路径(可在浏览器开发者工具的网络面板查看)。
解决方法:
确保fetch使用绝对路径,并添加Content-Type头:
const checkout = async () => { await fetch("/api/checkout", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ products: cart }), }) .then((response) => { if (!response.ok) throw new Error(response.statusText); return response.json(); }) .then((response) => { if (response.url) window.location.href = response.url; }) .catch(err => console.error("结账请求失败:", err)); };
内容的提问来源于stack exchange,提问作者user24573276

