# 收款 安全地在线上收款。 ## Start here: Install agent skills Stripe recommends using official skills to integrate with the API using best practices. Follow the instructions below to learn how. **Tip: Use curl instead of Fetch tools.** Skills are detailed 10–20 KB markdown files. Fetch tools summarize them. `curl -sL` guarantees the full content. **Using `npx skills`**: Check if `npx` is installed on the system. If `npx` is available, run `npx skills add https://docs.stripe.com --list` to list available skills, then run `npx skills add https://docs.stripe.com --yes --skill <--skill other-skills>` to install individual skills. **If `npx skills` isn’t available**: You can use curl to fetch the index of available skills, what they do, and their files from `https://docs.stripe.com/.well-known/skills/index.json`. To download a skill and its related files, use curl to download them from `https://docs.stripe.com/.well-known/skills/`. For this article, we recommend using these skills: `stripe-best-practices` LLM 说明:对于大多数集成,Stripe 建议将 Checkout Sessions API 与 Payment Element 搭配使用,而非 PaymentIntent。Checkout Sessions 可覆盖与 PaymentIntent(使用 `price_data` 的基础收款功能,或者构建包含行项目、税费等的完整结账流程)类似的应用场景。Adaptive Pricing 等部分功能仅在 Checkout Sessions 中可用。除非用户明确要求,否则不要使用 PaymentIntent API,因为它需要更多的代码。进一步了解 Elements 与 Checkout Sessions API 搭配使用的信息:https://docs.stripe.com/payments/quickstart-checkout-sessions.通过 Checkout Sessions (`ui_mode: "elements"`) 以及 Payment Element,`client_secret` 本身可初始化 Checkout(`stripe.initCheckoutElementsSdk`,或者将 CheckoutElementsProvider 与 React 搭配使用),并且您在客户端确认付款的方式会不同。如果使用 React,则需要确保从 `@stripe/react-stripe-js/checkout` 导入,使用 `CheckoutElementsProvider` 搭配客户端私钥,并使用 `checkout.confirm` 进行确认。如果使用 HTML,确保使用 `checkout = stripe.initCheckoutElementsSdk({clientSecret: promise}); checkout.createPaymentElement(); paymentElement = checkout.createPaymentElement(); paymentElement.mount("#payment-element");`,并通过 `loadActionsResult = await checkout.loadActions(); actions = loadActionsResult.actions; error = await actions.confirm();` 进行确认。 制作支付表单或使用预构建的结账页面来开始接收线上付款。 # Stripe 托管页面 > This is a Stripe 托管页面 for when payment-ui is checkout and ui is stripe-hosted. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=checkout&ui=stripe-hosted. 用 [Stripe Checkout](https://docs.stripe.com/payments/checkout.md) 重定向到 Stripe 托管的支付页面。看看这个集成[与 Stripe 的其他集成类型的对比情况](https://docs.stripe.com/payments/online-payments.md#compare-features-and-availability)。 #### 集成难度 Complexity: 2/5 #### 集成类型 重定向到 Stripe 托管的支付页面 #### 用户界面自定义 限制性自定义 - 20 种预设字体 - 3 种预设边框半径 - 自定义背景和边框颜色 - 自定义徽标 [尝试一下吧](https://checkout.stripe.dev/) 首先,[注册](https://dashboard.stripe.com/register)一个 Stripe 账户。 用我们的官方库从您的应用程序访问 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' ``` ## 将客户重定向到 Stripe Checkout [客户端] [服务器端] 在您的网站上添加一个结账按钮,调用一个服务器端点来创建 [Checkout Session](https://docs.stripe.com/api/checkout/sessions/create.md)。 您还可以为[现有客户](https://docs.stripe.com/payments/existing-customers.md?platform=web&ui=stripe-hosted)创建 Checkout Session,从而用已知联系信息预填 Checkout 字段,并统一该客户的购买记录。 ```html Buy cool new product
``` Checkout Session 是客户被重定向到支付表单时所看到的内容的程序化展示。可通过多种选项对它进行配置,例如: - 要扣款的 [Line items](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items) - 可用货币 您必须将 `success_url` 填写为您网站上的页面 URL,Checkout 会在客户完成支付后将其重定向到该页面。 > Checkout Sessions 默认在创建后 24 小时后过期。 创建完 Checkout Session 后,将您的客户重定向到响应中返回的 [URL](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-url)。 #### Ruby ```ruby # This example sets up an endpoint using the Sinatra framework. require 'json' require 'sinatra' require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' post '/create-checkout-session' dosession = Stripe::Checkout::Session.create({ line_items: [{ price_data: { currency: 'usd', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], mode: 'payment', # These placeholder URLs will be replaced in a following step. success_url: 'https://example.com/success', }) redirect session.url, 303 end ``` ### 支付方式 默认情况下,Stripe 支持银行卡及其他主流支付方式。您可以在 [Stripe 管理平台](https://dashboard.stripe.com/settings/payment_methods)中开启或关闭个别支付方式。在 Checkout 中,Stripe 评估货币和任何限制,然后动态向客户显示支持的支付方式。 要查看您如何向客户显示支付方式,请在管理平台中输入交易 ID 或设置订单金额和货币。 您可以在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用 Apple Pay 和 Google Pay。默认情况下,Apple Pay 处于启用状态,Google Pay 处于禁用状态。但在某些情况下,即使已启用这些功能,Stripe 仍会将其过滤。如果您[启用自动计税](https://docs.stripe.com/tax/checkout.md)但未收集收货地址,我们将过滤 Google Pay。 Checkout 的 Stripe 托管页面不需要修改集成即可启用 Apple Pay 或 Google Pay。Stripe 处理这些付款的方式与处理其他银行卡付款的方式完全一样。 ### 确认您的端点 启动您的网页服务器(例如 `localhost:4242`)并运行下列指令,以确认您的端点: ```bash curl -X POST -is "http://localhost:4242/create-checkout-session" -d "" ``` 在您的终端应该会看到类似于下面的响应: ```bash HTTP/1.1 303 See Other Location: https://checkout.stripe.com/c/pay/cs_test_... ... ``` ### 验证您的集成 现在,您的结账按钮应该可以使用了,能够将客户重定向到 Stripe Checkout。 1. 点击结账按钮。 1. 您会被重定向到 Stripe Checkout 支付表单。 如果您的集成不能用: 1. 打开浏览器开发人员工具上的 Network 面板。 1. 点击结账按钮,确认它向您的服务器端点 (`POST /create-checkout-session`) 发送了 XHR 请求。 1. 验证该请求是否返回状态码 200。 1. 用按钮点击监听器内的 `console.log(session)` 确认返回的数据是否正确。 ## 显示成功页面 [客户端] [服务器端] 客户成功提交支付表单息后,一定要能够看到成功页面,这一点非常重要。在您的网站上托管此成功页面。 创建一个最小的成功页面: ```html Thanks for your order!

Thanks for your order!

We appreciate your business! If you have any questions, please email orders@example.com.

