# 本人確認の結果を処理する

確認結果をリッスンし、構築済みの自社システムで自動的に対応をトリガできるようにします。

[本人確認書類を収集するモーダルを表示する](https://docs.stripe.com/identity/verify-identity-documents.md)コードを記述しました。次に、ユーザーが書類を送信したときに、確認結果をリッスンし、その対応をアプリケーションでトリガーできます。

このガイドでは、以下の方法について説明します。

1. 本人確認の処理が終了したら、イベント通知を受け取る。
2. 確認チェックの成功と失敗を処理する。
3. 本番環境でイベントハンドラを有効にする。

[本人確認チェック](https://docs.stripe.com/identity/verification-checks.md)は非同期で行われるため、確認結果がすぐに出力されるわけではありません。処理が完了すると、VerificationSession ステータスが更新され、確認された情報の使用が可能になります。Stripe はセッションでステータスが変化するたびに、[イベント](https://docs.stripe.com/api/events.md)を生成します。このガイドでは、[Ｗebhook](https://docs.stripe.com/webhooks.md) を実装して、確認結果が使用可能になったときにアプリに通知します。

## Stripe を設定する [サーバー側]

アプリケーションから 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'
```

## Webhook を作成して、VerificationSession イベントを処理する [サーバー側]

Webhook エンドポイント作成の詳細な手順については、[Webhook エンドポイントを構築する](https://docs.stripe.com/webhooks/quickstart.md)ガイドをご覧ください。

[Webhook](https://docs.stripe.com/webhooks.md) は、サーバー上のエンドポイントで、Stripe からのリクエストを受信し、アカウントで発生するイベントについて通知します。このステップでは、VerificationSession の [ステータス変更](https://docs.stripe.com/identity/verification-sessions.md) でイベントを受信するエンドポイントを構築します。

Stripe が未認証のリクエストを送信できるようにするため、Webhook エンドポイントはパブリックアクセスが可能なものである必要があります。Stripe ライブラリとリクエストヘッダーを使用し、イベントを送信したのが Stripe であることを確認する必要があります。

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// You can find your endpoint's secret in your webhook settings
const endpointSecret = 'whsec_...';

// This example uses Express to receive webhooks
const express = require('express');

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

const app = express();

// Use JSON parser for all non-webhook routes
app.use((req, res, next) => {
  if (req.originalUrl === '/webhook') {
    next();
  } else {
    bodyParser.json()(req, res, next);
  }
});

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
  let event;

  // Verify the event came from Stripe
  try {
    const sig = req.headers['stripe-signature'];
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    // On error, log and return the error message
    console.log(`❌ Error message: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Successfully constructed event

  res.json({received: true});
});

app.listen(4242, () => {
  console.log('Running on port 4242');
});
```

これで、Stripe からの通知をリッスンする基本的な構造とセキュリティが準備できています。次は、Webhook エンドポイントを更新して確認セッションイベントを処理します。

すべての [セッションイベント](https://docs.stripe.com/identity/verification-sessions.md#events) には、実行された検証チェックの詳細を含む[VerificationSession](https://docs.stripe.com/api/identity/verification_sessions.md) オブジェクトが含まれます。セッションイベントに含まれない検証済みの情報を取得する方法については、[本人確認結果へのアクセス](https://docs.stripe.com/identity/access-verification-results.md) を参照してください。

セッションのステータスに変化があると、Stripe は以下のイベントを送信します。

| イベント名 | 説明 | 次のステップ |
| --- | --- | --- |
| [identity.verification_session.verified](https://docs.stripe.com/api/events/types.md#event_types-identity.verification_session.verified) | すべての[本人確認チェック](https://docs.stripe.com/identity/verification-checks.md)の処理が完了し、確認のすべてが成功しました。 | アプリケーションで対応するアクションをトリガします。 |
| [identity.verification_session.requires_input](https://docs.stripe.com/api/events/types.md#event_types-identity.verification_session.requires_input) | すべての[本人確認チェック](https://docs.stripe.com/identity/verification-checks.md)の処理が完了し、少なくとも 1 つの確認が失敗しました。 | アプリケーションで関連するアクションをトリガーするとともに、ユーザーに本人確認の再試行を許可できます。 |

Webhook コードでは `identity.verification_session.verified` イベントおよび `identity.verification_session.requires_input` イベントを処理する必要があります。他の[セッションイベント](https://docs.stripe.com/identity/verification-sessions.md#events) に登録して、アプリで追加のリアクションをトリガーすることもできます。

### VerificationSession 確認済みステータス変化を処理する

本人確認チェックが完了し、すべての確認が成功すると、`identity.verification_session.verified` イベントが送信されます。

イベントハンドラにコードを追加して、すべての確認チェック成功を処理します。

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// You can find your endpoint's secret in your webhook settings
const endpointSecret = 'whsec_...';

// This example uses Express to receive webhooks
const express = require('express');

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

const app = express();

// Use JSON parser for all non-webhook routes
app.use((req, res, next) => {
  if (req.originalUrl === '/webhook') {
    next();
  } else {
    bodyParser.json()(req, res, next);
  }
});

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
  let event;

  // Verify the event came from Stripe
  try {
    const sig = req.headers['stripe-signature'];
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    // On error, log and return the error message
    console.log(`❌ Error message: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Successfully constructed event
  switch (event.type) {
    case 'identity.verification_session.verified': {
      // All the verification checks passed
      const verificationSession = event.data.object;
      break;
    }
  }

  res.json({received: true});
});

