Stripe + Next.js 终极指南(2026 版)
抱歉,我目前看不到要翻译的正文内容。请您把需要翻译的文本(除代码块和 URL 之外的部分)粘贴在这里,我会按照要求将其翻译成简体中文并保留原有的格式。
1. 2026 生命周期:嵌入式 vs. 托管
Stripe 现在大力推广 Embedded Checkout。与旧的重定向不同,它使用 iframe 或一个 web 组件,直接嵌入在你的 Next.js 页面 内部,使用户停留在你的域名上,同时将所有 PCI 合规性工作交给 Stripe。
2. 现代项目设置
我们将使用 App Router 和最新的 Stripe SDK 初始化一个 Next.js 项目。
npx create-next-app@latest my-store-2026 --typescript --tailwind --app
cd my-store-2026
npm install stripe @stripe/stripe-js @stripe/react-stripe-js
3. 安全的环境变量
切勿泄露你的 STRIPE_SECRET_KEY。在 2026 年,Next.js 环境变量受到严格约束。
# .env.local
STRIPE_SECRET_KEY="sk_test_51..."
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_51..."
STRIPE_WEBHOOK_SECRET="whsec_..."
4. 服务器操作模式
在 2026 文档中,Server Actions 已成为创建 Checkout Sessions 的标准方式。这消除了对 /api/checkout 文件夹的需求。
创建 src/app/actions/stripe.ts:
"use server";
import { stripe } from "@/lib/stripe";
import { headers } from "next/headers";
export async function createCheckoutSession(priceId: string) {
const origin = (await headers()).get("origin");
const session = await stripe.checkout.sessions.create({
ui_mode: "embedded", // Enables the 2026 Embedded UI
line_items: [{ price: priceId, quantity: 1 }],
mode: "subscription",
return_url: `${origin}/return?session_id={CHECKOUT_SESSION_ID}`,
});
return { clientSecret: session.client_secret };
}
5. 实现嵌入式结账
@stripe/react-stripe-js 中的 EmbeddedCheckout 组件提供了无重定向的无缝体验。
Create src/components/CheckoutForm.tsx:
"use client";
import { loadStripe } from "@stripe/stripe-js";
import {
EmbeddedCheckoutProvider,
EmbeddedCheckout,
} from "@stripe/react-stripe-js";
import { createCheckoutSession } from "@/app/actions/stripe";
const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
export default function CheckoutForm({
priceId,
}: {
priceId: string;
}) {
// Fetch the clientSecret via the Server Action
const fetchClientSecret = async () => {
const { clientSecret } = await createCheckoutSession(priceId);
return clientSecret as string;
};
return (
);
}
6. 关键:2026 年 Webhook 处理程序
即使使用 Server Actions,仍然需要 Route Handlers 来处理 Webhook,因为 Stripe 需要一个静态 URL 在支付成功时进行 “ping”。
创建 src/app/api/webhook/route.ts:
import { stripe } from "@/lib/stripe";
import { headers } from "next/headers";
export async function POST(req: Request) {
const body = await req.text();
const signature = (await headers()).get("stripe-signature")!;
let event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err: any) {
return new Response(`Webhook Error: ${err.message}`, { status: 400 });
}
// Handle the event
if (event.type === "checkout.session.completed") {
const session = event.data.object;
// 2026 Practice: Trigger a background sync or email service
console.log(`💰 Payment confirmed for ${session.id}`);
}
return new Response(null, { status: 200 });
}
2026 Stripe 文档新功能
- Link 认证元素: 自动检测用户是否拥有 “Link” 账户(Stripe 的一键结账),并预填其信息,可将转化率提升最高 10%。
- 自适应定价: 现在在 Checkout Sessions 中原生支持——Stripe 会根据用户的 IP 自动显示当地货币的价格。
- 增强的税号收集: 现在可以直接在会话创建时切换
tax_id_collection: { enabled: true },以在全球 B2B 税务合规中省去额外逻辑。 - 专业提示: 本地测试时使用 Stripe CLI。运行
stripe listen --forward-to localhost:3000/api/webhook即可在本机模拟成功支付。