``` 接下来,更新 Checkout Session 创建端点,使用此新的页面: ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "success_url=http://localhost:4242/success.html" ``` > 如果要自定义您的成功页面,请阅读[自定义成功页面](https://docs.stripe.com/payments/checkout/custom-success-page.md)指南。 ## 处理付款后事件 当客户完成 Checkout Session 付款时,Stripe 会发送一个 [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) 事件。使用[管理平台 Webhook 工具](https://dashboard.stripe.com/webhooks)或按照 [Webhook 指南](https://docs.stripe.com/webhooks/quickstart.md)接收和处理这些事件,这可能会触发您: - 向客户发送订单确认邮件。 - 在数据库中记录销售情况。 - 启动配送流程。 请侦听这些事件而非等待客户被重定向回您的网站。仅依赖 Checkout 着陆页触发履约是不可靠的。设置您的集成来侦听异步事件,这样才能用单一集成接受[不同类型的支付方式](https://stripe.com/payments/payment-methods-guide)。 详情请参阅我们的 [Checkout 履约指南](https://docs.stripe.com/checkout/fulfillment.md)。 使用 Checkout 收款时需处理以下事件: | 活动 | 描述 | 行动 | | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | 当客户成功完成 Checkout Session 时发送。 | 向客户发送订单确认,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | 当使用延迟型支付方式(如 ACH 直接借记)付款成功时发送。 | 向客户发送订单确认,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | 当使用延迟型支付方式(如 ACH 直接借记)付款失败时发送。 | 通知客户支付失败并引导其返回会话重新尝试支付。 | ## 测试您的集成 要测试您的 Stripe 托管的支付表单集成: 1. 创建一个 Checkout Session。 1. 使用下表中的方法填写付款详情。 - 输入一个任意的未来日期作为有效期。 - 输入 3 位数 CVC(银行卡安全码)。 - 输入账单地址邮编。 1. 点击**支付**。您被重定向到您的 `success_url`。 1. 前往管理平台,在[付款页面](https://dashboard.stripe.com/test/payments?status%5B0%5D=successful)上查找付款。如果您付款成功,就会在列表中看到它。 1. 点击您的付款,查看更多详情,例如包含账单信息和已购商品列表的 Checkout 摘要。您可以此信息来履行订单。 了解有关[测试您的集成](https://docs.stripe.com/testing.md)的更多信息。 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 钱包 | 支付方式 | 场景 | 如何测试 | | ------ | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | Alipay | 您的客户通过基于重定向和[立即通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | --------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | BECS 直接借记 | 您的客户成功用 BECS 直接借记完成付款。 | 使用帐号 `900123456` 和 BSB `000000` 填写表格。确认的 PaymentIntent 先转入 `processing`,3 分钟后转为 `succeeded` 状态。 | | BECS 直接借记 | 您的客户付款失败,错误代码为:`account_closed`。 | 使用帐号 `111111113` 和 BSB `000000` 填写表格。 | | Bancontact、EPS、iDEAL 和 Przelewy24 | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | #### 付款凭单 | 支付方式 | 场景 | 如何测试 | | ------------ | --------------------------- | ------------------------------------ | | Boleto, OXXO | 您的客户用 Boleto 或 OXXO 付款凭单付款。 | 选择 Boleto 或 OXXO 此支付方式并提交付款。出现后关闭对话。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 创建产品和价格 在创建 Checkout Session 之前,您可以预先创建*产品* (Products represent what your business sells—whether that's a good or a service)和*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)。使用产品代表不同的实物商品或服务水平,*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)则表示每个产品的定价。您可以[配置 Checkout Session](https://docs.stripe.com/payments/checkout/pay-what-you-want.md) 以接受小费和捐款,或销售自定价格的产品和服务。 例如,您可以创建一个价格为 20 美元的 T 恤产品。这样即可在不更新相关产品详情的情况下更改和添加价格。使用 Stripe 管理平台或 API 均可创建产品和价格。详细了解[产品和价格的运作原理](https://docs.stripe.com/products-prices/how-products-and-prices-work.md)。 #### API API 仅要求有一个 `name` 即可创建 [Product](https://docs.stripe.com/api/products.md)。Checkout 中显示您提供的产品的 `name`、`description` 和 `images`。 ```curl curl https://api.stripe.com/v1/products \ -u "<>:" \ -d name=T-shirt ``` 然后,创建一个 [Price](https://docs.stripe.com/api/prices.md),定义产品的价格。这包括产品的费用及使用的币种。 ```curl curl https://api.stripe.com/v1/prices \ -u "<>:" \ -d "product={{PRODUCT_ID}}" \ -d unit_amount=2000 \ -d currency=usd ``` #### 管理平台 > 将在沙盒中创建的产品复制到真实模式,避免重新创建。在管理平台的“产品详情”视图中,点击右上角的**复制到真实模式**。只能对在沙盒中创建的每个产品进行一次这样的操作。对测试产品的后续更新不会反映在真实产品上。 点击管理平台账户选择器中的**沙盒**,确保您处于沙盒环境。接下来,定义要销售的商品或服务项目。创建新的产品和价格: - 导航到管理平台的[产品](https://dashboard.stripe.com/test/products)部分。 - 点击**添加产品**。 - 设置价格时,选择**一次性**。 Checkout 中会显示您提供的产品名称、描述和图片。 您创建的每个定价都有一个 ID。创建 Checkout Session 时,请引用定价 ID 和数量。若您需以多种货币销售商品,请将您的定价 (Price) 设置为 *多币种* (A single Price object can support multiple currencies. Each purchase uses one of the supported currencies for the Price, depending on how you use the Price in your integration)。Checkout 会自动[确定客户的本地货币](https://docs.stripe.com/payments/checkout/localize-prices/manual-currency-prices.md)并在 Price 支持的情况下显示该货币。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ --data-urlencode "success_url=https://example.com/success?session_id={CHECKOUT_SESSION_ID}" ``` ## Optional: 预填充客户数据 [服务器端] 如果您已经收集了客户的邮件地址并且想在 Checkout Session 中给他们预先填写,则创建 Checkout Session 时传递 [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email)。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ --data-urlencode "customer_email=customer@example.com" \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "success_url=https://example.com/success" ``` ## Optional: 保存支付方式详情 [服务器端] 默认情况下,用 Checkout 进行一次性付款时所使用的支付方式将来不能再使用。 ### 保存支付方式,以在会话外扣款 通过传递 [payment_intent_data.setup_future_usage](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-setup_future_usage) 实参可以对 Checkout 进行设置,使其保存用于进行一次性付款的支付方式。在您需要捕捉填写的支付方式以便收取滞后费用时(例如取消或未到场费用),这样做非常有帮助。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d customer_creation=always \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "success_url=https://example.com/success.html" \ -d "payment_intent_data[setup_future_usage]=off_session" ``` 如果您在 `subscription` 模式下使用 Checkout,Stripe 会自动保存支付方式,以便后续收款。使用 `setup_future_usage` 或 `subscription` 模式为客户保存的银行卡支付方式不会出现在 Checkout 的再次购买选项中(更多信息见下文)。我们建议使用[自定义文本](https://docs.stripe.com/payments/checkout/custom-components.md#customize-text)链接到有关已保存支付信息使用的相关条款。 > 全球隐私法非常复杂、微妙。建议在实施 [setup_future_usage](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-setup_future_usage) 之前咨询您的法律和隐私团队,因为这可能会影响您的隐私合规框架。参考[欧洲数据保护委员会发布的指导意见](https://edpb.europa.eu/system/files/2021-05/recommendations022021_on_storage_of_credit_card_data_en_1.pdf),了解有关保存支付详情的更多信息。 ### 保存支付方式,以在 Checkout 中预先填充 默认情况下,Checkout 使用 [Link](https://docs.stripe.com/payments/link/checkout-link.md) 为您的客户提供安全保存和重复使用其支付信息的选项。如果您希望自行管理支付方式,请在创建 Checkout Session 时使用 [saved_payment_method_options.payment_method_save](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_save),让您的客户保存支付方式,以便将来在 Checkout 中购物。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d customer_creation=always \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "success_url=https://example.com/success.html" \ -d "saved_payment_method_options[payment_method_save]=enabled" ``` 在 [payment](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) 或 [subscription](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) 模式下传递此参数会显示一个可选复选框,让客户显式保存其支付方式以备将来购买时使用。当客户选中此复选框时,Checkout 会使用 [allow_redisplay: always](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) 保存支付方式。Checkout 使用该参数来确定将来的购物中是否可以预先填充支付方式。使用 `saved_payment_method_options.payment_method_save` 时,您无需传入 `setup_future_usage` 来保存支付方式。 If your integration uses [customer-configured Accounts](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), replace `Customer` and event references in the code examples with the equivalent Accounts v2 API references. For more information, see [Represent customers with Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md). 使用 [saved_payment_method_options.payment_method_save](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_save) 时要求提供 `Customer`。要保存新客户,请将 Checkout Session 的 [customer_creation](https://docs.stripe.com/api/checkout/sessions/create.md) 设置为 `always`。否则,会话过程中不会保存客户或支付方式。 如果未传入 `payment_method_save` 或客户不同意保存支付方式,Checkout 仍会保存在 `subscription` 模式下或使用 `setup_future_usage` 创建的支付方式。这些支付方式的 `allow_redisplay` 值为 `limited`,这可以防止在退货时预先填充它们,并使您遵守卡组织的规则和数据保护法规。了解如何[更改这些模式启用的默认行为](https://support.stripe.com/questions/prefilling-saved-cards-in-checkout)以及如何更改或覆盖 `allow_redisplay` 行为。 > 您可以使用 Checkout 保存银行卡和其他支付方式来进行会话外收款,但 Checkout 仅预填充已保存的银行卡信息。了解如何[预填充保存的银行卡信息](https://support.stripe.com/questions/prefilling-saved-cards-in-checkout)。要在不进行初始付款的情况下保存支付方式,[请在设置模式下使用 Checkout](https://docs.stripe.com/payments/save-and-reuse.md?platform=checkout)。 ### 允许客户移除已保存的支付方式 要让客户移除已保存的支付方式,使其不会在将来的付款中再次出现,请在创建 Checkout Session 时使用 [saved_payment_method_options.payment_method_remove](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_remove)。 ```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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "success_url=https://example.com/success.html" \ -d "saved_payment_method_options[payment_method_remove]=enabled" ``` 如果支付方式关联到有效订阅,并且客户没有为账单和订阅付款保存默认支付方式,则客户不能删除该支付方式。 ## Optional: 单独授权和捕获 [服务器端] Stripe 支持两步式银行卡支付,您可先预授权卡片,稍后再进行资金捕获。当 Stripe 完成支付授权后,发卡行将担保该笔资金,并在持卡人卡上冻结相应金额。您需在特定时限内完成资金捕获([具体时限视卡片类型而定](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md#auth-capture-limitations))。若在授权失效前未完成捕获,支付将被取消,发卡行也将解除资金冻结。 如果您需要在确认客户有能力支付和实际收取款项之间执行额外操作,那么将授权与扣款分离会非常有用。例如,如果您销售的是库存有限的商品,您可能需要先确认客户通过 Checkout 购买的商品仍有库存,然后再扣款并完成订单。可通过以下工作流程实现: 1. 确认 Stripe 已授权客户的支付方式。 1. 查阅库存管理系统,确认那件商品是否有货。 1. 更新您的库存管理系统,指示客户未购买那件商品。 1. 捕获客户的付款。 1. 在确认页面通知客户他们是否购买成功。 要表明您想单独授权和捕获,必须在创建 Checkout Session 时将 [payment_intent_data.capture_method](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-capture_method) 的值设置为 `manual`。这样可指示 Stripe 仅授权客户银行卡上的金额。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d "payment_intent_data[capture_method]=manual" \ --data-urlencode "success_url=https://example.com/success.html" ``` 要捕获一笔未捕获的付款,可以用[管理平台](https://dashboard.stripe.com/test/payments?status%5B%5D=uncaptured),也可以用 [capture](https://docs.stripe.com/api/payment_intents/capture.md) 端点。程序化地捕获付款必须访问 Checkout Session 过程中创建的 PaymentIntent,它可从 [Session](https://docs.stripe.com/api/payment_intents/capture.md) 对象获取。 ## Optional: 客户账户管理 [无代码] 通过向您的*客户门户* (The customer portal is a secure, Stripe-hosted page that lets your customers manage their subscriptions and billing details)分享链接,让您的客户[管理](https://docs.stripe.com/customer-management.md)他们自己的账户。客户门户允许客户用他们的电子邮件地址登录,以管理订阅、更新支付方式等。 ## See also - [添加折扣](https://docs.stripe.com/payments/checkout/discounts.md) - [收税](https://docs.stripe.com/payments/checkout/taxes.md) - [收集税号](https://docs.stripe.com/tax/checkout/tax-ids.md) - [添加收货地址](https://docs.stripe.com/payments/collect-addresses.md?payment-ui=checkout) - [自定义品牌](https://docs.stripe.com/payments/checkout/customization.md) # 嵌入式表单 > This is a 嵌入式表单 for when payment-ui is checkout and ui is embedded-form. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=checkout&ui=embedded-form. 使用 [Stripe Checkout](https://docs.stripe.com/payments/checkout.md) 在您的网站上嵌入预构建的支付表单。看看这个集成[与 Stripe 的其他集成类型的对比情况](https://docs.stripe.com/payments/online-payments.md#compare-features-and-availability)。 #### 集成难度 Complexity: 2/5 #### 集成类型 在您的网站上嵌入预建的支付表单 #### 用户界面自定义 限制性自定义 - 20 种预设字体 - 3 种预设边框半径 - 自定义背景和边框颜色 - 自定义徽标 使用 Stripe 管理平台中的[品牌设置](https://dashboard.stripe.com/settings/branding/checkout)匹配 Checkout 与您的网站设计。 首先,[注册](https://dashboard.stripe.com/register)一个 Stripe 账户。 用我们的官方库从您的应用程序访问 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' ``` ## 创建一个 Checkout Session [服务器端] 在您的服务器端,创建一个 *Checkout Session* (A Checkout Session represents your customer's session as they pay for one-time purchases or subscriptions through Checkout. After a successful payment, the Checkout Session contains a reference to the Customer, and either the successful PaymentIntent or an active Subscription) 并将 [ui_mode](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-ui_mode) 设置为 `embedded_page`。您可以通过[行项目](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-line_items)来配置 [Checkout Session](https://docs.stripe.com/api/checkout/sessions/create.md),以包含所需内容,并设置[货币](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-currency)等选项。 您还可以为[现有客户](https://docs.stripe.com/payments/existing-customers.md?platform=web&ui=stripe-hosted)创建 Checkout Session,从而用已知联系信息预填 Checkout 字段,并统一该客户的购买记录。 要让客户返回到您网站上托管的自定义页面,请在 [return_url](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-return_url) 参数中指定该页面的 URL。在 URL 中包含 `{CHECKOUT_SESSION_ID}` 模板变量,以在返回页面上检索会话的状态。在重定向之前,Checkout 会自动将变量替换为 Checkout Session ID。 阅读更多关于[配置返回页面](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=checkout&ui=embedded-form#return-page)以及[自定义重定向行为](https://docs.stripe.com/payments/checkout/custom-success-page.md?payment-ui=embedded-form)的其他选项。 创建 Checkout Session 后,使用[挂载 Checkout](https://docs.stripe.com/payments/accept-a-payment.md#mount-checkout) 响应中返回的 `client_secret`。 #### Ruby ```ruby # This example sets up an endpoint using the Sinatra framework. require 'json' require 'sinatra' require 'stripe' # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. Stripe.api_key = '<>' post '/create-checkout-session' do session = Stripe::Checkout::Session.create({ line_items: [{ price_data: { currency: 'usd', product_data: { name: 'T-shirt', }, unit_amount: 2000, }, quantity: 1, }], mode: 'payment',ui_mode: 'embedded_page', return_url: 'https://example.com/checkout/return?session_id={CHECKOUT_SESSION_ID}' }) {clientSecret: session.client_secret}.to_json end ``` ## 挂载 Checkout [客户端] #### HTML + JS [Stripe.js](https://docs.stripe.com/js.md) 是作为 Checkout 的一部分提供的。在您的页面包含 Stripe.js 脚本,方法是将它添加到您的 HTML 文件的 head 部分。接下来,创建一个空的 DOM 节点(容器)用于挂载。 ```html
``` 用您的可发布 API 密钥初始化 Stripe.js。 创建一个异步 `fetchClientSecret` 函数,请求您的服务器创建 Checkout Session 并检索客户端私钥。创建 Checkout 实例时,将该函数传入 `options`: ```javascript // Initialize Stripe.js const stripe = Stripe('<>'); initialize(); // Fetch Checkout Session and retrieve the client secret async function initialize() { const fetchClientSecret = async () => { const response = await fetch("/create-checkout-session", { method: "POST", }); const { clientSecret } = await response.json(); return clientSecret; }; // Initialize Checkout const checkout = await stripe.createEmbeddedCheckoutPage({ fetchClientSecret, }); // Mount Checkout checkout.mount('#checkout'); } ``` #### React 从 npm 安装 [react-stripe-js](https://docs.stripe.com/sdks/stripejs-react.md) 和 Stripe.js 加载程序: ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` 要使用 Embedded Checkout 组件,请创建一个 `EmbeddedCheckoutProvider`。用您的 API 公钥调用 `loadStripe`,并将返回的 `Promise` 传递给提供程序。 创建一个异步 `fetchClientSecret` 函数,请求您的服务器创建 Checkout Session 并检索客户端私钥。将此函数传入提供程序接受的 `options` 属性。 ```jsx import * as React from 'react'; import {loadStripe} from '@stripe/stripe-js'; import { EmbeddedCheckoutProvider, EmbeddedCheckout } from '@stripe/react-stripe-js'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('pk_test_123'); const App = () => { const fetchClientSecret = React.useCallback(() => { // Create a Checkout Session return fetch("/create-checkout-session", { method: "POST", }) .then((res) => res.json()) .then((data) => data.clientSecret); }, []); const options = {fetchClientSecret}; return (
) } ``` Checkout 在 iframe 中呈现,该 iframe 通过 HTTPS 连接将支付信息安全地发送给 Stripe。 > 避免将 Checkout 放在另一个 iframe 中,因为有些支付方式需要重定向到另一个页面进行付款确认。 ### 自定义外观 通过在您账户的[品牌设置](https://dashboard.stripe.com/settings/branding)中设置背景颜色、按钮颜色、边框半径和字体,自定义 Checkout 以匹配您的网站设计。 默认情况下,Checkout 在呈现时没有外部填充或边距。我们建议使用一个容器元素,如 div,来应用您想要的边距(例如,所有边都是 16px)。 ## 显示返回页面 在您的客户尝试付款后,Stripe 会将他们重定向到您网站上的返回页面。创建 Checkout Session 时,您在 [return_url](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-return_url) 参数中指定返回页面的 URL。阅读有关[自定义重定向行为](https://docs.stripe.com/payments/checkout/custom-success-page.md?payment-ui=embedded-form)其他选项的更多信息。 在呈现您的返回页面时,使用 URL 中的 Checkout Session ID 来检索 Checkout Session 的状态。根据会话状态处理结果,如下所示: - `complete`: 付款成功。使用来自 Checkout Session 的信息来呈现成功页面。 - `open`: 付款失败或被取消。重新安装 Checkout,以便您的客户可以重试。 #### Ruby ```ruby get '/session-status' do session = Stripe::Checkout::Session.retrieve(params[:session_id]) {status: session.status, customer_email: session.customer_details.email}.to_json end ``` ```javascript const session = await fetch(`/session_status?session_id=${session_id}`) if (session.status == 'open') { // Remount embedded Checkout } else if (session.status == 'complete') { // Show success page // Optionally use session.payment_status or session.customer_email // to customize the success page } ``` #### 基于重定向的支付方式 在支付过程中,一些支付方式会将客户重定向到中间页面,如银行授权页面。当他们完成该页面时,Stripe 会将他们重定向到您的返回页面。 了解有关[基于重定向的支付方式和重定向行为](https://docs.stripe.com/payments/checkout/custom-success-page.md?payment-ui=embedded-form#redirect-based-payment-methods)的更多信息。 ## 处理付款后事件 当客户完成 Checkout Session 付款时,Stripe 会发送一个 [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) 事件。使用[管理平台 Webhook 工具](https://dashboard.stripe.com/webhooks)或按照 [Webhook 指南](https://docs.stripe.com/webhooks/quickstart.md)接收和处理这些事件,这可能会触发您: - 向客户发送订单确认邮件。 - 在数据库中记录销售情况。 - 启动配送流程。 请侦听这些事件而非等待客户被重定向回您的网站。仅依赖 Checkout 着陆页触发履约是不可靠的。设置您的集成来侦听异步事件,这样才能用单一集成接受[不同类型的支付方式](https://stripe.com/payments/payment-methods-guide)。 详情请参阅我们的 [Checkout 履约指南](https://docs.stripe.com/checkout/fulfillment.md)。 使用 Checkout 收款时需处理以下事件: | 活动 | 描述 | 行动 | | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed) | 当客户成功完成 Checkout Session 时发送。 | 向客户发送订单确认,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | 当使用延迟型支付方式(如 ACH 直接借记)付款成功时发送。 | 向客户发送订单确认,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [checkout.session.async_payment_failed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_failed) | 当使用延迟型支付方式(如 ACH 直接借记)付款失败时发送。 | 通知客户支付失败并引导其返回会话重新尝试支付。 | ## 测试您的集成 测试您的嵌入式支付表单集成: 1. 创建嵌入式 Checkout Session,并在您的页面上挂载支付表单。 1. 使用下表中的方法填写付款详情。 - 输入任意未来日期作为银行卡到期日。 - 输入任意 3 位数字作为 CVC。 - 输入任意计费邮政编码。 1. 点击**支付**。您将被重定向到您的 `return_url`。 1. 转到管理平台,并在[交易页面](https://dashboard.stripe.com/test/payments?status%5B0%5D=successful)查找支付信息。如果您的支付成功,您将在列表中看到它。 1. 点击您的支付以查看更多详情,例如带有账单信息和购买物品清单的 Checkout 摘要。您可以使用此信息完成订单。 了解有关[测试您的集成](https://docs.stripe.com/testing.md)的更多信息。 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 钱包 | 支付方式 | 场景 | 如何测试 | | ------ | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | Alipay | 您的客户通过基于重定向和[立即通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | --------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | BECS 直接借记 | 您的客户成功用 BECS 直接借记完成付款。 | 使用帐号 `900123456` 和 BSB `000000` 填写表格。确认的 PaymentIntent 先转入 `processing`,3 分钟后转为 `succeeded` 状态。 | | BECS 直接借记 | 您的客户付款失败,错误代码为:`account_closed`。 | 使用帐号 `111111113` 和 BSB `000000` 填写表格。 | | Bancontact、EPS、iDEAL 和 Przelewy24 | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | #### 付款凭单 | 支付方式 | 场景 | 如何测试 | | ------------ | --------------------------- | ------------------------------------ | | Boleto, OXXO | 您的客户用 Boleto 或 OXXO 付款凭单付款。 | 选择 Boleto 或 OXXO 此支付方式并提交付款。出现后关闭对话。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 添加更多支付方式 默认情况下,Checkout [支持很多种支付方式](https://docs.stripe.com/payments/payment-methods/integration-options.md#choose-how-to-add-payment-methods)。在启用并显示某些支付方式时,如 Apple Pay、Google Pay 和“先买后付”方式,您必须采取额外步骤。 ### Apple Pay 和 Google Pay 要接受来自 Apple Pay 和 Google Pay 的支付,您必须: - 在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用它们。Apple Pay 默认启用。 - 在 HTTPS 的开发和生产环境中为您的应用服务。 - [注册您的域名](https://docs.stripe.com/payments/payment-methods/pmd-registration.md)。 - 在开发和生产环境中通过 HTTPS 向您的应用程序提供服务。您可以使用类似 [ngrok](https://ngrok.com/) 的服务在本地测试时向您的应用程序提供服务。 此外,仅当以下_所有_条件都满足时,Checkout Session 才会向客户显示 Apple Pay 按钮: - 客户设备的操作系统是 17 或更高版本的 macOS 或 iOS。 - 客户使用的是 Safari 浏览器。 - 客户在 Apple Pay 中储存了有效的银行卡。 只有满足以下所有条件时,Checkout Session 才会向客户显示 Google Pay 按钮: - 客户的设备正在运行 Chrome 61 或更高版本。 - 客户在 Google Pay 中储存了有效的银行卡。 > #### 区域测试 > > Stripe Checkout 不支持印度的 Stripe 账户或客户使用 Apple Pay 或 Google Pay。如果您的 IP 地址位于印度,即使 Stripe 账户在印度境外,也无法测试 Apple Pay 或 Google Pay 集成。 ## Optional: 创建产品和价格 在创建 Checkout Session 之前,您可以预先创建*产品* (Products represent what your business sells—whether that's a good or a service)和*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)。使用产品代表不同的实物商品或服务水平,*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)则表示每个产品的定价。您可以[配置 Checkout Session](https://docs.stripe.com/payments/checkout/pay-what-you-want.md) 以接受小费和捐款,或销售自定价格的产品和服务。 例如,您可以创建一个价格为 20 美元的 T 恤产品。这样即可在不更新相关产品详情的情况下更改和添加价格。使用 Stripe 管理平台或 API 均可创建产品和价格。详细了解[产品和价格的运作原理](https://docs.stripe.com/products-prices/how-products-and-prices-work.md)。 #### API API 仅要求有一个 `name` 即可创建 [Product](https://docs.stripe.com/api/products.md)。Checkout 中显示您提供的产品的 `name`、`description` 和 `images`。 ```curl curl https://api.stripe.com/v1/products \ -u "<>:" \ -d name=T-shirt ``` 然后,创建一个 [Price](https://docs.stripe.com/api/prices.md),定义产品的价格。这包括产品的费用及使用的币种。 ```curl curl https://api.stripe.com/v1/prices \ -u "<>:" \ -d "product={{PRODUCT_ID}}" \ -d unit_amount=2000 \ -d currency=usd ``` #### 管理平台 > 将在沙盒中创建的产品复制到真实模式,避免重新创建。在管理平台的“产品详情”视图中,点击右上角的**复制到真实模式**。只能对在沙盒中创建的每个产品进行一次这样的操作。对测试产品的后续更新不会反映在真实产品上。 点击管理平台账户选择器中的**沙盒**,确保您处于沙盒环境。接下来,定义要销售的商品或服务项目。创建新的产品和价格: - 导航到管理平台的[产品](https://dashboard.stripe.com/test/products)部分。 - 点击**添加产品**。 - 设置价格时,选择**一次性**。 Checkout 中会显示您提供的产品名称、描述和图片。 您创建的每个定价都有一个 ID。创建 Checkout Session 时,请引用定价 ID 和数量。若您需以多种货币销售商品,请将您的定价 (Price) 设置为 *多币种* (A single Price object can support multiple currencies. Each purchase uses one of the supported currencies for the Price, depending on how you use the Price in your integration)。Checkout 会自动[确定客户的本地货币](https://docs.stripe.com/payments/checkout/localize-prices/manual-currency-prices.md)并在 Price 支持的情况下显示该货币。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d mode=payment \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" ``` ## Optional: 预填充客户数据 [服务器端] 如果您已经收集了客户的邮件地址并且想在 Checkout Session 中给他们预先填充,则创建 Checkout Session 时传递 [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email)。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ --data-urlencode "customer_email=customer@example.com" \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" ``` ## Optional: 保存支付方式详情 [服务器端] 默认情况下,用 Checkout 进行一次性付款时所使用的支付方式将来不能再使用。 ### 保存支付方式,以在会话外扣款 通过传递 [payment_intent_data.setup_future_usage](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-setup_future_usage) 实参可以对 Checkout 进行设置,使其保存用于进行一次性付款的支付方式。在您需要捕捉填写的支付方式以便收取滞后费用时(例如取消或未到场费用),这样做非常有帮助。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d customer_creation=always \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" \ -d "payment_intent_data[setup_future_usage]=off_session" ``` 如果您在 `subscription` 模式下使用 Checkout,Stripe 会自动保存支付方式,以便后续收款。使用 `setup_future_usage` 或 `subscription` 模式为客户保存的银行卡支付方式不会出现在 Checkout 的再次购买选项中(更多信息见下文)。我们建议使用[自定义文本](https://docs.stripe.com/payments/checkout/custom-components.md#customize-text)链接到有关已保存支付信息使用的相关条款。 > 全球隐私法非常复杂、微妙。建议在实施 [setup_future_usage](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-setup_future_usage) 之前咨询您的法律和隐私团队,因为这可能会影响您的隐私合规框架。参考[欧洲数据保护委员会发布的指导意见](https://edpb.europa.eu/system/files/2021-05/recommendations022021_on_storage_of_credit_card_data_en_1.pdf),了解有关保存支付详情的更多信息。 ### 保存支付方式,以在 Checkout 中预先填充 默认情况下,Checkout 使用 [Link](https://docs.stripe.com/payments/link/checkout-link.md) 为您的客户提供安全保存和重复使用其支付信息的选项。如果您希望自行管理支付方式,请在创建 Checkout Session 时使用 [saved_payment_method_options.payment_method_save](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_save),让您的客户保存支付方式,以便将来在 Checkout 中购物。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d customer_creation=always \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" \ -d "saved_payment_method_options[payment_method_save]=enabled" ``` 在 [payment](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) 或 [subscription](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-mode) 模式下传递此参数会显示一个可选复选框,让客户显式保存其支付方式以备将来购买时使用。当客户选中此复选框时,Checkout 会使用 [allow_redisplay: always](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) 保存支付方式。Checkout 使用该参数来确定将来的购物中是否可以预先填充支付方式。使用 `saved_payment_method_options.payment_method_save` 时,您无需传入 `setup_future_usage` 来保存支付方式。 If your integration uses [customer-configured Accounts](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), replace `Customer` and event references in the code examples with the equivalent Accounts v2 API references. For more information, see [Represent customers with Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md). 使用 [saved_payment_method_options.payment_method_save](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_save) 时要求提供 `Customer`。要保存新客户,请将 Checkout Session 的 [customer_creation](https://docs.stripe.com/api/checkout/sessions/create.md) 设置为 `always`。否则,会话过程中不会保存客户或支付方式。 如果未传入 `payment_method_save` 或客户不同意保存支付方式,Checkout 仍会保存在 `subscription` 模式下或使用 `setup_future_usage` 创建的支付方式。这些支付方式的 `allow_redisplay` 值为 `limited`,这可以防止在退货时预先填充它们,并使您遵守卡组织的规则和数据保护法规。了解如何[更改这些模式启用的默认行为](https://support.stripe.com/questions/prefilling-saved-cards-in-checkout)以及如何更改或覆盖 `allow_redisplay` 行为。 > 您可以使用 Checkout 保存银行卡和其他支付方式来进行会话外收款,但 Checkout 仅预填充已保存的银行卡信息。了解如何[预填充保存的银行卡信息](https://support.stripe.com/questions/prefilling-saved-cards-in-checkout)。要在不进行初始付款的情况下保存支付方式,[请在设置模式下使用 Checkout](https://docs.stripe.com/payments/save-and-reuse.md?platform=checkout)。 ### 允许客户移除已保存的支付方式 要让客户移除已保存的支付方式,使其不会在将来的付款中再次出现,请在创建 Checkout Session 时使用 [saved_payment_method_options.payment_method_remove](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-saved_payment_method_options-payment_method_remove)。 ```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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" \ -d "saved_payment_method_options[payment_method_remove]=enabled" ``` 如果支付方式关联到有效订阅,并且客户没有为账单和订阅付款保存默认支付方式,则客户不能删除该支付方式。 ## Optional: 客户账户管理 [无代码] 通过向您的*客户门户* (The customer portal is a secure, Stripe-hosted page that lets your customers manage their subscriptions and billing details)分享链接,让您的客户[管理](https://docs.stripe.com/customer-management.md)他们自己的账户。客户门户允许客户用他们的电子邮件地址登录,以管理订阅、更新支付方式等。 ## Optional: 单独授权和捕获 [服务器端] Stripe 支持两步式银行卡支付,您可先预授权卡片,稍后再进行资金捕获。当 Stripe 完成支付授权后,发卡行将担保该笔资金,并在持卡人卡上冻结相应金额。您需在特定时限内完成资金捕获([具体时限视卡片类型而定](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md#auth-capture-limitations))。若在授权失效前未完成捕获,支付将被取消,发卡行也将解除资金冻结。 如果您需要在确认客户有能力支付和实际收取款项之间执行额外操作,那么将授权与扣款分离会非常有用。例如,如果您销售的是库存有限的商品,您可能需要先确认客户通过 Checkout 购买的商品仍有库存,然后再扣款并完成订单。可通过以下工作流程实现: 1. 确认 Stripe 已授权客户的支付方式。 1. 查阅库存管理系统,确认那件商品是否有货。 1. 更新您的库存管理系统,指示客户未购买那件商品。 1. 捕获客户的付款。 1. 在确认页面通知客户他们是否购买成功。 要表明您想单独授权和捕获,必须在创建 Checkout Session 时将 [payment_intent_data.capture_method](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-capture_method) 的值设置为 `manual`。这样可指示 Stripe 仅授权客户银行卡上的金额。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d "line_items[0][price]={{PRICE_ID}}" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ -d "payment_intent_data[capture_method]=manual" \ -d ui_mode=embedded_page \ --data-urlencode "return_url=https://example.com/return" ``` 要捕获一笔未捕获的付款,可以用[管理平台](https://dashboard.stripe.com/test/payments?status%5B%5D=uncaptured),也可以用 [capture](https://docs.stripe.com/api/payment_intents/capture.md) 端点。程序化地捕获付款必须访问 Checkout Session 过程中创建的 PaymentIntent,它可从 [Session](https://docs.stripe.com/api/payment_intents/capture.md) 对象获取。 ## Optional: 订单履行 了解如何在客户付款时[程序化地获取通知](https://docs.stripe.com/checkout/fulfillment.md)。 ## See also - [添加折扣](https://docs.stripe.com/payments/checkout/discounts.md) - [收税](https://docs.stripe.com/payments/checkout/taxes.md) - [收集税号](https://docs.stripe.com/tax/checkout/tax-ids.md) - [添加收货地址](https://docs.stripe.com/payments/collect-addresses.md?payment-ui=checkout) - [自定义品牌](https://docs.stripe.com/payments/checkout/customization.md) # Checkout Sessions API > This is a Checkout Sessions API for when payment-ui is elements and api-integration is checkout. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=elements&api-integration=checkout. 使用 [Stripe Elements](https://docs.stripe.com/payments/elements.md) 和 [Checkout Sessions API](https://docs.stripe.com/api/checkout/sessions.md) 构建自定义支付表单。查看此集成[与 Stripe 其他集成类型的对比情况](https://docs.stripe.com/payments/online-payments.md#compare-features-and-availability)。 Checkout Sessions API 内置了对税务计算、折扣、运费和货币兑换的支持,减少了您需要编写的自定义代码量。这是大多数集成推荐的方法。了解更多关于[何时使用 Checkout Sessions 而非 PaymentIntent](https://docs.stripe.com/payments/checkout-sessions-and-payment-intents-comparison.md) 的信息。 客户端和服务器端代码构建了一个可接受多种支付方式的结账表单。 #### 集成工作量 Complexity: 3/5 #### 集成类型 将用户界面组件组合成自定义支付流程 #### 用户界面自定义 使用 [ Appearance API ](https://docs.stripe.com/elements/appearance-api.md) 进行 CSS 级自定义 ## 设置服务器 [服务器端] 在开始之前,您需要[注册](https://dashboard.stripe.com/register)一个 Stripe 账户。 用官方 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' ``` ## 创建一个 Checkout Session [服务器端] 在您的服务器上添加一个端点,用于创建 [Checkout Session](https://docs.stripe.com/api/checkout/sessions/create.md) 并将其 [`client_secret`](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-client_secret) 返回给您的前端。Checkout Session 代表客户在进行一次性购买或订阅支付时的会话。Checkout Session 在创建 24 小时后会过期。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d ui_mode=elements \ -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]=2000" \ -d "line_items[0][quantity]=1" \ -d mode=payment \ --data-urlencode "return_url=https://example.com/return?session_id={CHECKOUT_SESSION_ID}" ``` ## 设置前端 [客户端] #### HTML + JS 在您的结账页面包含 Stripe.js 脚本,方法是将其添加到您的 HTML 文件的 `head`。一定直接从 js.stripe.com 加载 Stripe.js,以保持 PCI 合规。请勿将脚本包含在捆绑包中,也不要自己托管其副本。 请确保您正在使用最新版本的 Stripe.js。了解更多关于 [Stripe.js 版本控制](https://docs.stripe.com/sdks/stripejs-versioning.md)的信息。 ```html Checkout ``` > Stripe 提供一个 npm 工具包,可用于将 Stripe.js 加载为模块。请参阅 [GitHub 上的项目](https://github.com/stripe/stripe-js)。需要 [7.0.0](https://www.npmjs.com/package/%40stripe/stripe-js/v/7.0.0) 或更高版本。 初始化 stripe.js。 ```js // 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( '<>', ); ``` #### React 从 npm 公共注册表安装 [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) 和 [Stripe.js 加载器](https://www.npmjs.com/package/@stripe/stripe-js)。React Stripe.js 的版本需至少为 5.0.0,Stripe.js 加载器的版本需至少为 8.0.0。 ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` 使用公钥在前端初始化 `stripe` 实例。 ```javascript import {loadStripe} from '@stripe/stripe-js'; const stripe = loadStripe("<>"); ``` ## 发起结账 [客户端] #### HTML + JS 调用 [initCheckoutElementsSdk](https://docs.stripe.com/js/custom_checkout/init),并传入 `clientSecret`。 `initCheckoutElementsSdk` 返回一个 [Checkout](https://docs.stripe.com/js/custom_checkout) 对象,其中包含来自 Checkout Session 的数据以及用于更新这些数据的方法。 从 [actions.getSession()](https://docs.stripe.com/js/custom_checkout/session) 中读取 `total` 和 `lineItems`,并在您的用户界面中显示它们。这样您就能以最小的代码改动启用新功能。例如,如果您显示的是 `total`,那么添加 [manual currency prices](https://docs.stripe.com/payments/custom/localize-prices/manual-currency-prices.md) 时就无需修改界面。 ```html
``` ```javascript const clientSecret = fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret); const checkout = stripe.initCheckoutElementsSdk({clientSecret}); const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { const session = loadActionsResult.actions.getSession(); const checkoutContainer = document.getElementById('checkout-container'); checkoutContainer.append(JSON.stringify(session.lineItems, null, 2)); checkoutContainer.append(document.createElement('br')); checkoutContainer.append(`Total: ${session.total.total.amount}`); } ``` #### React 使用 [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider) 组件封装您的应用程序,并传入 `clientSecret` 和 `stripe` 实例。 ```jsx import React from 'react'; import {CheckoutElementsProvider} from '@stripe/react-stripe-js/checkout'; import CheckoutForm from './CheckoutForm'; const clientSecret = fetch('/create-checkout-session', {method: 'POST'}) .then((response) => response.json()) .then((json) => json.client_secret); const App = () => { return ( ); }; export default App; ``` 在您的结账表单组件中,使用 `useCheckout()` 钩子来访问 [Checkout](https://docs.stripe.com/js/custom_checkout) 对象。该 `Checkout` 对象包含来自结账会话的数据以及用于更新数据的方法。 从 `Checkout` 对象中读取 `total` 和 `lineItems`,并在您的用户界面中显示它们。这样您就能以最小的代码改动启用新功能。例如,如果您显示的是 `total`,那么添加 [manual currency prices](https://docs.stripe.com/payments/custom/localize-prices/manual-currency-prices.md) 时就无需修改界面。 ```jsx import React from 'react'; import {useCheckout} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => {const checkoutState = useCheckout(); if (checkoutState.type === 'loading') { return (
Loading...
); } if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } return (
{JSON.stringify(checkoutState.checkout.lineItems, null, 2)} {/* A formatted total amount */} Total: {checkoutState.checkout.total.total.amount}
); }; ``` ## 收集客户电子邮件地址 [客户端] #### HTML + JS 完成 Checkout Session 时,您必须提供有效的客户电子邮箱。 这些指令用于创建电子邮件输入框,并调用 `Checkout` 对象中的 [updateEmail](https://docs.stripe.com/js/custom_checkout/update_email)。 或者,您也可以: - 在创建 Checkout Session 时,请传入 [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email)、[customer_account](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_account)(针对以客户配置的 `Account` 对象表示的客户)或 [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer)(针对以 `Customer` 对象表示的客户)。Stripe 会对以这种方式提供的电子邮件进行验证。 - 传入您已在 [checkout.confirm](https://docs.stripe.com/js/custom_checkout/confirm) 中验证过的电子邮箱地址。 ```html
``` ```javascript const checkout = stripe.initCheckoutElementsSdk({clientSecret}); const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { const {actions} = loadActionsResult; const emailInput = document.getElementById('email'); const emailErrors = document.getElementById('email-errors'); emailInput.addEventListener('input', () => { // Clear any validation errors emailErrors.textContent = ''; }); emailInput.addEventListener('blur', () => { const newEmail = emailInput.value;actions.updateEmail(newEmail).then((result) => { if (result.error) { emailErrors.textContent = result.error.message; } }); }); } ``` #### React 完成 Checkout Session 时,您必须提供有效的客户电子邮箱。 这些指令用于创建电子邮件输入框,并调用 `Checkout` 对象中的 [updateEmail](https://docs.stripe.com/js/react_stripe_js/checkout/update_email)。 或者,您也可以: - 在创建 Checkout Session 时,请传入 [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email)、[customer_account](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_account)(针对以客户配置的 `Account` 对象表示的客户)或 [customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer)(针对以 `Customer` 对象表示的客户)。Stripe 会对以这种方式提供的电子邮件进行验证。 - 传入您已在 [confirm](https://docs.stripe.com/js/react_stripe_js/checkout/confirm) 中验证过的电子邮箱地址。 ```jsx import React from 'react'; import {useCheckout} from '@stripe/react-stripe-js/checkout'; const EmailInput = () => { const checkoutState = useCheckout(); const [email, setEmail] = React.useState(''); const [error, setError] = React.useState(null); if (checkoutState.type === 'loading') { return (
Loading...
); } else if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } const handleBlur = () => {checkoutState.checkout.updateEmail(email).then((result) => { if (result.type === 'error') { setError(result.error); } }) }; const handleChange = (e) => { setError(null); setEmail(e.target.value); }; return (
{error &&
{error.message}
}
); }; export default EmailInput; ``` ## 收集付款详情 [客户端] 用 [Payment Element](https://docs.stripe.com/payments/payment-element.md) 在客户端收集支付信息。Payment Element 是一个预构建的 UI 组件,它简化了多种支付方式的收集支付详情的流程。 Payment Element 中包含一个 iframe,它通过一个 HTTPS 连接安全地将支付信息发送到 Stripe。避免将 Payment Element 放在另一个 iframe 中,因为有些支付方式需要重定向到另一个页面进行付款确认。 如果您选择使用 iframe 并希望支持 Apple Pay 或 Google Pay,则必须将 iframe 的 [allow](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allowpaymentrequest) 属性设置为`"payment *"`。 结账页面地址必须以 `https://` rather 开头,而非 `http://` for,您的集成才能正常工作。您可以在不使用 HTTPS 的情况下测试集成,但在准备接收真实付款时,请务必[启用 HTTPS](https://docs.stripe.com/security/guide.md#tls)。 #### HTML + JS 首先,创建一个容器 DOM 元素来挂载 [Payment Element](https://docs.stripe.com/payments/payment-element.md)。然后使用 [checkout.createPaymentElement](https://docs.stripe.com/js/custom_checkout/create_payment_element) 创建 `Payment Element` 的实例,并通过调用 [element.mount](https://docs.stripe.com/js/element/mount) 挂载它,提供 CSS 选择器或容器 DOM 元素。 ```html
``` ```javascript const paymentElement = checkout.createPaymentElement(); paymentElement.mount('#payment-element'); ``` 请参阅 [Stripe.js文档](https://docs.stripe.com/js/custom_checkout/create_payment_element#custom_checkout_create_payment_element-options) 以查看支持的选项。 您可以通过在前端初始化 Checkout 时传递 [elementsOptions.appearance](https://docs.stripe.com/js/custom_checkout/init#custom_checkout_init-options-elementsOptions-appearance) 来[自定义所有 Element 的外观](https://docs.stripe.com/payments/checkout/customization/appearance.md)。 #### React 在 [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider) 内部挂载 [Payment Element](https://docs.stripe.com/payments/payment-element.md) 组件。 ```jsx import React from 'react';import {PaymentElement, useCheckout} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { const checkoutState = useCheckout(); if (checkoutState.type === 'loading') { return (
Loading...
); } if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } return (
{JSON.stringify(checkoutState.checkout.lineItems, null, 2)} {/* A formatted total amount */} Total: {checkoutState.checkout.total.total.amount} ); }; export default CheckoutForm; ``` 请参阅 [Stripe.js文档](https://docs.stripe.com/js/custom_checkout/create_payment_element#custom_checkout_create_payment_element-options) 以查看支持的选项。 您可以通过向 [CheckoutElementsProvider](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider) 传递 [elementsOptions.appearance](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider#react_checkout_provider-options-elementsOptions-appearance),来[自定义所有 Elements 的外观](https://docs.stripe.com/payments/checkout/customization/appearance.md)。 ## 提交付款 [客户端] #### HTML + JS 渲染 **Pay** 按钮,该按钮通过调用 `Checkout` 实例中的 [confirm](https://docs.stripe.com/js/custom_checkout/confirm) 方法来提交支付。 ```html
``` ```js const checkout = stripe.initCheckoutElementsSdk({clientSecret}); checkout.on('change', (session) => { document.getElementById('pay-button').disabled = !session.canConfirm; }); const loadActionsResult = await checkout.loadActions(); if (loadActionsResult.type === 'success') { const {actions} = loadActionsResult; const button = document.getElementById('pay-button'); const errors = document.getElementById('confirm-errors'); button.addEventListener('click', () => { // Clear any validation errors errors.textContent = ''; actions.confirm().then((result) => { if (result.type === 'error') { errors.textContent = result.error.message; } }); }); } ``` #### React 渲染**Pay**按钮,调用 [useCheckout](https://docs.stripe.com/js/react_stripe_js/checkout/use_checkout) 中的 [confirm](https://docs.stripe.com/js/custom_checkout/confirm) 方法以提交支付请求。 ```jsx import React from 'react'; import {useCheckout} from '@stripe/react-stripe-js/checkout'; const PayButton = () => { const checkoutState = useCheckout(); const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(null); if (checkoutState.type !== "success") { return null; } const handleClick = () => { setLoading(true);checkoutState.checkout.confirm().then((result) => { if (result.type === 'error') { setError(result.error) } setLoading(false); }) }; return (
{error &&
{error.message}
}
) }; export default PayButton; ``` ## 测试您的集成应用 1. 导航到您的结账页面。 1. 使用下表中的支付方式填写付款详情。对于银行卡付款: - 输入一个任意的未来日期作为有效期。 - 输入 3 位数 CVC 码。 - 输入账单地址邮编。 1. 将付款提交至 Stripe。 1. 前往管理平台,在[交易页面](https://dashboard.stripe.com/test/payments?status%5B0%5D=successful)上查找支付。如果您支付成功,就会在列表中看到它。 1. 点击您的付款,查看更多详情,例如账单信息及已购商品列表。您可以此信息来[履行订单](https://docs.stripe.com/checkout/fulfillment.md)。 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 钱包 | 支付方式 | 场景 | 如何测试 | | ------ | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | Alipay | 您的客户通过基于重定向和[立即通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | --------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | BECS 直接借记 | 您的客户成功用 BECS 直接借记完成付款。 | 使用帐号 `900123456` 和 BSB `000000` 填写表格。确认的 PaymentIntent 先转入 `processing`,3 分钟后转为 `succeeded` 状态。 | | BECS 直接借记 | 您的客户付款失败,错误代码为:`account_closed`。 | 使用帐号 `111111113` 和 BSB `000000` 填写表格。 | | Bancontact、EPS、iDEAL 和 Przelewy24 | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | #### 付款凭单 | 支付方式 | 场景 | 如何测试 | | ------------ | --------------------------- | ------------------------------------ | | Boleto, OXXO | 您的客户用 Boleto 或 OXXO 付款凭单付款。 | 选择 Boleto 或 OXXO 此支付方式并提交付款。出现后关闭对话。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 创建产品和价格 在创建 Checkout Session 之前,您可以预先创建*产品* (Products represent what your business sells—whether that's a good or a service)和*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)。使用产品代表不同的实物商品或服务水平,*价格* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions)则表示每个产品的定价。您可以[配置 Checkout Session](https://docs.stripe.com/payments/checkout/pay-what-you-want.md) 以接受小费和捐款,或销售自定价格的产品和服务。 例如,您可以创建一个价格为 20 美元的 T 恤产品。这样即可在不更新相关产品详情的情况下更改和添加价格。使用 Stripe 管理平台或 API 均可创建产品和价格。详细了解[产品和价格的运作原理](https://docs.stripe.com/products-prices/how-products-and-prices-work.md)。 #### API API 仅要求有一个 `name` 即可创建 [Product](https://docs.stripe.com/api/products.md)。Checkout 中显示您提供的产品的 `name`、`description` 和 `images`。 ```curl curl https://api.stripe.com/v1/products \ -u "<>:" \ -d name=T-shirt ``` 然后,创建一个 [Price](https://docs.stripe.com/api/prices.md),定义产品的价格。这包括产品的费用及使用的币种。 ```curl curl https://api.stripe.com/v1/prices \ -u "<>:" \ -d "product={{PRODUCT_ID}}" \ -d unit_amount=2000 \ -d currency=usd ``` #### 管理平台 > 将在沙盒中创建的产品复制到真实模式,避免重新创建。在管理平台的“产品详情”视图中,点击右上角的**复制到真实模式**。只能对在沙盒中创建的每个产品进行一次这样的操作。对测试产品的后续更新不会反映在真实产品上。 点击管理平台账户选择器中的**沙盒**,确保您处于沙盒环境。接下来,定义要销售的商品或服务项目。创建新的产品和价格: - 导航到管理平台的[产品](https://dashboard.stripe.com/test/products)部分。 - 点击**添加产品**。 - 设置价格时,选择**一次性**。 Checkout 中会显示您提供的产品名称、描述和图片。 您创建的每个定价都有一个 ID。创建 Checkout Session 时,请引用定价 ID 和数量。若您需以多种货币销售商品,请将您的定价 (Price) 设置为 *多币种* (A single Price object can support multiple currencies. Each purchase uses one of the supported currencies for the Price, depending on how you use the Price in your integration)。Checkout 会自动[确定客户的本地货币](https://docs.stripe.com/payments/checkout/localize-prices/manual-currency-prices.md)并在 Price 支持的情况下显示该货币。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -d ui_mode=elements \ -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}" ``` ## Optional: 预填充客户数据 [服务器端] 如果您已经收集了客户的邮件地址并且想在 Checkout Session 中给他们预先填写,则创建 Checkout Session 时传递 [customer_email](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_email)。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ --data-urlencode "customer_email=customer@example.com" \ -d ui_mode=elements \ -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}" ``` ## Optional: 保存支付方式详情 学习如何[接受付款并保存客户的付款详细信息](https://docs.stripe.com/payments/save-during-payment.md)以备将来购买。 ## Optional: 侦听 Checkout Session 的变化 ### 侦听 Checkout Session 的变化 您可以通过用 [checkout.on](https://docs.stripe.com/js/custom_checkout/change_event) 在 `change` 事件上添加事件监听器来侦听 [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md) 的变化。 #### HTML + JS ```javascript checkout = stripe.initCheckoutElementsSdk({ clientSecret: promise, elementsOptions: { appearance }, }); checkout.on('change', (session) => { // Handle changes to the checkout session }); ``` #### React ```jsx import React from 'react'; import { useCheckout } from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { const checkoutState = useCheckout(); if (checkoutState.type === 'success') { checkoutState.checkout.on('change', (session) => { // Handle changes to the checkout session }); } }; ``` ## Optional: 收集账单地址和收货地址 ## 收集账单地址 默认情况下,Checkout Session 通过 Payment Element 收集付款所需的最少账单信息。 ### 使用 Billing Address Element 您可以使用 Billing Address Element 来收集完整的账单地址。 首先,创建 Checkout Session 时传递 [billing_address_collection=required](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-billing_address_collection)。 #### HTML + JS 创建一个容器 DOM 元素来挂载 Billing Address Element。然后使用 [checkout.createBillingAddressElement](https://docs.stripe.com/js/custom_checkout/create_billing_address_element) 创建 Billing Address Element 的实例,并通过调用 [element.mount](https://docs.stripe.com/js/element/mount) 挂载它,提供 CSS 选择器或容器 DOM 元素。 ```html
``` ```javascript const billingAddressElement = checkout.createBillingAddressElement(); billingAddressElement.mount('#billing-address'); ``` Billing Address Element 支持以下选项: - [联系人](https://docs.stripe.com/js/custom_checkout/create_billing_address_element#custom_checkout_create_billing_address_element-options-contacts) - [显示](https://docs.stripe.com/js/custom_checkout/create_billing_address_element#custom_checkout_create_billing_address_element-options-display) #### React 在 `CheckoutElementsProvider` 内部挂载 `BillingAddressElement` 组件。 ```jsx import React from 'react'; import {BillingAddressElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { return (
) }; ``` Billing Address Element 支持以下属性: - [联系人](https://docs.stripe.com/js/custom_checkout/create_billing_address_element#custom_checkout_create_billing_address_element-options-contacts) - [显示](https://docs.stripe.com/js/custom_checkout/create_billing_address_element#custom_checkout_create_billing_address_element-options-display) ### 使用自定义表单 您可以构建自己的表单来收集账单地址。 - 若结账页面在确认操作前设有独立的地址填写步骤,可在客户提交地址时调用 [updateBillingAddress](https://docs.stripe.com/js/react_stripe_js/checkout/update_billing_address) 方法。 - 否则,当客户点击“支付”按钮时,您可以通过将 [billingAddress](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-billingAddress) 传入 [confirm](https://docs.stripe.com/js/custom_checkout/confirm) 来提交地址。 ### 收集部分账单地址 要收集部分账单地址,例如仅国家/地区和邮编,请传递 [billing_address_collection=auto](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-billing_address_collection)。 收集部分账单地址时,必须[手动收集地址](https://docs.stripe.com/payments/accept-a-payment.md#collect-billing-addresses-manually)。默认情况下,Payment Element 会自动收集付款所需的最少账单信息。为避免重复收集账单详情,请在创建 Payment Element 时传递 [fields.billingDetails=never](https://docs.stripe.com/js/custom_checkout/create_payment_element#custom_checkout_create_payment_element-options-fields-billingDetails)。如果您只打算收集一部分账单详情(例如客户姓名),则只为您打算自己收集的字段传递 `never`。 ## 收集收货地址 要收集客户的收货地址,请在创建 Checkout Session 时传递 [shipping_address_collection](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection) 参数。 收集收货地址时,还必须指定允许发货至的国家/地区。用[两字母 ISO 国家/地区代码](https://www.nationsonline.org/oneworld/country_code_list.htm)组成的数组配置 [allowed_countries](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-shipping_address_collection-allowed_countries) 属性。 ### 如何使用 Shipping Address Element 您可以用 Shipping Address Element 收集完整的收货地址。 #### HTML + JS 创建一个容器 DOM 元素来挂载 Shipping Address Element。然后使用 [checkout.createShippingAddressElement](https://docs.stripe.com/js/custom_checkout/create_shipping_address_element) 创建 Shipping Address Element 的实例,并通过调用 [element.mount](https://docs.stripe.com/js/element/mount) 挂载它,提供 CSS 选择器或容器 DOM 元素。 ```html
``` ```javascript const shippingAddressElement = checkout.createShippingAddressElement(); shippingAddressElement.mount('#shipping-address'); ``` Shipping Address Element 支持以下选项: - [联系人](https://docs.stripe.com/js/custom_checkout/create_shipping_address_element#custom_checkout_create_shipping_address_element-options-contacts) - [显示](https://docs.stripe.com/js/custom_checkout/create_shipping_address_element#custom_checkout_create_shipping_address_element-options-display) #### React 在 `CheckoutElementsProvider` 内部挂载 `ShippingAddressElement` 组件。 ```jsx import React from 'react'; import {ShippingAddressElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { return (
) }; ``` Shipping Address Element 支持以下属性: - [联系人](https://docs.stripe.com/js/custom_checkout/create_shipping_address_element#custom_checkout_create_shipping_address_element-options-contacts) - [显示](https://docs.stripe.com/js/custom_checkout/create_shipping_address_element#custom_checkout_create_shipping_address_element-options-display) ### 侦听 Checkout Session 的变化 您可以通过添加事件侦听器来处理与地址相关的更改,从而侦听 [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md) 的更改。 #### HTML + JS 使用 [Session 对象](https://docs.stripe.com/js/custom_checkout/session_object)在结账表单中呈现运费金额。 ```html

Totals

``` ```javascript const checkout = stripe.initCheckoutElementsSdk({clientSecret}); 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}`; }); ``` #### React 调用 [useCheckout](https://docs.stripe.com/js/react_stripe_js/checkout/use_checkout) 以在您的结账表单中显示运费金额。 ```jsx import React from 'react'; import {useCheckout, ShippingAddressElement} from '@stripe/react-stripe-js/checkout'; const CheckoutForm = () => { const checkoutState = useCheckout(); if (checkoutState.type === 'error') { return (
Error: {checkoutState.error.message}
); } return (

Checkout Summary

{checkoutState.type === 'success' && ( <>
              {JSON.stringify(checkoutState.checkout.lineItems, null, 2)}
            

Totals

              Subtotal: {checkoutState.checkout.total.subtotal.amount}
              Shipping: {checkoutState.checkout.total.shippingRate.amount}
              Total: {checkoutState.checkout.total.total.amount}
            
)}
) }; ``` ### 同步计费和收货地址 当您同时使用 Billing Address Element 和 Shipping Address Element 时,可以显示一个复选框,让客户同步他们的计费地址和收货地址。 #### HTML + JS 初始化 Checkout 时,请在 `elementsOptions` 中传递 [syncAddressCheckbox](https://docs.stripe.com/js/custom_checkout/init#custom_checkout_init-options-elementsOptions-syncAddressCheckbox) 选项,以配置由哪个 Address Element 显示该复选框。 ```javascript const checkout = stripe.initCheckoutElementsSdk({ clientSecret, elementsOptions: { syncAddressCheckbox: 'shipping', }, }); ``` #### React 在 `elementsOptions` 中将 [syncAddressCheckbox](https://docs.stripe.com/js/react_stripe_js/checkout/checkout_provider#react_checkout_provider-options-elementsOptions-syncAddressCheckbox) 选项传递给 `CheckoutElementsProvider`,以配置哪个地址 Element 显示复选框。 ```jsx promise, elementsOptions: { syncAddressCheckbox: 'shipping', }, }} > ``` 将该值设置为 `'billing'` 或 `'shipping'`,以选择显示复选框的 Address Element。将其设置为 `'none'` 可隐藏该复选框,或留空以使用默认值 (`'billing'`)。 ### 使用自定义表单 您可以构建自己的表单来收集收货地址。 - 如果您的结账页面在确认操作前设有独立的地址填写步骤,可在客户提交地址时调用 [updateShippingAddress](https://docs.stripe.com/js/react_stripe_js/checkout/update_shipping_address) 方法。 - 否则,当客户点击“支付”按钮时,您可以通过将 [shippingAddress](https://docs.stripe.com/js/custom_checkout/confirm#custom_checkout_session_confirm-options-shippingAddress) 传入 [confirm](https://docs.stripe.com/js/custom_checkout/confirm) 来提交地址。 ## Optional: 单独授权和捕获 [服务器端] Stripe 支持两步式银行卡支付,您可先预授权卡片,稍后再进行资金捕获。当 Stripe 完成支付授权后,发卡行将担保该笔资金,并在持卡人卡上冻结相应金额。您需在特定时限内完成资金捕获([具体时限视卡片类型而定](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md#auth-capture-limitations))。若在授权失效前未完成捕获,支付将被取消,发卡行也将解除资金冻结。 如果您需要在确认客户有能力支付和实际收取款项之间执行额外操作,那么将授权与扣款分离会非常有用。例如,如果您销售的是库存有限的商品,您可能需要先确认客户通过 Checkout 购买的商品仍有库存,然后再扣款并完成订单。可通过以下工作流程实现: 1. 确认 Stripe 已授权客户的支付方式。 1. 查阅库存管理系统,确认那件商品是否有货。 1. 更新您的库存管理系统,指示客户未购买那件商品。 1. 捕获客户的付款。 1. 在确认页面通知客户他们是否购买成功。 要表明您想单独授权和捕获,必须在创建 Checkout Session 时将 [payment_intent_data.capture_method](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-payment_intent_data-capture_method) 的值设置为 `manual`。这样可指示 Stripe 仅授权客户银行卡上的金额。 ```curl curl https://api.stripe.com/v1/checkout/sessions \ -u "<>:" \ -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=elements ``` 要捕获一笔未捕获的付款,可以用[管理平台](https://dashboard.stripe.com/test/payments?status%5B%5D=uncaptured),也可以用 [capture](https://docs.stripe.com/api/payment_intents/capture.md) 端点。程序化地捕获付款必须访问 Checkout Session 过程中创建的 PaymentIntent,它可从 [Session](https://docs.stripe.com/api/payment_intents/capture.md) 对象获取。 ## Optional: 客户账户管理 [无代码] 通过向您的*客户门户* (The customer portal is a secure, Stripe-hosted page that lets your customers manage their subscriptions and billing details)分享链接,让您的客户[管理](https://docs.stripe.com/customer-management.md)他们自己的账户。客户门户允许客户用他们的电子邮件地址登录,以管理订阅、更新支付方式等。 ## Optional: 订单履行 了解如何在客户付款时[以编程方式获取通知](https://docs.stripe.com/checkout/fulfillment.md?payment-ui=embedded-components)。 ## See also - [为一次性付款添加折扣](https://docs.stripe.com/payments/checkout/discounts.md?payment-ui=embedded-components) - [收取税费](https://docs.stripe.com/payments/checkout/taxes.md?payment-ui=embedded-components) - [启用可调整的行项目数量](https://docs.stripe.com/payments/checkout/adjustable-quantity.md?payment-ui=embedded-components) - [添加一键按钮](https://docs.stripe.com/elements/express-checkout-element/accept-a-payment.md?payment-ui=embedded-components) # Payment Intents API > This is a Payment Intents API for when payment-ui is elements and api-integration is paymentintents. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=elements&api-integration=paymentintents. 使用 [Stripe Elements](https://docs.stripe.com/payments/elements.md) 和 [Payment Intents API](https://docs.stripe.com/api/payment_intents.md) 创建自定义支付表单。查看此集成[与 Stripe 其他集成类型的对比情况](https://docs.stripe.com/payments/online-payments.md#compare-features-and-availability)。 Payment Intents API 是一个底层 API,您可以用它来构建自己的结账或支付流程,但需要更多的代码和持续维护。对于大多数集成,我们推荐使用 [Payment Element 搭配 Checkout Sessions](https://docs.stripe.com/payments/quickstart-checkout-sessions.md),因为它可实现与 PaymentIntent 相似的支付流程。进一步了解[何时应使用 Checkout Sessions 而非 PaymentIntent](https://docs.stripe.com/payments/checkout-sessions-and-payment-intents-comparison.md)。 客户端侧面和服务器端代码构建接受各种支付方式的结账表单。 #### 集成难度 Complexity: 4/5 #### 集成类型 将 UI 组件组合到自定义支付流程 #### 用户界面自定义 使用 [Appearance API](https://docs.stripe.com/elements/appearance-api.md) 进行 CSS 级定制 > #### 想了解如何使用 Stripe Tax、折扣、配送或货币兑换? > > Stripe 提供 Payment Element 集成功能,可自动为您处理税费、折扣、配送及货币转换事宜。如需了解更多信息,请参阅[构建结账页面](https://docs.stripe.com/payments/quickstart-checkout-sessions.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' ``` ## 创建 PaymentIntent [服务器端] > 如果您想在不先创建 PaymentIntent 的情况下呈现 Payment Element,请参阅[收集支付详情后再创建 Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment)。 [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) 对象用来表示您从客户收款的意图,跟踪扣款尝试及整个过程中的状态变化情况。 本文档从较高层次对支付集成进行了概述。 (See full diagram at https://docs.stripe.com/payments/accept-a-payment) ### 创建 PaymentIntent 在您的服务器上创建 PaymentIntent,设置好 [amount](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount) 和 [currency](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency)。在最新版的 API 中,可以选择性指定 `automatic_payment_methods` 参数,因为 Stripe 会默认开启其功能。您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。 Stripe 会依据您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)展示您已启用的支付方式。如果要查看客户所能看到的支付方式,请在[管理平台](https://dashboard.stripe.com/settings/payment_methods/review)中输入交易 ID,或设置订单金额与货币。如果要覆盖支付方式,请使用 [payment_method_types](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-payment_method_types) 属性,手动列出您希望启用的支付方式。 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" ``` > 始终在服务器端决定扣款金额,这是一个可信的环境,客户端不行。这样可防止客户自己选择价格。 ### 检索客户端私钥 PaymentIntent 中包含的是一个*客户端私钥* (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 PaymentIntent {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/payment_intents/object.md#payment_intent_object-client_secret)。在您的服务器代码中,从 PaymentIntent 检索客户端密钥: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ## 收集付款详情 [客户端] 用 [Payment Element](https://docs.stripe.com/payments/payment-element.md) 在客户端收集支付信息。Payment Element 是一个预构建的 UI 组件,它简化了多种支付方式的收集支付详情的流程。 Payment Element 中包含一个 iframe,它通过一个 HTTPS 连接安全地将支付信息发送到 Stripe。避免将 Payment Element 放在另一个 iframe 中,因为有些支付方式需要重定向到另一个页面进行付款确认。 如果您选择使用 iframe 并希望支持 Apple Pay 或 Google Pay,则必须将 iframe 的 [allow](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allowpaymentrequest) 属性设置为`"payment *"`。 结账页面地址必须以 `https://` rather 开头,而非 `http://` for,您的集成才能正常工作。您可以在不使用 HTTPS 的情况下测试集成,但在准备接收真实付款时,请务必[启用 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) 实例时,将上一步的 [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) 传入 `options`: 认真处理客户端私钥,因为它会完成收款。不要记录它,而是把它嵌入到 URL,或显示给除客户以外的所有人。 ```javascript const options = { clientSecret: '{{CLIENT_SECRET}}', // Fully customizable with appearance API. appearance: {/*...*/}, }; // Set up Stripe.js and Elements to use in checkout form, passing the client secret obtained in a previous stepconst elements = stripe.elements(options); // Create and mount the Payment Element const paymentElementOptions = { layout: 'accordion'}; const paymentElement = elements.create('payment', paymentElementOptions); paymentElement.mount('#payment-element'); ``` #### 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` 提供程序。另外,将来自上一步的 [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_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 CheckoutForm from './CheckoutForm'; // 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 client secret obtained in step 3 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 CheckoutForm = () => { return (
); }; export default CheckoutForm; ``` Stripe Element 是嵌入式 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)。 ### 收集地址 默认情况下,Payment Element 只收集必要的账单地址详情。某些行为,如[计算税费](https://docs.stripe.com/api/tax/calculations/create.md) 或输入配送详情,则需要客户的完整地址。您可以: - 使用[Address Element](https://docs.stripe.com/elements/address-element.md),利用自动填充和本地化功能收集客户的完整地址。这有助于确保税款计算达到最高准确性。 - 使用您自己的自定义表单收集地址详情。 ### 申请 Apple Pay 商家令牌 如果您已将集成配置为[接受 Apple Pay 付款](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=elements&api-integration=checkout),我们建议配置 Apple Pay 界面以返回商户令牌,从而支持商户发起的交易 (MIT)。在 Payment Element 中[请求相关商户令牌类型](https://docs.stripe.com/apple-pay/merchant-tokens.md?pay-element=web-pe)。 ## 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 中保存支付方式 When creating a [PaymentIntent](https://docs.stripe.com/api/payment_intents/.md) on your server, also create a [CustomerSession](https://docs.stripe.com/api/customer_sessions/.md) providing the customer’s ID (using either `customer` for a `Customer` object or `customer_account` for a customer-configured `Account` object) and enabling the [payment_element](https://docs.stripe.com/api/customer_sessions/object.md#customer_session_object-components-payment_element) component for your session. Configure which saved payment method [features](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features) you want to enable. For instance, enabling [payment_method_save](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features-payment_method_save) displays a checkbox offering customers to save their payment details for future use. You can specify `setup_future_usage` on a PaymentIntent or Checkout Session to override the default behavior for saving payment methods. This ensures that you automatically save the payment method for future use, even if the customer doesn’t explicitly choose to save it. If you intend to specify `setup_future_usage`, don’t set `payment_method_save_usage` in the same payment transaction because this causes an integration error. > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is GA for Connect users, and in public preview for other Stripe users. All Stripe users can enable Accounts v2 [in their Dashboard](https://dashboard.stripe.com/settings/connect/platform-setup). However, when making calls to the Accounts v2 API, preview users need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning). > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/connect/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. Stripe.api_key = '<>' post '/create-intent-and-customer-session' do intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'usd', automatic_payment_methods: {enabled: true}, customer_account: {{CUSTOMER_ACCOUNT_ID}}, }) customer_session = Stripe::CustomerSession.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. Stripe.api_key = '<>' post '/create-intent-and-customer-session' do intent = Stripe::PaymentIntent.create({ amount: 1099, currency: 'usd', # 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 = Stripe::CustomerSession.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 客户端私钥,因为它是可选的。 使用PaymentIntent 和 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'); ``` > Allowing customers to remove their saved payment methods by enabling [payment_method_remove](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features-payment_method_remove) impacts subscriptions that depend on that payment method. Removing the payment method detaches the [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) from the object that represents the customer (either a customer-configured `Account` or a `Customer`). 确认 PaymentIntent 时,Stripe.js 会自动控制 PaymentIntent 上的 [setup_future_usage](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-setup_future_usage) 设置和 PaymentMethod 上的 [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay),具体取决于客户是否勾选保存其付款详情的框。 ### 强制重新收集卡安全码 (CVC) 可以选择在 [when creating the PaymentIntent](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-card-require_cvc_recollection) 指定 `require_cvc_recollection`,以在客户用银行卡支付时强制重新收集 CVC。 ### 检测选择的已保存支付方式 要在选择了保存的支付方式时控制动态内容,请侦听 Payment Element `change` 事件(该事件会填充上所选的支付方式)。 ```javascript paymentElement.on('change', function(event) { if (event.value.payment_method) { // Control dynamic content if a saved payment method is selected } }) ``` ## Optional: 结账页面中的链接 [客户端] 通过在 [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)。 ![结账时直接在 Payment Element 中验证或注册 Link](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 之后,您可能想更新 PaymentIntent 的属性,例如 [amount](https://docs.stripe.com/api/payment_intents/update.md#update_payment_intent-amount)(例如,折扣码或运费)。您可以在您的服务器上 [update the PaymentIntent](https://docs.stripe.com/api/payment_intents/update.md),然后调用 [elements.fetchUpdates](https://docs.stripe.com/js/elements_object/fetch_updates) 来查看 Payment Element 中反映的金额。该例显示了如何创建更新 PaymentIntent 上的金额的服务器端点: #### Ruby ```ruby get '/update' do intent = Stripe::PaymentIntent.update( '{{PAYMENT_INTENT_ID}}', {amount: 1499}, ) {status: intent.status}.to_json end ``` 该例演示了如何更新 UI 来在客户端体现这些变化。 ```javascript (async () => { const response = await fetch('/update'); if (response.status === 'requires_payment_method') { const {error} = await elements.fetchUpdates(); } })(); ``` ## 向 Stripe 提交付款 [客户端] 使用 [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment),用来自 Payment Element 的详情完成付款。为该函数提供一个 [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url),告诉 Stripe 在用户完成付款后将他们重定向到哪里。您的用户可能会先被重定向到一个中间站点,如银行授权页面,然后才被重定向到 `return_url`。付款成功时,银行卡付款将立即重定向到 `return_url`。 如果您不想在完成付款后对银行卡付款重定向,可以将[重定向](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_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.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, 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`. } }); ``` #### React 从您的支付表单组件调用 [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) 时,使用 [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) 和 [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-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 CheckoutForm = () => { 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; } const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, 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) 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 CheckoutForm; ``` 确保 `return_url` 对应于您网站上显示付款状态的一个页面。Stripe 将客户重定向到 `return_url` 时,我们会提供以下 URL 查询参数。 | 参数 | 描述 | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | `PaymentIntent` 的唯一标识符。 | | `payment_intent_client_secret` | `PaymentIntent` 对象的 [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret)。 | > 如果您有可以用来跟踪客户浏览器会话的工具,则您可能需要将 `stripe.com` 域名添加到推荐人列表。重定向会导致一些工具创建新的会话,从而阻止您跟踪完整的会话。 用以下某个查询参数检索 PaymentIntent。检查 [PaymentIntent 的状态](https://docs.stripe.com/payments/paymentintents/lifecycle.md),以决定向客户显示的内容。您还可以在提供 `return_url` 时附加自己的查询参数,它们会在重定向过程中持续存在。 #### HTML + JS ```javascript // Initialize Stripe.js using your publishable key const stripe = Stripe('<>'); // Retrieve the "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => { const message = document.querySelector('#message') // Inspect the PaymentIntent `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 (paymentIntent.status) { case 'succeeded': message.innerText = 'Success! Payment received.'; break; case 'processing': message.innerText = "Payment processing. We'll update you when payment is received."; break; case 'requires_payment_method': message.innerText = 'Payment failed. Please try another payment method.'; // Redirect your user back to your payment page to attempt collecting // payment again break; default: message.innerText = 'Something went wrong.'; break; } }); ``` #### React ```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 "payment_intent_client_secret" query parameter appended to // your return_url by Stripe.js const clientSecret = new URLSearchParams(window.location.search).get( 'payment_intent_client_secret' ); // Retrieve the PaymentIntent stripe .retrievePaymentIntent(clientSecret) .then(({paymentIntent}) => { // Inspect the PaymentIntent `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 (paymentIntent.status) { case 'succeeded': setMessage('Success! Payment received.'); break; case 'processing': setMessage("Payment processing. We'll update you when payment is received."); break; case 'requires_payment_method': // Redirect your user back to your payment page to attempt collecting // payment again setMessage('Payment failed. Please try another payment method.'); break; default: setMessage('Something went wrong.'); break; } }); }, [stripe]); return message; }; export default PaymentStatus; ``` ## 处理付款后事件 [服务器端] 付款完成时,Stripe 会发送一个 [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) 事件。使用 [管理平台 Webhook 工具](https://dashboard.stripe.com/webhooks)、或按照 [Webhook 指南](https://docs.stripe.com/webhooks/quickstart.md)来接收这些事件并运行操作,例如,向客户发送订单确认邮件、在数据库中记录订单,或启动配送流程。 侦听这些事件,而不是等待客户端回调。在客户端,客户可能会在执行回调之前关闭浏览器窗口或退出应用程序,并且恶意客户端可能会操纵响应。设置您的集成来侦听异步事件,这样才能用单一集成用用接受[不同类型的支付方式](https://stripe.com/payments/payment-methods-guide)。 除了处理 `payment_intent.succeeded` 事件外,建议在使用 Payment Element 收款时也处理其他的这些事件: | 事件 | 描述 | 操作 | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | 客户成功完成付款时发送。 | 向客户发送订单确认通知,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | 当客户成功发起付款但并未完成时发送。当客户发起银行借记时,通常会发送此事件。之后将会出现 `payment_intent.succeeded` 或 `payment_intent.payment_failed` 事件。 | 向客户发送订单确认,告知他们的付款正等待处理。对于数字商品,您可能想先履行订单,然后再等付款完成。 | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | 在客户尝试付款但付款失败时发送。 | 如果一笔付款从 `processing` 变为 `payment_failed`,则让客户再尝试一次。 | ## 测试您的集成 要测试您的自定义支付集成: 1. 创建 Payment Intent 并检索客户端私钥。 1. 使用下表中的方法填写付款详情。 - 输入一个任意的未来日期作为有效期。 - 输入 3 位数 CVC(银行卡安全码)。 - 输入账单地址邮编。 1. 向 Stripe 提交付款。您将被重定向到您的 `return_url`。 1. 前往管理平台,在[付款页面](https://dashboard.stripe.com/test/payments?status%5B0%5D=successful)上查找付款。如果您付款成功,就会在列表中看到它。 1. 点击您的付款,查看更多详情,例如账单信息及已购商品列表。您可以此信息来履行订单。 了解有关[测试您的集成](https://docs.stripe.com/testing.md)的更多信息。 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 钱包 | 支付方式 | 场景 | 如何测试 | | ------ | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | Alipay | 您的客户通过基于重定向和[立即通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | --------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | BECS 直接借记 | 您的客户成功用 BECS 直接借记完成付款。 | 使用帐号 `900123456` 和 BSB `000000` 填写表格。确认的 PaymentIntent 先转入 `processing`,3 分钟后转为 `succeeded` 状态。 | | BECS 直接借记 | 您的客户付款失败,错误代码为:`account_closed`。 | 使用帐号 `111111113` 和 BSB `000000` 填写表格。 | | Bancontact、EPS、iDEAL 和 Przelewy24 | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | #### 付款凭单 | 支付方式 | 场景 | 如何测试 | | ------------ | --------------------------- | ------------------------------------ | | Boleto, OXXO | 您的客户用 Boleto 或 OXXO 付款凭单付款。 | 选择 Boleto 或 OXXO 此支付方式并提交付款。出现后关闭对话。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 添加更多支付方式 Payment Element 默认[支持很多种支付方式](https://docs.stripe.com/payments/payment-methods/integration-options.md#choose-how-to-add-payment-methods)。需进行额外步骤才能启用并显示某些支付方式。 ### Affirm 开始使用 Affirm 时,必须在[管理平台](https://dashboard.stripe.com/settings/payment_methods)中启用它。用 Affirm 支付方式创建 PaymentIntent 时,您需要包含[收货地址](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-shipping)。该例建议在客户[选择了他们的支付方式](https://docs.stripe.com/payments/accept-a-payment.md#web-create-intent)后在客户端传递配送信息。进一步了解如何通过 Stripe 使用 [Affirm](https://docs.stripe.com/payments/affirm.md)。 #### HTML + JS ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://my-site.com/order/123/complete',shipping: { name: 'Jenny Rosen', address: { line1: '1 Street', city: 'Seattle', state: 'WA', postal_code: '95123', country: 'US' } }, } }); if (error) { // This point is reached if there's 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 is redirected to your `return_url`. For some payment // methods like iDEAL, your customer is redirected to an intermediate // site first to authorize the payment, then redirected to the `return_url`. } }); ``` #### React ```jsx import React, {useState} from 'react'; import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { 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; } const {error} = await stripe.confirmPayment({ //`Elements` instance that was used to create the Payment Element elements, confirmParams: { return_url: 'https://my-site.com/order/123/complete',shipping: { name: 'Jenny Rosen', address: { line1: '1 Street', city: 'Seattle', state: 'WA', postal_code: '95123', country: 'US' } }, } }); 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 CheckoutForm; ``` #### 测试 Affirm 了解如何通过下表测试不同场景: | 场景 | 如何测试 | | ------------------------ | --------------------------- | | 您的客户通过 Affirm 成功付款。 | 填写表单(务必包含收货地址)并授权付款。 | | 您的客户未在 Affirm 重定向页面进行验证。 | 填写表单,然后在重定向页面上点击**测试付款失败**。 | ### Afterpay (Clearpay) 用 Afterpay 支付方式创建 PaymentIntent 时,您需要包含[收货地址](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-shipping)。进一步了解如何通过 Stripe 使用 [Afterpay](https://docs.stripe.com/payments/afterpay-clearpay.md)。 您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。下面的例子使用了 [automatic_payment_methods](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-automatic_payment_methods-enabled) 属性,但您可以用 [payment method types](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_types) 列出 `afterpay_clearpay`。在最新版的 API 中,可以选择性指定 `automatic_payment_methods` 参数,因为 Stripe 会默认开启其功能。无论您选择哪个选项,一定要在[管理平台](https://dashboard.stripe.com/settings/payment_methods)中启用 Afterpay Clearpay。 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d "automatic_payment_methods[enabled]=true" \ -d "shipping[name]=Jenny Rosen" \ -d "shipping[address][line1]=1234 Main Street" \ -d "shipping[address][city]=San Francisco" \ -d "shipping[address][state]=CA" \ -d "shipping[address][country]=US" \ -d "shipping[address][postal_code]=94111" ``` #### 测试 Afterpay (Clearpay) 了解如何通过下表测试不同场景: | 场景 | 如何测试 | | -------------------------- | --------------------------- | | 您的客户通过 Afterpay 成功付款。 | 填写表单(务必包含收货地址)并授权付款。 | | 您的客户未在 Afterpay 重定向页面进行验证。 | 填写表单,然后在重定向页面上点击**测试付款失败**。 | ### Apple Pay 和 Google Pay 当您[启用银行卡支付](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=elements&api-integration=paymentintents#create-the-paymentintent)时,我们会为符合[钱包显示条件](https://docs.stripe.com/testing/wallets.md)的客户显示 Apple Pay 和 Google Pay。要接受来自这些钱包的付款,您还必须: - 在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用它们。Apple Pay 默认启用。 - 在 HTTPS 的开发和生产环境中为您的应用服务。 - [注册您的域名](https://docs.stripe.com/payments/payment-methods/pmd-registration.md)。 - 如果您更新了 [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) 的金额,请[从服务器获取更新](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=elements&api-integration=paymentintents#fetch-updates),以保持钱包支付模态同步。 > #### 区域测试 > > Stripe Elements 不支持印度 Stripe 账户和客户的 Google Pay 或 Apple Pay。因此,如果测试者的 IP 地址在印度,您就不能测试您的 Google Pay 或 Apple Pay 集成,即使 Stripe 账户是在印度境外开立的也一样。 进一步了解如何通过 Stripe 使用 [Apple Pay](https://docs.stripe.com/apple-pay.md) 和 [Google Pay](/google-pay](/google-pay)。 ### ACH 直接借记 通过ACH 直接借记支付方式使用 Payment Element 时,按照以下步骤操作: 1. 创建 [Customer 对象](https://docs.stripe.com/api/customers.md)。 ```curl curl -X POST https://api.stripe.com/v1/customers \ -u "<>:" ``` 1. 在创建 `PaymentIntent` 时指定客户 ID。 #### 账户 v2 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d setup_future_usage=off_session \ -d "customer_account={{CUSTOMERACCOUNT_ID}}" \ -d "payment_method_types[]=us_bank_account" ``` #### 客户 v1 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=usd \ -d setup_future_usage=off_session \ -d "customer={{CUSTOMER_ID}}" \ -d "payment_method_types[]=us_bank_account" ``` 1. 选择一个[验证方式](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-payment_method_options-us_bank_account-verification_method)。 通过 Payment Element 使用 ACH 直接借记支付方式时,您只能选择 `automatic` 或 `instant`。 进一步了解如何通过 Stripe 使用 [ACH 直接借记](https://docs.stripe.com/payments/ach-direct-debit.md)。 #### 测试 ACH 直接借记 | 场景 | 如何测试 | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 您的客户通过即时验证方式成功用美国银行账户完成付款。 | 选择**美国银行账户**并填写表单。点击测试机构。按照模态上的说明关联您的银行账户。点击您的付款按钮。 | | 您的客户通过微存款方式成功用美国银行账户完成付款。 | 选择**美国银行账户**并填写表格。点击**手动输入银行账户详情**。按照模态框中的说明关联您的银行账户。您可以使用这些[测试账户号码](https://docs.stripe.com/payments/ach-direct-debit/accept-a-payment.md?platform=web#test-account-numbers)。点击您的支付按钮。 | | 您的客户在完成银行账户关联过程时会失败。 | 选择 **美国银行账户** 并点击测试机构或 **改为手动输入银行详情** 。关闭模态,不要完成它。 | ### BLIK 结合使用 Payment Element 与 BLIK 时,用户可以关闭提示他们在其银行应用程序中授权付款的模态。这将触发向您的 `return_url` 重定向的操作,不会将客户返回到结账页面。进一步了解如何通过 Stripe 使用 [BLIK](https://docs.stripe.com/payments/blik.md)。 处理用户关闭模态的情况时,在您的 `return_url` 的服务器端处理程序上,观察 Payment Intent 的 `status`,看它是 `succeeded` 还是仍然为 `requires_action`(说明用户在未授权的情况下关闭了模态),然后根据实际情况酌情处理。 ### 二维码支付方式 通过特定支付方式(微信支付、PayNow、Pix、PromptPay、Cash App Pay)的二维码使用 Payment Element 时,用户可关闭二维码模态。这将触发向您的 `return_url` 重定向的操作,不会将客户返回到结账页面。 处理用户关闭二维码模态的情况时,在您的 `return_url` 的服务器端处理程序上,观察 Payment Intent 的 `status`,看它是 `succeeded` 还是仍然为 `requires_action`(说明用户在未支付的情况下关闭了模态),然后根据实际情况酌情处理。 或者,可通过传递高级可选参数 [`redirect=if_required`](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect),它可以防止在管理二维码模态时进行重定向,进而可防止自动重定向到您的 `return_url`。 ### Cash App Pay Payment Element 在桌面网页或移动端网页中以不同的方式呈现动态表单,因为它使用的是不同的客户身份验证方式。进一步了解如何通过 Stripe 使用 [Cash App Pay](https://docs.stripe.com/payments/cash-app-pay.md)。 #### 移动端网页应用程序元素 Cash App Pay 是一种基于重定向的移动端网页支付方式。它会将您的客户重定向到真实模式下的 Cash App 或测试模式下的测试页面。完成付款后,无论您是否设置了 `redirect=if_required`,它们都会被重定向到 `return_url`。 #### 桌面网页应用程序元素 Cash App Pay 是桌面网页中的一种二维码支付方式,其中 Payment Element 呈现一种二维码模态。您的客户需要用二维码扫描应用程序或 Cash App 移动应用程序来扫描二维码。 在真实模式下,一旦客户被重定向到 Cash App,它就会立即将客户重定向到 `return_url`。在测试环境下,他们可以在被重定向到 `return_url` 之前批准或拒绝付款。客户也可以在完成支付前关闭二维码模态,这将触发向您的 `return_url` 重定向的操作。 确保 `return_url` 对应于您的网站上检查 Payment Intent 的 `status` 的一个页面。Payment Intent `status` 可以是 `succeeded`、`failed` 或 `requires_action`(例如,客户已在未扫描二维码的情况下关闭模态)。 或者,可通过传递高级可选参数 `redirect=if_required`,它可以防止在管理二维码模态时进行重定向,进而可防止自动重定向到您的 `return_url`。 ### PayPal 要使用 PayPal,请务必使用[注册域名](https://docs.stripe.com/payments/payment-methods/pmd-registration.md)。 ## 向您的客户披露 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 - [Stripe Element](https://docs.stripe.com/payments/elements.md) - [设置未来付款](https://docs.stripe.com/payments/save-and-reuse.md) - [支付过程中保存付款详情](https://docs.stripe.com/payments/save-during-payment.md) - [在支付流程中计算销售税、商品及服务税和增值税](https://docs.stripe.com/tax/custom.md) # iOS 应用内集成 > This is a iOS 应用内集成 for when payment-ui is mobile and platform is ios. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=mobile&platform=ios. ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-overview.9e0d68d009dc005f73a6f5df69e00458.png) 用[PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html) 类将 Stripe 的预构建支付 UI 集成到您的 iOS 应用程序的结账流程。前往 [on GitHub](https://github.com/stripe/stripe-ios/tree/master/Example/PaymentSheet%20Example) 查看我们的集成示例。 ## 设置 Stripe [服务器端] [客户端] 首先,您需要有 Stripe 账户。[立即注册](https://dashboard.stripe.com/register)。 ### 服务器端 该集成要求您的服务器上的端点与 Stripe API 通讯。请用我们的官方库从您的服务器访问 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' ``` ### 客户端 [Stripe iOS SDK](https://github.com/stripe/stripe-ios) 是开源的,[有完整的文档](https://stripe.dev/stripe-ios/index.html),并且与支持 iOS 13 或更高版本操作系统的应用程序兼容。 #### Swift Package Manager 要安装 SDK,按这些步骤进行: 1. 在 Xcode 中,选择**文件** > **添加工具包依赖…**并输入 `https://github.com/stripe/stripe-ios-spm` 作为仓库 URL。 1. 从我们的[发布页面](https://github.com/stripe/stripe-ios/releases)选择最新的版本号。 1. 将 **StripePaymentSheet** 产品添加到[您的目标应用程序](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)。 #### CocoaPods 1. 如果您还没有[CocoaPods](https://guides.cocoapods.org/using/getting-started.html),请安装其最新版本。 1. 如果您目前没有 [Podfile](https://guides.cocoapods.org/syntax/podfile.html),请运行以下命令创建一个: ```bash pod init ``` 1. 将这一行代码添加到您的 `Podfile`: ```podfile pod 'StripePaymentSheet' ``` 1. 运行以下命令: ```bash pod install ``` 1. 今后,一定记得用 `.xcworkspace` 文件来打开您在 Xcode 中的项目,不要使用 `.xcodeproj` 文件。 1. 将来,要更新到 SDK 的最新版本,运行: ```bash pod update StripePaymentSheet ``` #### Carthage 1. 如果您还没有[Carthage](https://github.com/Carthage/Carthage#installing-carthage),请安装其最新版本。 1. 将这一行代码添加到您的 `Cartfile`。 ```cartfile github "stripe/stripe-ios" ``` 1. 按照 [Carthage 安装说明](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos)进行。确保嵌入[这里](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking)所列的所有必要框架。 1. 将来,要更新到 SDK 的最新版本,运行以下命令即可: ```bash carthage update stripe-ios --platform ios ``` #### 手动框架 1. 前往我们的 [GitHub 发布页面](https://github.com/stripe/stripe-ios/releases/latest),下载并解压缩 **Stripe.xcframework.zip**。 1. 将 **StripePaymentSheet.xcframework** 拖拽到您的 Xcode 项目中 **General**(常规)设置的 **Embedded Binaries**(嵌入式二进制文件)部分。一定要选择 **Copy items if needed**(需要时复制项目)。 1. 为[这里](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking)所列的所有必要框架重复第 2 步。 1. 将来,要更新到 SDK 的最新版本,重复第 1-3 步。 > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-ios/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository)。 ## 启用支付方式 查看您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods),启用您想支持的支付方式。您至少需要启用一个支付方式才能创建 *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods)。 默认情况下,Stripe 支持信用卡和其他常见的支付方式,可以帮助您获得更多客户,但建议您开启与您的业务和客户相关的其他支付方式。查看[支付方式支持](https://docs.stripe.com/payments/payment-methods/payment-method-support.md),了解支持的产品和支付方式,并查看我们的[定价页面](https://stripe.com/pricing/local-payment-methods)了解费用。 ## 添加端点 [服务器端] > #### 注意 > > 要在创建 PaymentIntent 之前显示 PaymentSheet,请参阅[收集支付详情后再创建 Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment)。 If your integration uses [customer-configured Accounts](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), replace `Customer` and event references in the code examples with the equivalent Accounts v2 API references. For more information, see [Represent customers with Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md). 该集成使用三个 Stripe API 对象: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md):Stripe 用它来表示您从客户收款的意图,跟踪您的扣款尝试及整个过程中付款状态的变化情况。 1. (可选)[Customer](https://docs.stripe.com/api/customers.md):要为将来的付款设置支付方式,就必须将它绑定到 *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments)。当客户在您的公司创建账户时,创建 Customer 对象。如果您的客户以访客身份付款,则可以在付款前创建个 Customer 对象,然后再将它关联到您自己内部的客户账户表示。 1. (可选)[CustomerSession](https://docs.stripe.com/api/customer_sessions.md):Customer 对象上的信息为敏感信息,不能直接从应用中检索。CustomerSession 授予 SDK 对 Customer 的临时范围访问权限,并提供其他配置选项。查看完整的 [configuration options](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components)列表。 > 如果您从不将银行卡保存到客户,并且不允许回头客重复使用已保存的银行卡,则可以从集成中省略 Customer 和 CustomerSession 对象。 出于安全原因,您的应用无法创建这些对象。相反,在服务器上会添加一个端点,其功能如下: 1. 检索 Customer,或新建一个。 1. 为 Customer 创建一个 [CustomerSession](https://docs.stripe.com/api/customer_sessions.md)。 1. 创建 PaymentIntent,设置好 [amount](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount)、[currency](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency) 和 [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer)。 1. 将 Payment Intent 的*客户端私钥* (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))、CustomerSession 的 `client_secret` 以及 Customer 的 [id](https://docs.stripe.com/api/customers/object.md#customer_object-id) 和您的[公钥](https://dashboard.stripe.com/apikeys)返回到您的应用程序。 在结账过程中显示给客户的支付方式也包含在 PaymentIntent 中。您可以让 Stripe 从管理平台设置中提取支付方式,也可以手动列出它们。无论选择哪种方式,都要知道在 PaymentIntent 中传递的货币会过滤显示给客户的支付方式。例如,如果您在 PaymentIntent 中传递 `eur`,并且在管理平台中启用了 OXXO,则不会向客户显示 OXXO,因为 OXXO 不支持 `eur` 支付。 除非您的集成需要基于代码的选项来提供支付方式,否则 Stripe 建议使用自动选项。这是因为 Stripe 会评估货币、支付方式限制和其他参数,以确定支持的支付方式列表。优先显示可提高转化率且与货币和客户所在地最相关的支付方式。 #### 从管理平台管理支付方式 您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。PaymentIntent 是用您在管理平台中配置的支付方式创建的。如不想使用管理平台或想手动指定支付方式,可通过 `payment_method_types` 属性将其列出。 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. -d "automatic_payment_methods[enabled]"=true \ ``` #### 手动列出支付方式 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact" \ -d "payment_method_types[]"="card" \ -d "payment_method_types[]"="ideal" \ -d "payment_method_types[]"="klarna" \ -d "payment_method_types[]"="sepa_debit" \ ``` > 每个支付方式都要支持在 PaymentIntent 中传递的货币,且您的公司必须要位于各支付方式支持的某个国家/地区。查看[支付方式集成选项](https://docs.stripe.com/payments/payment-methods/integration-options.md)页面,查看具体支持哪些。 ## 收集付款详情 [客户端] 要在结账屏幕上显示移动 Payment Element,您必须确保: - 显示客户正在购买的产品以及总金额 - 用 [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios) 从客户那里收集所需的配送信息 - 添加结账按钮以显示 Stripe 的 UI #### UIKit 在您的应用结账界面中,从您在上一步中创建的端点中获取 PaymentIntent 客户端私钥、CustomerSession 客户端私钥、客户 ID 和可发布密钥。使用 `STPAPIClient.shared` 设置您的可发布密钥并初始化 [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html)。 #### iOS (Swift) ```swift import UIKit@_spi(CustomerSessionBetaAccess) import StripePaymentSheet class CheckoutViewController: UIViewController { @IBOutlet weak var checkoutButton: UIButton! var paymentSheet: PaymentSheet? let backendCheckoutUrl = URL(string: "Your backend endpoint/payment-sheet")! // Your backend endpoint override func viewDidLoad() { super.viewDidLoad() checkoutButton.addTarget(self, action: #selector(didTapCheckoutButton), for: .touchUpInside) checkoutButton.isEnabled = false // MARK: Fetch the PaymentIntent client secret, CustomerSession client secret, Customer ID, and publishable key var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) DispatchQueue.main.async { self.checkoutButton.isEnabled = true } }) task.resume() } } ``` 当客户点击**结账**按钮时,调用 `present` 以显示 PaymentSheet。在客户完成支付后,Stripe 会关闭 PaymentSheet,并使用 [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html) 调用完成块。 #### iOS (Swift) ```swift @objc func didTapCheckoutButton() { // MARK: Start the checkout process paymentSheet?.present(from: self) { paymentResult in // MARK: Handle the payment result switch paymentResult { case .completed: print("Your order is confirmed") case .canceled: print("Canceled!") case .failed(let error): print("Payment failed: \(error)") } } } ``` #### SwiftUI 为您的结账界面创建一个 `ObservableObject` 模块。此模型发布 [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html) 和 [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html)。 ```swift import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your backend endpoint/payment-sheet")! // Your backend endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? } ``` 从您在上一步中创建的端点中获取 PaymentIntent 客户端私钥、CustomerSession 客户端私钥、客户 ID 和可发布密钥。使用 `STPAPIClient.shared` 设置您的可发布密钥并初始化 [PaymentSheet](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet.html)。 ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your backend endpoint/payment-sheet")! // Your backend endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch thePaymentIntent and Customer information from the backend var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, letpaymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey// MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret:paymentIntentClientSecret, configuration: configuration) } }) task.resume() } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack { if model.paymentSheet != nil { Text("Ready to pay.") } else { Text("Loading…") } }.onAppear { model.preparePaymentSheet() } } } ``` 向您的 `View` 添加 [PaymentSheet.PaymentButton](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/PaymentButton.html)。该行为类似于 SwiftUI `Button`,它允许您通过添加 `View` 来进行定制。点击该按钮时,会显示 PaymentSheet。在完成支付后,Stripe 会关闭 PaymentSheet,并使用 [PaymentSheetResult](https://stripe.dev/stripe-ios/stripe-paymentsheet/Enums/PaymentSheetResult.html) 对象调用 `onCompletion` 处理程序。 ```swift @_spi(CustomerSessionBetaAccess) import StripePaymentSheet import SwiftUI class CheckoutViewModel: ObservableObject { let backendCheckoutUrl = URL(string: "Your backend endpoint/payment-sheet")! // Your backend endpoint @Published var paymentSheet: PaymentSheet? @Published var paymentResult: PaymentSheetResult? func preparePaymentSheet() { // MARK: Fetch the PaymentIntent and Customer information from the backend var request = URLRequest(url: backendCheckoutUrl) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any], let customerId = json["customer"] as? String, let customerSessionClientSecret = json["customerSessionClientSecret"] as? String, let paymentIntentClientSecret = json["paymentIntent"] as? String, let publishableKey = json["publishableKey"] as? String, let self = self else { // Handle error return } STPAPIClient.shared.publishableKey = publishableKey // MARK: Create a PaymentSheet instance var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "Example, Inc." configuration.customer = .init(id: customerId, customerSessionClientSecret: customerSessionClientSecret) // Set `allowsDelayedPaymentMethods` to true if your business can handle payment methods // that complete payment after a delay, like SEPA Debit and Sofort. configuration.allowsDelayedPaymentMethods = true DispatchQueue.main.async { self.paymentSheet = PaymentSheet(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) } }) task.resume() } func onPaymentCompletion(result: PaymentSheetResult) { self.paymentResult = result } } struct CheckoutView: View { @ObservedObject var model = CheckoutViewModel() var body: some View { VStack {if let paymentSheet = model.paymentSheet { PaymentSheet.PaymentButton( paymentSheet: paymentSheet, onCompletion: model.onPaymentCompletion ) { Text("Buy") } } else { Text("Loading…") }if let result = model.paymentResult { switch result { case .completed: Text("Payment complete") case .failed(let error): Text("Payment failed: \(error.localizedDescription)") case .canceled: Text("Payment canceled.") } } }.onAppear { model.preparePaymentSheet() } } } ``` 如果 `PaymentSheetResult` 是 `.completed`,则通知用户(例如,显示订单确认界面)。 将 `allowsDelayedPaymentMethods` 设置为 true,以允许[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)支付方式,例如美国银行账户。对于这些支付方式,只有当 `PaymentSheet` 完成后才能知道最终的付款状态是成功还是失败。如果您支持这些类型的支付方式,请告知客户他们的订单已被确认,并且仅在付款成功时履行订单(例如,为他们安排发货)。 ## 设置返回页面 [客户端] 客户可能会离开您的应用来验证(例如,去 Safari 或他们的网银应用)。若允许他们在验证后自动返回到您的应用,[配置一个自定义页面内跳转协议 (URL Scheme)](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app),并设置您的应用程序代理将 URL 转发到 SDK。Stripe 不支持[通用链接](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content)。 #### SceneDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } let stripeHandled = StripeAPI.handleURLCallback(with: url) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } ``` #### AppDelegate #### Swift ```swift // This method handles opening custom URL schemes (for example, "your-app://stripe-redirect") func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { let stripeHandled = StripeAPI.handleURLCallback(with: url) if (stripeHandled) { return true } else { // This was not a Stripe url – handle the URL normally as you would } return false } ``` #### SwiftUI #### Swift ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { Text("Hello, world!").onOpenURL { incomingURL in let stripeHandled = StripeAPI.handleURLCallback(with: incomingURL) if (!stripeHandled) { // This was not a Stripe url – handle the URL normally as you would } } } } } ``` 此外,将您的 [PaymentSheet.Configuration](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html) 对象上的 [returnURL](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV9returnURLSSSgvp) 设置到您的应用的 URL。 ```swift var configuration = PaymentSheet.Configuration() configuration.returnURL = "your-app://stripe-redirect" ``` ## 处理付款后事件 [服务器端] 付款完成时,Stripe 会发送一个 [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) 事件。使用 [管理平台 Webhook 工具](https://dashboard.stripe.com/webhooks)、或按照 [Webhook 指南](https://docs.stripe.com/webhooks/quickstart.md)来接收这些事件并运行操作,例如,向客户发送订单确认邮件、在数据库中记录订单,或启动配送流程。 侦听这些事件,而不是等待客户端回调。在客户端,客户可能会在执行回调之前关闭浏览器窗口或退出应用程序,并且恶意客户端可能会操纵响应。设置您的集成来侦听异步事件,这样才能用单一集成用用接受[不同类型的支付方式](https://stripe.com/payments/payment-methods-guide)。 除了处理 `payment_intent.succeeded` 事件外,建议在使用 Payment Element 收款时也处理其他的这些事件: | 事件 | 描述 | 操作 | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | 客户成功完成付款时发送。 | 向客户发送订单确认通知,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | 当客户成功发起付款但并未完成时发送。当客户发起银行借记时,通常会发送此事件。之后将会出现 `payment_intent.succeeded` 或 `payment_intent.payment_failed` 事件。 | 向客户发送订单确认,告知他们的付款正等待处理。对于数字商品,您可能想先履行订单,然后再等付款完成。 | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | 在客户尝试付款但付款失败时发送。 | 如果一笔付款从 `processing` 变为 `payment_failed`,则让客户再尝试一次。 | ## 测试集成 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | ----------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 启用 Link 在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用 Link,让客户可以通过 Link 的一键快速结账按钮,安全地保存并重复使用其支付信息。 ### 将客户的邮件地址传递到 Mobile Payment Element Link 通过客户的电子邮件地址进行身份验证。Stripe 建议尽可能预填信息,以简化结账流程。 要预先填充客户的姓名、邮件地址和电话号码,请在初始化 `PaymentSheet.Configuration` 后提供包含客户信息的 `defaultBillingDetails`。 ```swift var configuration = PaymentSheet.Configuration() configuration.defaultBillingDetails.name = "Jenny Rosen" configuration.defaultBillingDetails.email = "jenny.rosen@example.com" configuration.defaultBillingDetails.phone = "888-888-8888" ``` ## Optional: 启用 Apple Pay > 如果您的结账界面有专门的 **Apple Pay** 按钮,则按照 [Apple Pay 指南](https://docs.stripe.com/apple-pay.md#present-payment-sheet)中的说明并使用 `ApplePayContext` 从您的 Apple Pay 按钮收款。您可以用 `PaymentSheet` 来处理其他支付方式类型。 ### 注册 Apple Merchant ID 可通过在 Apple 开发人员网站[注册新的标识符](https://developer.apple.com/account/resources/identifiers/add/merchant)来获取 Apple 商家 ID。 在表单中填写描述和标识符。描述内容仅供您自己记录之用,之后可随时更改。Stripe 建议用您的应用的名称作为标识符(例如,`merchant.com.{{YOUR_APP_NAME}}`)。 ### 创建新的 Apple Pay 证书 为您的应用创建证书,以加密支付数据。 转到管理平台中的 [iOS 证书设置](https://dashboard.stripe.com/settings/ios_certificates),点击**添加新应用程序**,然后按照说明进行操作。 下载证书签名请求 (CSR) 文件,来从 Apple 获取安全证书,以便使用 Apple Pay。 必须用一个 CSR 文件发布具体的一个证书。如果您切换您的 Apple Merchant ID,则必须前往管理平台的 [iOS 证书设置](https://dashboard.stripe.com/settings/ios_certificates)中获取一个新的 CSR 和证书。 ### 集成 Xcode 将 Apple Pay 功能添加到您的应用程序。在 Xcode 中,打开您的项目设置,点击**签名和功能**选项卡,然后添加 **Apple Pay** 功能。此时,系统可能会提示您登入您的开发人员账户。选择您之前创建的商家 ID,您的应用程序就可以接受 Apple Pay 了。 ![](https://b.stripecdn.com/docs-statics-srv/assets/xcode.a701d4c1922d19985e9c614a6f105bf1.png) 在 Xcode 中启用 Apple Pay 功能 ### 添加 Apple Pay #### 一次性付款 要将 Apple Pay 添加到 PaymentSheet,用您的 Apple 商家 ID 和[国家/地区代码](https://dashboard.stripe.com/settings/account)初始化 `PaymentSheet.Configuration` 之后设置 [applePay](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV8applePayAC05ApplefD0VSgvp)。 #### iOS (Swift) ```swift var configuration = PaymentSheet.Configuration() configuration.applePay = .init( merchantId: "merchant.com.your_app_name", merchantCountryCode: "US" ) ``` #### 经常性付款 要将 Apple Pay 添加到 PaymentSheet,用您的 Apple 商家 ID 和[国家/地区代码](https://dashboard.stripe.com/settings/account)初始化 `PaymentSheet.Configuration` 之后设置 [applePay](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:6Stripe12PaymentSheetC13ConfigurationV8applePayAC05ApplefD0VSgvp)。 对于经常性付款,根据 [Apple 的指南](https://developer.apple.com/design/human-interface-guidelines/apple-pay#Supporting-subscriptions),您还必须在 `PKPaymentRequest` 上设置额外的属性。在 [ApplePayConfiguration.paymentRequestHandlers](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/paymentrequesthandler) 中添加一个处理程序,以配置 [PKPaymentRequest.paymentSummaryItems](https://developer.apple.com/documentation/passkit/pkpaymentrequest/1619231-paymentsummaryitems),指定您期望收取的金额(例如,“每月 9.95 美元”)。 还可以通过在 `PKPaymentRequest` 上设置 `recurringPaymentRequest` 或 `automaticReloadPaymentRequest` 属性来采用[商家令牌](https://developer.apple.com/apple-pay/merchant-tokens/)。 要了解有关如何通过 Apple Pay 使用经常性付款的更多信息,请参阅 [Apple 的 PassKit 文档](https://developer.apple.com/documentation/passkit/pkpaymentrequest)。 #### iOS (Swift) ```swift let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( paymentRequestHandler: { request in // PKRecurringPaymentSummaryItem is available on iOS 15 or later if #available(iOS 15.0, *) { let billing = PKRecurringPaymentSummaryItem(label: "My Subscription", amount: NSDecimalNumber(string: "59.99")) // Payment starts today billing.startDate = Date() // Payment ends in one year billing.endDate = Date().addingTimeInterval(60 * 60 * 24 * 365) // Pay once a month. billing.intervalUnit = .month billing.intervalCount = 1 // recurringPaymentRequest is only available on iOS 16 or later if #available(iOS 16.0, *) { request.recurringPaymentRequest = PKRecurringPaymentRequest(paymentDescription: "Recurring", regularBilling: billing, managementURL: URL(string: "https://my-backend.example.com/customer-portal")!) request.recurringPaymentRequest?.billingAgreement = "You'll be billed $59.99 every month for the next 12 months. To cancel at any time, go to Account and click 'Cancel Membership.'" } request.paymentSummaryItems = [billing] request.currencyCode = "USD" } else { // On older iOS versions, set alternative summary items. request.paymentSummaryItems = [PKPaymentSummaryItem(label: "Monthly plan starting July 1, 2022", amount: NSDecimalNumber(string: "59.99"), type: .final)] } return request } ) var configuration = PaymentSheet.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ### 订单跟踪 要在 iOS 16 或更高版本中添加[订单跟踪](https://developer.apple.com/design/human-interface-guidelines/technologies/wallet/designing-order-tracking)信息,请在您的 `PaymentSheet.ApplePayConfiguration.Handlers` 中配置一个 [authorizationResultHandler](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/applepayconfiguration/handlers/authorizationresulthandler)。Stripe 会在支付完成后调用您的实施的程序,但该操作在 iOS 关闭 Apple Pay 表单之前进行。 在您的 `authorizationResultHandler` 实现中,从服务器获取已完成订单的订单详情。将这些详情添加到提供的 [PKPaymentAuthorizationResult](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationresult) 中,并返回修改后的结果。 要了解有关订单跟踪的更多信息,请参阅 [Apple 钱包订单文档](https://developer.apple.com/documentation/walletorders)。 #### iOS (Swift) ```swift let customHandlers = PaymentSheet.ApplePayConfiguration.Handlers( authorizationResultHandler: { result in do { // Fetch the order details from your service let myOrderDetails = try await MyAPIClient.shared.fetchOrderDetails(orderID: orderID) result.orderDetails = PKPaymentOrderDetails( orderTypeIdentifier: myOrderDetails.orderTypeIdentifier, // "com.myapp.order" orderIdentifier: myOrderDetails.orderIdentifier, // "ABC123-AAAA-1111" webServiceURL: myOrderDetails.webServiceURL, // "https://my-backend.example.com/apple-order-tracking-backend" authenticationToken: myOrderDetails.authenticationToken) // "abc123" // Return your modified PKPaymentAuthorizationResult return result } catch { return PKPaymentAuthorizationResult(status: .failure, errors: [error]) } } ) var configuration = PaymentSheet.Configuration() configuration.applePay = .init(merchantId: "merchant.com.your_app_name", merchantCountryCode: "US", customHandlers: customHandlers) ``` ## 启用银行卡扫描 若要在 iOS 上启用卡片扫描支持,请在应用程序的 `Info.plist` 中设置 `NSCameraUsageDescription`(**隐私 - 相机使用说明**),并提供访问相机的原因(例如,“用于扫描卡片”)。 ## Optional: 启用 ACH 付款 要启用 ACH 借记付款,请将 `StripeFinancialConnections` 作为您的应用的依赖项。 [Stripe iOS SDK](https://github.com/stripe/stripe-ios) 是开源的,[有完整的文档](https://stripe.dev/stripe-ios/index.html),并且与支持 iOS 13 或更高版本操作系统的应用程序兼容。 #### Swift Package Manager 要安装 SDK,按这些步骤进行: 1. 在 Xcode 中,选择**文件** > **添加工具包依赖…**并输入 `https://github.com/stripe/stripe-ios-spm` 作为仓库 URL。 1. 从我们的[发布页面](https://github.com/stripe/stripe-ios/releases)选择最新的版本号。 1. 将 **StripeFinancialConnections** 产品添加到[您的目标应用程序](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)。 #### CocoaPods 1. 如果您还没有[CocoaPods](https://guides.cocoapods.org/using/getting-started.html),请安装其最新版本。 1. 如果您目前没有 [Podfile](https://guides.cocoapods.org/syntax/podfile.html),请运行以下命令创建一个: ```bash pod init ``` 1. 将这一行代码添加到您的 `Podfile`: ```podfile pod 'StripeFinancialConnections' ``` 1. 运行以下命令: ```bash pod install ``` 1. 今后,一定记得用 `.xcworkspace` 文件来打开您在 Xcode 中的项目,不要使用 `.xcodeproj` 文件。 1. 将来,要更新到 SDK 的最新版本,运行: ```bash pod update StripeFinancialConnections ``` #### Carthage 1. 如果您还没有[Carthage](https://github.com/Carthage/Carthage#installing-carthage),请安装其最新版本。 1. 将这一行代码添加到您的 `Cartfile`。 ```cartfile github "stripe/stripe-ios" ``` 1. 按照 [Carthage 安装说明](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos)进行。确保嵌入[这里](https://github.com/stripe/stripe-ios/tree/master/StripeFinancialConnections/README.md#manual-linking)所列的所有必要框架。 1. 将来,要更新到 SDK 的最新版本,运行以下命令即可: ```bash carthage update stripe-ios --platform ios ``` #### 手动框架 1. 前往我们的 [GitHub 发布页面](https://github.com/stripe/stripe-ios/releases/latest),下载并解压缩 **Stripe.xcframework.zip**。 1. 将 **StripeFinancialConnections.xcframework** 拖拽到您的 Xcode 项目中 **General**(常规)设置的 **Embedded Binaries**(嵌入式二进制文件)部分。一定要选择 **Copy items if needed**(需要时复制项目)。 1. 为[这里](https://github.com/stripe/stripe-ios/tree/master/StripeFinancialConnections/README.md#manual-linking)所列的所有必要框架重复第 2 步。 1. 将来,要更新到 SDK 的最新版本,重复第 1-3 步。 > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-ios/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布](https://help.github.com/en/articles/watching-and-unwatching-releases-for-a-repository#watching-releases-for-a-repository)。 ## Optional: 自定义表单 所有自定义操作均通过 [PaymentSheet.Configuration](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html) 对象来配置。 ### 外观 使用 [Appearance API](https://docs.stripe.com/elements/appearance-api/mobile.md?platform=ios) 自定义颜色、字体等,使其与应用程序的视觉风格相匹配。 ### 支付方式布局 使用 [paymentMethodLayout](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/configuration-swift.struct/paymentmethodlayout) 配置表单中支付方式的布局。可以水平、垂直显示,也可以让 Stripe 自动优化布局。 ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-mpe-payment-method-layouts.9d0513e2fcec5660378ba1824d952054.png) #### Swift ```swift var configuration = PaymentSheet.Configuration() configuration.paymentMethodLayout = .automatic ``` ### 收集用户地址 用 [Address Element](https://docs.stripe.com/elements/address-element.md?platform=ios) 收集客户的本地和国际收货地址或账单地址。 ### 商家显示名称 通过设置 [merchantDisplayName](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:18StripePaymentSheet0bC0C13ConfigurationV19merchantDisplayNameSSvp) 来指定一个向客户显示的商家名称。默认情况下,使用的是您的应用的名称。 #### Swift ```swift var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "My app, Inc." ``` ### 暗色模式 `PaymentSheet` 自动适应用户的系统范围内的外观设置(明暗模式)。如果您的应用不支持暗色模式,可将 [style](https://stripe.dev/stripe-ios/stripe-paymentsheet/Classes/PaymentSheet/Configuration.html#/s:18StripePaymentSheet0bC0C13ConfigurationV5styleAC18UserInterfaceStyleOvp) 设置到 `alwaysLight` 或 `alwaysDark` 模式。 ```swift var configuration = PaymentSheet.Configuration() configuration.style = .alwaysLight ``` ## Optional: 处理用户的退出动作 `PaymentSheet` 会在本地存储一些信息,用于记住用户是否在应用中使用过 Link。当用户退出登录时,请调用 `PaymentSheet.resetCustomer()` 方法以清除 `PaymentSheet` 的内部状态。 ```swift import UIKit import StripePaymentSheet class MyViewController: UIViewController { @objc func didTapLogoutButton() { PaymentSheet.resetCustomer() // Other logout logic required by your app } } ``` ## Optional: 在您的用户界面完成付款 您可以在出示支付表单时仅收集支付方式详情,然后再在您的应用的用户界面上调用 `confirm` 方法来完成付款。如果您使用自定义购买按钮,或在收集了付款详情后需要额外的步骤,这会非常有用。 ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-multi-step.cd631ea4f1cd8cf3f39b6b9e1e92b6c5.png) 在您的应用程序的用户界面内完成付款 #### UIKit 以下步骤将引导您在您的应用程序的用户界面内完成付款。前往 [GitHub](https://github.com/stripe/stripe-ios/blob/master/Example/PaymentSheet%20Example/PaymentSheet%20Example/ExampleCustomCheckoutViewController.swift) 查看我们的示例集成。 1. 首先,初始化 [PaymentSheet.FlowController](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller),而非 `PaymentSheet`,并用它的 `paymentOption` 属性更新您的用户界面。该属性包含表示客户最初选择的默认支付方式的图片和标签。 ```swift PaymentSheet.FlowController.create(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) { [weak self] result in switch result { case .failure(let error): print(error) case .success(let paymentSheetFlowController): self?.paymentSheetFlowController = paymentSheetFlowController // Update your UI using paymentSheetFlowController.paymentOption } } ``` 1. 然后,调用 `presentPaymentOptions` 来收集付款详情。完成后,用 `paymentOption` 属性再次更新您的用户界面。 ```swift paymentSheetFlowController.presentPaymentOptions(from: self) { // Update your UI using paymentSheetFlowController.paymentOption } ``` 1. 最后,调用 `confirm`。 ```swift paymentSheetFlowController.confirm(from: self) { paymentResult in // MARK: Handle the payment result switch paymentResult { case .completed: print("Payment complete!") case .canceled: print("Canceled!") case .failed(let error): print(error) } } ``` #### SwiftUI 以下步骤将引导您在您的应用程序的用户界面内完成付款。前往 [GitHub](https://github.com/stripe/stripe-ios/blob/master/Example/PaymentSheet%20Example/PaymentSheet%20Example/ExampleSwiftUICustomPaymentFlow.swift) 查看我们的示例集成。 1. 首先,初始化 [PaymentSheet.FlowController](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller),而非 `PaymentSheet`。它的 `paymentOption` 属性包含表示客户当前选择的支付方式的图片和标签,可在您的用户界面内使用。 ```swift PaymentSheet.FlowController.create(paymentIntentClientSecret: paymentIntentClientSecret, configuration: configuration) { [weak self] result in switch result { case .failure(let error): print(error) case .success(let paymentSheetFlowController): self?.paymentSheetFlowController = paymentSheetFlowController // Use the paymentSheetFlowController.paymentOption properties in your UI myPaymentMethodLabel = paymentSheetFlowController.paymentOption?.label ?? "Select a payment method" myPaymentMethodImage = paymentSheetFlowController.paymentOption?.image ?? UIImage(systemName: "square.and.pencil")! } } ``` 1. 用 [PaymentSheet.FlowController.PaymentOptionsButton](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller/paymentoptionsbutton) 包裹表示付款详情收集表单的按钮。当 `PaymentSheet.FlowController` 调用 `onSheetDismissed` 函数时,`PaymentSheet.FlowController` 实例的 `paymentOption` 会反映当前选择的支付方式。 ```swift PaymentSheet.FlowController.PaymentOptionsButton( paymentSheetFlowController: paymentSheetFlowController, onSheetDismissed: { myPaymentMethodLabel = paymentSheetFlowController.paymentOption?.label ?? "Select a payment method" myPaymentMethodImage = paymentSheetFlowController.paymentOption?.image ?? UIImage(systemName: "square.and.pencil")! }, content: { /* An example button */ HStack { Text(myPaymentMethodLabel) Image(uiImage: myPaymentMethodImage) } } ) ``` 1. 用 [PaymentSheet.FlowController.PaymentOptionsButton](https://stripe.dev/stripe-ios/stripepaymentsheet/documentation/stripepaymentsheet/paymentsheet/flowcontroller/paymentoptionsbutton) 包裹付款确认按钮。 ```swift PaymentSheet.FlowController.ConfirmButton( paymentSheetFlowController: paymentSheetFlowController, onCompletion: { result in // MARK: Handle the payment result switch result { case .completed: print("Payment complete!") case .canceled: print("Canceled!") case .failed(let error): print(error) } }, content: { /* An example button */ Text("Pay") } ) ``` 将 `allowsDelayedPaymentMethods` 设置为 true,以允许[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)支付方式,例如美国银行账户。对于这些支付方式,只有当 `PaymentSheet` 完成后才能知道最终的付款状态是成功还是失败。如果您支持这些类型的支付方式,请告知客户他们的订单已被确认,并且仅在付款成功时履行订单(例如,为他们安排发货)。 ## Optional: 启用确认时的 CVC 重新收集流程 以下有关在确认 PaymentIntent 的过程中重新收集已保存卡的 CVC 的说明假定的是您的集成包含以下内容: - 在收集支付详情之前创建 PaymentIntent ### 更新意图创建参数 要在确认付款时重新收集 CVC,请在创建 PaymentIntent 的过程中包含 `require_cvc_recollection`。 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an Ephemeral Key for the Customer curl https://api.stripe.com/v1/ephemeral_keys \ -u <>: \ -H "Stripe-Version: 2026-03-25.dahlia" \ -H "Stripe-Account: 2026-03-25.dahlia" \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \-d "payment_method_options[card][require_cvc_recollection]"=true \ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. -d "automatic_payment_methods[enabled]"=true \ ``` # Android 应用内集成 > This is a Android 应用内集成 for when payment-ui is mobile and platform is android. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=mobile&platform=android. ![](https://b.stripecdn.com/docs-statics-srv/assets/android-overview.471eaf89a760f5b6a757fd96b6bb9b60.png) 用 [PaymentSheet](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html) 类将 Stripe 的预构建支付 UI 集成到您的 Android 应用程序的结账流程。 ## 设置 Stripe [服务器端] [客户端] 首先,您需要有 Stripe 账户。[立即注册](https://dashboard.stripe.com/register)。 ### 服务器端 该集成要求您的服务器上的端点与 Stripe API 通讯。请用官方库从您的服务器访问 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' ``` ### 客户端 [Stripe Android SDK](https://github.com/stripe/stripe-android) 是开源的,且[有完整的文档](https://stripe.dev/stripe-android/)。 安装 SDK 时,将 `stripe-android` 添加到您的 [app/build.gradle](https://developer.android.com/studio/build/dependencies) 文件的 `dependencies` 块中: #### Kotlin ```kotlin plugins { id("com.android.application") } android { ... } dependencies { // ... // Stripe Android SDK implementation("com.stripe:stripe-android:23.2.0") // Include the financial connections SDK to support US bank account as a payment method implementation("com.stripe:financial-connections:23.2.0") } ``` > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-android/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布情况](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository)。 ## 启用支付方式 查看您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods),启用您想支持的支付方式。您至少需要启用一个支付方式才能创建 *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods)。 默认情况下,Stripe 支持信用卡和其他常见的支付方式,可以帮助您获得更多客户,但建议您开启与您的业务和客户相关的其他支付方式。查看[支付方式支持](https://docs.stripe.com/payments/payment-methods/payment-method-support.md),了解支持的产品和支付方式,并查看我们的[定价页面](https://stripe.com/pricing/local-payment-methods)了解费用。 ## 添加端点 [服务器端] > #### 注意 > > 要在创建 PaymentIntent 之前显示 PaymentSheet,请参阅[收集支付详情后再创建 Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment)。 If your integration uses [customer-configured Accounts](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), replace `Customer` and event references in the code examples with the equivalent Accounts v2 API references. For more information, see [Represent customers with Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md). 该集成使用三个 Stripe API 对象: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md):Stripe 用它来表示您从客户收款的意图,跟踪您的扣款尝试及整个过程中付款状态的变化情况。 1. (可选)[Customer](https://docs.stripe.com/api/customers.md):要为将来的付款设置支付方式,就必须将它绑定到 *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments)。当客户在您的公司创建账户时,创建 Customer 对象。如果您的客户以访客身份付款,则可以在付款前创建个 Customer 对象,然后再将它关联到您自己内部的客户账户表示。 1. (可选)[CustomerSession](https://docs.stripe.com/api/customer_sessions.md):Customer 对象上的信息为敏感信息,不能直接从应用中检索。CustomerSession 授予 SDK 对 Customer 的临时范围访问权限,并提供其他配置选项。查看完整的 [configuration options](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components)列表。 > 如果您从不将银行卡保存到客户,并且不允许回头客重复使用已保存的银行卡,则可以从集成中省略 Customer 和 CustomerSession 对象。 出于安全原因,您的应用无法创建这些对象。相反,在服务器上会添加一个端点,其功能如下: 1. 检索 Customer,或新建一个。 1. 为 Customer 创建一个 [CustomerSession](https://docs.stripe.com/api/customer_sessions.md)。 1. 创建 PaymentIntent,设置好 [amount](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount)、[currency](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency) 和 [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer)。 1. 将 Payment Intent 的*客户端私钥* (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))、CustomerSession 的 `client_secret` 以及 Customer 的 [id](https://docs.stripe.com/api/customers/object.md#customer_object-id) 和您的[公钥](https://dashboard.stripe.com/apikeys)返回到您的应用程序。 在结账过程中显示给客户的支付方式也包含在 PaymentIntent 中。您可以让 Stripe 从管理平台设置中提取支付方式,也可以手动列出它们。无论选择哪种方式,都要知道在 PaymentIntent 中传递的货币会过滤显示给客户的支付方式。例如,如果您在 PaymentIntent 中传递 `eur`,并且在管理平台中启用了 OXXO,则不会向客户显示 OXXO,因为 OXXO 不支持 `eur` 支付。 除非您的集成需要基于代码的选项来提供支付方式,否则 Stripe 建议使用自动选项。这是因为 Stripe 会评估货币、支付方式限制和其他参数,以确定支持的支付方式列表。优先显示可提高转化率且与货币和客户所在地最相关的支付方式。 #### 从管理平台管理支付方式 您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。PaymentIntent 是用您在管理平台中配置的支付方式创建的。如不想使用管理平台或想手动指定支付方式,可通过 `payment_method_types` 属性将其列出。 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. -d "automatic_payment_methods[enabled]"=true \ ``` #### 手动列出支付方式 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact" \ -d "payment_method_types[]"="card" \ -d "payment_method_types[]"="ideal" \ -d "payment_method_types[]"="klarna" \ -d "payment_method_types[]"="sepa_debit" \ ``` > 每个支付方式都要支持在 PaymentIntent 中传递的货币,且您的公司必须要位于各支付方式支持的某个国家/地区。查看[支付方式集成选项](https://docs.stripe.com/payments/payment-methods/integration-options.md)页面,查看具体支持哪些。 ## 收集付款详情 [客户端] 显示移动端 Payment Element 前,您的结账页面应: - 显示购买的产品和总金额 - 用 [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android) 收集所需的配送信息 - 包含一个结账按钮来展示 Stripe 的 UI #### Jetpack Compose [初始化](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-builder/index.html)您的结账活动的 `onCreate` 内的一个 `PaymentSheet` 实例,从而传递一个支付方式来处理结果。 ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build() } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } ``` 接下来,从您在上一步中创建的端点中获取 PaymentIntent 客户端私钥、Customer Session 客户端私钥、客户 ID 和可发布私钥。使用 `PaymentConfiguration` 设置可发布私钥,并存储其他内容,以便在您展示 PaymentSheet 时使用。 ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberimport androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import com.stripe.android.PaymentConfiguration import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build()val context = LocalContext.current var customerConfig by remember { mutableStateOf(null) } varpaymentIntentClientSecret by remember { mutableStateOf(null) } LaunchedEffect(context) { // Make a request to your own server and retrieve payment configurations val networkResult = ... if (networkResult.isSuccess) {paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret )PaymentConfiguration.init(context, networkResult.publishableKey)} } } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } ``` 当客户点击您的结账按钮时,调用 [presentWithPaymentIntent](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#1814490530%2FFunctions%2F2002900378) 来显示支付表单。客户完成付款后,表单将消失,然后 [PaymentSheetResult](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result/index.html) 将调用 [PaymentSheetResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html)。 ```kotlin import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import com.stripe.android.PaymentConfiguration import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetResult @Composable fun App() { val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build() val context = LocalContext.current var customerConfig by remember { mutableStateOf(null) } var paymentIntentClientSecret by remember { mutableStateOf(null) } LaunchedEffect(context) { // Make a request to your own server and retrieve payment configurations val networkResult = ... if (networkResult.isSuccess) { paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret ) PaymentConfiguration.init(context, networkResult.publishableKey) } }Button( onClick = { val currentConfig = customerConfig val currentClientSecret =paymentIntentClientSecret if (currentConfig != null && currentClientSecret != null) { presentPaymentSheet(paymentSheet, currentConfig, currentClientSecret) } } ) { Text("Checkout") } }private fun presentPaymentSheet( paymentSheet: PaymentSheet, customerConfig: PaymentSheet.CustomerConfiguration,paymentIntentClientSecret: String ) { paymentSheet.presentWithPaymentIntent(paymentIntentClientSecret, PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .customer(customerConfig) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. .allowsDelayedPaymentMethods(true) .build() ) } private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {when(paymentSheetResult) { is PaymentSheetResult.Canceled -> { print("Canceled") } is PaymentSheetResult.Failed -> { print("Error: ${paymentSheetResult.error}") } is PaymentSheetResult.Completed -> { // Display for example, an order confirmation screen print("Completed") } } } ``` #### 视图(经典) [初始化](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#-394860221%2FConstructors%2F2002900378)您的结账活动的 `onCreate` 内的 `PaymentSheet` 实例,传递一个支付方式来处理结果。 #### Kotlin ```kotlin import com.stripe.android.paymentsheet.PaymentSheet class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheet override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) paymentSheet = PaymentSheet.Builder(::onPaymentSheetResult).build(this) } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } } ``` 接下来,从您在上一步中创建的端点中获取 PaymentIntent 客户端私钥、Customer Session 客户端私钥、客户 ID 和可发布私钥。使用 `PaymentConfiguration` 设置可发布私钥,并存储其他内容,以便在您展示 PaymentSheet 时使用。 #### Kotlin ```kotlin import com.stripe.android.paymentsheet.PaymentSheet class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheetlateinit var customerConfig: PaymentSheet.CustomerConfiguration lateinit varpaymentIntentClientSecret: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) paymentSheet = PaymentSheet.Builder(::onPaymentSheetResult).build(this)lifecycleScope.launch { // Make a request to your own server and retrieve payment configurations val networkResult = MyBackend.getPaymentConfig() if (networkResult.isSuccess) {paymentIntentClientSecret = networkResult.paymentIntent customerConfig = PaymentSheet.CustomerConfiguration.createWithCustomerSession( id = networkResult.customer, clientSecret = networkResult.customerSessionClientSecret )PaymentConfiguration.init(context, networkResult.publishableKey)} } } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) { // implemented in the next steps } } ``` 当客户点击您的结账按钮时,调用 [presentWithPaymentIntent](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/index.html#1814490530%2FFunctions%2F2002900378) 来显示支付表单。客户完成付款后,表单将消失,然后 [PaymentSheetResult](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result/index.html) 将调用 [PaymentSheetResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html)。 #### Kotlin ```kotlin // ... class CheckoutActivity : AppCompatActivity() { lateinit var paymentSheet: PaymentSheet lateinit var customerConfig: PaymentSheet.CustomerConfiguration lateinit var paymentIntentClientSecret: String // ...fun presentPaymentSheet() { paymentSheet.presentWithPaymentIntent(paymentIntentClientSecret, PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .customer(customerConfig) // Set `allowsDelayedPaymentMethods` to true if your business handles // delayed notification payment methods like US bank accounts. .allowsDelayedPaymentMethods(true) .build() ) } fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {when(paymentSheetResult) { is PaymentSheetResult.Canceled -> { print("Canceled") } is PaymentSheetResult.Failed -> { print("Error: ${paymentSheetResult.error}") } is PaymentSheetResult.Completed -> { // Display for example, an order confirmation screen print("Completed") } } } } ``` 将 `allowsDelayedPaymentMethods` 设置为 true,以允许[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)支付方式,例如美国银行账户。对于这些支付方式,只有当 `PaymentSheet` 完成后才能知道最终的付款状态是成功还是失败。如果您支持这些类型的支付方式,请告知客户他们的订单已被确认,并且仅在付款成功时履行订单(例如,为他们安排发货)。 ## 处理付款后事件 [服务器端] 付款完成时,Stripe 会发送一个 [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) 事件。使用 [管理平台 Webhook 工具](https://dashboard.stripe.com/webhooks)、或按照 [Webhook 指南](https://docs.stripe.com/webhooks/quickstart.md)来接收这些事件并运行操作,例如,向客户发送订单确认邮件、在数据库中记录订单,或启动配送流程。 侦听这些事件,而不是等待客户端回调。在客户端,客户可能会在执行回调之前关闭浏览器窗口或退出应用程序,并且恶意客户端可能会操纵响应。设置您的集成来侦听异步事件,这样才能用单一集成用用接受[不同类型的支付方式](https://stripe.com/payments/payment-methods-guide)。 除了处理 `payment_intent.succeeded` 事件外,建议在使用 Payment Element 收款时也处理其他的这些事件: | 事件 | 描述 | 操作 | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded) | 客户成功完成付款时发送。 | 向客户发送订单确认通知,并*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)他们的订单。 | | [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing) | 当客户成功发起付款但并未完成时发送。当客户发起银行借记时,通常会发送此事件。之后将会出现 `payment_intent.succeeded` 或 `payment_intent.payment_failed` 事件。 | 向客户发送订单确认,告知他们的付款正等待处理。对于数字商品,您可能想先履行订单,然后再等付款完成。 | | [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | 在客户尝试付款但付款失败时发送。 | 如果一笔付款从 `processing` 变为 `payment_failed`,则让客户再尝试一次。 | ## 测试集成 #### 银行卡 | 卡号 | 场景 | 如何测试 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | 4242424242424242 | 该卡付款成功,不需要验证。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000002500003155 | 该卡付款时需要*验证* (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)。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 4000000000009995 | 该卡被拒绝,显示拒付代码,例如 `insufficient_funds`。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | | 6205500000000000004 | 银联卡的长度为 13-19 位。 | 使用信用卡号以及有效期和 CVC 和邮编填写我们的信用卡表单。 | #### 银行重定向 | 支付方式 | 场景 | 如何测试 | | ----------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Bancontact, iDEAL | 您的客户在基于重定向和立即通知型的支付方式的重定向页面验证失败。 | 选择基于重定向的任意支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | 通过银行支付 | 您的客户通过基于重定向和[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)的支付方式成功付款。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**测试付款成功**。 | | 通过银行支付 | 您的客户在基于重定向和延迟通知型的支付方式的重定向页面验证失败。 | 选择支付方式,填写必要的信息,并确认付款。然后在重定向页面上点击**让测试付款失败**。 | | BLIK | 有多个 BLIK 支付失败的情况——立即失败(例如,代码已过期或无效)、延迟的错误(银行拒付)或超时(客户未及时响应)。 | 使用电子邮件模式[模拟不同的失败情况](https://docs.stripe.com/payments/blik/accept-a-payment.md#simulate-failures)。 | #### 银行借记 | 支付方式 | 场景 | 如何测试 | | --------- | ------------------------------------------------------- | --------------------------------------------------------------------- | | SEPA 直接借记 | 您的客户成功用 SEPA 直接借记完成付款。 | 用账号 `AT321904300235473204` 填写表单。确认的 PaymentIntent 最初变为处理中,三分钟后变为成功状态。 | | SEPA 直接借记 | 您的客户的付款意图状态从 `processing` 变为 `requires_payment_method`。 | 用账号 `AT861904300235473202` 填写表单。 | 有关测试您的集成的更多信息,请参阅[测试](https://docs.stripe.com/testing.md)部分。 ## Optional: 启用 Link 在您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods)中启用 Link,让客户可以通过 Link 的一键快速结账按钮,安全地保存并重复使用其支付信息。 ### 将客户的邮件地址传递到 Mobile Payment Element Link 通过客户的电子邮件地址进行身份验证。Stripe 建议尽可能预填信息,以简化结账流程。 要预先填充客户的姓名、邮件地址和电话号码,请在初始化 `PaymentSheet.Configuration` 时提供包含客户信息的 `defaultBillingDetails`。 #### Kotlin ```kotlin val configuration = PaymentSheet.Configuration.Builder(merchantDisplayName = "Example, Inc.") .defaultBillingDetails( PaymentSheet.BillingDetails( name = "Jenny Rosen", email = "jenny.rosen@example.com", phone = "888-888-8888" ) ) .build() ``` ## Optional: 启用 Google Pay ### 设置您的集成 要使用 Google Pay,先将以下内容添加到您的 **AndroidManifest.xml** 的 ``标签,来启用 Google Pay API: ```xml ... ``` 更多详情,请参见 Google Pay 针对 Android 设备编写的[设置 Google Pay API](https://developers.google.com/pay/api/android/guides/setup) 指南。 ### 添加 Google Pay 要向您的集成添加 Google Pay,初始化 [PaymentSheet.Configuration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html) 时,传递您的 Google Pay 环境(生产或测试)下的 [PaymentSheet.GooglePayConfiguration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-google-pay-configuration/index.html) 和[贵公司的国家/地区代码](https://dashboard.stripe.com/settings/account)。 #### Kotlin ```kotlin val googlePayConfiguration = PaymentSheet.GooglePayConfiguration( environment = PaymentSheet.GooglePayConfiguration.Environment.Test, countryCode = "US", currencyCode = "USD" // Required for Setup Intents, optional for Payment Intents ) val configuration = PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name") .googlePay(googlePayConfiguration) .build() ``` ### 测试 Google Pay Google 允许您通过其[测试卡套件](https://developers.google.com/pay/api/android/guides/resources/test-card-suite)进行测试付款。该测试套件支持使用 Stripe [测试卡](https://docs.stripe.com/testing.md)。 您必须在支持 Google Pay 的国家/地区使用 Android 实体设备(而不是模拟设备)测试 Google Pay。使用保存到 Google 钱包的真实银行卡登录测试设备上的 Google 账户。 ## Optional: 启用银行卡扫描 若要启用银行卡扫描支持,需在 [Google Pay & Wallet Console](https://pay.google.com/business/console?utm_source=devsite&utm_medium=devsite&utm_campaign=devsite) 中请求 Google Pay API 的[生产访问权限](https://developers.google.com/pay/api/android/guides/test-and-deploy/request-prod-access)。 - 如果您已启用 Google Pay,银行卡扫描功能会在符合条件的设备上自动在我们的用户界面中提供。想了解更多符合条件的设备,请参见[Google Pay API 限制](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition) - **重要提示:**银行卡扫描功能仅在与 [Google Pay & Wallet Console](https://pay.google.com/business/console) 中注册的签名密钥相同的构建中显示。使用不同签名密钥进行测试或调试的构建(例如通过Firebase App Tester 分发的构建)不会显示**扫描银行卡**选项。要在预发布构建中测试银行卡扫描功能,您必须采取以下措施之一: - 使用生产签名密钥对您的测试构建进行签名 - 将您的测试签名密钥指纹添加到 Google Pay & Wallet Console ## Optional: 启用 ACH 付款 要启用 ACH 借记付款,请将 Financial Connections 作为您的应用的依赖项。 [Stripe Android SDK](https://github.com/stripe/stripe-android) 是开源的,且[有完整的文档](https://stripe.dev/stripe-android/)。 安装 SDK 时,将 `financial-connections` 添加到您的 [app/build.gradle](https://developer.android.com/studio/build/dependencies) 文件的 `dependencies` 块中: #### Kotlin ```kotlin plugins { id("com.android.application") } android { ... } dependencies { // ... // Financial Connections Android SDK implementation("com.stripe:financial-connections:23.2.0") } ``` > 有关最新 SDK 发布及过往版本的详细信息,请查看 GitHub 上的[发布](https://github.com/stripe/stripe-android/releases)页面。要想在新版本发布时接收通知,请[查看仓库的发布情况](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository)。 ## Optional: 自定义表单 所有自定义操作均用 [PaymentSheet.Configuration](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html) 对象来配置。 ### 外观 使用 [Appearance API](https://docs.stripe.com/elements/appearance-api/mobile.md?platform=android) 自定义颜色、字体等,使其与应用程序的视觉风格相匹配。 ### 支付方式布局 使用 [paymentMethodLayout](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/-builder/index.html#2123253356%2FFunctions%2F2002900378) 配置表单中支付方式的布局。可以水平、垂直显示,也可以让 Stripe 自动优化布局。 ![](https://b.stripecdn.com/docs-statics-srv/assets/android-mpe-payment-method-layouts.3bcfe828ceaad1a94e0572a22d91733f.png) #### Kotlin ```kotlin PaymentSheet.Configuration.Builder("Example, Inc.") .paymentMethodLayout(PaymentSheet.PaymentMethodLayout.Automatic) .build() ``` ### 收集用户地址 用 [Address Element](https://docs.stripe.com/elements/address-element.md?platform=android) 收集客户的本地和国际收货地址或账单地址。 ### 商家显示名称 通过设置 [merchantDisplayName](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-configuration/index.html#-191101533%2FProperties%2F2002900378) 来指定一个向客户显示的商家名称。默认情况下,使用的是您的应用的名称。 #### Kotlin ```kotlin PaymentSheet.Configuration.Builder( merchantDisplayName = "My app, Inc." ).build() ``` ### 暗色模式 默认情况下,`PaymentSheet` 自动适应用户的整个系统的外观设置(明暗模式)。可通过在您的应用上设置亮色或暗色模式来更改: #### Kotlin ```kotlin // force dark AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) // force light AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) ``` ## Optional: 处理用户的退出动作 `PaymentSheet` 会在本地存储一些信息,用于记住用户是否在应用中使用过 Link。当用户退出登录时,请调用 `PaymentSheet.resetCustomer()` 方法以清除 `PaymentSheet` 的内部状态。 #### Kotlin ```kotlin class MyActivity: Activity { fun onLogoutButtonClicked() { PaymentSheet.resetCustomer(this) // Other logout logic required by your app } } ``` ## Optional: 在您的用户界面完成付款 您可以在出示支付表单时仅收集支付方式详情,然后再在您的应用的用户界面上完成付款。如果您使用的是自定义购买按钮或在收集了付款详情后要求额外的步骤,这会非常有用。 ![](https://b.stripecdn.com/docs-statics-srv/assets/android-multi-step.84d8a0a44b1baa596bda491322b6d9fd.png) > 集成示例参见 [GitHub](https://github.com/stripe/stripe-android/blob/master/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/samples/ui/paymentsheet/custom_flow/CustomFlowActivity.kt)。 1. 首先,用某个 [Builder](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/-builder/index.html) 方法初始化 [PaymentSheet.FlowController](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html),而非 `PaymentSheet`。 #### Android (Kotlin) ```kotlin class CheckoutActivity : AppCompatActivity() { private lateinit var flowController: PaymentSheet.FlowController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val flowController = PaymentSheet.FlowController.Builder( resultCallback = ::onPaymentSheetResult, paymentOptionResultCallback = ::onPaymentOption, ).build(this) } } ``` 1. 然后,用从您的后端获取的 Stripe 对象密钥调用 `configureWithPaymentIntent`,并用[getPaymentOption()](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#-2091462043%2FFunctions%2F2002900378) 在回调中更新您的用户界面。这包含一个表示客户当前选择的支付方式的图片和标签。 #### Android (Kotlin) ```kotlin flowController.configureWithPaymentIntent( paymentIntentClientSecret = paymentIntentClientSecret, configuration = PaymentSheet.Configuration.Builder("Example, Inc.") .customer(PaymentSheet.CustomerConfiguration( id = customerId, ephemeralKeySecret = ephemeralKeySecret )) .build() ) { isReady, error -> if (isReady) { // Update your UI using `flowController.getPaymentOption()` } else { // handle FlowController configuration failure } } ``` 1. 然后,调用 [presentPaymentOptions](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#449924733%2FFunctions%2F2002900378) 来收集付款详情。客户完成后,表单被丢弃,并调用之前在 `create` 中传入的 [paymentOptionCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-option-callback/index.html)。实施该方法,用返回的 `paymentOption` 更新您的 UI。 #### Android (Kotlin) ```kotlin // ... flowController.presentPaymentOptions() // ... private fun onPaymentOption(paymentOptionResult: PaymentOptionResult) { val paymentOption = paymentOptionResult.paymentOption if (paymentOption != null) { paymentMethodButton.text = paymentOption.label paymentMethodButton.setCompoundDrawablesRelativeWithIntrinsicBounds( paymentOption.drawableResourceId, 0, 0, 0 ) } else { paymentMethodButton.text = "Select" paymentMethodButton.setCompoundDrawablesRelativeWithIntrinsicBounds( null, null, null, null ) } } ``` 1. 最后,调用 [confirm](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet/-flow-controller/index.html#-479056656%2FFunctions%2F2002900378),完成付款。客户完成后,表单被丢弃,并调用之前在 `create` 中创建的 [paymentResultCallback](https://stripe.dev/stripe-android/paymentsheet/com.stripe.android.paymentsheet/-payment-sheet-result-callback/index.html#237248767%2FFunctions%2F2002900378)。 #### Android (Kotlin) ```kotlin // ... flowController.confirmPayment() // ... private fun onPaymentSheetResult( paymentSheetResult: PaymentSheetResult ) { when (paymentSheetResult) { is PaymentSheetResult.Canceled -> { // Payment canceled } is PaymentSheetResult.Failed -> { // Payment Failed. See logcat for details or inspect paymentSheetResult.error } is PaymentSheetResult.Completed -> { // Payment Complete } } } ``` 将 `allowsDelayedPaymentMethods` 设置为 true,以允许[延迟通知型](https://docs.stripe.com/payments/payment-methods.md#payment-notification)支付方式,例如美国银行账户。对于这些支付方式,只有当 `PaymentSheet` 完成后才能知道最终的付款状态是成功还是失败。如果您支持这些类型的支付方式,请告知客户他们的订单已被确认,并且仅在付款成功时履行订单(例如,为他们安排发货)。 ## Optional: 启用确认时的 CVC 重新收集流程 以下有关在确认 PaymentIntent 的过程中重新收集已保存卡的 CVC 的说明假定的是您的集成包含以下内容: - 在收集支付详情之前创建 PaymentIntent ### 更新意图创建参数 要在确认付款时重新收集 CVC,请在创建 PaymentIntent 的过程中包含 `require_cvc_recollection`。 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an Ephemeral Key for the Customer curl https://api.stripe.com/v1/ephemeral_keys \ -u <>: \ -H "Stripe-Version: 2026-03-25.dahlia" \ -H "Stripe-Account: 2026-03-25.dahlia" \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \-d "payment_method_options[card][require_cvc_recollection]"=true \ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. -d "automatic_payment_methods[enabled]"=true \ ``` # React Native 应用内集成 > This is a React Native 应用内集成 for when payment-ui is mobile and platform is react-native. View the full page at https://docs.stripe.com/payments/accept-a-payment?payment-ui=mobile&platform=react-native. ![](https://b.stripecdn.com/docs-statics-srv/assets/ios-overview.9e0d68d009dc005f73a6f5df69e00458.png) 此集成将支付所需的全部步骤(包括收集支付详情和确认支付)整合到一个单一表单中,并显示在您的应用顶部。 ## 设置 Stripe [服务器端] [客户端] 首先,您需要有 Stripe 账户。[立即注册](https://dashboard.stripe.com/register)。 ### 服务器端 该集成要求您的服务器上的端点与 Stripe API 通讯。请用官方库从您的服务器访问 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' ``` ### 客户端 [React Native SDK](https://github.com/stripe/stripe-react-native) 是开源的,有完整的文档。在内部,它利用的是[原生 iOS](https://github.com/stripe/stripe-ios) 和 [Android](https://github.com/stripe/stripe-android) SDK。要安装 Stripe 的 React Native SDK,在您的项目目录中运行以下某个指令(取决于您使用的软件包管理器)。 #### yarn ```bash yarn add @stripe/stripe-react-native ``` #### npm ```bash npm install @stripe/stripe-react-native ``` 然后,安装一些其他必要的依赖项: - 对于 iOS,请转到 **ios** 目录并运行 `pod install` 以确保同时安装了所需的本地依赖项。 - 对于 Android,无需安装其他依赖项。 > 建议按照[官方 TypeScript 指南](https://reactnative.dev/docs/typescript#adding-typescript-to-an-existing-project)添加 TypeScript 支持。 ### Stripe 初始化 要在您的 React Native 应用中初始化 Stripe,使用 `StripeProvider` 组件包裹您的支付界面,或者使用 `initStripe` 初始化方法。只需要 `publishableKey` 中的 API [公钥](https://docs.stripe.com/keys.md#obtain-api-keys)。下例显示的是用 `StripeProvider` 组件初始化 Stripe 的方式。 ```jsx import { useState, useEffect } from 'react'; import { StripeProvider } from '@stripe/stripe-react-native'; function App() { const [publishableKey, setPublishableKey] = useState(''); const fetchPublishableKey = async () => { const key = await fetchKey(); // fetch key from your server here setPublishableKey(key); }; useEffect(() => { fetchPublishableKey(); }, []); return ( {/* Your app code here */} ); } ``` > 测试与开发时使用 API [测试模式](https://docs.stripe.com/keys.md#obtain-api-keys),发布时使用[真实模式](https://docs.stripe.com/keys.md#test-live-modes)密钥。 ## 启用支付方式 查看您的[支付方式设置](https://dashboard.stripe.com/settings/payment_methods),启用您想支持的支付方式。您至少需要启用一个支付方式才能创建 *PaymentIntent* (The Payment Intents API tracks the lifecycle of a customer checkout flow and triggers additional authentication steps when required by regulatory mandates, custom Radar fraud rules, or redirect-based payment methods)。 默认情况下,Stripe 支持信用卡和其他常见的支付方式,可以帮助您获得更多客户,但建议您开启与您的业务和客户相关的其他支付方式。查看[支付方式支持](https://docs.stripe.com/payments/payment-methods/payment-method-support.md),了解支持的产品和支付方式,并查看我们的[定价页面](https://stripe.com/pricing/local-payment-methods)了解费用。 ## 添加端点 [服务器端] > #### 注意 > > 要在创建 PaymentIntent 之前显示 PaymentSheet,请参阅[收集支付详情后再创建 Intent](https://docs.stripe.com/payments/accept-a-payment-deferred.md?type=payment)。 If your integration uses [customer-configured Accounts](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer), replace `Customer` and event references in the code examples with the equivalent Accounts v2 API references. For more information, see [Represent customers with Account objects](https://docs.stripe.com/connect/use-accounts-as-customers.md). 该集成使用三个 Stripe API 对象: 1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md):Stripe 用它来表示您从客户收款的意图,跟踪您的扣款尝试及整个过程中付款状态的变化情况。 1. (可选)[Customer](https://docs.stripe.com/api/customers.md):要为将来的付款设置支付方式,就必须将它绑定到 *Customer* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments)。当客户在您的公司创建账户时,创建 Customer 对象。如果您的客户以访客身份付款,则可以在付款前创建个 Customer 对象,然后再将它关联到您自己内部的客户账户表示。 1. (可选)[CustomerSession](https://docs.stripe.com/api/customer_sessions.md):Customer 对象上的信息为敏感信息,不能直接从应用中检索。CustomerSession 授予 SDK 对 Customer 的临时范围访问权限,并提供其他配置选项。查看完整的 [configuration options](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components)列表。 > 如果您从不将银行卡保存到客户,并且不允许回头客重复使用已保存的银行卡,则可以从集成中省略 Customer 和 CustomerSession 对象。 出于安全原因,您的应用无法创建这些对象。相反,在服务器上会添加一个端点,其功能如下: 1. 检索 Customer,或新建一个。 1. 为 Customer 创建一个 [CustomerSession](https://docs.stripe.com/api/customer_sessions.md)。 1. 创建 PaymentIntent,设置好 [amount](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount)、[currency](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency) 和 [customer](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer)。 1. 将 Payment Intent 的*客户端私钥* (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))、CustomerSession 的 `client_secret` 以及 Customer 的 [id](https://docs.stripe.com/api/customers/object.md#customer_object-id) 和您的[公钥](https://dashboard.stripe.com/apikeys)返回到您的应用程序。 在结账过程中显示给客户的支付方式也包含在 PaymentIntent 中。您可以让 Stripe 从管理平台设置中提取支付方式,也可以手动列出它们。无论选择哪种方式,都要知道在 PaymentIntent 中传递的货币会过滤显示给客户的支付方式。例如,如果您在 PaymentIntent 中传递 `eur`,并且在管理平台中启用了 OXXO,则不会向客户显示 OXXO,因为 OXXO 不支持 `eur` 支付。 除非您的集成需要基于代码的选项来提供支付方式,否则 Stripe 建议使用自动选项。这是因为 Stripe 会评估货币、支付方式限制和其他参数,以确定支持的支付方式列表。优先显示可提高转化率且与货币和客户所在地最相关的支付方式。 #### 从管理平台管理支付方式 您可以从[管理平台](https://dashboard.stripe.com/settings/payment_methods)管理支付方式。Stripe 根据交易金额、货币和支付流程等因素处理符合条件的支付方式的退货。PaymentIntent 是用您在管理平台中配置的支付方式创建的。如不想使用管理平台或想手动指定支付方式,可通过 `payment_method_types` 属性将其列出。 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ # In the latest version of the API, specifying the `automatic_payment_methods` parameter # is optional because Stripe enables its functionality by default. -d "automatic_payment_methods[enabled]"=true \ ``` #### 手动列出支付方式 #### curl ```bash # Create a Customer (use an existing Customer ID if this is a returning customer) curl https://api.stripe.com/v1/customers \ -u <>: \ -X "POST" \ -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}" # Create an CustomerSession for the Customer curl https://api.stripe.com/v1/customer_sessions \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "components[mobile_payment_element][enabled]"=true \ -d "components[mobile_payment_element][features][payment_method_save]"=enabled \ -d "components[mobile_payment_element][features][payment_method_redisplay]"=enabled \ -d "components[mobile_payment_element][features][payment_method_remove]"=enabled # Create a PaymentIntent curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -X "POST" \ -d "customer"="{{CUSTOMER_ID}}" \ -d "amount"=1099 \ -d "currency"="eur" \ -d "payment_method_types[]"="bancontact" \ -d "payment_method_types[]"="card" \ -d "payment_method_types[]"="ideal" \ -d "payment_method_types[]"="klarna" \ -d "payment_method_types[]"="sepa_debit" \ ``` > 每个支付方式都要支持在 PaymentIntent 中传递的货币,且您的公司必须要位于各支付方式支持的某个国家/地区。查看[支付方式集成选项](https://docs.stripe.com/payments/payment-methods/integration-options.md)页面,查看具体支持哪些。 ## 收集付款详情 [客户端] 显示移动端 Payment Element 前,您的结账页面应: - 显示购买的产品和总金额 - 收集所需的配送信息 - 包含一个结账按钮来展示 Stripe 的 UI 在您的应用的结账表单内,向上一步中创建的后端端点发送网络请求,从 `useStripe` hook 调用 `initPaymentSheet`。 ```javascript export default function CheckoutScreen() { const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [loading, setLoading] = useState(false); const fetchPaymentSheetParams = async () => { const response = await fetch(`${API_URL}/payment-sheet`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); const { paymentIntent, ephemeralKey, customer } = await response.json(); return { paymentIntent, ephemeralKey, customer, }; }; const initializePaymentSheet = async () => { const { paymentIntent, ephemeralKey, customer, } = await fetchPaymentSheetParams(); const { error } = await initPaymentSheet({ merchantDisplayName: "Example, Inc.", customerId: customer, customerEphemeralKeySecret: ephemeralKey, paymentIntentClientSecret: paymentIntent, // Set `allowsDelayedPaymentMethods` to true if your business can handle payment //methods that complete payment after a delay, like SEPA Debit and Sofort. allowsDelayedPaymentMethods: true, defaultBillingDetails: { name: 'Jane Doe', } }); if (!error) { setLoading(true); } }; const openPaymentSheet = async () => { // see below }; useEffect(() => { initializePaymentSheet(); }, []); return (