如何在NextJS+CommerceJS+Stripe电商站添加Bancontact支付?
实现Bancontact支付方案及PaymentIntents的作用
一、PaymentIntents是实现Bancontact的正确方式
Bancontact属于异步支付方式,需要用户跳转至银行页面完成授权,后续通过回调通知支付结果,这种场景必须依赖Stripe的Payment Intents API来跟踪支付状态,无法用原代码中直接创建PaymentMethod的即时支付逻辑实现。
二、代码修改及关键步骤
1. 前端切换为Payment Element(推荐)
Payment Element会自动适配展示Bancontact和银行卡选项,无需单独维护不同支付组件,替换原有CardElement:
import { loadStripe } from "@stripe/stripe-js"; import { Elements, PaymentElement, ElementsConsumer } from "@stripe/react-stripe-js"; import { Stripe, StripeElements } from "@stripe/stripe-js/types/stripe-js"; import { useCheckout } from "@/context/checkout"; const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY as string); export const PaymentSection: React.FC = () => { const { token, shippingData, handleCaptureCheckout } = useCheckout(); // 配置Elements,指定支付方式和订单信息 const elementsOptions = { mode: "payment", amount: token?.total.raw || 0, currency: "eur", // Bancontact仅支持欧元 paymentMethodTypes: ["card", "bancontact"], }; const handleSubmit = async ( event: React.FormEvent<HTMLFormElement>, elements: StripeElements | null, stripe: Stripe | null ) => { event.preventDefault(); if (!stripe || !elements || !token || !shippingData) return; // 调用confirmPayment处理支付流程,Bancontact会自动跳转至银行页面 const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}/order-confirmation`, }, }); if (error) { console.error("支付失败:", error.message); return; } // 这里需要先从后端获取PaymentIntent的client_secret const orderData = { line_items: token.line_items, customer: { firstname: shippingData.customer.firstname, lastname: shippingData.customer.lastname, email: shippingData.customer.email, }, shipping: { name: shippingData.shipping.name, street: shippingData.shipping.street, town_city: shippingData.shipping.town_city, county_state: shippingData.shipping.county_state, postal_zip_code: shippingData.shipping.postal_zip_code, country: shippingData.shipping.country, }, fulfillment: { shipping_method: "fadfda" }, payment: { gateway: "stripe", stripe: { client_secret: "从后端接口获取的PaymentIntent client_secret", }, }, }; handleCaptureCheckout(token.id, orderData); }; return ( <section className="w-full h-screen flex justify-center items-center"> <Elements stripe={stripePromise} options={elementsOptions}> <ElementsConsumer> {({ elements, stripe }) => ( <form onSubmit={(e) => handleSubmit(e, elements, stripe)} className="w-full" > <PaymentElement /> <br /> <br /> <div style={{ display: "flex", justifyContent: "space-between" }}> <button type="submit" disabled={!stripe} color="primary"> Pay </button> </div> </form> )} </ElementsConsumer> </Elements> </section> ); };
2. 后端核心逻辑(不可缺少)
Bancontact的异步特性要求后端处理PaymentIntent创建和支付结果回调:
- 接收前端传来的CommerceJS checkout token,获取订单金额和货币
- 调用Stripe SDK创建PaymentIntent,参数包含
amount、currency: "eur"、payment_method_types: ["bancontact", "card"] - 将PaymentIntent的
client_secret返回给前端 - 配置Stripe webhook监听
payment_intent.succeeded事件,触发时调用CommerceJS的checkout.capture完成订单
3. 注意事项
- Bancontact仅支持欧元,需确保订单货币为EUR
- 必须配置Stripe webhook,否则无法捕获用户跳转后完成的支付
- 原代码中直接传入
payment_method_id的逻辑仅适用于银行卡,Bancontact需要依赖PaymentIntent的client_secret
内容的提问来源于stack exchange,提问作者Milosz_p
相关产品推荐
相关产品推荐

