# 付款状态更新

监测并验证付款状态，以便响应成功和失败的付款。

*PaymentIntents* (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) 根据客户或支付方式所采取的动作进行更新。您的集成可通过检查 PaymentIntent 来确定付款过程的状态，从而您可以对需要进一步干预的状态做出业务上的行动或响应。

您还可以用 Stripe 管理平台来配置您的账户，让它给您发送有关付款状态的邮件，例如付款成功。在[用户设置](https://dashboard.stripe.com/settings/user)中更改您的[邮件通知](https://docs.stripe.com/get-started/account/teams.md#email-notifications)。

## 支付状态和 PaymentIntent 状态

管理平台中的 [Payments](https://dashboard.stripe.com/payments) 页面会显示每笔付款的支付状态，您可以使用该状态过滤列表。该状态是对付款的概括，但不包含 PaymentIntent 的 [ status ](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-status) 字段所提供的额外详情。

PaymentIntent 的 `status` 字段用于追踪付款状态，并指示付款何时需要进一步处理或客户操作。使用 PaymentIntent 的付款可能需要提供支付方式、进行确认或执行其他操作才能成功。在管理平台中，这些状态对应**未完成**。

如需了解支付处于未完成状态的原因，请点击该笔支付，并使用 [Workbench Inspector](https://docs.stripe.com/workbench/overview.md#inspector) 以 JSON 格式查看 PaymentIntent 的详情。搜索 `status` 字段可查看确切值。

下表将各 PaymentIntent `status` 值与管理平台中的支付状态一一对应。尝试过期、特定拒绝代码等边缘情况可能影响该对应关系。请使用 API 或 Workbench Inspector 获取权威状态。

| PaymentIntent `status` | 支付状态 | 描述 |
| --- | --- | --- |
| `requires_payment_method` | **未完成** | 该状态通常出现于无 [latest_charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) 记录，或支付意向尚未进入收款环节的情况。根据支付方式、金额及报错信息的不同，支付状态还可能显示为**部分已付款**、**待资金到账**或**支付失败**。 |
| `requires_confirmation` | **未完成** | 在客户提供支付信息并准备确认后出现。大多数集成都跳过此状态，因为集成会在确认付款时提交支付方式信息。 |
| `requires_action` | **未完成** | 在付款需要额外操作（例如通过 [3DS 验证](https://docs.stripe.com/payments/3d-secure.md)进行身份验证）时出现。在特定验证或错误条件下，管理平台中的付款状态也可能为**部分已付款**、**待资金到账**或**支付失败**。 |
| `processing` | **待处理** | 在所需操作已完成且付款采用 *异步支付方式* (Asynchronous payment methods can take up to several days to confirm whether the payment has been successful. During this time, the payment can't be guaranteed)（例如银行借记）时出现。此类支付方式可能需要数天时间处理。 |
| `requires_capture` | **未扣款**或**部分扣款** | 如果您的流程使用[单独扣款](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md)，则会发生这种情况。如果收到与意向相关的任何金额，则状态为**部分扣款**。如果未收到任何金额，则状态为**未扣款**。 |
| `succeeded` | **已成功** | 状态为`已成功`的 PaymentIntent 意味着相应的支付流程已完成。资金在您的账户中，您可以履行订单。

如果付款操作失败（例如由于交易被拒），PaymentIntent 的状态将返回到 `requires_payment_method`，以便可以重试付款。

后续的退款、争议及处理结果会反映在 Charge 对象上。即使 PaymentIntent 仍保持`已成功`状态，这些情况也可能改变您在管理平台中看到的内容。 |
| `已取消` | **已取消** | 在付款被取消时出现。若该付款意图是因账单流程失败而被取消，且最新一笔扣款失败，则状态可能显示为**失败**。 |

## 处理后续操作

部分支付方式需要额外步骤（例如身份验证）才能完成付款流程。确认 PaymentIntent 时，Stripe.js 会自动处理这些步骤；但若您采用的是高级集成方案，也可手动处理。

PaymentIntent 的 [next_action](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action) 属性显示了您的集成必须处理以完成付款的下一步骤。可用的后续操作因支付方式而异。有关完整列表，请参阅 [API 参考文档](https://docs.stripe.com/api.md#payment_intent_object-next_action-type)。

了解如何[处理支付方式要求的后续操作](https://docs.stripe.com/payments/payment-methods/overview.md)。

## 在客户端查看 PaymentIntent 状态

当在客户端使用 [confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) 函数完成支付时，您可以检查返回的 PaymentIntent 以确定其当前状态：

```javascript
(async () => {
  const {paymentIntent, error} = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: 'https://example.com/order/complete',
    },
    redirect: 'if_required',
  });
  if (error) {
    // Handle error here
  } else if (paymentIntent && paymentIntent.status === 'succeeded') {
    // Handle successful payment here
  }
})();
```

以下是使用 `confirmPayment` 函数的可能结果：

| **事件** | **发生了什么** | **期望的集成** |
| --- | --- | --- |
| 通过 PaymentIntent 来解决 | 客户在您的结账页面完成了付款 | 通知客户他们付款成功了 |
| 通过错误提示来解决 | 客户在您的结账页面付款失败 | 显示错误消息并提示客户再次尝试 |

由 `confirmPayment` 返回的 promise 会在支付流程完成或因错误失败时得到解析。当支付成功完成并返回 PaymentIntent 时，状态始终为 `succeeded`（如果[稍后捕获](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md)，则为 `requires_capture`）。当支付需要身份验证等额外步骤时，promise 不会解析，直到该步骤完成或超时。

## 在不使用 confirmPayment 的情况下在客户端检查 PaymentIntent 状态

若要在不使用 `confirmPayment` 函数的情况下检查 PaymentIntent 的状态，请使用 [retrievePaymentIntent](https://docs.stripe.com/js/payment_intents/retrieve_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))，独立检索它。

```javascript
(async () => {
  const {paymentIntent} = await stripe.retrievePaymentIntent(clientSecret);
  if (paymentIntent && paymentIntent.status === 'succeeded') {
    // Handle successful payment here
  } else {
    // Handle unsuccessful, processing, or canceled payments and API errors here
  }
})();
```

以下是确认之后 PaymentIntent 的一些[可能状态](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-status)：

| **发生了什么** | **期望的 PaymentIntent 状态** |
| --- | --- |
| 客户在您的结账页面完成了付款 | `succeeded` |
| 客户未完成结账 | `requires_action` |
| 客户在您的结账页面付款失败 | `requires_payment_method` |

[阅读关于 PaymentIntent 状态的更多信息](https://docs.stripe.com/payments/paymentintents/lifecycle.md)。

## 用 Webhooks 监测 PaymentIntent

Stripe 可向您的服务器发送 *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) 事件，在 PaymentIntent 的状态发生变化时通知您，您可以将它用于确定何时履行订单和服务等目的。

不要尝试在客户端处理订单*履行* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)操作，因为客户在付款完成后就可能离开页面，但这时还未来得及发起订单履行过程。相反，应该利用 Webhooks 来监测 `payment_intent.succeeded` 事件，并异步处理订单履行，不要尝试在客户端发起履行过程。

> 您可以使用轮询代替 Webhook 来监控由异步操作引发的变更——即反复检索 PaymentIntent 来检查其状态——但这种方式可靠性较低，且可能会触发速率限制。Stripe 会对 API 请求强制执行[速率限制](https://docs.stripe.com/testing.md#rate-limits)，因此如果您使用轮询，请务必谨慎。

要处理 Webhook 事件，先在您的服务器上创建一个路径，然后在[管理平台](https://dashboard.stripe.com/account/webhooks)内配置一个对应的 Webhook 端点。支付成功时，Stripe 发送 `payment_intent.succeeded` 事件，失败时发送 `payment_intent.payment_failed` 事件。

Webhook 有效载荷中包含 PaymentIntent 对象。下例显示了如何处理这两种事件：

#### Ruby

```ruby
require 'sinatra'
require 'stripe'

post '/webhook' do
    payload = request.body.read
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    event = nil

    begin
        event = Stripe::Webhook.construct_event(
            payload, sig_header, endpoint_secret
        )
    rescue JSON::ParserError => e
        # Invalid payload
        status 400
        return
    rescue Stripe::SignatureVerificationError => e
        # Invalid signature
        status 400
        return
    end

    case event['type']
    when 'payment_intent.succeeded'
        intent = event['data']['object']
        puts "Succeeded:", intent['id']
        # Fulfill the customer's purchase
    when 'payment_intent.payment_failed'
        intent = event['data']['object']
        error_message = intent['last_payment_error'] && intent['last_payment_error']['message']
        puts "Failed:", intent['id'], error_message
        # Notify the customer that payment failed
    end

    status 200
end
```

付款失败时，可通过查看 PaymentIntent 的 `last_payment_error` 属性找到更多详细信息。可通知客户他们未完成付款，并鼓励他们换一种支付方式重试。重新用同一 PaymentIntent 继续跟踪客户的下单状态。

### 处理特定的 Webhook 事件

下面的列表描述了 Webhook 事件的处理方式：

| 事件 | 描述 | 后续步骤 |
| --- | --- | --- |
| `processing` | 客户支付已成功提交至 Stripe。此情况仅适用于具有[延迟成功确认](https://docs.stripe.com/payments/payment-methods.md#payment-notification)功能的支付方式。 | 等待发起的付款成功或失败 |
| `succeeded` | 客户支付成功。 | 交付购买的商品或服务。 |
| `amount_capturable_updated` | 客户支付已获授权，待捕获。 | 捕获可用于支付的款项。 |
| `payment_failed` | 客户支付被卡组织拒绝或已过期。 | 请通过电子邮件或推送通知联系客户，并提示他们提供其他支付方式。 |

要在本地测试 Webhook，您可以使用 [Stripe CLI](https://docs.stripe.com/cli.md)。安装后，您可以将事件转发到服务器：

```bash
stripe listen --forward-to localhost:4242/webhook
Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
```

了解有关[设置 webhooks](https://docs.stripe.com/webhooks.md) 的更多信息。

## 识别 PaymentIntent 上的收款

当您尝试对客户收款时，PaymentIntent 会创建一个 [Charge](https://docs.stripe.com/api/charges.md)。要获取最近收款的 ID，请查看 PaymentIntent 的 [latest_charge](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-latest_charge) 属性：

#### Ruby

```ruby

# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
# Find your keys at https://dashboard.stripe.com/apikeys.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')

intent = client.v1.payment_intents.retrieve('{{PAYMENT_INTENT_ID}}')
latest_charge = intent.latest_charge
```

要查看与 PaymentIntent 相关的所有收款，包括任何未成功的收款，请[列出所有收款](https://docs.stripe.com/api/charges/list.md#list_charges-payment_intent)，并指定 `payment_intent​` 参数。

```curl
curl -G https://api.stripe.com/v1/charges \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "payment_intent={{PAYMENTINTENT_ID}}"
```
