# 支払いステータスの更新

支払いステータスを監視および確認して、支払いの成功と失敗に対応できるようにします。

*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 のステータス

ダッシュボードの[支払い](https://dashboard.stripe.com/payments)ページには各支払いのステータスが表示され、リストをフィルタリングする際に使用できます。このステータスは支払いを要約するものですが、PaymentIntent の[ステータス](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-status)が提供する追加の詳細は含まれません。

PaymentIntent の `status` は、支払いのステータスを追跡し、支払いで追加の処理や顧客のアクションが必要な時期を示します。PaymentIntent を使用する支払いでは、成功させるために決済手段、確認、またはその他のアクションが必要になる場合があります。ダッシュボードでは、これらの状態は **不完全** にマッピングされます。

支払いの不完全なステータスを理解するには、支払いをクリックして[ワークベンチインスペクター](https://docs.stripe.com/workbench/overview.md#inspector)を使用し、PaymentIntent の詳細を JSON で確認します。`status` を検索して、正確な値を確認します。

以下の表は、各 PaymentIntent の`status`をダッシュボードの支払いのステータスにマッピングしています。期限切れの試行や特定の拒否コードなどのエッジケースは、このマッピングに影響する可能性があります。信頼できる状態を取得するには、API またはワークベンチインスペクターを使用してください。

| 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` | **未完了** | 支払いに [3D セキュア](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 のステータスが `succeeded` である場合、対応する決済フローが完了していることを意味します。資金はアカウントに入金されており、注文のフルフィルメントを実行できます。

支払い処理が失敗した場合 (支払い拒否など)、支払いを再試行できるように PaymentIntent のステータスは `requires_payment_method` に戻ります。

その後の返金、不審請求の申し立て、結果は、Charge に反映されます。PaymentIntent が `succeeded` のままであっても、ダッシュボードの表示が変更される場合があります。 |
| `canceled` | **キャンセル済み** | 支払いがキャンセルされた場合に発生します。失敗した請求書フローの一部としてインテントがキャンセルされ、最新の支払いが失敗した場合、ステータスは **失敗** と表示されることがあります。 |

## 次のアクションを処理

一部の決済手段では、決済プロセスを完了するために認証などの追加のステップが必要になります。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)をご確認ください。

## クライアントで 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` が返すプロミスは、決済プロセスが完了するか、エラーで失敗した時点で解決されます。正常に完了して PaymentIntent が返される場合、ステータスは常に `succeeded` です ([capturing later](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md) の場合は `requires_capture`)。決済に認証などの追加のステップが必要な場合、そのステップが完了するかタイムアウトするまで、プロミスは完了しません。

## confirmPayment を使用せずにクライアントで PaymentIntent のステータスを確認する

`confirmPayment` 関数を使用せずに PaymentIntent のステータスを確認するには、*client secret* (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)) を渡して、[retrievePaymentIntent](https://docs.stripe.com/js/payment_intents/retrieve_payment_intent) 関数で個別に取得します。

```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)。

## Webhook で PaymentIntent を監視する

Stripe は、PaymentIntent のステータスが変化した時にサーバーに *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) イベントを送信して通知することできます。この機能は、商品やサービスのフルフィルメントを実行する時期の決定などに利用できます。

顧客が支払いの完了後、フルフィルメントプロセスの開始前にページを離れる可能性があるため、クライアント側で注文の*フルフィルメント* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected)を処理しないようにしてください。クライアント側でフルフィルメントを開始するのではなく、Webhook を使用して `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 オブジェクトが含まれます。次の例は、この 2 つのイベントの処理方法を示しています。

#### 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/stripe-cli.md) を使用できます。Stripe CLI をインストールすると、サーバーにイベントを転送できるようになります。

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

[Webhook の設定](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}}"
```
