Next.js 13集成Stripe收款:如何获取/计算多币种交易手续费?
获取Stripe交易手续费的解决方案
核心原因
前端通过stripe.confirmCardPayment返回的结果不包含手续费信息——手续费属于后端敏感数据,必须通过Stripe后端API或Webhook获取。
方案一:支付成功后后端查询Payment Intent详情
1. 新增后端接口获取Payment Intent详情
在app/api/get-payment-intent/route.ts创建新接口:
import { NextResponse, NextRequest } from "next/server"; import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { typescript: true, apiVersion: "2023-08-16", }); export async function POST(req: NextRequest) { const { paymentIntentId } = await req.json(); try { const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId); // 提取手续费(转换为实际币种单位,Stripe返回的是最小单位如分) const fee = paymentIntent.charges.data[0]?.fee; return NextResponse.json({ fee: fee ? fee / 100 : null, currency: paymentIntent.currency, amountReceived: paymentIntent.amount_received / 100 }, { status: 200 }); } catch (error: any) { return NextResponse.json({ error: error.message }, { status: 400 }); } }
2. 修改前端支付成功逻辑
在onSubmit函数的成功分支中调用新接口,获取并存储手续费:
// ...原有代码 } else { // 获取Payment Intent ID const paymentIntentId = result.paymentIntent.id; // 调用后端接口获取手续费 const feeRes = await axios.post("/api/get-payment-intent", { paymentIntentId: paymentIntentId }); const { fee, currency } = feeRes.data; const data = { campaign, transactionRecord: result, fee: fee, feeCurrency: currency }; PaymentService.saveTransactionRecord(data).then((res) => { console.log("res: ", res); setIsSubmitting(false); setPaymentStatus(`Payment succeeded! Fee: ${fee} ${currency}`); setShowAlert(true); setAlertMessage(`Payment succeeded! Fee: ${fee} ${currency}`); setAlertType("success"); setTimeout(() => { router.push("/dashboard/campaigns"); }, 1000); }); } // ...
方案二:使用Stripe Webhook(推荐)
Webhook是Stripe主动通知后端交易状态变更的方式,可靠性更高,避免前端请求延迟或失败:
1. 创建Webhook接口
在app/api/stripe-webhook/route.ts新增:
import { NextResponse, NextRequest } from "next/server"; import Stripe from "stripe"; import { buffer } from "node:stream/consumers"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { typescript: true, apiVersion: "2023-08-16", }); export async function POST(req: NextRequest) { const buf = await buffer(req.body); const sig = req.headers.get("stripe-signature")!; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!; let event; try { event = stripe.webhooks.constructEvent(buf, sig, webhookSecret); } catch (err: any) { return NextResponse.json({ error: `Webhook Error: ${err.message}` }, { status: 400 }); } // 监听支付成功事件 if (event.type === "payment_intent.succeeded") { const paymentIntent = event.data.object as Stripe.PaymentIntent; const fee = paymentIntent.charges.data[0]?.fee; if (fee) { // 将手续费存储到你的数据库,关联对应交易记录 await PaymentService.updateTransactionFee({ paymentIntentId: paymentIntent.id, fee: fee / 100, currency: paymentIntent.currency }); } } return NextResponse.json({ received: true }, { status: 200 }); }
2. 配置Stripe后台
在Stripe后台Webhooks设置中,添加端点https://你的域名/api/stripe-webhook,订阅payment_intent.succeeded事件,将生成的Webhook Secret添加到环境变量STRIPE_WEBHOOK_SECRET。
关键说明
- Stripe返回的手续费为最小货币单位(如欧元分、美元分),需除以100转换为实际金额。
- 手续费由Stripe根据你的账户费率、交易币种、支付方式自动计算,可通过Stripe后台的费用工具估算。
- 多币种交易的手续费会以对应交易币种返回,无需额外转换。
内容的提问来源于stack exchange,提问作者ammar
相关产品推荐
相关产品推荐

