如何在Next.js 13应用中集成Stripe预构建结账表单
Next.js 13 集成 Stripe 预构建结账表单完整步骤
1. 安装依赖
直接用包管理器安装所需依赖:
npm install stripe @stripe/stripe-js # 或 yarn add stripe @stripe/stripe-js # 或 pnpm add stripe @stripe/stripe-js
2. 配置环境变量
在项目根目录创建 .env.local 文件,添加以下内容(替换为你自己的 Stripe 密钥和项目地址):
STRIPE_SECRET_KEY=sk_test_你的Stripe秘钥 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_你的Stripe公钥 NEXT_PUBLIC_APP_URL=http://localhost:3000
3. 创建后端结账会话 API
在 app/api/checkout/route.ts 中编写 API 路由,用于生成 Stripe 结账会话:
import { NextResponse } from 'next/server'; import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-06-20', // 使用最新的API版本 }); export async function POST(request: Request) { try { const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [ { price: 'price_你的Stripe价格ID', // 替换为你在Stripe后台创建的价格ID quantity: 1, }, ], mode: 'payment', success_url: `${process.env.NEXT_PUBLIC_APP_URL}/success`, cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/cancel`, }); return NextResponse.json({ sessionId: session.id }); } catch (error) { return NextResponse.json( { error: (error as Error).message }, { status: 500 } ); } }
4. 前端实现结账按钮
在需要添加结账功能的页面(比如 app/checkout/page.tsx)中,编写触发结账的组件:
'use client'; import { loadStripe } from '@stripe/stripe-js'; import { useState } from 'react'; const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!); export default function CheckoutPage() { const [isLoading, setIsLoading] = useState(false); const handleCheckout = async () => { setIsLoading(true); try { const stripe = await stripePromise; if (!stripe) throw new Error('Stripe初始化失败'); // 调用后端API获取会话ID const response = await fetch('/api/checkout', { method: 'POST' }); const data = await response.json(); if (!response.ok) throw new Error(data.error); // 跳转到Stripe预构建结账页面 const result = await stripe.redirectToCheckout({ sessionId: data.sessionId, }); if (result.error) throw new Error(result.error.message); } catch (error) { alert(`结账失败: ${(error as Error).message}`); } finally { setIsLoading(false); } }; return ( <div className="flex items-center justify-center h-screen"> <button onClick={handleCheckout} disabled={isLoading} className="px-6 py-3 bg-blue-600 text-white rounded hover:bg-blue-700" > {isLoading ? '处理中...' : '立即支付'} </button> </div> ); }
5. (可选)配置Webhook处理支付结果
如果需要在支付完成后执行业务逻辑(比如更新订单状态),创建 app/api/webhook/route.ts:
import { NextResponse } from 'next/server'; import Stripe from 'stripe'; import { headers } from 'next/headers'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-06-20', }); // 禁用默认的body解析,需要读取原始请求体 export const config = { api: { bodyParser: false, }, }; export async function POST(request: Request) { const body = await request.text(); const signature = headers().get('stripe-signature')!; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!; // 从Stripe控制台获取Webhook密钥 let event: Stripe.Event; try { event = stripe.webhooks.constructEvent(body, signature, webhookSecret); } catch (error) { return NextResponse.json({ error: '签名验证失败' }, { status: 400 }); } // 根据事件类型处理逻辑 switch (event.type) { case 'checkout.session.completed': const session = event.data.object as Stripe.Checkout.Session; // 这里添加你的业务逻辑,比如保存订单到数据库 console.log('支付成功,会话ID:', session.id); break; default: console.log(`未处理的事件类型: ${event.type}`); } return NextResponse.json({ received: true }); }
注意事项
- 确保在Stripe控制台正确配置Webhook端点(测试环境用
http://localhost:3000/api/webhook,生产环境用你的域名),并获取Webhook密钥添加到.env.local中 - 测试支付可以使用Stripe提供的测试卡号:
4242 4242 4242 4242,有效期随便填未来日期,CVV随便填3位数字 - 部署时要确保环境变量正确配置,且
NEXT_PUBLIC_APP_URL设置为生产环境域名
内容的提问来源于stack exchange,提问作者Ahmed Nadeem
相关产品推荐
相关产品推荐

