# カード支払いを回収する

Stripe Terminal を使用したカード支払いの回収ができるように、アプリケーションとバックエンドを準備します。

# iOS


Payment Intents API を初めて使用する場合には、以下のリソースが役立ちます。

- [Payment Intents API](https://docs.stripe.com/payments/payment-intents.md)
- [PaymentIntent (支払いインテント) オブジェクト](https://docs.stripe.com/api/payment_intents.md)
- [その他の支払いシナリオ](https://docs.stripe.com/payments/more-payment-scenarios.md)

Stripe Terminal で支払いを回収するには、アプリケーションに決済フローを記述する必要があります。Stripe Terminal SDK を使用して、1 つの支払いセッションを表すオブジェクトである [PaymentIntent (支払いインテント)](https://docs.stripe.com/api.md#payment_intents) を作成して更新します。

Terminal の組み込みは支払いプロセスにおける失敗に対応できるように設計されており、支払いプロセスを複数のステップに分割し、各ステップを安全に再試行できるようになっています。

1. [PaymentIntent を作成](https://docs.stripe.com/terminal/payments/collect-card-payment.md#create-payment)します。
2. [決済を処理](https://docs.stripe.com/terminal/payments/collect-card-payment.md#process-payment)します。顧客のカードの承認は、SDK が決済を処理するときに行われます。
3. (オプション) [支払いをキャプチャーする](https://docs.stripe.com/terminal/payments/collect-card-payment.md#capture-payment)

## PaymentIntent を作成する [クライアント側] [サーバー側]

支払いを回収する最初のステップは、支払いフローを開始することです。顧客がチェックアウトを開始するとき、アプリケーションは `PaymentIntent` オブジェクトを作成する必要があります。これは、Stripe での新しい支払いセッションを表します。

- [createPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)createPaymentIntent:completion:)

クライアント側またはサーバー側で `PaymentIntent` を作成できます。

[テスト金額](https://docs.stripe.com/terminal/references/testing.md#physical-test-cards)を使用して、さまざまな結果を生成してみてください。`00` で終わる金額では、支払いが承認されます。

> #### 拒否されたカードの PaymentIntents を再作成しない
> 
> クレジットカードが拒否された場合は、決済インテントを再作成しないでください。代わりに、同じ決済インテントを再利用して、[二重請求を回避](https://docs.stripe.com/terminal/payments/collect-card-payment.md#avoiding-double-charges)します。

### クライアント側

クライアントから `PaymentIntent` を作成します。

#### Swift

```swift
import UIKit
import StripeTerminal

class PaymentViewController: UIViewController {

    // ...

    // Action for a "Checkout" button
    func checkoutAction() throws {
        let params = try PaymentIntentParametersBuilder(amount: 1000, currency: "usd").build()
        Terminal.shared.createPaymentIntent(params) { createResult, createError in
            if let error = createError {
                print("createPaymentIntent failed: \(error)")
            } else if let paymentIntent = createResult {
                print("createPaymentIntent succeeded")
                // ...
            }

        }
    }

    // ...
}
```

### サーバー側

支払いの開始に必要な情報がアプリですぐに利用できない場合は、サーバで `PaymentIntent` を作成することができます。

次の例は、サーバで `PaymentIntent` を作成する方法を示しています。

#### curl

```bash
curl https://api.stripe.com/v1/payment_intents \
  -u <<YOUR_SECRET_KEY>>: \
  -d "amount"=1000 \
  -d "currency"="usd" \
  -d "payment_method_types[]"="card_present" \
  -d "capture_method"="manual"
```

Terminal の支払いでは、`payment_method_types` パラメータに `card_present` が含まれている必要があります。

以下のように決済フローを制御できます。

- `card_present` 支払いの支払いフローを完全に制御するには、`capture_method` を `manual` に設定します。これにより、支払いを確定する前に照合ステップを追加できます。
- 1 ステップで支払いのオーソリとキャプチャーを行うには、`capture_method` を `automatic` に設定します。

オーストラリアで決済を受け付けるには、`capture_method` を`automatic`または `manual_preferred` に設定する必要があります。詳細については、Stripe の[オーストラリアのドキュメント](https://docs.stripe.com/terminal/payments/regional.md?integration-country=AU)をご覧ください。カナダで Interac 支払いを受け付けるには、`payment_method_types` に `interac_present` も含める必要があります。詳細については、Stripe の[カナダのドキュメント](https://docs.stripe.com/terminal/payments/regional.md?integration-country=CA)をご覧ください。

`PaymentIntent` には、個々の `PaymentIntent` に固有のキーである [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) が含まれています。client secret を使用するには、これをサーバーで `PaymentIntent` から取得し、[クライアント側に渡す](https://docs.stripe.com/payments/payment-intents.md#passing-to-client)必要があります。

#### Ruby

```ruby
post '/create_payment_intent' do
  intent = # ... Create or retrieve the PaymentIntent
  {client_secret: intent.client_secret}.to_json
end
```

- [retrievePaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)retrievePaymentIntent:completion:)

`PaymentIntent` を取得するには、client secret を使用して `retrievePaymentIntent` を呼び出します。

`PaymentIntent` を取得したら、それを使用して `processPaymentIntent` を呼び出します。

#### Swift

```swift
func checkoutButtonAction() {
    // ... Fetch the client secret from your backend
    Terminal.shared.retrievePaymentIntent(clientSecret: clientSecret) { retrieveResult, retrieveError in
        if let error = retrieveError {
            print("retrievePaymentIntent failed: \(error)")
        }
        else if let paymentIntent = retrieveResult {
            print("retrievePaymentIntent succeeded: \(paymentIntent)")
            // ...
        }
    }
}
```

## 支払いを処理する [クライアント側]

顧客が提示したカードで決済を即時に処理するか、決済の処理に進む前にカード詳細を調べるかを選択できます。大半のユースケースでは、API コール数が少なく抑えられ、統合がシンプルになるため、即時に処理することをお勧めします。ただし、カードの承認前に独自のビジネスロジックを挿入する場合は、収集と確定の 2 段階のフローを使用できます。

#### 即時に処理する

PaymentIntent を作成したら、次に決済を処理します。リーダーは顧客に対してカードをタップまたは挿入するように求め、その後、決済が承認されます。

- [processPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)processPaymentIntent:delegate:completion:)

決済の処理中に、カード会員がウォレットからカードを取得するまでに数秒かかったり、決済中にオペレーターに質問したりする可能性があります。

#### Swift

```swift


// Action for a "Checkout" button
func checkoutAction() throws {
  let params = try PaymentIntentParametersBuilder(amount: 1000, currency: "usd").build()
  Terminal.shared.createPaymentIntent(params) { createResult, createError in
      if let error = createError {
          print("createPaymentIntent failed: \(error)")
      } else if let paymentIntent = createResult {
          print("createPaymentIntent succeeded")
          self.processCancelable = Terminal.shared.processPaymentIntent(paymentIntent, collectConfig: nil, confirmConfig: nil) { processResult, processError in
              if let error = processError {
                  print("processPaymentIntent failed: \(error)")
              } else if let processedPaymentIntent = processResult {
                  print("processPaymentIntent succeeded")
                  // Notify your backend to capture the PaymentIntent
                  if let stripeId = processedPaymentIntent.stripeId {
                      APIClient.shared.capturePaymentIntent(stripeId) { captureError in
                          if let error = captureError {
                              print("capturePaymentIntent failed: \(error)")
                          } else {
                              print("capturePaymentIntent succeeded")
                          }
                      }
                  } else {
                      print("Payment processed offline");
                  }
              }
          }
      }
  }
}
```

### 収集をキャンセルする

#### プログラムによるキャンセル

- [Cancelable (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCancelable.html)

iOS SDK から返される `Cancelable` オブジェクトを使用して、PaymentIntent の処理をキャンセルできます。

#### 顧客によるキャンセル

- [setCustomerCancellation (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfigurationBuilder.html#/c:objc\(cs\)SCPCollectPaymentIntentConfigurationBuilder\(im\)setCustomerCancellation)
- [CustomerCancellation (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPCustomerCancellation.html)

スマートリーダーは、デフォルトで顧客にキャンセルボタンを表示します。これを無効にするには、`customerCancellation` を `.disableIfAvailable` に設定します。

キャンセルボタンをタップすると、現在の取引がキャンセルされます。

#### Swift

```swift

let collectConfig = try CollectPaymentIntentConfigurationBuilder()
    .setCustomerCancellation(.disableIfAvailable) // turn OFF the cancel button, ON by default
    .build()
Terminal.shared.collectPaymentMethod(paymentIntent: paymentIntent, collectConfig: collectConfig) {
    intentWithPaymentMethod, attachError in
}
```

### イベントを処理する

- [ReaderDisplayDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPReaderDisplayDelegate.html)

内蔵ディスプレイのない [Stripe M2](https://docs.stripe.com/terminal/readers/stripe-m2.md) などのリーダーを使用して決済手段を収集する場合、決済手段収集プロセスのイベントをアプリからユーザーに表示できるようにする必要があります。これらのイベントは、ユーザーが決済を正常に収集するのに役立ちます (カードを再試行する、別のカードを試す、別の読み取り方法を使用するなど)。

取引が開始されると、SDK は `ReaderInputOptions` 値をアプリのリーダー表示ハンドラに渡し、受け入れ可能な入力の種類 (`Swipe`、`Insert`、`Tap` など) を示します。アプリの決済 UI で、これらのオプションのいずれかを使用してカードを提示することを求めるプロンプトをユーザーに表示します。

取引中に、SDK がアプリに対して、アプリのリーダー表示ハンドラに `ReaderDisplayMessage` 値を渡すことで、ユーザーに追加のプロンプト (`Retry Card` など) を表示するように要求する場合があります。これらのメッセージが決済 UI でユーザーに表示されることを確認してください。

#### Swift

```swift
 // MARK: MobileReaderDelegate - only needed for mobile readers, this is the delegate set during connectReader

 func reader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions) {
     readerMessageLabel.text = Terminal.stringFromReaderInputOptions(inputOptions)
 }

 func reader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
     readerMessageLabel.text = Terminal.stringFromReaderDisplayMessage(displayMessage)
 }
```

### iPhone のタッチ決済で決済を収集する

アプリケーション側で決済を収集する準備ができると、Stripe Terminal iOS SDK がその画面を引き継いで収集プロセスを処理します。[process payment](https://docs.stripe.com/terminal/payments/collect-card-payment.md#process-payment) メソッドを呼び出した後、アプリケーションは実行中のままになりますが、iPhone ではカード会員に全画面のプロンプトが表示され、カードまたは NFC ベースのモバイルウォレットを提示するように求められます。カードの読み取りエラーが発生した場合は、再試行を求めるプロンプトが表示されます。提示に成功すると、成功の表示が返され、アプリケーションに制御が返されます。
![iPhone のタッチ決済による支払いの回収](https://b.stripecdn.com/docs-statics-srv/assets/ttpoi-payment-collection.50a552f2d75b8a3b92a439810cd9361d.png)

支払いの回収

- 決済を手動でキャプチャーする場合、`processPaymentIntent` 呼び出しが成功すると、`PaymentIntent` のステータスが `requires_capture` になります。
- 支払いの自動キャプチャーでは、`PaymentIntent` は `succeeded` 状態に移行します。

2 日以内に PaymentIntent を手動でキャプチャーする必要があり、キャプチャーしなければオーソリは期限切れになり、売上は顧客にリリースされます。

### 失敗に対処する

- [ConfirmPaymentIntentError (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPConfirmPaymentIntentError.html#/c:objc\(cs\)SCPConfirmPaymentIntentError\(py\)paymentIntent)

決済の処理に失敗した場合、SDK は更新された `PaymentIntent` を含むエラーを返します (Stripe によって拒否された場合)。アプリケーションでは、`PaymentIntent` を調べてエラーの対処方法を判断する必要があります。

| PaymentIntent ステータス        | 意味                                                 | 解決策                                                                            |
| -------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------ |
| `requires_payment_method`  | 支払い方法が拒否されました                                      | 同じ `PaymentIntent` を使用して `processPaymentIntent` を再度呼び出し、別の決済手段の収集を試みます。        |
| `requires_confirmation`    | 一時的な接続の問題                                          | 同じ `PaymentIntent` を使用して `processPaymentIntent` を再度呼び出し、リクエストを再試行します。          |
| `PaymentIntent` が `nil` です | Stripe へのリクエストがタイムアウトし、`PaymentIntent` のステータスが不明です | 元の `PaymentIntent` の処理を再試行します。新しく作成しないでください。新しく作成すると、カード会員に複数の承認が発生する可能性があります。 |

タイムアウトが複数回、連続して発生する場合、接続に問題がある可能性があります。アプリがインターネットと通信できることを確認してください。

### 二重請求を避ける

`PaymentIntent` オブジェクトは、Stripe での資金移動を可能にします。1 つの取引を表すには、`PaymentIntent` を 1 つ使用します。

カードが (残高不足などのために) 拒否された後、同じ `PaymentIntent` を再利用して、顧客が別のカードで再試行できるようにします。

`PaymentIntent` を編集する場合、`processPaymentIntent` を呼び出してリーダーの決済情報を更新する必要があります。

`PaymentIntent` を Stripe で処理するには、ステータスが `requires_payment_method` である必要があります。承認済み、キャプチャー済み、キャンセル済みの `PaymentIntent` をリーダーで処理することはできません。

#### 収集、検査、確認

PaymentIntent を作成したら、次に決済を処理します。リーダーは顧客に対してカードをタップまたは挿入するように求め、その後 PaymentMethod を作成します。

## PaymentMethod を収集する

- [collectPaymentMethod (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)collectPaymentMethod:delegate:completion:)

`PaymentIntent` を作成したら、次のステップは SDK で決済手段を収集することです。

決済手段を収集するには、アプリをリーダーに接続する必要があります。アプリが `collectPaymentMethod` を呼び出した後、接続されたリーダーはカードが提示されるのを待ちます。

#### Swift

```swift


import UIKit
import StripeTerminal

class PaymentViewController: UIViewController, ReaderDisplayDelegate {


    // Label for displaying messages from the card reader
    let readerMessageLabel = UILabel(frame: .zero)
    var collectCancelable: Cancelable? = nil

    // ...

    // Action for a "Checkout" button
    func checkoutAction() throws {
        let params = try PaymentIntentParametersBuilder(amount: 1000, currency: "usd").build()
        Terminal.shared.createPaymentIntent(params) { createResult, createError in
            if let error = createError {
                print("createPaymentIntent failed: \(error)")
            }
            else if let paymentIntent = createResult {
                print("createPaymentIntent succeeded")
                self.collectCancelable = Terminal.shared.collectPaymentMethod(paymentIntent) { collectResult, collectError in
                    if let error = collectError {
                        print("collectPaymentMethod failed: \(error)")
                    }
                    else if let paymentIntent = collectResult {
                        print("collectPaymentMethod succeeded")
                        // ... Confirm the payment
                    }
                }
            }

        }
    }
 }

 // MARK: MobileReaderDelegate - only needed for mobile readers, this is the delegate set during connectReader

 func reader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions = []) {
     readerMessageLabel.text = Terminal.stringFromReaderInputOptions(inputOptions)
 }

 func reader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
     readerMessageLabel.text = Terminal.stringFromReaderDisplayMessage(displayMessage)
 }
 // MARK: ReaderDisplayDelegate

 func terminal(_ terminal: Terminal, didRequestReaderInput inputOptions: ReaderInputOptions = []) {
     readerMessageLabel.text = Terminal.stringFromReaderInputOptions(inputOptions)
 }

 func terminal(_ terminal: Terminal, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
     readerMessageLabel.text = Terminal.stringFromReaderDisplayMessage(displayMessage)
 }
```

この方法では、接続されたカードリーダーを使用して暗号化された決済手段のデータを収集し、その暗号化されたデータをローカルの `PaymentIntent` に関連付けます。

### 支払い方法の詳細をオプションで調査する

- [CollectPaymentIntentConfiguration (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfiguration.html)
- [CardPresentDetails (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCardPresentDetails.html)

高度なユースケースでは、提示されたカードの支払い方法の詳細を調査し、オーソリ前に自社のビジネスロジックを実行できます。

`CollectPaymentIntentConfigurationBuilder` の `setUpdatePaymentIntent` セッターを使用して、`PaymentMethod` をサーバー側の `PaymentIntent` に関連付けます。このデータは `collectPaymentMethod` レスポンスで返されます。   

#### Swift

```swift


class PaymentViewController: UIViewController, ReaderDisplayDelegate {
    // ...

    // Action for a "Checkout" button
    func checkoutAction() throws {
        let params = try PaymentIntentParametersBuilder(amount: 1000, currency: "usd").build()
        Terminal.shared.createPaymentIntent(params) { createResult, createError in
            if let error = createError {
                print("createPaymentIntent failed: \(error)")
            }
            else if let paymentIntent = createResult {
                print("createPaymentIntent succeeded")
                let collectConfig = try CollectPaymentIntentConfigurationBuilder().setUpdatePaymentIntent(true).build()
                self.collectCancelable = Terminal.shared.collectPaymentMethod(paymentIntent: paymentIntent, collectConfig: collectConfig) {
                  collectResult, collectError in
                    if let error = collectError {
                        print("collectPaymentMethod failed: \(error)")
                    }
                    else if let paymentIntent = collectResult {
                        print("collectPaymentMethod succeeded")
                        if let paymentMethod = paymentIntent.paymentMethod,
                            let card = paymentMethod.cardPresent ?? paymentMethod.interacPresent {

                            // ... Perform business logic on card
                        }

                        // ... Confirm the payment
                    }
                }
            }

        }
    }
 }
```

このメソッドは、収集した暗号化済みの決済手段データを、`PaymentIntent` オブジェクトの更新とともにアタッチします。決済を確定するまで、オーソリは不要です。

決済手段収集後、30 秒以内に決済を承認またはキャンセルする必要があります。

SDK が[オフラインで実行](https://docs.stripe.com/terminal/features/operate-offline/collect-card-payments.md)されている場合、`PaymentIntent` オブジェクトには `paymentMethod` フィールドがありません。

この時点で、カードブランド、口座情報、その他の役立つデータなどの属性にアクセスできます。

Stripe は `wallet.type` 属性で示すとおり、取引でモバイルウォレットが使用されたかどうかを検出するよう試みます。ただし、カード発行会社がモバイルウォレットのリーダーによる識別に対応していない場合、この属性は自動入力されないため、正確な検出は保証されません。承認後に[決済が処理](https://docs.stripe.com/terminal/payments/collect-card-payment.md#process-payment)されると、Stripe はネットワークから最新の情報を取得し、`wallet.type` を更新します。

### 収集をキャンセルする

#### プログラムによるキャンセル

- [Cancelable (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCancelable.html)

iOS SDK から返される `Cancelable` オブジェクトを使用して、支払い方法の収集をキャンセルできます。

#### 顧客によるキャンセル

- [setCustomerCancellation (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPCollectPaymentIntentConfigurationBuilder.html#/c:objc\(cs\)SCPCollectPaymentIntentConfigurationBuilder\(im\)setCustomerCancellation)
- [CustomerCancellation (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Enums/SCPCustomerCancellation.html)

スマートリーダーは、デフォルトで顧客にキャンセルボタンを表示します。これを無効にするには、`customerCancellation` を `.disableIfAvailable` に設定します。

キャンセルボタンをタップすると、現在の取引がキャンセルされます。

#### Swift

```swift

let collectConfig = try CollectPaymentIntentConfigurationBuilder()
    .setCustomerCancellation(.disableIfAvailable) // turn OFF the cancel button, ON by default
    .build()
Terminal.shared.collectPaymentMethod(paymentIntent: paymentIntent, collectConfig: collectConfig) {
    intentWithPaymentMethod, attachError in
}
```

### イベントを処理する

- [ReaderDisplayDelegate (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Protocols/SCPReaderDisplayDelegate.html)

内蔵ディスプレイのない [Stripe M2](https://docs.stripe.com/terminal/readers/stripe-m2.md) などのリーダーを使用して決済手段を収集する場合、決済手段収集プロセスのイベントをアプリからユーザーに表示できるようにする必要があります。これらのイベントは、ユーザーが決済を正常に収集するのに役立ちます (カードを再試行する、別のカードを試す、別の読み取り方法を使用するなど)。

取引が開始されると、SDK は `ReaderInputOptions` 値をアプリのリーダー表示ハンドラに渡し、受け入れ可能な入力の種類 (`Swipe`、`Insert`、`Tap` など) を示します。アプリの決済 UI で、これらのオプションのいずれかを使用してカードを提示することを求めるプロンプトをユーザーに表示します。

取引中に、SDK がアプリに対して、アプリのリーダー表示ハンドラに `ReaderDisplayMessage` 値を渡すことで、ユーザーに追加のプロンプト (`Retry Card` など) を表示するように要求する場合があります。これらのメッセージが決済 UI でユーザーに表示されることを確認してください。

#### Swift

```swift
 // MARK: MobileReaderDelegate - only needed for mobile readers, this is the delegate set during connectReader

 func reader(_ reader: Reader, didRequestReaderInput inputOptions: ReaderInputOptions) {
     readerMessageLabel.text = Terminal.stringFromReaderInputOptions(inputOptions)
 }

 func reader(_ reader: Reader, didRequestReaderDisplayMessage displayMessage: ReaderDisplayMessage) {
     readerMessageLabel.text = Terminal.stringFromReaderDisplayMessage(displayMessage)
 }
```

### iPhone のタッチ決済で決済を収集する

アプリケーション側で決済を収集する準備ができると、Stripe Terminal iOS SDK がその画面を引き継いで収集プロセスを処理します。[process payment](https://docs.stripe.com/terminal/payments/collect-card-payment.md#process-payment) メソッドを呼び出した後、アプリケーションは実行中のままになりますが、iPhone ではカード会員に全画面のプロンプトが表示され、カードまたは NFC ベースのモバイルウォレットを提示するように求められます。カードの読み取りエラーが発生した場合は、再試行を求めるプロンプトが表示されます。提示に成功すると、成功の表示が返され、アプリケーションに制御が返されます。
![iPhone のタッチ決済による支払いの回収](https://b.stripecdn.com/docs-statics-srv/assets/ttpoi-payment-collection.50a552f2d75b8a3b92a439810cd9361d.png)

支払いの回収

## PaymentIntent を確定する

- [confirmPaymentIntent (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPTerminal.html#/c:objc\(cs\)SCPTerminal\(im\)confirmPaymentIntent:completion:)

顧客から決済手段を収集できたら、次のステップでは SDK で決済を確定します。決済を続行する準備ができたら、[前のステップ](https://docs.stripe.com/terminal/payments/collect-card-payment.md#collect-inspect-payment-method)からの更新後の `PaymentIntent` を使用して `confirmPaymentIntent` を呼び出します。

- 決済の手動キャプチャーでは、`confirmPaymentIntent` 呼び出しが成功すると、`PaymentIntent` のステータスが `requires_capture` になります。
- 支払いの自動キャプチャーでは、`PaymentIntent` は `succeeded` 状態に移行します。

クライアント側では常に Terminal SDK を使用して PaymentIntents を確定します。サーバー側の確定により、PIN プロンプトなどの重要なやり取りがバイパスされ、取引が失敗する可能性があります。

#### Swift

```swift


// Action for a "Checkout" button
func checkoutAction() throws {
  let params = try PaymentIntentParametersBuilder(amount: 1000, currency: "usd").build()
  Terminal.shared.createPaymentIntent(params) { createResult, createError in
      if let error = createError {
          print("createPaymentIntent failed: \(error)")
      } else if let paymentIntent = createResult {
          print("createPaymentIntent succeeded")
          self.collectCancelable = Terminal.shared.collectPaymentMethod(paymentIntent) { collectResult, collectError in
              if let error = collectError {
                  print("collectPaymentMethod failed: \(error)")
              } else if let collectPaymentMethodPaymentIntent = collectResult {
                  print("collectPaymentMethod succeeded")
                  // ... Confirm the payment
                  self.confirmCancelable = Terminal.shared.confirmPaymentIntent(collectPaymentMethodPaymentIntent) { confirmResult, confirmError in
                      if let error = confirmError {
                          print("confirmPaymentIntent failed: \(error)")
                      } else if let confirmedPaymentIntent = confirmResult {
                          print("confirmPaymentIntent succeeded")
                          // Notify your backend to capture the PaymentIntent
                          if let stripeId = confirmedPaymentIntent.stripeId {
                              APIClient.shared.capturePaymentIntent(stripeId) { captureError in
                                  if let error = captureError {
                                      print("capture failed: \(error)")
                                  } else {
                                      print("capture succeeded")
                                  }
                              }
                          } else {
                              print("Payment collected offline");
                          }
                      }
                  }
              }
          }
      }
  }
```

2 日以内に PaymentIntent を手動でキャプチャーする必要があり、キャプチャーしなければオーソリは期限切れになり、売上は顧客にリリースされます。

### 失敗に対処する

- [ConfirmPaymentIntentError (iOS)](https://stripe.dev/stripe-terminal-ios/docs/Classes/SCPConfirmPaymentIntentError.html#/c:objc\(cs\)SCPConfirmPaymentIntentError\(py\)paymentIntent)

決済の確定に失敗した場合、SDK は更新された `PaymentIntent` を含むエラーを返します。アプリケーションでは、`PaymentIntent` を調べてエラーの対処方法を判断する必要があります。

| PaymentIntent のステータス       | 意味                                                 | 解決策                                                                                            |
| -------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `requires_payment_method`  | 支払い方法が拒否されました                                      | 同じ `PaymentIntent` を使用して `collectPaymentMethod` を再度呼び出し、別の決済手段の収集を試みます。                        |
| `requires_confirmation`    | 一時的な接続の問題                                          | 同じ `PaymentIntent` を使用して `confirmPaymentIntent` を再度呼び出し、リクエストを再試行します。                          |
| `PaymentIntent` が `nil` です | Stripe へのリクエストがタイムアウトし、`PaymentIntent` のステータスが不明です | 元の `PaymentIntent` の確定を再試行します。新しい PaymentIntent を作成しないでください。新しく作成すると、カード会員に複数の承認が発生する可能性があります。 |

タイムアウトが複数回、連続して発生する場合、接続に問題がある可能性があります。アプリがインターネットと通信できることを確認してください。

### 二重請求を避ける

`PaymentIntent` オブジェクトは、Stripe での資金移動を可能にします。1 つの取引を表すには、`PaymentIntent` を 1 つ使用します。

カードが (残高不足などのために) 拒否された後、同じ `PaymentIntent` を再利用して、顧客が別のカードで再試行できるようにします。

`PaymentIntent` を編集する場合、`collectPaymentMethod` を呼び出してリーダーの決済情報を更新する必要があります。

`PaymentIntent` を Stripe で確定するには、ステータスが `requires_payment_method` である必要があります。承認済み、キャプチャー済み、キャンセル済みの `PaymentIntent` をリーダーで確定することはできません。

## 支払いをキャプチャーする [サーバー側]

[ステップ 1](https://docs.stripe.com/terminal/payments/collect-card-payment.md#create-payment) の `PaymentIntent` の作成時に `capture_method` を `manual` として定義した場合、SDK はオーソリ済みでキャプチャーはされていない `PaymentIntent` をアプリケーションに返します。[オーソリとキャプチャー](https://docs.stripe.com/payments/place-a-hold-on-a-payment-method.md)の違いについて、詳細を確認してください。

アプリが SDK から確定済みの `PaymentIntent` を受信したら、その支払いをキャプチャーするようにアプリからバックエンドに対して通知するようにしてください。バックエンドにエンドポイントを作成し、`PaymentIntent` ID を受け付け、それをキャプチャーするように Stripe API にリクエストを送信します。

```curl
curl -X POST https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/capture \
  -u "<<YOUR_SECRET_KEY>>:"
```

`capture` コールが成功すると、`PaymentIntent` のステータスは `succeeded` になります。

キャプチャーされたプラットフォーム手数料が連結アカウントに対して正確であることを確認するために、支払いを手動でキャプチャーする前にそれぞれの `PaymentIntent` を調べ、必要に応じてプラットフォーム手数料を修正します。

### 支払いを照合する

ビジネスの支払いアクティビティを監視するため、毎日の最後の作業としてサーバで PaymentIntent と内部注文システムを照合することをお勧めします。

`PaymentIntent` のステータスが `requires_capture` のままの場合には、以下の 2 つの可能性があります。

**顧客のカード明細上の不要なオーソリ**

- 原因: ユーザーが取引の途中でアプリの決済フローを中止した
- 解決策:キャプチャーされていない `PaymentIntent` が、サーバーにある完了済みの注文に関連付けられていない場合には、[キャンセル](https://docs.stripe.com/api/payment_intents/cancel.md)できます。キャンセルされた `PaymentIntent` を使用して支払いを実行することはできません。

**顧客からの売上回収が未完了**

- 原因: 支払いをキャプチャーするようにバックエンドに通知する、アプリからのリクエストのエラー
- 解決策:キャプチャーされていない `PaymentIntent` が、サーバにある完了済みの注文に関連付けられており、その注文について他の支払い (現金による支払いなど) を受けていない場合には、この PaymentIntent を[キャプチャー](https://docs.stripe.com/api/payment_intents/capture.md)できます。

### チップを徴収する (アメリカのみ)

アメリカでは、対象となるユーザーは[売上確定時に領収書でチップを受け取る](https://docs.stripe.com/terminal/features/collecting-tips/on-receipt.md)ことができます。

