使用 Stripe Elements 和 Checkout Sessions 在您的网站上构建一个结账页面,这是一种可管理税费、折扣、运费等内容的集成方式。
仅当您的任一钱包绑定了有效的卡时,演示中才会显示 Google Pay 或 Apple Pay。
在开始之前,您需要注册 一个 Stripe 账户。
用官方 Stripe 库从您的应用程序访问 API。
npm install stripe@18.0.0 --save
将 SDK 设置为至少使用 2025-03-31. basil
API 版本。
import Stripe from 'stripe' ;
const stripe = new Stripe ( 'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
, {
apiVersion : '2025-03-31.basil' as any ,
} ) ;
在服务器上添加一个终结点,用于创建 Checkout Session 并将其客户端私钥 返回到前端。Checkout Session 表示您的客户在进行一次性付款或订阅时的会话。Checkout Sessions 创建后 24 小时过期。
import express , { Express } from 'express' ;
const app : Express = express ( ) ;
app . post ( '/create-checkout-session' , async ( req : Express . Request , res : Express . Response ) => {
const session = await stripe . checkout . sessions . create ( {
line_items : [
{
price_data : {
currency : 'usd' ,
product_data : {
name : 'T-shirt' ,
} ,
unit_amount : 2000 ,
} ,
quantity : 1 ,
} ,
] ,
mode : 'payment' ,
ui_mode : 'custom' ,
return_url : 'https://example.com/return?session_id={CHECKOUT_SESSION_ID} '
} ) ;
res . json ( { checkoutSessionClientSecret : session . client_secret } ) ;
} ) ;
app . listen ( 3000 , ( ) => {
console . log ( 'Running on port 3000' ) ;
} ) ;
在您的结账页面包含 Stripe.js 脚本,方法是将其添加到您的 HTML 文件的 head
。一定直接从 js.stripe.com 加载 Stripe.js,以保持 PCI 合规。请勿将脚本包含在捆绑包中,也不要自己托管其副本。
您需要通过包含以下脚本标签 <script src="https://js. stripe. com/basil/stripe. js"></script>
将 Stripe.js 从 v3 更新为 basil
。了解有关 Stripe.js 版本控制 的更多信息。
初始化 stripe.js。
const stripe = Stripe (
'pk_test_TYooMQauvdEDq54NiTphI7jx'
,
) ;
创建一个 fetchClientSecret
函数。此函数从您的服务器检索客户端密钥,并返回一个解析为客户端密钥的 Promise 对象。调用 initCheckout ,传入fetchClientSecret
。initCheckout
返回一个解析为checkout 实例的 Promise。
结账 对象作为您的结账页面的基础,包含来自结账会话的数据和更新会话的方法。
checkout.session() 返回的对象包含您的价格信息。建议在您的 UI 中读取并显示会话中的 total
和 lineItems
。
这样,您只需最少量的代码修改即可开启新功能。例如,添加手动货币价格 ,如果显示 total
,则不需要更改 UI。
const fetchClientSecret = ( ) => {
return fetch ( '/create-checkout-session' , { method : 'POST' } )
. then ( ( response ) => response . json ( ) )
. then ( ( json ) => json . checkoutSessionClientSecret ) ;
} ;
stripe . initCheckout ( { fetchClientSecret } )
. then ( ( checkout ) => {
const checkoutContainer = document . getElementById ( 'checkout-container' ) ;
checkoutContainer . append ( JSON . stringify ( checkout . lineItems , null , 2 ) ) ;
checkoutContainer . append ( document . createElement ( 'br' ) ) ;
checkoutContainer . append ( ` Total: ${ checkout . session ( ) . total . total . amount } ` ) ;
} ) ;
< div id = "checkout-container" > </ div >
创建电子邮件输入以收集客户的电子邮件地址。当客户完成输入来验证并保存电子邮件地址时,调用 updateEmail 。
根据您的结账表单的设计,可通过以下方式调用 updateEmail
:
在提交付款 之前。也可以调用 updateEmail
来提前验证,例如模糊输入。 在转到下一步之前,例如点击保存 按钮(如果您的表单包含多个步骤)。 < input type = "text" id = "email" />
< div id = "email-errors" > </ div >
stripe . initCheckout ( { fetchClientSecret } ) . then ( ( checkout ) => {
const emailInput = document . getElementById ( 'email' ) ;
const emailErrors = document . getElementById ( 'email-errors' ) ;
emailInput . addEventListener ( 'input' , ( ) => {
emailErrors . textContent = '' ;
} ) ;
emailInput . addEventListener ( 'blur' , ( ) => {
const newEmail = emailInput . value ;
checkout . updateEmail ( newEmail ) . then ( ( result ) => {
if ( result . error ) {
emailErrors . textContent = result . error . message ;
}
} ) ;
} ) ;
} ) ;
用 Payment Element 在客户端收集支付信息。Payment Element 是一个预构建的 UI 组件,它简化了多种支付方式的收集支付详情的流程。
渲染一个支付 按钮,该按钮调用 confirm 从 checkout 实例提交付款。
< button id = "pay-button" > Pay </ button >
< div id = "confirm-errors" > </ div >
stripe . initCheckout ( { fetchClientSecret } ) . then ( ( checkout ) => {
const button = document . getElementById ( 'pay-button' ) ;
const errors = document . getElementById ( 'confirm-errors' ) ;
button . addEventListener ( 'click' , ( ) => {
errors . textContent = '' ;
checkout . confirm ( ) . then ( ( result ) => {
if ( result . type === 'error' ) {
errors . textContent = result . error . message ;
}
} ) ;
} ) ;
} ) ;
导航到您的结账页面。 使用下表中的支付方式填写付款详情。对于银行卡付款:输入一个任意的未来日期作为有效期。 输入 3 位数 CVC 码。 输入账单地址邮编。 将付款提交至 Stripe。 前往管理平台,在交易页面 上查找支付。如果您支付成功,就会在列表中看到它。 点击您的付款,查看更多详情,例如账单信息及已购商品列表。您可以此信息来履行订单 。 卡号 场景 如何测试 4242 4242 4242 4242 该卡付款成功,不需要验证。 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 4000 0025 0000 3155 该卡付款时需要验证 。 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 4000 0000 0000 9995 该卡被拒绝,显示拒付代码,例如 insufficient_ funds
。 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 6205 5000 0000 0000 004 银联卡的长度为 13-19 位。 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。
有关测试您的集成的更多信息,请参阅测试 部分。
创建 Checkout Session 之前,您可以预先创建产品 和价格 。用“产品”表示不同的实物商品或服务等级,用“价格” 表示每个产品的定价。
例如,您可以创建一个价格为 20 美元的 T 恤产品。这样即可在不更新相关产品详情的情况下更改和添加价格。使用 Stripe 管理平台或 API 均可创建产品和价格。详细了解产品和价格的运作原理 。
API 仅要求有一个 name
即可创建 Product 。Checkout 中显示您提供的产品的 name
、description
和 images
。
curl https://api.stripe.com/v1/products \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
-d name = T-shirt
然后,创建一个 Price ,定义产品的价格。这包括产品的费用及使用的币种。
curl https://api.stripe.com/v1/prices \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
-d product = \
-d unit_amount = 2000 \
-d currency = usd
创建的每个价格都会有一个 ID。创建 Checkout Session 时,要引用价格 ID 和数量。如果您以多币种销售,则将您的 Price 设置为多币种 。Checkout 自动确定客户的本地货币 ,在 Price 支持时呈现该货币。
curl https://api.stripe.com/v1/checkout/sessions \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
-d ui_mode = custom \
-d mode = payment \
-d "line_items[0][price]" = {{PRICE_ID}} \
-d "line_items[0][quantity]" = 1 \
- -data -urlencode return_url = " https://example.com/return?session_id={CHECKOUT_SESSION_ID} "
如果您已经收集了客户的邮件地址并且想在 Checkout Session 中给他们预先填写,则创建 Checkout Session 时传递 customer_email 。
curl https://api.stripe.com/v1/checkout/sessions \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
- -data -urlencode customer_email = "customer@example.com" \
-d ui_mode = custom \
-d mode = payment \
-d "line_items[0][price]" = {{PRICE_ID}} \
-d "line_items[0][quantity]" = 1 \
- -data -urlencode return_url = " https://example.com/return?session_id={CHECKOUT_SESSION_ID} "
侦听 Checkout Session 的变化 您可以通过用 checkout.on 在 change
事件上添加事件监听器来侦听 Checkout Session 的变化。
checkout = await stripe . initCheckout ( {
fetchClientSecret : ( ) => promise ,
elementsOptions : { appearance } ,
} ) ;
checkout . on ( 'change' , ( session ) => {
} ) ;
收集账单地址 默认情况下,Checkout Session 通过 Payment Element 收集付款所需的最少账单信息。
使用 Billing Address Element 您可以使用 Billing Address Element 来收集完整的账单地址。
首先,创建 Checkout Session 时传递 billing_address_collection=required 。
创建一个容器 DOM 元素来挂载 Billing Address Element。然后使用 checkout.createBillingAddressElement 创建 Billing Address Element 的实例,并通过调用 element.mount 挂载它,提供 CSS 选择器或容器 DOM 元素。
< div id = "billing-address" > </ div >
const billingAddressElement = checkout . createBillingAddressElement ( ) ;
billingAddressElement . mount ( '#billing-address' ) ;
Billing Address Element 支持以下选项:
使用自定义表单 您可以构建自己的表单来收集账单地址。
收集部分账单地址 要收集部分账单地址,例如仅国家/地区和邮编,请传递 billing_address_collection=auto 。
收集部分账单地址时,必须手动收集地址 。默认情况下,Payment Element 会自动收集付款所需的最少账单信息。为避免重复收集账单详情,请在创建 Payment Element 时传递 fields.billingDetails=never 。如果您只打算收集一部分账单详情(例如客户姓名),则只为您打算自己收集的字段传递 never
。
收集收货地址 要收集客户的收货地址,请在创建 Checkout Session 时传递 shipping_address_collection 参数。
收集收货地址时,还必须指定允许发货至的国家/地区。用两字母 ISO 国家/地区代码 组成的数组配置 allowed_countries 属性。
如何使用 Shipping Address Element 您可以用 Shipping Address Element 收集完整的收货地址。
创建一个容器 DOM 元素来挂载 Shipping Address Element。然后使用 checkout.createShippingAddressElement 创建 Shipping Address Element 的实例,并通过调用 element.mount 挂载它,提供 CSS 选择器或容器 DOM 元素。
< div id = "shipping-address" > </ div >
const shippingAddressElement = checkout . createShippingAddressElement ( ) ;
shippingAddressElement . mount ( '#shipping-address' ) ;
Shipping Address Element 支持以下选项:
侦听 Checkout Session 的变化 您可以通过添加事件侦听器来处理与地址相关的更改,从而侦听 Checkout Session 的更改。
使用 Session 对象 在结账表单中呈现运费金额。
< div >
< h3 > Totals </ h3 >
< div id = "subtotal" > </ div >
< div id = "shipping" > </ div >
< div id = "total" > </ div >
</ div >
stripe . initCheckout ( { clientSecret } ) . then ( ( checkout ) => {
const subtotal = document . getElementById ( 'subtotal' ) ;
const shipping = document . getElementById ( 'shipping' ) ;
const total = document . getElementById ( 'total' ) ;
checkout . on ( 'change' , ( session ) => {
subtotal . textContent = ` Subtotal: ${ session . total . subtotal . amount } ` ;
shipping . textContent = ` Shipping: ${ session . total . shippingRate . amount } ` ;
total . textContent = ` Total: ${ session . total . total . amount } ` ;
} )
} )
使用自定义表单 您可以构建自己的表单来收集收货地址。
可选 单独授权和捕获 Stripe 支持银行卡两步验证付款,因此您可以先对银行卡进行授权,然后稍后再捕获。当 Stripe 授权付款时,发卡行为客户卡上的资金提供担保并冻结客户卡上的付款金额。然后您会有一定的时间来捕获资金,具体取决于银行卡 )。如果您在授权过期之前不捕获付款,则付款会被取消,并且发卡行释放扣留的资金。
如果在确认客户能够支付与向其收款这两项操作之间还需要其他操作,则将授权与捕获分离开来是非常有帮助的。例如,如果您销售的产品库存有限,则需要确认客户用 Checkout 购买的商品仍然有货,然后才能捕获他们的付款并履行订单。通过以下流程实现:
确认 Stripe 已授权客户的支付方式。 查阅库存管理系统,确认那件商品是否有货。 更新您的库存管理系统,指示客户未购买那件商品。 捕获客户的付款。 在确认页面通知客户他们是否购买成功。 要表明您想单独授权和捕获,必须在创建 Checkout Session 时将 payment_intent_data.capture_method 的值设置为 manual
。这样可指示 Stripe 仅授权客户银行卡上的金额。
curl https://api.stripe.com/v1/checkout/sessions \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
-d "line_items[0][price]" = {{PRICE_ID}} \
-d "line_items[0][quantity]" = 1 \
-d mode = payment \
-d "payment_intent_data[capture_method]" = manual \
-d return_url = {{RETURN_URL}} \
-d ui_mode = custom
要捕获一笔未捕获的付款,可以用管理平台 ,也可以用 capture 端点。程序化地捕获付款必须访问 Checkout Session 过程中创建的 PaymentIntent,它可从 Session 对象获取。
通过向您的客户门户 分享链接,让您的客户管理 他们自己的账户。客户门户允许客户用他们的电子邮件地址登录,以管理订阅、更新支付方式等。
另见