# 付款状态更新 监测并验证付款状态,以便响应成功和失败的付款。 *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 状态 用 [confirmCardPayment](https://docs.stripe.com/js.md#stripe-confirm-card-payment) 函数在客户端完成付款时,您可以通过检查返回的 PaymentIntent 来确定其当前状态: ```javascript (async () => { const {paymentIntent, error} = await stripe.confirmCardPayment(clientSecret); if (error) { // Handle error here } else if (paymentIntent && paymentIntent.status === 'succeeded') { // Handle successful payment here } })(); ``` 以下是使用 `confirmCardPayment` 函数时可能出现的结果: | **事件** | **发生了什么** | **期望的集成** | | -------------------- | -------------- | --------------- | | 通过 PaymentIntent 来解决 | 客户在您的结账页面完成了付款 | 通知客户他们付款成功了 | | 通过错误提示来解决 | 客户在您的结账页面付款失败 | 显示错误消息并提示客户再次尝试 | `confirmCardPayment` 返回的 promise 会在付款流程完成或因某种错误失败时进行解析。成功完成并返回 PaymentIntent 时,状态始终会是 `succeeded`(如果是[稍后捕获](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md),则是 `requires_capture`)。当付款需要额外步骤时,例如身份验证,则在此步骤完成或超时之前不会解析此 promise。 ## 在不使用 confirmCardPayment 的情况下在客户端检查 PaymentIntent 状态 若要在不使用 `confirmCardPayment` 函数的情况下检查 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` | 客户支付被卡组织拒绝或已过期。 | 请通过电子邮件或推送通知联系客户,并提示他们提供其他支付方式。 | 要在本地测试 Webhooks,可以使用 [Stripe CLI](https://docs.stripe.com/stripe-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('<>') 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 "<>:" \ -d "payment_intent={{PAYMENTINTENT_ID}}" ``` ## 处理后续操作 某些支付方式需要完成额外的步骤才能完成付款流程,例如身份验证。Stripe.js 会在确认 PaymentIntent 时自动处理它们,但如果您有高级集成,也可以手动处理。 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),详细了解如何处理它们需要采取的后续操作。