app.listen(4242, () => {
  console.log('Running on port 4242');
});
```

このイベントを処理する際には、次のことも考慮してください。

- 確認ステータスを独自のデータベースに保存する
- 本人確認されたことをユーザーに知らせるメールを送信する
- VerificationSession の[確認された出力](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-verified_outputs)を[拡張](https://docs.stripe.com/api/expanding_objects.md)し、予測される値と比較します。

### VerificationSession requires_input のステータス変化を処理する

1 つ以上のチェックが失敗した場合、`identity.verification_session.requires_input` イベントが送信されます。確認セッションの [last_error](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-last_error) ハッシュを調べて、特定の失敗の原因を確認して対処できます。

- [last_error.code](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-last_error-code) フィールドを使用して、確認の失敗をプログラムで処理可能です。
- [last_error.reason](https://docs.stripe.com/api/identity/verification_sessions/object.md#identity_verification_session_object-last_error-reason) フィールドには、失敗の理由を示すメッセージが含まれます。このフィールドをユーザーに提示できます。

#### イベントエラーコード

#### セッション

| エラーコード | 説明 |
| --- | --- |
| `consent_declined` | ユーザーが Stripe による確認を拒否しました。法律顧問に問い合わせて、手動審査など、生体認証以外の本人確認方法を提供する義務があるかどうかご確認ください。 |
| `under_supported_age` | Stripe は未成年のユーザーの本人確認を行いません。 |
| `country_not_supported` | Stripe は、ご指定の国のユーザーの本人確認を行いません。 |

#### 身分証明書

| エラーコード | 説明 |
| --- | --- |
| `document_expired` | 提供された身分証明書の有効期限が切れています。 |
| `document_unverified_other` | Stripe は、提供された本人確認書類を確認できませんでした。[対応している書類タイプのリストをご覧ください](https://docs.stripe.com/identity/verification-checks.md?type=document)。 |
| `document_type_not_supported` | 提供された本人確認書類は、セッションで[許可されている書類のタイプ](https://docs.stripe.com/api/identity/verification_sessions/create.md#create_identity_verification_session-options-document-allow_document_types)ではありません。 |

#### 顔写真

| エラーコード | 説明 |
| --- | --- |
| `selfie_document_missing_photo` | 提供された身分証明書に顔の写真が含まれていませんでした。 |
| `selfie_face_mismatch` | 撮影された顔の画像は文書の顔と一致しませんでした。 |
| `selfie_unverified_other` | Stripeは、提供された顔写真を確認できませんでした。 |
| `selfie_manipulated` | 撮影された顔の画像が加工処理されていました。 |

#### ID 番号

| エラーコード | 説明 |
| --- | --- |
| `id_number_unverified_other` | Stripe は、提供された ID 番号を確認できませんでした。[対応している ID 番号のリストをご覧ください](https://docs.stripe.com/identity/verification-checks.md?type=id-number)。 |
| `id_number_insufficient_document_data` | 提供された書類には、ID 番号との照合に十分なデータが含まれていませんでした。 |
| `id_number_mismatch` | 提供された情報は、グローバルデータベースと照合できませんでした。 |

#### 住所 (招待のみ)

| エラーコード | 説明 |
| --- | --- |
| `address_mismatch` | 提供された情報は、グローバルデータベースと照合できませんでした。 |

イベントハンドラにコードを追加して、確認チェック失敗を処理します。

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// You can find your endpoint's secret in your webhook settings
const endpointSecret = 'whsec_...';

// This example uses Express to receive webhooks
const express = require('express');

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

const app = express();

// Use JSON parser for all non-webhook routes
app.use((req, res, next) => {
  if (req.originalUrl === '/webhook') {
    next();
  } else {
    bodyParser.json()(req, res, next);
  }
});

app.post('/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
  let event;

  // Verify the event came from Stripe
  try {
    const sig = req.headers['stripe-signature'];
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    // On error, log and return the error message
    console.log(`❌ Error message: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Successfully constructed event
  switch (event.type) {
    case 'identity.verification_session.verified': {
      // All the verification checks passed
      const verificationSession = event.data.object;
      break;
    }
    case 'identity.verification_session.requires_input': {
      // At least one of the verification checks failed
      const verificationSession = event.data.object;

      console.log('Verification check failed: ' + verificationSession.last_error.reason);

      // Handle specific failure reasons
      switch (verificationSession.last_error.code) {
        case 'document_unverified_other': {
          // The document was invalid
          break;
        }
        case 'document_expired': {
          // The document was expired
          break;
        }
        case 'document_type_not_supported': {
          // document type not supported
          break;
        }
        default: {
          // ...
        }
      }
    }
  }

  res.json({received: true});
});

