# カード支払いを回収する Stripe Terminal を使用したカード支払いの回収ができるように、アプリケーションとバックエンドを準備します。 # React Native 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 (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#createPaymentIntent) クライアント側またはサーバー側で `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` を作成します。 ```js const {error, paymentIntent} = await createPaymentIntent({ amount: 1000, currency: "usd", }); ``` ### サーバー側 支払いの開始に必要な情報がアプリですぐに利用できない場合は、サーバで `PaymentIntent` を作成することができます。 次の例は、サーバで `PaymentIntent` を作成する方法を示しています。 #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -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 (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#retrievePaymentIntent) `PaymentIntent` を取得するには、client secret を使用して `retrievePaymentIntent` を呼び出します。 `PaymentIntent` を取得したら、それを使用して `processPaymentIntent` を呼び出します。 ```js const { paymentIntent, error } = await retrievePaymentIntent(clientSecret); if (error) { // Placeholder for handling exception return; } // Placeholder for collecting payment method ``` ## 支払いを処理する [クライアント側] 顧客が提示したカードで決済を即時に処理するか、決済の処理に進む前にカード詳細を調べるかを選択できます。大半のユースケースでは、API コール数が少なく抑えられ、統合がシンプルになるため、即時に処理することをお勧めします。ただし、カードの承認前に独自のビジネスロジックを挿入する場合は、収集と確定の 2 段階のフローを使用できます。 #### 即時に処理する PaymentIntent を作成したら、次に決済を処理します。リーダーは顧客に対してカードをタップまたは挿入するように求め、その後、決済が承認されます。 - [processPaymentIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#processpaymentintent) 決済の処理中に、カード会員がウォレットからカードを取得するまでに数秒かかったり、決済中にオペレーターに質問したりする可能性があります。 ```js const { paymentIntent, error } = await processPaymentIntent({ paymentIntent: paymentIntent, }); if (error) { // Placeholder for handling exception return; } // Notify your backend to capture the PaymentIntent ``` ### 収集をキャンセルする #### プログラムによるキャンセル - [cancelProcessPaymentIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#cancelprocesspaymentintent) React Native SDK で `cancelProcessPaymentIntent` を呼び出すことで、PaymentIntent の処理をキャンセルできます。 #### 顧客によるキャンセル - [customerCancellation (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/types/CustomerCancellation.html) スマートリーダーは、デフォルトで顧客にキャンセルボタンを表示します。これを無効にするには、`customerCancellation` を `'disableIfAvailable'` に設定します。 キャンセルボタンをタップすると、現在の取引がキャンセルされます。 ```js const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent,customerCancellation: 'disableIfAvailable' }); if (error) { // Placeholder for handling exception } // Placeholder for processing PaymentIntent ``` ### イベントを処理する - [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks) 内蔵ディスプレイのない [Stripe M2](https://docs.stripe.com/terminal/readers/stripe-m2.md) などのリーダーを使用して決済手段を収集する場合、決済手段収集プロセスのイベントをアプリからユーザーに表示できるようにする必要があります。これらのイベントは、ユーザーが決済を正常に収集するのに役立ちます (カードを再試行する、別のカードを試す、別の読み取り方法を使用するなど)。 取引が開始されると、SDK は `ReaderInputOptions` 値をアプリのリーダー表示ハンドラに渡し、受け入れ可能な入力の種類 (`Swipe`、`Insert`、`Tap` など) を示します。アプリの決済 UI で、これらのオプションのいずれかを使用してカードを提示することを求めるプロンプトをユーザーに表示します。 取引中に、SDK がアプリに対して、アプリのリーダー表示ハンドラに `ReaderDisplayMessage` 値を渡すことで、ユーザーに追加のプロンプト (`Retry Card` など) を表示するように要求する場合があります。これらのメッセージが決済 UI でユーザーに表示されることを確認してください。 ```js useStripeTerminal({ onDidRequestReaderInput: (options) => { // Placeholder for updating your app's checkout UI Alert.alert(options.join('/')); }, onDidRequestReaderDisplayMessage: (message) => { Alert.alert(message); }, }); ``` - 決済を手動でキャプチャーする場合、`processPaymentIntent` 呼び出しが成功すると、`PaymentIntent` のステータスが `requires_capture` になります。 - 支払いの自動キャプチャーでは、`PaymentIntent` は `succeeded` 状態に移行します。 2 日以内に PaymentIntent を手動でキャプチャーする必要があり、キャプチャーしなければオーソリは期限切れになり、売上は顧客にリリースされます。 ### 失敗に対処する - [StripeError (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeError.html) 決済の処理に失敗した場合、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 (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#collectpaymentmethod) `PaymentIntent` を作成したら、次のステップは SDK で決済手段を収集することです。 決済手段を収集するには、アプリをリーダーに接続する必要があります。アプリが `collectPaymentMethod` を呼び出した後、接続されたリーダーはカードが提示されるのを待ちます。 ```js const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent }); if (error) { // Placeholder for handling exception } // Placeholder for processing PaymentIntent ``` この方法では、接続されたカードリーダーを使用して暗号化された決済手段のデータを収集し、その暗号化されたデータをローカルの `PaymentIntent` に関連付けます。 ### 支払い方法の詳細をオプションで調査する - [CollectPaymentMethodParams (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/types/CollectPaymentMethodParams.html) - [CardPresentDetails (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/types/CardPresentDetails.html) 高度なユースケースでは、提示されたカードの支払い方法の詳細を調査し、オーソリ前に自社のビジネスロジックを実行できます。 `updatePaymentIntent` パラメーターを使用して、`PaymentMethod` をサーバー側の `PaymentIntent` に関連付けます。このデータは `collectPaymentMethod` レスポンスで返されます。 ```js const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent, updatePaymentIntent: true, }); if (error) { // Placeholder for handling exception } // Placeholder for processing PaymentIntent ``` このメソッドは、収集した暗号化済みの決済手段データを、`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` を更新します。 ### 収集をキャンセルする #### プログラムによるキャンセル - [cancelCollectPaymentMethod (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#cancelcollectpaymentmethod) React Native SDK で [cancelCollectPaymentMethod](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#cancelcollectpaymentmethod) を呼び出すことで、決済手段の回収をキャンセルできます。 #### 顧客によるキャンセル - [customerCancellation (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/types/CustomerCancellation.html) スマートリーダーは、デフォルトで顧客にキャンセルボタンを表示します。これを無効にするには、`customerCancellation` を `'disableIfAvailable'` に設定します。 キャンセルボタンをタップすると、現在の取引がキャンセルされます。 ```js const { paymentIntent, error } = await collectPaymentMethod({ paymentIntent: paymentIntent,customerCancellation: 'disableIfAvailable' }); if (error) { // Placeholder for handling exception } // Placeholder for processing PaymentIntent ``` ### イベントを処理する - [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks) 内蔵ディスプレイのない [Stripe M2](https://docs.stripe.com/terminal/readers/stripe-m2.md) などのリーダーを使用して決済手段を収集する場合、決済手段収集プロセスのイベントをアプリからユーザーに表示できるようにする必要があります。これらのイベントは、ユーザーが決済を正常に収集するのに役立ちます (カードを再試行する、別のカードを試す、別の読み取り方法を使用するなど)。 取引が開始されると、SDK は `ReaderInputOptions` 値をアプリのリーダー表示ハンドラに渡し、受け入れ可能な入力の種類 (`Swipe`、`Insert`、`Tap` など) を示します。アプリの決済 UI で、これらのオプションのいずれかを使用してカードを提示することを求めるプロンプトをユーザーに表示します。 取引中に、SDK がアプリに対して、アプリのリーダー表示ハンドラに `ReaderDisplayMessage` 値を渡すことで、ユーザーに追加のプロンプト (`Retry Card` など) を表示するように要求する場合があります。これらのメッセージが決済 UI でユーザーに表示されることを確認してください。 ```js useStripeTerminal({ onDidRequestReaderInput: (options) => { // Placeholder for updating your app's checkout UI Alert.alert(options.join('/')); }, onDidRequestReaderDisplayMessage: (message) => { Alert.alert(message); }, }); ``` ## PaymentIntent を確定する - [confirmPaymentIntent (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#confirmpaymentintent) 顧客から決済手段を収集できたら、次のステップでは 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 プロンプトなどの重要なやり取りがバイパスされ、取引が失敗する可能性があります。 ```js const { paymentIntent, error } = await confirmPaymentIntent({ paymentIntent: paymentIntent }); if (error) { // Placeholder for handling exception return; } // Placeholder for notifying your backend to capture paymentIntent.id ``` 2 日以内に PaymentIntent を手動でキャプチャーする必要があり、キャプチャーしなければオーソリは期限切れになり、売上は顧客にリリースされます。 ### 失敗に対処する - [StripeError (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeError.html) 決済の確定に失敗した場合、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 "<>:" ``` `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)ことができます。