# 在不付款的情况下保存客户的支付方式 了解如何保存支付方式并稍后收款。 # Checkout Sessions API > This is a Checkout Sessions API for when payment-ui is embedded-components. View the full page at https://docs.stripe.com/payments/save-and-reuse?payment-ui=embedded-components. [Checkout Sessions API 在`设置`模式](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode)下可让您保存客户的支付详情,而无需初始付款。如果您想现在吸纳客户,为他们设置付款流程,并在将来(客户离线时)使用 Payment Intents API 向他们收款,此功能会非常有用。 您可以使用此集成设置经常性付款或创建一次性付款,稍后再确定最终金额(通常在客户收到您的服务后)。 > #### 线下刷卡交易 > > 线下刷卡交易,如[通过 Stripe Terminal 收取银行卡信息](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md),使用不同的流程来保存支付方式。 ## 合规 在保存客户的支付详情时,您需要负责遵守所有适用的法律、法规和卡组织规则。如果您想要保存客户的支付方式以供将来使用,则通常会适用于这些要求,例如在结账流程中向他们显示客户的支付方式以供将来购物使用,或者在他们不主动使用您的网站或应用程序时向他们扣款。在您的网站或应用程序中添加条款,说明您计划如何保存支付方式的详细信息,并允许客户选择加入。 当您保存支付方式时,仅能将其用于您在条款中明确规定的特定用途。若要在客户离线时向其支付方式扣款,并将其保存为未来购买的可选方式,请务必事先明确获取客户对此特定用途的同意。例如,可添加一个“保存我的支付方式以便未来使用”的复选框来征得客户同意。 要在客户离线时向客户收款,请确保您的条款包括以下内容: - 客户同意您代其对指定的交易发起一次或一系列付款。 - 付款的预期时间和频率(例如,款项是用于定期分期付款、订阅付款,还是不定期充值)。 - 如何确定付款金额。 - 若该支付方式用于订阅服务,需包含您的取消政策。 请务必保留客户书面同意这些条款的记录。 > 如果您需要使用服务器端手动确认,或者您的集成应用需要单独展示支付方式,请参阅我们的[替代指南](https://docs.stripe.com/payments/save-and-reuse-cards-only.md)。 ## 设置 Stripe [服务器端] 首先,[创建 Stripe 账户](https://dashboard.stripe.com/register)或[登录](https://dashboard.stripe.com/login)。 用我们的官方库从您的应用程序访问 Stripe API: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## 创建客户 [服务器端] 要为未来支付设置支付方式,必须将其附加到代表客户的对象上。当客户创建账户或与您的企业进行首次交易时,通过 Accounts v2 API 创建客户配置的[账户](https://docs.stripe.com/api/v2/core/accounts/create.md)对象,或通过客户 API 创建[客户](https://docs.stripe.com/api/customers/create.md)对象。 > #### 使用 Accounts v2 API 表示客户 > > Accounts v2 API 通常面向 Connect 用户开放,并对其他 Stripe 用户开放公开预览。如果您参与了 Accounts v2 预览,您需要在代码中[指定预览版本](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning)。 > > 如需申请 Accounts v2 预览版的访问权限, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 ```curl curl -X POST https://api.stripe.com/v2/core/accounts \ -H "Authorization: Bearer <>" \ -H "Stripe-Version: 2026-04-22.preview" ``` #### Customers v1 ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## 使用设置模式 [服务器端] 使用 [mode=setup](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) 创建 Checkout Session。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=setup \ -d ui_mode=elements \ -d currency=usd ``` ## 将支付方式关联到客户 [服务器端] 如果您没有使用现有客户创建 Checkout Session,请使用*PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs)的 ID,将支付方式[关联](https://docs.stripe.com/api/payment_methods/attach.md)到客户账户。 否则,支付方式会自动关联到您在创建 Checkout Session 时提供的客户。 #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}}/attach \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" ``` ## 检索支付方式 [服务器端] 客户成功完成 Checkout Session 后,处理 [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) Webhook。在 Webhook 中检索 Session 对象,然后执行以下操作: - 获取[setup_intent](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-setup_intent) 键的值,即 Checkout Session 期间创建的 SetupIntent ID。 - 使用 SetupIntent ID[检索](https://docs.stripe.com/api/setup_intents/retrieve.md) SetupIntent 对象。返回的对象包含一个[payment_method](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-payment_method) ID,您可以在下一步将其关联到客户账户。 了解有关[设置 Webhook 的更多信息](https://docs.stripe.com/webhooks.md)。 ## 以后对保存的支付方式扣款 [服务器端] 将 PaymentMethod 关联到客户账户后,您可以使用 [PaymentIntent](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method) 进行*离线* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information) 付款: - 请将 [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) 设为 `Account` ID,或将 [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer) 设为 `Customer` ID;同时将 [payment_method](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method) 设为 `PaymentMethod` ID。 - 将 [off_session](https://docs.stripe.com/api/payment_intents/confirm.md#confirm_payment_intent-off_session) 设置为 `true`,表示客户在尝试支付期间不在您的结账流程中,无法履行由合作伙伴(如发卡行、银行或其他支付机构)提出的身份验证请求。如果在您的结账流程中,合作伙伴请求身份验证,Stripe 会使用之前*会话内* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method) 交易中的客户信息请求豁免。如果不符合豁免条件,PaymentIntent 可能会导致错误。 - 将 PaymentIntent 的 [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) 属性值设置为 `true`,这会导致在创建 PaymentIntent 时立即进行确认。 #### Accounts v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method={{PAYMENTMETHOD_ID}}" \ -d off_session=true \ -d confirm=true ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method={{PAYMENTMETHOD_ID}}" \ -d off_session=true \ -d confirm=true ``` 若支付尝试失败,请求也会失败并返回 402 HTTP 状态码,且 PaymentIntent 状态会变为 *requires\_payment\_method* (This status appears as "requires_source" in API versions before 2019-02-11)。请通知客户返回您的应用程序(例如,通过发送电子邮件或应用内通知),并引导客户进入新的 Checkout Session 以选择其他支付方式。 #### Accounts v2 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "line_items[0][price_data][currency]=usd" \ -d "line_items[0][price_data][product_data][name]=T-shirt" \ -d "line_items[0][price_data][unit_amount]=1099" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=elements \ --data-urlencode "return_url=https://example.com/return" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "line_items[0][price_data][currency]=usd" \ -d "line_items[0][price_data][product_data][name]=T-shirt" \ -d "line_items[0][price_data][unit_amount]=1099" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=elements \ --data-urlencode "return_url=https://example.com/return" ``` # Setup Intents API > This is a Setup Intents API for when payment-ui is elements. View the full page at https://docs.stripe.com/payments/save-and-reuse?payment-ui=elements. [Setup Intents API](https://docs.stripe.com/api/setup_intents.md) 允许您在不先付款的情况下保存客户的支付信息。如果您想先让客户入驻,设置他们的支付方式,然后将来对他们扣款(甚至离线时),那么这样做就非常有用。 可以用此集成设置经常性付款或创建一次性付款,稍后再确定最终金额(通常在客户收到您的服务后)。 > #### 有卡交易 > > 有卡交易(例如通过 Stripe Terminal 收集银行卡详情)使用不同的流程来保存支付方式。有关详情,请查看 [Terminal 文档](https://docs.stripe.com/terminal/features/saving-payment-details/save-directly.md)。 ## 合规 保存客户的支付详情时,您有责任遵守所有适用的法律、法规和卡组织规则。如果您想保存客户的支付方式供未来使用,例如在未来购买的结账流程中向客户显示其支付方式或在客户未主动使用您的网站或应用时向其收费,这些要求通常适用。在您的网站或应用中添加条款,说明您计划如何保存支付方式详细信息并允许客户选择加入。 当您保存支付方式时,仅能将其用于您在条款中明确规定的特定用途。若要在客户离线时向其支付方式扣款,并将其保存为未来购买的可选方式,请务必事先明确获取客户对此特定用途的同意。例如,可添加一个“保存我的支付方式以便未来使用”的复选框来征得客户同意。 要在客户离线时向其收费,请确保您的条款包括以下内容: - 客户同意您代其对指定的交易发起一次或一系列付款。 - 预期的付款时间和频率(例如,收款是计划的分期付款、订阅付款还是计划外充值)。 - 如何确定付款金额。 - 如果支付方式是用于支付订阅服务,那即同意您的取消政策。 请务必让客户书面同意这些条款并做好记录。 > 如果您需要采用手动服务器端确认方式,或者您的集成需要单独提供支付方式,请参阅我们的[替代指南](https://docs.stripe.com/payments/save-and-reuse-cards-only.md)。 ## 设置 Stripe [服务器端] 首先,[创建 Stripe 账户](https://dashboard.stripe.com/register)或[登录](https://dashboard.stripe.com/login)。 用我们的官方库从您的应用程序访问 Stripe API: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## 启用支付方式 查看您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods),启用您想支持的支付方式。您至少需要启用一个支付方式才能在下一步中创建 *SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method)。 默认情况下,Stripe 支持信用卡和其他常见的支付方式,可以帮助您获得更多客户,但建议您开启与您的业务和客户相关的其他支付方式。查看[支付方式支持](https://docs.stripe.com/payments/payment-methods/payment-method-support.md),了解支持的产品和支付方式,并查看我们的[定价页面](https://stripe.com/pricing/local-payment-methods)了解费用。 ## 创建一个 Customer [服务器端] 要为未来支付设置支付方式,必须将其附加到代表客户的对象上。当客户创建账户或与您的企业进行首次交易时,通过 Accounts v2 API 创建客户配置的[账户](https://docs.stripe.com/api/v2/core/accounts/create.md)对象,或通过客户 API 创建[客户](https://docs.stripe.com/api/customers/create.md)对象。 > #### 使用 Accounts v2 API 表示客户 > > Accounts v2 API 通常面向 Connect 用户开放,并对其他 Stripe 用户开放公开预览。如果您参与了 Accounts v2 预览,您需要在代码中[指定预览版本](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning)。 > > 如需申请 Accounts v2 预览版的访问权限, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` ## 创建 SetupIntent [服务器端] > 如果您想在不先创建 SetupIntent 的情况下呈现 Payment Element,请参阅[收集支付详情后再创建 Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=setup)。 [SetupIntent](https://docs.stripe.com/api/setup_intents.md) 是一个对象,表示您为将来的付款设置客户支付方式的意图。在结账过程中显示给客户的支付方式也包含在 `SetupIntent` 中。您可以让 Stripe 自动从您的管理平台设置中拉取支付方式,或者手动列出。 除非您的集成在提供支付方式时需要有代码选项,否则 Stripe 推荐使用自动选项。这是因为 Stripe 会评估货币、支付方式限制及其他参数,来确定支持的支付方式列表。如果某些支付方式会提高转化率且与货币和客户位置最相关,这些支付方式会排在最前面。排序靠后的支付方式隐藏在溢出菜单下方。 #### 从管理平台管理支付方式 某些支付方式无法保存以供将来使用,并且客户在设置未来支付时不会看到这些支付方式作为选项。有关管理支付方式的更多详细信息,请参阅[支付方式集成选项](https://docs.stripe.com/payments/payment-methods/integration-options.md)。 您可以选择在启用 `automatic_payment_methods` 的情况下创建 SetupIntent,并利用您在管理平台中配置的支付方式来创建 SetupIntent。可以选择性指定 `automatic_payment_methods` 参数,因为 Stripe 会在最新版 API 中默认开启其功能。 您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。 #### Accounts v2 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "automatic_payment_methods[enabled]=true" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d "automatic_payment_methods[enabled]=true" ``` #### 手动列出支付方式 用您想支持的一系列[支付方式](https://docs.stripe.com/payments/payment-methods/integration-options.md)在您的服务器上创建一个 SetupIntent。 #### Accounts v2 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method_types[]=bancontact" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=ideal" ``` #### Customers v1 ```curl curl https://api.stripe.com/v1/setup_intents \ -u "<>:" \ -d customer={{CUSTOMER_ID}} \ -d "payment_method_types[]=bancontact" \ -d "payment_method_types[]=card" \ -d "payment_method_types[]=ideal" ``` ### 检索客户端私钥 SetupIntent 中包含的是一个*客户端私钥* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)),用于在客户端安全地完成支付流程。有不同的方法可以将客户端私钥传递到客户端。 #### 单页应用 使用浏览器的 `fetch` 功能,从您的服务器上的端点获取客户端私钥。如果您的客户端是单页应用,特别是用现代的前端框架(例如 React)搭建的情况,则该方法最为合适。创建服务于客户端私钥的服务器端点: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the SetupIntent {client_secret: intent.client_secret}.to_json end ``` 然后在客户端用 JavaScript 获取客户端私钥: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### 服务端呈现 从服务器将客户端私钥传递到客户端。如果在将静态内容发送到浏览器之前,您的应用程序会在服务器上生成静态内容,则此种方法最有效。 在您的结账表单中添加 [client_secret](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret)。在您的服务器代码中,从 SetupIntent 检索客户端密钥: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the SetupIntent erb :checkout end ``` > #### 使用 Radar > > 默认情况下,在不先付款的情况下保存客户的支付方式时,[Radar](https://docs.stripe.com/radar.md) 不会对 SetupIntent 执行操作。如果想默认激活,可前往 [Radar 设置](https://dashboard.stripe.com/settings/radar),然后启用**对保存以供将来使用的支付方式使用 Radar**。 ## 收集付款详情 [客户端] 您已经可以用 [Payment Element](https://docs.stripe.com/payments/payment-element.md) 收集付款详情了。Payment Element 是一个预构建的 UI 组件,它简化了很多种支付方式的付款详情收集工作。 Payment Element 中包含一个 iframe,它通过一个 HTTPS 连接安全地将支付信息发送到 Stripe。结账页面上的地址也必须以 `https://` 开头,不能是 `http://`,否则您的集成无法工作。您不这样做也可以测试您的集成,但在您准备好接受真实付款时记得[启用 HTTPS](https://docs.stripe.com/security/guide.md#tls)。 #### HTML + JS ### 设置 Stripe.js Payment Element 自动可以获取,这是 Stripe.js 的功能。在您的结账页面包含 Stripe.js 脚本,方法是将它添加到您的 HTML 文件的 `head` 部分。为保持 PCI 合规,始终从 js.stripe.com 加载 Stripe.js。不要把脚本打包或自行保留副本。 ```html Checkout ``` 用下面的 JavaScript 在您的结账页面创建一个 Stripe 实例: ```javascript // Set your publishable key: remember to change this to your live publishable key in production // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe('<>'); ``` ### 将 Payment Element 添加到您的支付设置页面 Payment Element 需要存在于您的支付设置页面的某个地方。用您的支付表单中的唯一 ID 创建一个空的 DOM 节点(容器): ```html
``` 加载之前的表单后,创建一个 Payment Element 实例,并将它放入容器的 DOM 节点。创建 [Elements](https://docs.stripe.com/js/elements_object/create) 实例时,将来自上一步的[客户端私钥](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret)传递到 `options`: ```javascript const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements using the SetupIntent's client secretconst elements = stripe.elements(options); // Create and mount the Payment Element const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element'); ``` Payment Element 呈现一个动态表单,您的客户可在这里选择一个支付方式。对于每个支付方式,表单会自动请求客户填写必要的支付详情。 ### 自定义外观 在创建 `elements` 实例时,将 [appearance 对象](https://docs.stripe.com/js/elements_object/create#stripe_elements-options-appearance)传入 `options`,自定义 Payment Element,使其与网站设计相匹配。Stripe Elements 是一套可直接使用的用户界面组件集合。如需进一步自定义表单或收集其他客户信息,请查阅 [Elements 文档](https://docs.stripe.com/payments/elements.md)。 ### 申请 Apple Pay 商家令牌 如果您接受 Apple Pay 付款,建议配置 `applePay` [选项](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-applePay),以修改 Apple Pay 界面中的显示内容。通过这样做,Apple Pay 的[商家令牌](https://docs.stripe.com/apple-pay/merchant-tokens.md?pay-element=web-pe)将被使用。下面的示例显示的是 2030 年 1 月 5 日开始的付款配置。该信息将反映在 Apple Pay 界面中。 ```javascript const paymentElement = elements.create('payment', { applePay: { deferredPaymentRequest: { paymentDescription: 'My deferred payment', managementURL: 'https://example.com/billing', deferredBilling: { amount: 2500, label: 'Deferred Fee', deferredPaymentDate: new Date('2030-01-05') }, } }, // Other options }); ``` #### React ### 设置 Stripe.js 从 npm 公共注册处安装 [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) 和 [Stripe.js 加载器](https://www.npmjs.com/package/@stripe/stripe-js): ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` ### 向您的支付设置页面添加并配置 Elements 提供程序 要使用 Payment Element 组件,请将您的支付设置页面组件包装在 [Elements 提供程序](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider)中。用您的公钥调用 `loadStripe`,然后将返回的 `Promise` 传递给 `Elements` 提供程序。同时将上一步获得的[客户端私钥](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret) 以 `options` 形式传递给 `Elements` 提供程序。 ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import SetupForm from './SetupForm'; // Make sure to call `loadStripe` outside of a component's render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('<>'); function App() { const options = { // passing the SetupIntent's client secret clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` ### 添加 Payment Element 组件 用 `PaymentElement` 组件构建您的表单。 ```jsx import React from 'react'; import {PaymentElement} from '@stripe/react-stripe-js'; const SetupForm = () => { return (
); }; export default SetupForm; ``` Stripe Elements 是嵌入式 UI 组件的集合。要进一步定制您的表单,或收集其他客户信息,请浏览 [Element 文档](https://docs.stripe.com/payments/elements.md)。 Payment Element 呈现一个动态表单,您的客户可在这里选择一个支付方式。对于每个支付方式,表单会自动请求客户填写必要的支付详情。 ### 自定义外观 自定义 Payment Element,使其匹配您的网站设计风格,方法是在创建 `Elements` 提供程序时向 `options` 传递[外观对象](https://docs.stripe.com/js/elements_object/create#stripe_elements-options-appearance)。 ### 申请 Apple Pay 商家令牌 如果您接受 Apple Pay 付款,建议配置 `applePay` [选项](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-applePay),以修改 Apple Pay 界面中的显示内容。通过这样做,Apple Pay 的[商家令牌](https://docs.stripe.com/apple-pay/merchant-tokens.md?pay-element=web-pe)将被使用。下面的示例显示的是 2030 年 1 月 5 日开始的付款配置。该信息将反映在 Apple Pay 界面中。 ```jsx import React from 'react'; import {PaymentElement} from '@stripe/react-stripe-js'; const SetupForm = () => { const options = { applePay: { deferredPaymentRequest: { paymentDescription: 'My deferred payment', managementURL: 'https://example.com/billing', deferredBilling: { amount: 2500, label: 'Deferred Fee', deferredPaymentDate: new Date('2030-01-05') }, } }, // Other options }; return (
); }; export default SetupForm; ``` ### 配置货币 将 SetupIntents 与 [automatic_payment_methods](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-automatic_payment_methods) 一起使用时,您可以在[创建 Payment Element](https://docs.stripe.com/js/elements_object/create#stripe_elements-options-currency) 时指定货币。Payment Element 呈现已启用的支持所提供货币的支付方式。有关更多详细信息,请参阅 [Payment Element 文档](https://docs.stripe.com/payments/payment-methods/integration-options.md)。 ### 收集地址 默认情况下,Payment Element 只收集必要的账单地址详情。某些行为,如[计算税费](https://docs.stripe.com/api/tax/calculations/create.md) 或输入配送详情,则需要客户的完整地址。您可以: - 使用[Address Element](https://docs.stripe.com/elements/address-element.md),利用自动填充和本地化功能收集客户的完整地址。这有助于确保税款计算达到最高准确性。 - 使用您自己的自定义表单收集地址详情。 ## Optional: Link in your checkout page [客户端] 通过在 [Payment Element](https://docs.stripe.com/payments/payment-element.md) 中使用 [Link](https://docs.stripe.com/payments/link.md),让您的客户结账更快捷。您可以为任何已登录并使用 Link 的客户自动填写信息,无论他们最初是在其他商家的 Link 中保存的信息。默认的 Payment Element 集成在卡片表单中包含了 Link 提示。要管理 Payment Element 中的 Link,请前往您的 [支付方式设置](https://dashboard.stripe.com/settings/payment_methods)。 ![Authenticate or enroll with Link directly in the Payment Element during checkout](https://b.stripecdn.com/docs-statics-srv/assets/link-in-pe.2efb5138a4708b781b8a913ebddd9aba.png) 收集客户邮箱地址,用于 Link 身份验证或注册 ### 集成选项 您可以通过两种方式将 Link 与 Payment Element 集成。其中,Stripe 建议在可用的情况下将客户邮箱地址传递给 Payment Element。在决定使用哪种方案时,请务必考虑您的结账流程: | 集成选项 | 结账流程 | 描述 | | ------------------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | | 向 Payment Element 传递客户电子邮件地址 (Recommended) | - 您的客户在登入结账页面前先输入他们的电子邮件地址(例如,在之前的账户创建步骤)。 - 您偏向于使用自己的电子邮件输入栏。 | 通过编程方式将客户邮箱地址传递给 Payment Element。在此情境下,客户直接在支付表单中(而非通过单独的用户界面组件)进行 Link 身份验证。 | | 在 Payment Element 中收集客户电子邮件地址 | - 您的客户可以在结账时选择直接在 Payment Element 中输入邮箱地址,并进行 Link 的身份验证或注册。 - 无须修改代码。 | 如果客户尚未注册 Link,并在 Payment Element 中选择了一种支持的支付方式,系统会提示他们使用 Link 保存其支付详情。对于已注册的客户,Link 会自动填写其支付信息。 | 使用[defaultValues](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options-defaultValues) 将客户电子邮件地址传递给 Payment Element。 ```javascript const paymentElement = elements.create('payment', { defaultValues: { billingDetails: { email: 'foo@bar.com', } }, // Other options }); ``` 如需了解更多信息,请阅读如何[构建包含 Link 的自定义结账页面](https://docs.stripe.com/payments/link/add-link-elements-integration.md)。 ## Optional: 保存并检索客户支付方式 您可以配置 Payment Element 来保存客户的支付方式以备将来使用。本部分向您展示如何集成[保存的支付方式功能](https://docs.stripe.com/payments/save-customer-payment-methods.md),从而让 Payment Element: - 提示买家同意保存支付方式 - 买家同意时,存储支付方式 - 向买家显示已存储的支付方式,以方便日后购物使用 - 买家更换时[自动更新丢失或过期的银行卡](https://docs.stripe.com/payments/cards/overview.md#automatic-card-updates) ![Payment Element 和保存的支付方式复选框](https://b.stripecdn.com/docs-statics-srv/assets/spm-save.fe0b24afd0f0a06e0cf4eecb0ce2403a.png) 保存支付方式 ![已选择保存了支付方式的 Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/spm-saved.5dba5a8a190a9a0e9f1a99271bed3f4b.png) 复用以前保存的支付方式。 ### 允许在 Payment Element 中保存支付方式 在服务端创建 [CustomerSession](https://docs.stripe.com/api/customer_sessions/.md) 时:提供客户 ID(`Customer` 对象使用 `customer`,客户配置型 `Account` 对象使用 `customer_account`),并为会话启用 [payment_element](https://docs.stripe.com/api/customer_sessions/object.md#customer_session_object-components-payment_element) 组件。配置需要启用的已保存支付方式[功能](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features)。例如,启用 [payment_method_save](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features-payment_method_save) 后,页面将展示勾选框,允许客户保存支付信息,用于后续付款。 您可在 PaymentIntent 或 Checkout Session 中指定 `setup_future_usage`,以此覆盖保存支付方式的默认行为。这一配置会自动保存支付方式供后续使用,即便客户未主动选择保存。若您已指定 `setup_future_usage`,请勿在同一笔支付交易中同时配置 `payment_method_save_usage`,否则会引发集成错误。 > #### 使用 Accounts v2 API 表示客户 > > Accounts v2 API 通常面向 Connect 用户开放,并对其他 Stripe 用户开放公开预览。如果您参与了 Accounts v2 预览,您需要在代码中[指定预览版本](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning)。 > > 如需申请 Accounts v2 预览版的访问权限, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent-and-customer-session' do intent = client.v1.setup_intents.create({ automatic_payment_methods: {enabled: true}, customer_account: {{CUSTOMER_ACCOUNT_ID}}, }) customer_session = client.v1.customer_sessions.create({ customer_account: {{CUSTOMER_ACCOUNT_ID}}, components: { payment_element: { enabled: true, features: { payment_method_redisplay: 'enabled', payment_method_save: 'enabled', payment_method_save_usage: 'off_session', payment_method_remove: 'enabled', }, }, }, }) { client_secret: intent.client_secret, customer_session_client_secret: customer_session.client_secret }.to_json end ``` #### Customers v1 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') post '/create-intent-and-customer-session' do intent = client.v1.setup_intents.create({ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. automatic_payment_methods: {enabled: true}, customer: {{CUSTOMER_ID}}, }) customer_session = client.v1.customer_sessions.create({ customer: {{CUSTOMER_ID}}, components: { payment_element: { enabled: true, features: { payment_method_redisplay: 'enabled', payment_method_save: 'enabled', payment_method_save_usage: 'off_session', payment_method_remove: 'enabled', }, }, }, }) { client_secret: intent.client_secret, customer_session_client_secret: customer_session.client_secret }.to_json end ``` 您的 Element 实例使用 CustomerSession 的*客户端私钥* (A client secret is used with your publishable key to authenticate a request for a single object. Each client secret is unique to the object it's associated with)来访问该客户保存的支付方式。创建 CustomerSession 时正确[处理错误](https://docs.stripe.com/error-handling.md)。如果发生错误,您不需要向 Element 实例提供 CustomerSession 客户端私钥,因为它是可选的。 使用SetupIntent 和 CustomerSession 的客户端私钥创建 Element 实例。然后,用这个 Element 实例创建一个 Payment Element。 ```javascript // Create the CustomerSession and obtain its clientSecret const res = await fetch("/create-intent-and-customer-session", { method: "POST" }); const { customer_session_client_secret: customerSessionClientSecret } = await res.json(); const elementsOptions = { clientSecret: '{{CLIENT_SECRET}}',customerSessionClientSecret, // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret // and CustomerSession's client secret obtained in a previous step const elements = stripe.elements(elementsOptions); // Create and mount the Payment Element const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element'); ``` 确认 SetupIntent 时,Stripe.js 会自动控制 PaymentMethod 上的 [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) 设置,具体取决于客户是否勾选保存其付款详情的框。 ### 检测选择的已保存支付方式 要在选择了保存的支付方式时控制动态内容,请侦听 Payment Element `change` 事件(该事件会填充上所选的支付方式)。 ```javascript paymentElement.on('change', function(event) { if (event.value.payment_method) { // Control dynamic content if a saved payment method is selected } }) ``` ## 向 Stripe 提交支付详情 [客户端] 使用 Payment Element 收集的详情,用 [stripe.confirmSetup](https://docs.stripe.com/js/setup_intents/confirm_setup) 完成设置。为该函数提供一个 [return_url](https://docs.stripe.com/api/setup_intents/create.md#create_setup_intent-return_url),以便 Stripe 知道在用户完成设置后对他们进行重定向。我们可能会先将他们重定向到一个中间站点,如银行授权页面,然后才将他们重定向到 `return_url`。 如果您的客户保存他们的银行卡详情,则在设置成功后,我们会立即将他们重定向到 `return_url`。如果您不想对银行卡付款重定向,可以将 [redirect](https://docs.stripe.com/js/setup_intents/confirm_setup#confirm_setup_intent-options-redirect) 设置为 `if_required`。这样就会只对使用基于重定向支付方式的客户进行重定向。 #### HTML + JS ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmSetup({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/account/payments/setup-complete', } }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }); ``` #### React 从您的支付表单组件调用 [stripe.confirmSetup](https://docs.stripe.com/js/setup_intents/confirm_setup) 时,使用 [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) and [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook) hook。 如果您不想用 hooks,而是想使用传统的类组件 (Class Components),则可以使用 [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer)。 ```jsx import React, {useState} from 'react'; import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js'; const SetupForm = () => { const stripe = useStripe(); const elements = useElements(); const [errorMessage, setErrorMessage] = useState(null); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return null; } const {error} = await stripe.confirmSetup({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://example.com/account/payments/setup-complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) setErrorMessage(error.message); } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }; return (
{/* Show error message to your customers */} {errorMessage &&
{errorMessage}
} ) }; export default SetupForm; ``` 请确保 `return_url` 与您网站上的页面相对应,该页面[提供 `SetupIntent` 的状态](https://docs.stripe.com/payments/payment-intents/verifying-status.md)。当我们将客户重定向到 `return_url` 时,Stripe 会提供以下 URL 查询参数来验证状态。您也可以在提供 `return_url` 时附加自己的查询参数,这些参数会在重定向流程中保留。 | 参数 | 描述 | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `setup_intent` | `SetupIntent` 的唯一标识符。 | | `setup_intent_client_secret` | `SetupIntent` 对象的[客户端私钥](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret)。 | 您可调用 [stripe.retrieveSetupIntent](https://docs.stripe.com/js/setup_intents/retrieve_setup_intent),通过 `setup_intent_client_secret` 查询参数获取 `SetupIntent`。`SetupIntent` 确认成功后,会将返回的 `PaymentMethod` ID(位于 `result.setupIntent.payment_method` 中)保存到所提供的客户配置型 `Account` 或 `Customer`。 #### HTML + JS ```javascript // Initialize Stripe.js using your publishable key const stripe = Stripe('{PUBLISHABLE_KEY}'); // Retrieve the "setup_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'setup_intent_client_secret' ); // Retrieve the SetupIntent stripe.retrieveSetupIntent(clientSecret).then(({setupIntent}) => { const message = document.querySelector('#message') // Inspect the SetupIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (setupIntent.status) { case 'succeeded': { message.innerText = 'Success! Your payment method has been saved.'; break; } case 'processing': { message.innerText = "Processing payment details. We'll update you when processing is complete."; break; } case 'requires_payment_method': { message.innerText = 'Failed to process payment details. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; } } }); ``` #### React ```jsx // PaymentStatus.jsx import React, {useState, useEffect} from 'react'; import {useStripe} from '@stripe/react-stripe-js'; const PaymentStatus = () => { const stripe = useStripe(); const [message, setMessage] = useState(null); useEffect(() => { if (!stripe) { return; } // Retrieve the "setup_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'setup_intent_client_secret' ); // Retrieve the SetupIntent stripe .retrieveSetupIntent(clientSecret) .then(({setupIntent}) => { // Inspect the SetupIntent `status` to indicate the status of the payment // to your customer. // // Some payment methods will [immediately succeed or fail][0] upon // confirmation, while others will first enter a `processing` state. // // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification switch (setupIntent.status) { case 'succeeded': setMessage('Success! Your payment method has been saved.'); break; case 'processing': setMessage("Processing payment details. We'll update you when processing is complete."); break; case 'requires_payment_method': // Redirect your user back to your payment page to attempt collecting // payment again setMessage('Failed to process payment details. Please try another payment method.'); break; } }); }, [stripe]); return message }; export default PaymentStatus; ``` > 如果您有可以用来跟踪客户浏览器会话的工具,则您可能需要将 `stripe.com` 域名添加到推荐人列表。重定向会导致一些工具创建新的会话,从而阻止您跟踪完整的会话。 ## 以后对保存的支付方式扣款 [服务器端] > #### 合规 > > 保存客户的支付详情时,您有责任遵守所有适用的法律、法规和卡组织规则。向您的最终客户呈现之前用过的支付方式以供未来购物使用时,确保您所列出的支付方式已从客户那里收集保存支付方式详情以供将来具体使用的同意书。对于绑定到客户的支付方式,要区分哪些可以哪些不可以作为保存的支付方式供未来购物使用,请使用 [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) 参数。 要查找可用于扣款的支付方式,请列出与客户关联的支付方式。此示例列出了银行卡,但您可以列出任何受支持的[类型](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-type)。 > #### 使用 Accounts v2 API 表示客户 > > Accounts v2 API 通常面向 Connect 用户开放,并对其他 Stripe 用户开放公开预览。如果您参与了 Accounts v2 预览,您需要在代码中[指定预览版本](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning)。 > > 如需申请 Accounts v2 预览版的访问权限, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. #### Accounts v2 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d type=card ``` #### Customers v1 ```curl curl -G https://api.stripe.com/v1/payment_methods \ -u "<>:" \ -d "customer={{CUSTOMER_ID}}" \ -d type=card ``` 当您准备在*离线会话* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information)期间向客户扣款时,请使用 `Customer` 或客户配置的 `Account` 的 ID,以及 `PaymentMethod` 的 ID,配合支付金额和币种来创建 `PaymentIntent`。同时设置其他几个参数以完成离线会话支付: - 将 [off_session](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-off_session) 设置为 true,表示客户当前不在您的结账流程中,因此无法响应任何身份验证请求。如果在结账流程中,合作方(如发卡行或银行)要求进行身份验证,Stripe 会使用之前*会话内* (A payment is described as on-session if it occurs while the customer is actively in your checkout flow and able to authenticate the payment method)交易中的客户信息来申请豁免。若不符合豁免条件,`PaymentIntent` 可能会抛出错误。 - 将 [confirm](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-confirm) 设置为 true,以便在创建 `PaymentIntent` 时立即触发确认。 - 将 [payment_method](https://docs.stripe.com/api.md#create_payment_intent-payment_method) 设置为 `PaymentMethod` 的 ID。 - 根据您在集成中如何代表客户,请将 [customer_account](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer_account) 设为客户配置型 `Account` 的 ID,或将 [customer](https://docs.stripe.com/api.md#create_payment_intent-customer) 设为 `Customer` 的 ID。 #### 账户 v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` #### 客户 v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "customer={{CUSTOMER_ID}}" \ -d payment_method={{PAYMENT_METHOD_ID}} \ --data-urlencode "return_url=https://example.com/order/123/complete" \ -d off_session=true \ -d confirm=true ``` 付款尝试失败时,请求也会失败,并显示 402 HTTP 状态码,PaymentIntent 的状态为 *requires\_payment\_method* (This status appears as "requires_source" in API versions before 2019-02-11)。您必须通知客户返回到您的应用程序(例如,发送电子邮件或应用程序内通知)来完成付款。 检查 Stripe API 库引发的 [error](https://docs.stripe.com/api/errors/handling.md) 的代码。如果付款因 [authentication_required](https://docs.stripe.com/declines/codes.md) 拒付代码而失败,则使用被拒绝的 PaymentIntent 的客户端私钥和 confirmPayment 来允许客户授权付款。 ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ // The client secret of the PaymentIntent clientSecret, confirmParams: { return_url: 'https://example.com/order/123/complete', }, }); if (error) { // This point will only be reached if there is an immediate error when // confirming the payment. Show error to your customer (for example, payment // details incomplete) const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; } else { // Your customer will be redirected to your `return_url`. For some payment // methods like iDEAL, your customer will be redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }); ``` > `stripe.confirmPayment` 可能需要几秒才能完成。该时间内,禁止表单重复提交,并显示一个类似于微调器的等待指示器。如果收到错误,则向客户显示,重新启用表单,然后隐藏掉等待指示器。如果客户必须执行额外的步骤来完成付款,如身份验证,Stripe.js 将引导其完成该流程。 如果付款因其他原因失败,如资金不足,则将客户跳转到一个支付页面来输入新的支付方式信息。您可以重新使用现有的 PaymentIntent 来用新的支付详情来重新尝试付款。 ## 测试集成 用测试付款详情和测试重定向页面验证您的集成。点击下方选项卡,查看每个支付方式的详情。 #### 银行卡 | 支付方式 | 场景 | 如何测试 | | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | | 信用卡 | 银行卡设置成功,不要求*验证* (Strong Customer Authentication (SCA) is a regulatory requirement in effect as of September 14, 2019, that impacts many European online payments. It requires customers to use two-factor authentication like 3D Secure to verify their purchase)。 | 填写我们的信用卡表单,卡号是 `4242 4242 4242 4242`,有效期、CVC(银行卡安全码)以及邮编可任意填写。 | | 信用卡 | 该卡在初始设置时需要身份验证,在后续付款时会直接成功。 | 填写我们的信用卡表单,卡号是 `4000 0025 0000 3155`,有效期、CVC(银行卡安全码)以及邮编可任意填写。 | | 信用卡 | 该卡在初始设置时需要身份验证,在后续付款时也需要身份验证。 | 填写我们的信用卡表单,卡号是 `4000 0027 6000 3184`,有效期、CVC(银行卡安全码)以及邮编可任意填写。 | | 信用卡 | 设置过程中卡被拒绝了。 | 填写我们的信用卡表单,卡号是 `4000 0000 0000 9995`,有效期、CVC(银行卡安全码)以及邮编可任意填写。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | ---------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Bancontact | 您的客户用 Bancontact 成功设置了一个 SEPA 直接借记支付方式,供未来使用。 | 在 Bancontact 表单中使用一个任意的名称,然后在重定向页面上点击**授权付款设置**。 | | Bancontact | 您的客户未在 Bancontact 重定向页面进行验证。 | 在 Bancontact 表单中使用一个任意的名称,然后在重定向页面上点击**让测试设置失败**。 | | BECS 直接借记 | 您的客户成功用 BECS 直接借记完成付款。 | 请使用账号 `900123456` 填写表单。已确认的 `PaymentIntent` 状态会先变为 `processing`,3 分钟后变为 `succeeded`。 | | BECS 直接借记 | 您的客户付款失败,错误代码为:`account_closed`。 | 用账号 `111111113` 填写表单。 | | iDEAL | 您的客户用 iDEAL 成功设置了 [SEPA 直接借记](https://docs.stripe.com/payments/sepa-debit.md)支付方式,供未来使用。 | 在 iDEAL 表单中使用任意的名称和银行,然后在重定向页面上点击**授权测试设置**。 | | iDEAL | 您的客户未在 iDEAL 重定向页面进行验证。 | 选择银行,并在 iDEAL 表单中使用一个任意的名称,然后在重定向页面上点击**让测试设置失败**。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 请使用账号 `AT321904300235473204` 填写表单。已确认的 `PaymentIntent` 状态会先变为 `processing`,3 分钟后变为 `succeeded`。 | | SEPA 直接借记 | 您的客户的 `PaymentIntent` 状态会从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | ### 测试对保存的 SEPA 借记 PaymentMethod 的收款 当使用 iDEAL、Bancontact 或 Sofort 确认 `SetupIntent` 时,会生成一个 [SEPA 直接借记](https://docs.stripe.com/payments/sepa-debit.md) *支付方式* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs)。SEPA 直接借记是一种[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)支付方式,其状态会先变为中间的 `processing` 状态,几天后再变为 `succeeded` 或 `requires_payment_method` 状态。 #### 邮箱 将 `payment_method.billing_details.email` 设置为以下值之一,以测试 `PaymentIntent` 的状态转换。您可以在电子邮箱地址开头添加自定义文本,后面跟一个下划线。例如,使用 `test_1_generatedSepaDebitIntentsFail@example.com` 将会生成一个在用于 `PaymentIntent` 时始终失败的 SEPA 直接借记 PaymentMethod。 | 邮件地址 | 描述 | | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | | `generatedSepaDebitIntentsSucceed@example.com` | `PaymentIntent` 的状态从 `processing` 转换为 `succeeded`。 | | `generatedSepaDebitIntentsSucceedDelayed@example.com` | 至少三分钟后,`PaymentIntent` 的状态从 `processing` 转换为 `succeeded`。 | | `generatedSepaDebitIntentsFail@example.com` | `PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`。 | | `generatedSepaDebitIntentsFailDelayed@example.com` | 至少三分钟后,`PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`。 | | `generatedSepaDebitIntentsSucceedDisputed@example.com` | `PaymentIntent` 的状态从 `processing` 转换为 `succeeded`,但会立即产生争议。 | | `generatedSepaDebitIntentsFailsDueToInsufficientFunds@example.com` | `PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`,并带有 `insufficient_funds` 失败代码。 | #### PaymentMethod 使用这些 PaymentMethod 来测试 `PaymentIntent` 的状态转换。这些令牌对于自动化测试非常有用,可立即在服务器上将 PaymentMethod 附加到SetupIntent。 | 支付方式 | 描述 | | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | `pm_bancontact_generatedSepaDebitIntentsSucceed` | `PaymentIntent` 的状态从 `processing` 转换为 `succeeded`。 | | `pm_bancontact_generatedSepaDebitIntentsSucceedDelayed` | 至少三分钟后,`PaymentIntent` 的状态从 `processing` 转换为 `succeeded`。 | | `pm_bancontact_generatedSepaDebitIntentsFail` | `PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`。 | | `pm_bancontact_generatedSepaDebitIntentsFailDelayed` | 至少三分钟后,`PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`。 | | `pm_bancontact_generatedSepaDebitIntentsSucceedDisputed` | `PaymentIntent` 的状态从 `processing` 转换为 `succeeded`,但会立即产生争议。 | | `pm_bancontact_generatedSepaDebitIntentsFailsDueToInsufficientFunds` | `PaymentIntent` 的状态从 `processing` 转换为 `requires_payment_method`,并带有 `insufficient_funds` 失败代码。 | ## Optional: 自定义布局 [客户端] 您可以自定义 Payment Element 的布局(手风琴或制表符式)来适应您的结账界面。有关各属性的更多信息,请查看 [elements.create](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options)。 #### 手风琴 创建 Payment Element 时,可以通过传递布局 `type` 和其它可选属性来开始使用布局功能: ```javascript const paymentElement = elements.create('payment', { layout: { type: 'accordion', defaultCollapsed: false, radios: 'always', spacedAccordionItems: false } }); ``` #### 标签 ### 指定布局 将布局的值设置为 `tabs`。您还可以选择指定其他属性,如下例所示: ```javascript const paymentElement = elements.create('payment', { layout: { type: 'tabs', defaultCollapsed: false, } }); ``` 下图是用不同的布局配置呈现的相同 Payment Element。 ![三种结账表单体验](https://b.stripecdn.com/docs-statics-srv/assets/pe_layout_example.525f78bcb99b95e49be92e5dd34df439.png) Payment Element 布局 ## Optional: Apple Pay 和 Google Pay [客户端] 当您[启用银行卡支付](https://docs.stripe.com/payments/save-and-reuse.md?platform=web&ui=elements#create-intent)时,我们会为符合[钱包显示条件](https://docs.stripe.com/testing/wallets.md)的客户显示 Apple Pay 和 Google Pay。要接受来自这些钱包的付款,您还必须: - 在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用它们。Apple Pay 默认启用。 - [注册您的域名](https://docs.stripe.com/payments/payment-methods/pmd-registration.md)。 > #### 区域测试 > > Stripe Elements 不支持印度 Stripe 账户和客户的 Google Pay 或 Apple Pay。因此,如果测试者的 IP 地址在印度,您就不能测试您的 Google Pay 或 Apple Pay 集成,即使 Stripe 账户是在印度境外开立的也一样。 ## 向您的客户披露 Stripe Stripe 收集有关客户与 Elements 互动的信息,以向您提供服务、防范欺诈并改进其服务。这包括使用 Cookie 和 IP 地址来识别客户在单次结账会话中看到的 Elements。您有责任披露并获得 Stripe 以这些方式使用数据所需的所有权利和许可。有关更多信息,请访问我们的[隐私中心](https://stripe.com/legal/privacy-center#as-a-business-user-what-notice-do-i-provide-to-my-end-customers-about-stripe)。 ## See also - [接受付款](https://docs.stripe.com/payments/accept-a-payment.md) - [支付过程中保存付款详情](https://docs.stripe.com/payments/save-during-payment.md) - [Elements Appearance API](https://docs.stripe.com/elements/appearance-api.md) - [发送完整的风险因素](https://docs.stripe.com/radar/optimize-risk-factors.md)