app.listen(4242, () => {
  console.log('Running on port 4242');
});
```

ユースケースによっては、本人確認に失敗した場合に、確認の再試行をユーザーに許可することが必要になります。その場合、送信試行回数を制限することをお勧めします。

このイベントを処理する際には、次のことも考慮してください。

- 収集された情報を手動で確認する
- 本人確認が失敗したことをユーザーに知らせるメールを送信する
- ユーザーに代替の本人確認方法を提供する

## 本番環境に移行する

イベントハンドラのエンドポイントを本番環境にデプロイしたら、エンドポイントを設定して、Stripeが本番環境のイベントの送信先を認識できるようにします。実装を本番環境に円滑に移行するには、[開発チェックリスト](https://docs.stripe.com/get-started/checklist/go-live.md) を確認することもお勧めします。

Webhook エンドポイントは、[ワークベンチ](https://docs.stripe.com/workbench.md)で設定するか、API を使用してプログラムで設定します。

### ダッシュボードでエンドポイントを追加する

1. ワークベンチの [Webhook タブ](https://dashboard.stripe.com/workbench/webhooks)で、**送信先を追加**をクリックして新しい Webhook エンドポイントを追加します。
2. Stripe API のバージョンを入力します。
3. リッスンするイベントを選択します。[確認セッションイベント](https://docs.stripe.com/identity/verification-sessions.md#events)の一覧をご覧ください。
4. **続行**をクリックし、使用可能な送信先タイプのリストから**Webhook エンドポイント**を選択します。
5. **続行**をクリックし、エンドポイントの URL、オプションの名前、オプションの説明を入力します。
6. **送信先を作成する**をクリックします。

### API を使用してエンドポイントを追加する

プログラムで [Webhook エンドポイントを作成](https://docs.stripe.com/api/webhook_endpoints/create.md) することもできます。Workbench のフォームと同様に、イベントの送信先として任意の URL を入力したり、登録するイベントタイプを入力したりできます。

```bash
curl https://api.stripe.com/v1/webhook_endpoints \
  -u <<YOUR_SECRET_KEY>>: \
  -d "url"="https://{{DOMAIN}}/my/webhook/endpoint" \
  -d "enabled_events[]"="identity.verification_session.verified" \
  -d "enabled_events[]"="identity.verification_session.requires_input"
```

## See also

- [Webhook エンドポイントをテストする](https://docs.stripe.com/webhooks.md#test-webhook)
- [Webhook 使用のベストプラクティス](https://docs.stripe.com/webhooks.md#best-practices)
- [Webhook 開発チェックリスト](https://docs.stripe.com/get-started/checklist/go-live.md)
