# 2 段階の確認機能を構築する

ユーザーが支払いの詳細を入力した後に、オプションの確認ページを追加するか、検証を実行します。

ほとんどのシナリオでは [標準統合](https://docs.stripe.com/payments/accept-a-payment-deferred.md) を推奨していますが、この導入では Checkout にステップを追加できます。これにより、注文を確定する前に次のような他のアクションを実行できます。

- 顧客に確認用の注文詳細を提示します。
- 追加の検証を実行しています。
- 税額を計算し、合計納税額を更新する。

## Stripe を設定する

まず、Stripe アカウントが必要です。[今すぐ登録してください](https://dashboard.stripe.com/register)。

アプリケーションから Stripe API にアクセスするには、Stripe の公式ライブラリを使用します。

#### Ruby

```bash
# Available as a gem
sudo gem install stripe
```

```ruby
# If you use bundler, you can add this line to your Gemfile
gem 'stripe'
```

## 支払い方法を有効にする

> この実装方法では、BLIK または Automated Clearing Settlement System (ACSS) を使用する事前承認済み口座振替には対応していません。また、クライアント側で遅延 PaymentIntent を作成する場合、PaymentIntent には顧客が設定した [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer) または [Customer](https://docs.stripe.com/api/customers/object.md) オブジェクトが必要ですが、クライアント側のフローではこれに対応していないため、`customer_balance` を動的な決済手段とともに使用することはできません。`customer_balance` を使用するには、`Account` または `Customer` を指定して、`PaymentIntent` をサーバー側で作成し、その `client_secret` をクライアントに返します。

[支払い方法の設定](https://dashboard.stripe.com/settings/payment_methods)を表示して、サポートする支払い方法を有効にします。*PaymentIntent* (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) を作成するには、少なくとも 1 つは支払い方法を有効にする必要があります。

多くの顧客から決済を受け付けられるよう、Stripe では、カードやその他一般的な決済手段がデフォルトで有効になっていますが、ビジネスや顧客に適した追加の決済手段を有効にすることをお勧めします。プロダクトと決済手段のサポートについては[決済手段のサポート](https://docs.stripe.com/payments/payment-methods/payment-method-support.md)を、手数料については[料金体系ページ](https://stripe.com/pricing/local-payment-methods)をご覧ください。

## 支払いの詳細を収集する [クライアント側]

[Payment Element](https://docs.stripe.com/payments/payment-element.md) を使用して、iFrame で収集された支払い情報を HTTPS 接続で安全に Stripe に送信します。

> #### iFrame の競合
> 
> Payment Element を別の iframe 内に配置しないでください。支払い確認のために別のページにリダイレクトする必要がある支払い方法と競合します。

構築済みのシステムを機能させるには、決済ページの URL の先頭を `https://` rather ではなく `http://` for にする必要があります。HTTPS を使用しなくても導入をテストできますが、本番環境で決済を受け付ける準備が整ったら、必ず HTTPS を [有効](https://docs.stripe.com/security/guide.md#tls) にしてください。

#### HTML + JS

### Stripe.js を設定する

Payment Element は Stripe.js の機能として自動的に使用できるようになります。決済ページに Stripe.js スクリプトを含めるには、HTML ファイルの `head` にスクリプトを追加します。常に js.stripe.com から Stripe.js を直接読み込むことにより、PCI 準拠が維持されます。スクリプトをバンドルに含めたり、そのコピーを自身でホストしたりしないでください。

```html
<head>
  <title>Checkout</title>
  <script src="https://js.stripe.com/dahlia/stripe.js"></script>
</head>
```

購入ページで次の JavaScript を使用して、Stripe のインスタンスを作成します。

```javascript
// Set your publishable key: remember to change this to your live publishable key in production
// See your keys here: https://dashboard.stripe.com/apikeys
const stripe = Stripe('<<YOUR_PUBLISHABLE_KEY>>');
```

### Payment Element を決済ページに追加する

Payment Element を決済ページに配置する場所が必要です。決済フォームで、一意の ID を持つ空の DOM ノード (コンテナー) を作成します。

```html
<form id="payment-form">
  <div id="payment-element">
    <!-- Elements will create form elements here -->
  </div>
  <button id="submit">Submit</button>
  <div id="error-message">
    <!-- Display error message to your customers here -->
  </div>
</form>
```

フォームが読み込まれたら、モード、金額、通貨を指定して Elements インスタンスを作成します。これらの値から、Element が顧客に表示する支払い方法が決定されます。

次に、Payment Element のインスタンスを作成し、コンテナーの DOM ノードにマウントします。

```javascript
const options = {
  mode:'payment',
  amount: 1099,
  currency: 'usd',
  // Fully customizable with appearance API.
  appearance: {/*...*/},
};

// Set up Stripe.js and Elements to use in checkout form
const elements = stripe.elements(options);

// Create and mount the Payment Element
const paymentElementOptions = { layout: 'accordion'};
const paymentElement = elements.create('payment', paymentElementOptions);
paymentElement.mount('#payment-element');
```

#### React

### Stripe.js を設定する

npm パブリックレジストリーから [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) と [Stripe.js ローダー](https://www.npmjs.com/package/@stripe/stripe-js)をインストールします。

```bash
npm install --save @stripe/react-stripe-js @stripe/stripe-js
```

### Elements プロバイダーを決済ページに追加して設定する

Payment Element コンポーネントを使用するには、決済画面コンポーネントを [Elements プロバイダー](https://docs.stripe.com/sdks/stripejs-react.md?ui=elements#elements-provider)でラップします。公開可能キーを使用して `loadStripe` を呼び出し、返された `Promise` を `Elements` プロバイダーに渡します。

`Elements` プロバイダーは、モード、金額、通貨も受け付けます。これらの値により、顧客に表示される支払い方法が決定されます。

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';

import CheckoutForm from './CheckoutForm';

// Make sure to call `loadStripe` outside of a component's render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('<<YOUR_PUBLISHABLE_KEY>>');

function App() {
  const options = {
    mode:'payment',
    amount: 1099,
    currency: 'usd',
    // Fully customizable with appearance API.
    appearance: {/*...*/},
  };

  return (
    <Elements stripe={stripePromise} options={options}>
      <CheckoutForm />
    </Elements>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
```

### Payment Element コンポーネントを追加する

`PaymentElement` コンポーネントを使用して、フォームを構築します。

```jsx
import React from 'react';
import {PaymentElement} from '@stripe/react-stripe-js';

const CheckoutForm = () => {
  return (
    <form>
      <PaymentElement />
      <button>Submit</button>
    </form>
  );
};

export default CheckoutForm;
```

Payment Element によって動的なフォームが表示され、顧客はここで支払い方法を選択できます。このフォームでは、顧客が選択した支払い方法で必要な決済の詳細のすべてが自動的に収集されます。

`Elements` プロバイダーを作成する際に [Appearance (デザイン) オブジェクト](https://docs.stripe.com/elements/appearance-api.md) を `options` に渡すことで、サイトのデザインに合わせて Payment Element をカスタマイズできます。

### 住所を収集

デフォルトでは、Payment Element は必要な請求住所の詳細のみを収集します。[税金の計算](https://docs.stripe.com/api/tax/calculations/create.md)、配送先情報を入力するなどの一部の動作では、顧客の完全な住所が必要です。次のように対応できます。

- [Address Element](https://docs.stripe.com/elements/address-element.md) を使用して、オートコンプリートとローカリゼーションの機能を利用して、顧客の完全な住所を収集します。これにより、最も正確な税金計算が可能になります。
- 独自のカスタムフォームを使用して住所の詳細を収集する。

## Optional: レイアウトをカスタマイズする [クライアント側]

決済フローインターフェイスに合わせて Payment Element のレイアウト (アコーディオンまたはタブ) をカスタマイズできます。各プロパティについて、詳細は [elements.create](https://docs.stripe.com/js/elements_object/create_payment_element#payment_element_create-options) をご覧ください。

#### アコーディオン

Payment Element の作成時にレイアウトの `type` と他のオプションプロパティーを渡すと、レイアウト機能の使用を開始できます。

```javascript
const paymentElement = elements.create('payment', {
  layout: {
    type: 'accordion',
    defaultCollapsed: false,
    radios: 'always',
    spacedAccordionItems: false
  }
});
```

#### タブ

### レイアウトを指定する

レイアウトの値を `tabs` に設定します。以下の例のようなその他のプロパティーを指定するオプションもあります。

```javascript
const paymentElement = elements.create('payment', {
  layout: {
    type: 'tabs',
    defaultCollapsed: false,
  }
});
```

以下の画像は、異なるレイアウト設定を適用した同一 Payment Element の表示を示しています。
![3 つの決済フォーム体験](https://b.stripecdn.com/docs-statics-srv/assets/pe_layout_example.525f78bcb99b95e49be92e5dd34df439.png)

Payment Element のレイアウト

## Optional: デザインをカスタマイズする [クライアント側]

これで、Payment Element がページに追加されました。次は、デザインに合わせて外観をカスタマイズできます。Payment Element のカスタマイズについての詳細は、[Elements Appearance API](https://docs.stripe.com/elements/appearance-api.md) をご覧ください。
![Payment Element をカスタマイズする](https://b.stripecdn.com/docs-statics-srv/assets/appearance_example.e076cc750983bf552baf26c305e7fc90.png)

Payment Element をカスタマイズする

## Optional: 顧客の支払い方法を保存および取得する

将来の利用に備えて顧客の決済手段を保存するように Payment Element を設定できます。このセクションでは、[決済手段の保存機能](https://docs.stripe.com/payments/save-customer-payment-methods.md)を導入する方法を説明しています。Payment Element で以下を実行できます。

- 顧客に決済手段を保存することの同意を求める
- 顧客が同意した場合に決済手段を保存する
- 将来の購入時に保存した決済手段を顧客に表示する
- 顧客がカードを置き換えたときに、[紛失したカードや有効期限切れのカードを自動的に更新する](https://docs.stripe.com/payments/cards/overview.md#automatic-card-updates)
![Payment Element と保存した決済手段のチェックボックス](https://b.stripecdn.com/docs-statics-srv/assets/spm-save.fe0b24afd0f0a06e0cf4eecb0ce2403a.png)

決済手段を保存します。
![保存された支払い方法が選択された Payment Element](https://b.stripecdn.com/docs-statics-srv/assets/spm-saved.5dba5a8a190a9a0e9f1a99271bed3f4b.png)

以前に保存した支払い方法を再利用します。

### Payment Element で支払い方法の保存機能を有効にする

顧客の ID を指定し (`customer` は `Customer` オブジェクト用、`customer_account` は顧客設定の `Account` オブジェクト用)、セッションで [payment_element](https://docs.stripe.com/api/customer_sessions/object.md#customer_session_object-components-payment_element) コンポーネントを有効にして、サーバー上に [CustomerSession](https://docs.stripe.com/api/customer_sessions/.md) を作成します。有効にする保存済み決済手段の [features](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features) を設定します。たとえば、[payment_method_save](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features-payment_method_save) を有効にすると、顧客が決済情報を保存して今後利用できるようにするチェックボックスが表示されます。

PaymentIntent または Checkout Session で `setup_future_usage` を指定すると、決済手段の保存に関するデフォルトの動作を上書きできます。これにより、顧客が明示的に保存を選択しなくても、今後の利用に備えて決済手段が自動的に保存されます。`setup_future_usage` を指定する場合は、同じ決済取引で `payment_method_save_usage` を設定しないでください。設定すると導入エラーが発生します。

> #### Accounts v2 API を使用した顧客の表現
> 
> Accounts v2 API では、Connect ユーザーには一般提供され、その他の Stripe ユーザーには公開プレビューで提供されます。Accounts v2 プレビューの一部である場合は、コードで[プレビューバージョン](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning)を指定する必要があります。
> 
> Accounts v2 のプレビューに参加するには、ダッシュボードの [Account previews and features](https://dashboard.stripe.com/settings/previews) に移動して、**Global Payouts の再利用可能な決済手段**を有効にします。
> 
> ほとんどのユースケースでは、[Customer](https://docs.stripe.com/api/customers.md) オブジェクトを使用するのではなく、[顧客を顧客設定済みの Account オブジェクトとしてモデル化する](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md)ことをお勧めします。

#### Accounts v2

#### 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>>')

post '/create-customer-session' do
  customer_session = client.v1.customer_sessions.create({
    customer_account: {{CUSTOMER_ACCOUNT_ID}},
    components: {
        payment_element: {
          enabled: true,
          features: {
            payment_method_redisplay: 'enabled',
            payment_method_save: 'enabled',
            payment_method_save_usage: 'off_session',
            payment_method_remove: 'enabled',
          },
        },
      },
  })
  {
    customer_session_client_secret: customer_session.client_secret
  }.to_json
end
```

#### Customers v1

#### 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>>')

post '/create-customer-session' do
  customer_session = client.v1.customer_sessions.create({
    customer: {{CUSTOMER_ID}},
    components: {
        payment_element: {
          enabled: true,
          features: {
            payment_method_redisplay: 'enabled',
            payment_method_save: 'enabled',
            payment_method_save_usage: 'off_session',
            payment_method_remove: 'enabled',
          },
        },
      },
  })
  {
    customer_session_client_secret: customer_session.client_secret
  }.to_json
end
```

Elements インスタンスはその CustomerSession の *client secret* (A client secret is used with your publishable key to authenticate a request for a single object. Each client secret is unique to the object it's associated with) を使用して、顧客が保存した支払い方法にアクセスします。CustomerSession の作成時に適切に[エラーを処理](https://docs.stripe.com/error-handling.md)します。エラーが発生した場合、CustomerSession の client secret はオプションなので、Elements インスタンスに指定する必要はありません。

CustomerSession の client secret を使用して Elements インスタンスを作成します。次に、Elements インスタンスを使用して、Payment Element を作成します。

```javascript
// Create the CustomerSession and obtain its clientSecret
const res = await fetch("/create-customer-session", {
  method: "POST"
});

const {
  customer_session_client_secret: customerSessionClientSecret
} = await res.json();

const elementsOptions = {
  mode: 'payment',
  amount: 1099,
  currency: 'usd',
  customerSessionClientSecret,
  // Fully customizable with appearance API.
  appearance: {/*...*/},
};

// Set up Stripe.js and Elements to use in checkout form, passing the client secret
// and CustomerSession's client secret obtained in a previous step
const elements = stripe.elements(elementsOptions);

// Create and mount the Payment Element
const paymentElementOptions = { layout: 'accordion'};
const paymentElement = elements.create('payment', paymentElementOptions);
paymentElement.mount('#payment-element');
```

PaymentIntent の確定時に、顧客が支払いの詳細を保存するためのボックスにチェックマークを付けたかどうかに応じて、Stripe.js が PaymentIntent の [setup_future_usage](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-setup_future_usage) および [allow_redisplay](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay) の設定をコントロールします。

### セキュリティコードの再収集を実行する

オプションとして、[PaymentIntent の作成時](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-card-require_cvc_recollection)と [Elements の作成時](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-paymentMethodOptions-card-require_cvc_recollection)の両方に `require_cvc_recollection` を指定して、顧客がカードで支払う場合にセキュリティコードの再収集を実行します。

### 保存した支払い方法の選択内容を検出する

保存した支払い方法を選択したときにコンテンツを動的に制御するには、Payment Element の `change` イベントをリッスンします。このイベントには、選択した支払い方法の情報が入力されています。

```javascript
paymentElement.on('change', function(event) {
  if (event.value.payment_method) {
    // Control dynamic content if a saved payment method is selected
  }
})
```

## Optional: 追加の Elements オプション [クライアント側]

[Elements オブジェクト](https://docs.stripe.com/js/elements_object/create_without_intent)は、支払いの回収に影響する追加オプションを受け入れます。指定したオプションを基に Payment Element は、有効化した決済手段の中から利用可能なものを表示します。詳しくは、[決済手段のサポート](https://docs.stripe.com/payments/payment-methods/payment-method-support.md)をご覧ください。

指定する Elements オプション ( `captureMethod`、`setupFutureUsage`、`paymentMethodOptions` など) が、Intent の作成時および確定時に渡す同等のパラメーターと一致していることを確認してください。パラメーターが一致しないと、予期しない動作やエラーが発生する可能性があります。

Intent を作成する前に実装で Payment Element をレンダリングする場合、支払い金額が 0 のときは、アメリカの銀行口座の少額預金による確認が省略されます。

| プロパティー | タイプ | 説明 | 必須 |
| --- | --- | --- | --- |
| `mode` | - `payment`
- `setup`
- `subscription` | Payment Element が *PaymentIntent* (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)、*SetupIntent* (The Setup Intents API lets you build dynamic flows for collecting payment method details for future payments. It tracks the lifecycle of a payment setup flow and can trigger additional authentication steps if required by law or by the payment method)、または*サブスクリプション* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis)で使用されているかどうかを示します。 | はい |
| `currency` | `string` | 顧客に請求する金額の通貨。 | はい |
| `amount` | `number` | Apple Pay、Google Pay、または BNPL の UI で示される、顧客に請求する金額。 | `payment` および `subscription` のモードの場合 |
| `setupFutureUsage` | - `off_session`
- `on_session` | Payment Element によって収集された決済の詳細を使用して、今後の決済を行う意図を示します。 | いいえ |
| `captureMethod` | - `automatic`
- `automatic_async`
- `manual` | 顧客の口座から売上をキャプチャーするタイミングを管理します。 | いいえ |
| `onBehalfOf` | `string` | Connect のみ。取引に関する金銭的責任を負う Stripe アカウント ID。このオプションが実装に関連するかを判断するには、[ユースケース](https://docs.stripe.com/connect/charges.md)をご覧ください。 | いいえ |
| `paymentMethodTypes` | `string[]` | 表示する決済手段タイプのリスト。この属性を省略して、[Stripe ダッシュボード](https://dashboard.stripe.com/settings/payment_methods)で決済手段を管理できます。 | いいえ |
| `paymentMethodConfiguration` | `string` | [Stripe ダッシュボード](https://dashboard.stripe.com/settings/payment_methods)で決済手段を管理するときに使用する[決済手段の設定](https://docs.stripe.com/api/payment_method_configurations.md)。指定しない場合は、既定の構成が使用されます。 | いいえ |
| `paymentMethodCreation` | `manual` | [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method_elements) を使用して、Elements インスタンスから PaymentMethods が作成されるようにします。 | いいえ |
| `paymentMethodOptions` | `{us_bank_account: {verification_method: string}}` | `us_bank_account` 決済手段の確認オプション。[Payment Intents](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-us_bank_account-verification_method) と同じ確認手段を受け入れます。 | いいえ |
| `paymentMethodOptions` | `{card: {installments: {enabled: boolean}}}` | [Stripe ダッシュボード](https://dashboard.stripe.com/settings/payment_methods)で決済手段を管理していないときに、カード分割払いプランの選択 UI を手動で有効化できるようにします。`mode='payment'` を設定し、「さらに」`paymentMethodTypes` を明示的に指定する必要があります。それ以外の場合は、エラーが発生します。`paymentMethodCreation='manual'` とは互換性がありません。 | いいえ |
| `paymentMethodOptions` | `{[paymentMethod]: {setup_future_usage: string}}` | 再利用をサポートする決済手段にのみ `setup_future_usage` を指定できます。`mode` が `payment` の場合にのみ適用されます。各決済手段の値は、確定時に PaymentIntent の対応する `payment_method_options[paymentMethod][setup_future_usage]` と一致している必要があります。サポートされている決済手段と値については、[Stripe.js リファレンス](https://docs.stripe.com/js/elements_object/create_without_intent#stripe_elements_no_intent-options-paymentMethodOptions)を参照してください。 | いいえ |

## ConfirmationToken を作成する [クライアント側]

> #### レガシーの実装で createPaymentMethod を使用する
> 
> レガシーの実装を使用している場合は、サーバーで支払いを確定するために `stripe.createPaymentMethod` の情報を使用している場合があります。このガイドに従って [Confirmation Tokens に移行する](https://docs.stripe.com/payments/payment-element/migration-ct.md)ことをお勧めしますが、以前のドキュメントを参照して [2 段階の確認機能を構築する](https://docs.stripe.com/payments/build-a-two-step-confirmation-legacy.md)こともできます。

顧客が決済フォームを送信すると、[stripe.createConfirmationToken](https://docs.stripe.com/js/confirmation_tokens/create_confirmation_token) が呼び出され *ConfirmationToken* (ConfirmationTokens help capture data from your client, such as your customer's payment instruments and shipping address, and are used to confirm a PaymentIntent or SetupIntent) を作成し、支払いの確定前に追加の検証ロジックまたはビジネスロジックをサーバーに送信します。[`payment_method_preview`](https://docs.stripe.com/api/confirmation_tokens/object.md#confirmation_token_object-payment_method_preview) フィールドを調べることで、追加のロジックを実行できます。

#### HTML + JS

```javascript
const form = document.getElementById('payment-form');
const submitBtn = document.getElementById('submit');

const handleError = (error) => {
  const messageContainer = document.querySelector('#error-message');
  messageContainer.textContent = error.message;
  submitBtn.disabled = false;
}

form.addEventListener('submit', async (event) => {
  // We don't want to let default form submission happen here,
  // which would refresh the page.
  event.preventDefault();

  // Prevent multiple form submissions
  if (submitBtn.disabled) {
    return;
  }

  // Disable form submission while loading
  submitBtn.disabled = true;

  // Trigger form validation and wallet collection
  const {error: submitError} = await elements.submit();
  if (submitError) {
    handleError(submitError);
    return;
  }

  // Create the ConfirmationToken using the details collected by the Payment Element
  const {error, confirmationToken} = await stripe.createConfirmationToken({
    elements,
    params: {
      payment_method_data: {
        billing_details: {
          name: 'Jenny Rosen',
        }
      }
    }
  });

  if (error) {
    // This point is only reached if there's an immediate error when
    // creating the ConfirmationToken. Show the error to your customer (for example, payment details incomplete)
    handleError(error);
    return;
  }

  // Now that you have a ConfirmationToken, you can use it in the following steps to render a confirmation page or run additional validations on the server
  return fetchAndRenderSummary(confirmationToken)
});
```

#### React

```jsx
import React, {useState} from 'react';
import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js';

export default function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();

  const [errorMessage, setErrorMessage] = useState();
  const [loading, setLoading] = useState(false);

  const handleError = (error) => {
    setLoading(false);
    setErrorMessage(error.message);
  }

  const handleSubmit = async (event) => {
    // We don't want to let default form submission happen here,
    // which would refresh the page.
    event.preventDefault();

    if (!stripe) {
      // Stripe.js hasn't yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }

    setLoading(true);

    // Trigger form validation and wallet collection
    const {error: submitError} = await elements.submit();
    if (submitError) {
      handleError(submitError);
      return;
    }

    // Create the ConfirmationToken using the details collected by the Payment Element
    const {error, confirmationToken} = await stripe.createConfirmationToken({
      elements,
      params: {
        payment_method_data: {
          billing_details: {
            name: 'Jenny Rosen',
          }
        }
      }
    });

    if (error) {
      // This point is only reached if there's an immediate error when
      // creating the ConfirmationToken. Show the error to your customer (for example, payment details incomplete)
      handleError(error);
      return;
    }

    // Now that you have a ConfirmationToken, you can use it in the following steps to render a confirmation page or run additional validations on the server
    return fetchAndRenderSummary(confirmationToken)
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      <button type="submit" disabled={!stripe || loading}>
        Submit
      </button>
      {errorMessage && <div>{errorMessage}</div>}
    </form>
  );
}
```

## 確認ページで支払いの詳細を表示する

この時点で、確認ページの表示に必要な情報をすべて入手しています。サーバーを呼び出して必要な情報を取得し、それに応じて確認ページを表示します。

#### Node.js

```javascript
// Using Express
const express = require('express');
const app = express();
app.use(express.json());

app.post('/summarize-payment', async (req, res) => {
  try {
    // Retrieve the confirmationTokens and generate the response
    const confirmationToken = await stripe.confirmationTokens.retrieve(req.body.confirmation_token_id);
    const response = summarizePaymentDetails(confirmationToken);

    // Send the response to the client
    res.json(response);
  } catch (e) {
    // Display error on client
    return res.json({ error: e.message });
  }
});

function summarizePaymentDetails(confirmationToken) {
  // Use confirmationToken.payment_method_preview to derive the applicable summary fields for your UI
  return {
    type: confirmationToken.payment_method_preview.type,
    // Add other values (such as Tax Calculation amount) as needed here
  };
}
```

#### JavaScript

```javascript
const fetchAndRenderSummary = async (confirmationToken) => {
  const res = await fetch('/summarize-payment', {
    method: "POST",
    body: JSON.stringify({ confirmation_token_id: confirmationToken.id }),
  });

  const summary = await res.json();

  // Render the summary object returned by your server
};
```

## Optional: 決済前に税金を計算する [サーバー側]

Payment Element はデフォルトでは税金を計算しません。[Tax API](https://docs.stripe.com/api/tax.md) を使用して取引の税額を計算します。

> Payment Element で課税される税金を計算するには、まず以下を行う必要があります。
> 
> - [Stripe Tax を有効にする](https://docs.stripe.com/tax/calculating.md)
- [請求先住所を収集](https://docs.stripe.com/payments/build-a-two-step-confirmation.md#collect-addresses)

`summarizePaymentDetails` 関数を更新して、ConfirmationToken から返される顧客の請求先住所に基づき、税額計算を作成するようにしてください。

### Before

```js
  function summarizePaymentDetails(confirmationToken) {
    // Use confirmationToken.payment_method_preview to derive the applicable summary fields for your UI
  }
```

### After

```js
  function summarizePaymentDetails(confirmationToken) {
    tax_calculation = await stripe.tax.calculations.create({
      currency: 'usd',
      line_items: [
        {
          amount: 1000,
          reference: 'L1',
        },
      ],
      customer_details: {
        // Use ConfirmationToken's address for TaxCalculation
        address: confirmationToken.paymentMethodPreview.billingDetails.address,
        address_source: 'shipping',
      },
    });
```

支払い金額に税金を含む合計金額を顧客に提示できるように、支払い金額と税額計算 `amount_total` を含むように申告書を更新します。

### Before

```js
  return {
    type: confirmationToken.payment_method_preview.type,
    // Add other values as needed here
  };
```

### After

```js
  return {
    type: confirmationToken.payment_method_preview.type,
    // Add any other values from TaxCalculation for your display purposes. For example, you can use [tax_breakdown](/tax/standalone-tax-api#tax-breakdowns) to display what tax was applied
    amount_total: tax_calculation.amount_total,
    tax_calculation_id: tax_calculation.id
    // Add other values as needed here
  };
```

## PaymentIntent を作成する [サーバー側]

> #### 支払い確定の直前にカスタムビジネスロジックを実行する
> 
> 支払いの確定ガイドの[ステップ 5](https://docs.stripe.com/payments/finalize-payments-on-the-server.md?platform=web&type=payment#submit-payment) に移動して、支払い確定の直前にカスタムのビジネスロジックを実行します。または、以下のステップに従って既存のシステムをシンプルにします。ここでは、クライアント側で `stripe.confirmPayment` を使用して、支払いの確定と次のアクションの処理の両方を行います。

顧客が支払いフォームを送信したら、サーバーで `amount` と `currency` を有効にして {% glossary term=“payment-intents”" %}PaymentIntent** を作成します。

*クライアントシークレット* (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)) 値をクライアントに返して、Stripe.js が支払いプロセスを完了できるようにします。

次の例には、オプションの[税金の計算](https://docs.stripe.com/payments/build-a-two-step-confirmation.md#calculate-tax)を示すコメント付きコードが含まれています。

#### Accounts v2

#### Ruby

```ruby
require 'stripe'
# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
Stripe.api_key = '<<YOUR_SECRET_KEY>>'

post '/create-intent' do
  # If you used a Tax Calculation, optionally recalculate taxes
  # confirmation_token = Stripe::ConfirmationToken.retrieve(params[:confirmation_token_id])
  # summarized_payment_details = summarize_payment_details(confirmation_token)

  intent = Stripe::PaymentIntent.create({
    # To allow saving and retrieving payment methods, provide the Account ID.
    customer_account: customer_account.id,
    # If you used a Tax Calculation, use its `amount_total`.
    # amount: summarized_payment_details.amount_total,
    amount: 1099,
    currency: 'usd',
    # Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default.
    automatic_payment_methods: {enabled: true},
    # If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax.
    # hooks: {
    #  inputs: {
    #    tax: {
    #      calculation: tax_calculation.id
    #    }
    #  }
    #}
  },
  #{
  #  stripe_version: '2025-09-30.preview' }
  )
  {client_secret: intent.client_secret}.to_json
end
```

#### Customers v1

#### Ruby

```ruby
require 'stripe'
# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')

post '/create-intent' do
  # If you used a Tax Calculation, optionally recalculate taxes
  # confirmation_token = client.v1.confirmation_tokens.retrieve(params[:confirmation_token_id])
  # summarized_payment_details = summarize_payment_details(confirmation_token)

  intent = client.v1.payment_intents.create({
    # To allow saving and retrieving payment methods, provide the Customer ID.
    customer: customer.id,
    # If you used a Tax Calculation, use its `amount_total`.
    # amount: summarized_payment_details.amount_total,
    amount: 1099,
    currency: 'usd',
    # Specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default.
    automatic_payment_methods: {enabled: true},
    # If you used a Tax Calculation, link it to the PaymentIntent to make sure any transitions accurately reflect the tax.
    # hooks: {
    #  inputs: {
    #    tax: {
    #      calculation: tax_calculation.id
    #    }
    #  }
    #}
  },
  #{
  #  stripe_version: '2025-09-30.preview' }
  )
  {client_secret: intent.client_secret}.to_json
end
```

## Stripe に支払いを送信する [クライアント側]

[stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) を使用して、Payment Element の詳細を使って支払いを完了します。

前のページで作成した ConfirmationToken の ID を含む `confirmation_token` を指定します。この ID には、Payment Element から収集された支払い情報が含まれます。

この関数に [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) を指定して、支払い完了後に Stripe がユーザーをリダイレクトする場所を示します。ユーザーは、最初に銀行の認証ページなどの中間サイトにリダイレクトされてから、`return_url` にリダイレクトされる場合があります。カード支払いでは、支払いが成功するとすぐに `return_url` にリダイレクトされます。

支払い完了後にカード支払いのリダイレクトを行わない場合は、[redirect](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect) を `if_required` に設定できます。これにより、リダイレクトベースの決済手段で購入した顧客のみがリダイレクトされます。

#### HTML + JS

```javascript

const form = document.getElementById('payment-form');
const submitBtn = document.getElementById('submit');

const handleError = (error) => {
  const messageContainer = document.querySelector('#error-message');
  messageContainer.textContent = error.message;
  submitBtn.disabled = false;
}

form.addEventListener('submit', async (event) => {
  // We don't want to let default form submission happen here,
  // which would refresh the page.
  event.preventDefault();

  // Prevent multiple form submissions
  if (submitBtn.disabled) {
    return;
  }

  // Disable form submission while loading
  submitBtn.disabled = true;

  // Create the PaymentIntent and obtain clientSecret
  const res = await fetch("/create-intent", {
    method: "POST",
  });

  const {client_secret: clientSecret} = await res.json();

  // Confirm the PaymentIntent using the details collected by the ConfirmationToken
  const {error} = await stripe.confirmPayment({
    clientSecret,
    confirmParams: {
      confirmation_token: '{{CONFIRMATION_TOKEN_ID}}',
      return_url: 'https://example.com/order/123/complete',
    },
  });

  if (error) {
    // This point is only reached if there's an immediate error when
    // confirming the payment. Show the error to your customer (for example, payment details incomplete)
    handleError(error);
  } else {
    // Your customer is redirected to your `return_url`. For some payment
    // methods like iDEAL, your customer is redirected to an intermediate
    // site first to authorize the payment, then redirected to the `return_url`.
  }
});

```

#### React

```jsx
import React, {useState} from 'react';
import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js';

export default function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();

  const [errorMessage, setErrorMessage] = useState();
  const [loading, setLoading] = useState(false);

  const handleError = (error) => {
    setLoading(false);
    setErrorMessage(error.message);
  }

  const handleSubmit = async (event) => {
    // We don't want to let default form submission happen here,
    // which would refresh the page.
    event.preventDefault();

    if (!stripe) {
      // Stripe.js hasn't yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }

    setLoading(true);

    // Create the PaymentIntent and obtain clientSecret
    const res = await fetch("/create-intent", {
      method: "POST",
    });

    const {client_secret: clientSecret} = await res.json();

    // Confirm the PaymentIntent using the details collected by the ConfirmationToken
    const {error} = await stripe.confirmPayment({
      clientSecret,
      confirmParams: {
        confirmation_token: '{{CONFIRMATION_TOKEN_ID}}',
        return_url: 'https://example.com/order/123/complete',
      },
    });

    if (error) {
      // This point is only reached if there's an immediate error when
      // confirming the payment. Show the error to your customer (for example, payment details incomplete)
      handleError(error);
    } else {
      // Your customer is redirected to your `return_url`. For some payment
      // methods like iDEAL, your customer is redirected to an intermediate
      // site first to authorize the payment, then redirected to the `return_url`.
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      <button type="submit" disabled={!stripe || loading}>
        Submit Payment
      </button>
      {errorMessage && <div>{errorMessage}</div>}
    </form>
  );
}
```

## 顧客に Stripe を開示する

Stripe は顧客の Elements とのやり取りに関する情報を収集して、サービスを提供し、不正利用を防止し、サービスを向上します。これには、Cookie と IP アドレスを使用して、1 つの決済フローセッションで顧客に表示する Elements を特定することが含まれます。Stripe がこのような方法でデータを使用するために必要なすべての権利と同意について開示し、これらを取得することはお客様の責任です。詳細については、[プライバシーセンター](https://stripe.com/legal/privacy-center#as-a-business-user-what-notice-do-i-provide-to-my-end-customers-about-stripe)をご覧ください。

## See also

[実装を設計](https://docs.stripe.com/payments/payment-element/design-an-integration.md)
