# 迁移到 Payment Intents API

> #### Payment Element 集成应用特性
> 
> 您可以与 Payment Element 集成，以管理订阅、税务、折扣、运费和货币兑换。如需了解更多信息，请参阅[构建结账页面](https://docs.stripe.com/payments/quickstart.md)指南。

了解如何迁移当前银行卡和 Charges API 集成。

迁移支付流程可能让人望而却步。您可以安全地逐步采用 Payment Intents API，并与 Charges API 并行使用。为此，您可以将迁移过程拆分为以下步骤：

1. [更新您的 API 版本和客户端库](https://docs.stripe.com/payments/payment-intents/migration.md#api-version)。
2. 如果适用，[迁移从 Charge 属性读取的代码](https://docs.stripe.com/payments/payment-intents/migration/charges.md)，使自己在通过 Charges API 和 Payment Intents API 创建的收款之间有一致的读取路径。这可以确保读取端集成能够适应您的新旧支付集成。
3. 将您在[网页端](https://docs.stripe.com/payments/payment-intents/migration.md#web)、[iOS 端](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=mobile&platform=ios)和 [Android 端](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=mobile&platform=android)现有的 Charges API集成迁移至使用 Payment Intents API。
4. 迁移您的集成，[在 Customer 对象上保存银行卡](https://docs.stripe.com/payments/payment-intents/migration.md#saved-cards)。
5. [使用监管测试卡进行测试](https://docs.stripe.com/testing.md#regulatory-cards)，确保您升级后的集成能够正确处理身份验证。

## 更新您的 API 版本和客户端库

虽然 Payment Intents API 支持所有 API 版本，但我们建议您[升级到最新的 API 版本](https://docs.stripe.com/upgrades.md)。如果您决定使用早于 [2019-02-11](https://docs.stripe.com/upgrades.md#2019-02-11) 的 API 版本，请在阅读代码示例时注意以下两项更改：

- `requires_source` 已更名为 `requires_payment_method`
- `requires_source_action` 已更名为 `requires_action`

此外，如果您使用我们的 [SDK](https://docs.stripe.com/sdks.md) 之一，请升级到库的最新版本以使用 Payment Intents API。

## 迁移您的一次性付款流程

#### Elements

用 Stripe.js & Elements 构建集成时涉及以下步骤：

1. 注册您的 Intent，在服务器端收款
2. 在客户端收集支付信息
3. 开始创建付款
4. 在服务器端履行客户的订单

### 第 1 步：注册 Intent，在服务器端收款

在您的服务器端[创建 PaymentIntent](https://docs.stripe.com/payments/payment-intents.md)，并使它[可在客户端访问](https://docs.stripe.com/payments/payment-intents.md#passing-to-client)。

### 第 2 步：在客户端收集支付信息

使用收集银行卡信息的 [confirmCardPayment](https://docs.stripe.com/js.md#stripe-confirm-card-payment) 函数，并直接将其提交到 Stripe。

### 第 3 步：开始创建付款

在您现有的集成中，最后一步是用令牌化的支付方式在您的服务器上创建收款。这已经没有必要了，因为会由 `confirmCardPayment`函数（上一步中调用的）发起收款的创建过程。

### 第 4 步：履行客户订单

通过自动确认功能，会根据客户端的客户操作为您异步创建收款，因此您必须[监测 webhooks](https://docs.stripe.com/payments/payment-intents/verifying-status.md)，确定付款何时成功完成。要执行诸如在客户付款成功后履行订单等步骤，请实施 webhooks 支持并监测 `payment_intent.succeeded` 事件。

### Before

如果收款成功，则执行。

### After

订阅 `payment_intent.succeeded` Webhook 并在 Webhook 处理程序中执行。

您已完成迁移，现在，请用下一部分的测试卡验证您升级后的集成能否处理 3DS 验证。

#### 支付请求按钮

Stripe.js 的[支付请求按钮](https://docs.stripe.com/stripe-js/elements/payment-request-button.md)会与 Payment Intents API 一起使用，因为它使用的是从传统 PaymentRequest 集成获取的令牌并绑定到了 PaymentIntent。

用 PaymentRequest 构建集成时涉及以下步骤：

1. 注册您的 Intent，在服务器端收款
2. 在客户端收集支付信息
3. 开始创建付款
4. 在服务器端履行客户的订单

或者，使用 [Express Checkout Element](https://docs.stripe.com/elements/express-checkout-element.md) 向客户提供多个一键支付按钮，包括 Apple Pay、Google Pay、Link 和 PayPal。

### 第 1 步：注册 Intent，在服务器端收款

在您的服务器端[创建 PaymentIntent](https://docs.stripe.com/payments/payment-intents.md)，并使它[可在客户端访问](https://docs.stripe.com/payments/payment-intents.md#passing-to-client)。

### 第 2 步：在客户端收集支付信息

侦听 `PaymentRequest` 对象的 `token` 事件，它提供一个令牌和回调函数，可用于表示付款何时完成。

要改变此集成，使其支持 Payment Intents API，请使用 [confirmCardPayment](https://docs.stripe.com/js.md#stripe-confirm-card-payment) 函数并给它传递令牌 ID，而非向您的服务器发送令牌。`confirmCardPayment` 函数返回的 Promise 状态被解析后，调用完成回调函数。

### 第 3 步：开始创建付款

在您现有的集成中，最后一步是用令牌化的支付方式在您的服务器上创建收款。这已经没有必要了，因为会由 `confirmCardPayment`函数（上一步中调用的）发起收款的创建过程。

### 第 4 步：履行客户订单

通过自动确认功能，会根据客户端的客户操作为您异步创建收款，因此您必须[监测 webhooks](https://docs.stripe.com/payments/payment-intents/verifying-status.md)，确定付款何时成功完成。要执行诸如在客户付款成功后履行订单等步骤，请实施 webhooks 支持并监测 `payment_intent.succeeded` 事件。

### Before

如果收款成功，则执行。

### After

订阅 `payment_intent.succeeded` Webhook 并在 Webhook 处理程序中执行。

您已完成迁移，现在，请用下一部分的测试卡验证您升级后的集成能否处理 3DS 验证。

#### 旧版 Checkout

如果您使用的是旧版 Checkout，则升级到[新版 Checkout](https://docs.stripe.com/payments/checkout.md)，这是用 Stripe 收款最快的方式。通过它，您可以接受一次性付款和订阅。在您的服务器上未使用 Stripe API 的情况下，也可以使用 Checkout。按照 [Checkout 迁移指南](https://docs.stripe.com/payments/checkout/migration.md)迁移您的当前集成。

如果您更倾向于自行构建结账流程，请切换到 [Elements](https://docs.stripe.com/payments/elements.md)。假设您已升级至 Elements，您可以参考 [Elements 迁移指南](https://docs.stripe.com/payments/payment-intents/migration.md#web)构建 Payment Intents API 集成。

#### Stripe.js v2

要将现有的 Stripe.js v2 集成升级为使用 Payment Intents API，首先更新您的集成以使用 Elements 收集付款信息。Elements 提供预构建的 UI 组件，并通过 SAQ A 报告提供简单的 [PCI 合规性](https://docs.stripe.com/security/guide.md)。

在您升级至 Elements 后，可以按照 [Elements 迁移指南](https://docs.stripe.com/payments/payment-intents/migration.md#web)来构建 Payment Intents API 集成。

## 迁移您的集成，在 Customer 对象上保存银行卡

#### 结账流程中保存银行卡

在结账流程收集银行卡信息的 Payment Intents API 集成包含以下步骤：

1. 注册您的 Intent，在服务器端收款
2. 在客户端收集支付信息
3. 开始创建付款
4. 在服务器端履行客户的订单

### 第 1 步：注册 Intent，在服务器端收款

[在服务器端创建 PaymentIntent](https://docs.stripe.com/payments/payment-intents.md)。如果您主要是想在用户位于您的应用程序之外时向他们收款，则将 [setup_future_usage](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-setup_future_usage) 设置为 `off_session`，或者如果您打算在应用程序中向他们收款，则设置为 `on_session`。如果您打算同时使用该卡进行会话内和会话外付款，请使用 `off_session`。在确认 PaymentIntent 并完成客户所需的任何操作后，提供 `setup_future_usage` 参数和 Customer ID 会将生成的 PaymentMethod 保存到该 Customer。接下来，使 PaymentIntent [可以在客户端被访问](https://docs.stripe.com/payments/payment-intents.md#passing-to-client)。

### 第 2 步：在客户端收集支付信息

使用收集银行卡信息的 [confirmCardPayment](https://docs.stripe.com/js.md#stripe-confirm-card-payment) 函数，并直接将其提交到 Stripe。

最后，将支付方式(`paymentIntent.payment_method`)绑定到客户。

### 第 3 步：开始创建付款

在您现有的集成中，最后一步是用令牌化的支付方式在您的服务器上创建收款。这已经没有必要了，因为会由 `confirmCardPayment`函数（上一步中调用的）发起收款的创建过程。

### 第 4 步：履行客户订单

通过自动确认功能，会根据客户端的客户操作为您异步创建收款，因此您必须[监测 webhooks](https://docs.stripe.com/payments/payment-intents/verifying-status.md)，确定付款何时成功完成。要执行诸如在客户付款成功后履行订单等步骤，请实施 webhooks 支持并监测 `payment_intent.succeeded` 事件。

### Before

如果收款成功，则执行。

### After

订阅 `payment_intent.succeeded` Webhook 并在 Webhook 处理程序中执行。

您已完成迁移，现在，请用下一部分的测试卡验证您升级后的集成能否处理 3DS 验证。

#### 在结账流程外保存银行卡

对于您在结账流程之外保存卡信息的现有集成，需要进行几处调整。首先，在您的服务器上创建一个 [SetupIntent](https://docs.stripe.com/api/setup_intents.md)。SetupIntent 可以在不进行首次付款的情况下对卡片进行身份验证。

将 SetupIntent 的[客户端私钥](https://docs.stripe.com/api/setup_intents/object.md#setup_intent_object-client_secret)传递到您的客户端，然后在客户输入银行卡详情后使用 [confirmCardSetup](https://docs.stripe.com/js.md#stripe-confirm-card-setup) 函数，不要使用 [createToken](https://docs.stripe.com/js.md#stripe-create-token) 或 [createSource](https://docs.stripe.com/js.md#stripe-create-source)。

如果法规要求，则 [confirmCardSetup](https://docs.stripe.com/js.md#stripe-confirm-card-setup) 会提示用户对卡进行验证。

[confirmCardSetup](https://docs.stripe.com/js.md#stripe-confirm-card-setup) 成功时，`setupIntent.payment_method` 将包含一个 [PaymentMethod](https://docs.stripe.com/api/payment_methods/object.md)，可将它绑定到 Customer。

将该 PaymentMethod 的 ID 传递到您的服务器，然后用 Payment Methods API 而非 Customers API [将支付方式绑定](https://docs.stripe.com/api/payment_methods/attach.md)到 Customer 对象。

#### 用保存的银行卡支付

当使用之前保存的支付方式付款时，您必须同时指定客户对象的 ID 以及之前保存的 Cards、Source 或 PaymentMethod 的 ID。在此之前，如果未指定支付方式，系统会默认使用该客户对象上的默认支付来源。现在您必须明确传入所需的支付方式。

如果客户为*会话外* (A payment is described as off-session if it occurs without the direct involvement of the customer, using previously-collected payment information)，则必须将付款标记为会话外付款。有关更多信息，请查看[对保存的银行卡扣款](https://docs.stripe.com/payments/save-and-reuse.md?platform=web&ui=elements#charge-saved-payment-method)。

## 访问保存的支付方式

若要显示客户之前保存的 Cards、Sources 和PaymentMethods，请通过[列出支付方式](https://docs.stripe.com/api/payment_methods/list.md)，而不是读取客户对象的 [sources](https://docs.stripe.com/api/customers/object.md#customer_object-sources) 属性。这一点是必需的，因为添加到客户对象的新 PaymentMethod 不会同步复制到客户对象的 Sources 属性中。

## 测试集成

务必要对您的集成进行全面测试，确保其可以正确处理需要及不需要额外验证的银行卡，这一点非常重要。在[沙盒环境](https://docs.stripe.com/keys.md#test-live-modes)下用这些卡号（到期日可以是任意未来的日期，任意三位 CVC 均可），测试需要和不需要身份验证的两种情况。

| 卡号 | 验证 | 描述 |
| --- | --- | --- |
| 4000002500003155 | 设置或首次交易时需要 | 此测试卡要求对[一次性付款](https://docs.stripe.com/payments/accept-a-payment.md?platform=web)进行验证。但如果您是用 [Setup Intents API](https://docs.stripe.com/payments/save-and-reuse.md) 设置的此卡并且后续付款使用保存的银行卡，则不需要进一步验证。 |
| 4000002760003184 | 必填 | 该测试卡要求对所有交易进行身份验证。 |
| 4000008260003178 | 必填 | 该测试卡需要验证，但在验证成功后，付款会被拒绝，并显示 `insufficient_funds` 失败代码。 |
| 4000000000003055 | 支持 | 该测试卡支持通过 3DS 2.0 进行身份验证，但对此不做要求。在沙盒中使用此银行卡支付不需要额外的身份验证，除非您的[沙盒 Radar 规则](https://docs.stripe.com/payments/3d-secure/authentication-flow.md#three-ds-radar) 要求身份验证。 |

在您的应用程序或[付款演示](https://stripe-payments-demo.appspot.com)中使用这些卡，查看不同的行为。

## See also

- [iOS 版 PaymentIntent](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=mobile&platform=ios)
- [Android 版 PaymentIntent](https://docs.stripe.com/payments/accept-a-payment.md?payment-ui=mobile&platform=android)
