# 收款

安全地在线上收款。

对于大多数集成，Stripe 建议将 Checkout Sessions API 与 Payment Element 搭配使用，而非 Payment Intents。Checkout Sessions 可覆盖与 Payment Intents（使用 `price_data` 的基础收款功能，或者构建包含明细项、税费等的完整结账流程）类似的应用场景。Adaptive Pricing 等部分功能仅在 Checkout Sessions 中可用。除非用户明确要求，否则不要使用 Payment Intent API，因为它需要的代码明显更多。进一步了解 Elements 与 Checkout Sessions API 搭配使用的信息：https://docs.stripe.com/payments/quickstart.通过 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 CLI（`npm i -g @stripe/cli`）并运行命令 `stripe sandbox create --help`，以配置一个含可用 API 密钥的匿名 Stripe 沙盒。无需注册账户。

制作支付表单或使用预构建的结账页面来开始接收线上付款。

# 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) 查看我们的集成示例。

或者，从[代码快速入门](https://docs.stripe.com/payments/mobile/quickstart.md?platform=ios)开始，构建或下载可运行的示例。

> #### Accounts v2 API 支持
> 
> Payment Sheet 不支持 *客户配置的账户* (Account configurations represent role-based functionality that you can enable for accounts, such as merchant, customer, or recipient)，仅支持 `Customer` 对象。

## 设置 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。
2. 从我们的[发布页面](https://github.com/stripe/stripe-ios/releases)选择最新的版本号。
3. 将 **StripePaymentSheet** 产品添加到[您的目标应用程序](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)。

#### Carthage

1. 如果您还没有[Carthage](https://github.com/Carthage/Carthage#installing-carthage)，请安装其最新版本。
2. 将这一行代码添加到您的 `Cartfile`。
   ```cartfile
   github "stripe/stripe-ios"
   ```
3. 按照 [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)所列的所有必要框架。
4. 将来，要更新到 SDK 的最新版本，运行以下命令即可：
   ```bash
   carthage update stripe-ios --platform ios
   ```

#### 手动框架

1. 前往我们的 [GitHub 发布页面](https://github.com/stripe/stripe-ios/releases/latest)，下载并解压缩 **Stripe.xcframework.zip**。
2. 将 **StripePaymentSheet.xcframework** 拖拽到您的 Xcode 项目中 **General**（常规）设置的 **Embedded Binaries**（嵌入式二进制文件）部分。一定要选择 **Copy items if needed**（需要时复制项目）。
3. 为[这里](https://github.com/stripe/stripe-ios/tree/master/StripePaymentSheet/README.md#manual-linking)所列的所有必要框架重复第 2 步。
4. 将来，要更新到 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)。

该集成使用三个 Stripe API 对象：

1. [PaymentIntent](https://docs.stripe.com/api/payment_intents.md)：Stripe 用它来表示您从客户收款的意图，跟踪您的扣款尝试及整个过程中付款状态的变化情况。
2. （可选）[Customer](https://docs.stripe.com/api/customers.md)：要设置用于未来支付的支付方式，您必须将其关联到客户。当客户在您的企业创建账户时，请创建对象来代表该客户。如果您的客户以访客身份付款，您可以在付款前创建 `Customer` 对象，随后再将其与您内部的客户账户表示关联起来。
3. （可选）[CustomerSession](https://docs.stripe.com/api/customer_sessions.md)：用于表示客户的对象信息属于敏感数据，无法从应用中直接获取。`CustomerSession` 会为 SDK 提供针对 `Customer` 对象的临时、受限访问权限，并提供额外的[配置选项](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components)。

> 如果您从不为客户保存卡片，您可以从集成中省略 `Customer` 对象和 `CustomerSession` 对象。

出于安全原因，您的应用无法创建这些对象。相反，在服务器上会添加一个端点，其功能如下：

1. 检索 `Customer` 对象或创建新对象。
2. 为 `Customer` 创建 [CustomerSession](https://docs.stripe.com/api/customer_sessions.md)。
3. 创建包含[金额](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-amount)、[货币](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-currency)和[客户](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-customer)的 `PaymentIntent`。
4. 向您的应用返回 `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))、`CustomerSession` 的 `client_secret`、`Customer` ID，以及您的[可发布密钥](https://dashboard.stripe.com/apikeys)。

请确保在 `PaymentIntent` 上设置的 `Customer`，与您在 `CustomerSession` 上设置的保持一致。

在结账过程中显示给客户的支付方式也包含在 PaymentIntent 中。您可以让 Stripe 从管理平台设置中提取支付方式，也可以手动列出它们。无论选择哪种方式，都要知道在 PaymentIntent 中传递的货币会过滤显示给客户的支付方式。例如，如果您在 PaymentIntent 中传递 `eur`，并且在管理平台中启用了 OXXO，则不会向客户显示 OXXO，因为 OXXO 不支持 `eur` 支付。

除非您的集成需要基于代码的选项来提供支付方式，否则 Stripe 建议使用自动选项。这是因为 Stripe 会评估货币、支付方式限制和其他参数，以确定支持的支付方式列表。优先显示可提高转化率且与货币和客户所在地最相关的支付方式。

#### 从管理平台管理支付方式

您可以在[管理平台](https://dashboard.stripe.com/settings/payment_methods)中管理支付方式。Stripe 会根据您配置的可用支付方式，并结合交易金额、币种和支付流程等因素，创建 `PaymentIntent`。如果您不想使用管理平台，或者希望手动指定允许的支付方式，可以使用 `allowed_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 <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}"

# Create a CustomerSession for the Customer
curl https://api.stripe.com/v1/customer_sessions \
  -u <<YOUR_SECRET_KEY>>: \
  -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 <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -d "customer"="{{CUSTOMER_ID}}" \
  -d "amount"=1099 \
  -d "currency"="eur" \

  -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 <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}"

# Create a CustomerSession for the Customer
curl https://api.stripe.com/v1/customer_sessions \
  -u <<YOUR_SECRET_KEY>>: \
  -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 <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -d "customer"="{{CUSTOMER_ID}}" \
  -d "amount"=1099 \
  -d "currency"="eur" \
  -d "allowed_payment_method_types[]"="bancontact" \
  -d "allowed_payment_method_types[]"="card" \
  -d "allowed_payment_method_types[]"="ideal" \
  -d "allowed_payment_method_types[]"="klarna" \
  -d "allowed_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` 客户端私钥、`Customer` 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 back-end endpoint/payment-sheet")! // Your back-end endpoint
  @Published var paymentSheet: PaymentSheet?
  @Published var paymentResult: PaymentSheetResult?
}
```

从您在上一步中创建的端点获取 PaymentIntent 客户端私钥、CustomerSession 客户端私钥、`Customer` 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 back-end endpoint/payment-sheet")! // Your back-end endpoint
  @Published var paymentSheet: PaymentSheet?
  @Published var paymentResult: PaymentSheetResult?

  func preparePaymentSheet() {
    // MARK: Fetch thePaymentIntent and Customer information from the back end
    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 back-end endpoint/payment-sheet")! // Your back-end endpoint
  @Published var paymentSheet: PaymentSheet?
  @Published var paymentResult: PaymentSheetResult?

  func preparePaymentSheet() {
    // MARK: Fetch the PaymentIntent and Customer information from the back end
    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<UIOpenURLContext>) {
    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: Enable 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"
```

### 处理用户登出

`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: 启用 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。
2. 从我们的[发布页面](https://github.com/stripe/stripe-ios/releases)选择最新的版本号。
3. 将 **StripeFinancialConnections** 产品添加到[您的目标应用程序](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app)。

#### Carthage

1. 如果您还没有[Carthage](https://github.com/Carthage/Carthage#installing-carthage)，请安装其最新版本。
2. 将这一行代码添加到您的 `Cartfile`。
   ```cartfile
   github "stripe/stripe-ios"
   ```
3. 按照 [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)所列的所有必要框架。
4. 将来，要更新到 SDK 的最新版本，运行以下命令即可：
   ```bash
   carthage update stripe-ios --platform ios
   ```

#### 手动框架

1. 前往我们的 [GitHub 发布页面](https://github.com/stripe/stripe-ios/releases/latest)，下载并解压缩 **Stripe.xcframework.zip**。
2. 将 **StripeFinancialConnections.xcframework** 拖拽到您的 Xcode 项目中 **General**（常规）设置的 **Embedded Binaries**（嵌入式二进制文件）部分。一定要选择 **Copy items if needed**（需要时复制项目）。
3. 为[这里](https://github.com/stripe/stripe-ios/tree/master/StripeFinancialConnections/README.md#manual-linking)所列的所有必要框架重复第 2 步。
4. 将来，要更新到 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
```

### 默认账单详情

要为支付表单中收集的账单详情设置默认值，请配置 `defaultBillingDetails` 属性。`paymentSheet` 会用您提供的值预先填充其字段。

```swift
var configuration = PaymentSheet.Configuration()
configuration.defaultBillingDetails.address.country = "US"
configuration.defaultBillingDetails.email = "foo@bar.com"
```

### 收集账单详情

使用 `billingDetailsCollectionConfiguration` 指定您希望在支付表单中收集账单详情的方式。

可以收集客户的姓名、邮件地址、电话号码和地址。

完整的地址收集功能包含 Stripe 针对受支持国家/地区提供的自动完成功能，无需额外设置。

> 使用自动完成功能即表示您同意遵守 [Google Maps 平台可接受的使用政策](https://cloud.google.com/maps-platform/terms/aup)。如果您违反该政策，Stripe 可能会停用自动完成功能，或采取其他必要措施。

如果您只想收集支付方式所需的账单详情，请将 `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` 设置为 true。在这种情况下，`configuration.defaultBillingDetails` 将被设置为该支付方式的[账单详情](https://docs.stripe.com/api/payment_methods/object.md?lang=node#payment_method_object-billing_details)。

如果您想收集支付方式不一定要求的其他账单详情，请将 `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` 设置为 false。在这种情况下，通过 UI 收集的账单详情将被设置为该支付方式的账单详情。

```swift
var configuration = PaymentSheet.Configuration()
configuration.defaultBillingDetails.email = "foo@bar.com"
configuration.billingDetailsCollectionConfiguration.name = .always
configuration.billingDetailsCollectionConfiguration.email = .never
configuration.billingDetailsCollectionConfiguration.address = .full
configuration.billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod = true
```

> 请咨询律师，了解与收集信息有关的法律。仅在需要收集号码来完成交易时，才收集手机号码。

## 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 <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -H "Stripe-Account: {{CONNECTED_ACCOUNT_ID}}"

# Create an Ephemeral Key for the Customer
curl https://api.stripe.com/v1/ephemeral_keys \
  -u <<YOUR_SECRET_KEY>>: \
  -H "Stripe-Version: 2026-09-30.endive" \
  -H "Stripe-Account: 2026-09-30.endive" \
  -X "POST" \
  -d "customer"="{{CUSTOMER_ID}}" \

# Create a PaymentIntent
curl https://api.stripe.com/v1/payment_intents \
  -u <<YOUR_SECRET_KEY>>: \
  -X "POST" \
  -d "customer"="{{CUSTOMER_ID}}" \
  -d "amount"=1099 \
  -d "currency"="eur" \
  -d "payment_method_options[card][require_cvc_recollection]"=true \

  -d "automatic_payment_methods[enabled]"=true \
```

