# 機能設計書 140-WhatsApp認可

## 概要

本ドキュメントは、Chatwootシステムにおける「WhatsApp認可」機能の設計仕様を記載する。本機能は、WhatsApp Business APIチャネルを設定するためのEmbedded Signup認証フローを実装する。

### 本機能の処理概要

WhatsApp認可機能は、WhatsApp Business Cloud APIを使用した顧客対応をChatwootで管理するための認証基盤を提供する。Meta（Facebook）のEmbedded Signup機能を使用して、WhatsApp Businessアカウントとの連携を確立し、メッセージの送受信を可能にする。

**業務上の目的・背景**：
WhatsAppは世界で最も広く使用されているメッセージングアプリであり、多くの企業がカスタマーサポートチャネルとして活用している。Chatwootとの連携により、WhatsApp Businessメッセージを他のチャネル（チャット、メール等）と統合的に管理できるようになる。これにより、グローバルな顧客基盤への効率的なサポート提供を実現する。

**機能の利用シーン**：
- 新規にWhatsApp Businessチャネルを追加する場合
- 既存のWhatsApp連携を再認可する場合
- WhatsApp Business Cloud APIへの移行（アップグレード）を行う場合

**主要な処理内容**：
1. Embedded Signupパラメータの受信と検証
2. 認可コードからアクセストークンへの変換
3. 電話番号情報の取得と検証
4. トークンアクセス権限の検証
5. WhatsAppチャネルの作成または再認可
6. Webhookの設定
7. チャネルヘルスチェック

**関連システム・外部連携**：
- WhatsApp Business Cloud API
- Meta Graph API
- Embedded Signup（Meta Business Suite）
- Webhooks（メッセージ受信）

**権限による制御**：
- WhatsApp認可を実行するにはログインユーザーである必要がある
- 既存インボックスの再認可には対象インボックスへのアクセス権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 48 | インボックス新規作成画面 | 主画面 | 新しいWhatsAppチャネルの作成開始 |
| 49 | チャネル設定画面 | 主画面 | WhatsApp認可フローの開始 |
| 50 | インボックス設定画面 | 参照画面 | 認可完了後の設定画面 |
| 101 | WhatsAppキャンペーン画面 | 参照画面 | WhatsApp送信チャネル設定 |

## 機能種別

OAuth認証 / 外部API連携 / データ作成・更新

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| code | String | Yes | Embedded Signup認可コード | 空でないこと |
| business_id | String | Yes | Meta Business ID | 空でないこと |
| waba_id | String | Yes | WhatsApp Business Account ID | 空でないこと |
| phone_number_id | String | No | 電話番号ID | 新規作成時はオプション |
| inbox_id | Integer | No（再認可時必須） | 再認可対象のインボックスID | 存在するインボックス |

### 入力データソース

- Embedded Signup認証コールバック
- 管理画面からの認可開始リクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | Boolean | 処理成功フラグ |
| id | Integer | 作成/更新されたインボックスID |
| name | String | インボックス名 |
| channel_type | String | 'whatsapp' |
| message | String | 再認可時のメッセージ |

### 出力先

- データベース（channel_whatsapp, inboxes テーブル）
- API レスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. 認可リクエスト受信（AuthorizationsController#create）
   └─ inbox_id存在時: 再認可検証
   └─ パラメータ検証（code, business_id, waba_id）

2. Embedded Signupサービス処理
   └─ 認可コードでアクセストークン取得（TokenExchangeService）
   └─ 電話番号情報取得（PhoneInfoService）
   └─ トークンアクセス検証（TokenValidationService）

3. チャネル作成/再認可
   └─ 新規: ChannelCreationService
   └─ 再認可: ReauthorizationService

4. Webhook設定
   └─ setup_webhooksでWebhook登録

5. ヘルスチェック
   └─ HealthServiceでチャネル状態確認
   └─ ペンディング状態の場合、再認可プロンプト

6. レスポンス返却
   └─ 成功レスポンス（id, name, channel_type）
```

### フローチャート

```mermaid
flowchart TD
    A[開始: WhatsApp認可リクエスト] --> B{inbox_id存在?}
    B -->|Yes| C[再認可検証]
    B -->|No| D[パラメータ検証]
    C --> E{再認可必要?}
    E -->|No| F[422エラー]
    E -->|Yes| D
    D --> G{必須パラメータOK?}
    G -->|No| H[エラーレスポンス]
    G -->|Yes| I[EmbeddedSignupService実行]
    I --> J[トークン交換]
    J --> K[電話番号情報取得]
    K --> L[トークン検証]
    L --> M{inbox_id存在?}
    M -->|Yes| N[ReauthorizationService]
    M -->|No| O[ChannelCreationService]
    N --> P[Webhook設定]
    O --> P
    P --> Q[ヘルスチェック]
    Q --> R{ペンディング状態?}
    R -->|Yes| S[prompt_reauthorization!]
    R -->|No| T[正常完了]
    S --> U[成功レスポンス]
    T --> U
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-140-01 | 必須パラメータ | code, business_id, waba_idは必須 | 認可リクエスト時 |
| BR-140-02 | 再認可条件 | 再認可は、reauthorization_required?がtrueまたはEmbeddedへのアップグレード可能な場合のみ | 再認可時 |
| BR-140-03 | whatsapp_cloudプロバイダー | Embedded Signupは whatsapp_cloud プロバイダーのみ対応 | アップグレード時 |
| BR-140-04 | Webhook明示呼び出し | after_commitではなく明示的にsetup_webhooks呼び出し | チャネル作成/再認可後 |
| BR-140-05 | ヘルスチェック | ペンディング状態の場合は再認可プロンプト | チャネル作成後 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| チャネル作成 | channel_whatsapp | INSERT | 新規WhatsAppチャネル作成 |
| インボックス作成 | inboxes | INSERT | インボックス作成とチャネル関連付け |
| チャネル更新 | channel_whatsapp | UPDATE | トークン・電話番号情報の更新 |

### テーブル別操作詳細

#### channel_whatsapp

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | phone_number | phone_info[:phone_number] | WhatsApp電話番号 |
| INSERT/UPDATE | phone_number_id | params[:phone_number_id] | 電話番号ID |
| INSERT/UPDATE | provider | 'whatsapp_cloud' | プロバイダー識別子 |
| INSERT/UPDATE | provider_config | { access_token, business_id, ... } | OAuth トークン・設定情報 |
| INSERT | account_id | account.id | アカウントID |

#### inboxes

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | business_name or phone_number | ビジネス名または電話番号 |
| INSERT | channel_type | 'Channel::Whatsapp' | チャネルタイプ |
| INSERT | channel_id | 作成されたチャネルID | ポリモーフィック関連 |
| INSERT | account_id | account.id | アカウントID |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 422 | Unprocessable Entity | 必須パラメータ不足 | 全パラメータを提供 |
| 422 | Unprocessable Entity | 再認可不要（reauthorization_required? = false） | 不要なら実行しない |
| 422 | Unprocessable Entity | トークン交換失敗 | 再度認可フローを開始 |
| 500 | Internal Server Error | その他のエラー | ログ確認、再試行 |

### リトライ仕様

- エラー発生時、例外をキャプチャしてエラーレスポンスを返却
- スタックトレースをログに出力

## トランザクション仕様

- EmbeddedSignupServiceは各サービスを順次呼び出し
- 個々のサービスでの例外は呼び出し元に伝播

## パフォーマンス要件

- Meta Graph API呼び出しは外部依存のため、タイムアウトを適切に設定
- 複数のAPIコール（トークン交換、電話番号情報、トークン検証）を逐次実行

## セキュリティ考慮事項

- アクセストークンは暗号化して保存
- Business ID、WABA IDはログに出力されない
- Webhookの設定はセキュアなエンドポイントを使用

## 備考

- Embedded Signupを使用（従来のSystem User方式とは異なる）
- source: 'embedded_signup'でafter_commitコールバックをスキップ
- ヘルスチェックでペンディング状態を検出して再認可プロンプト

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: 認可コントローラーを理解する

WhatsApp認可のエントリーポイントを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | authorizations_controller.rb | `app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb` | 認可処理の全体構造 |

**主要処理フロー**:
- **7-13行目**: create アクション
  - validate_embedded_signup_params!でパラメータ検証
  - process_embedded_signupでサービス呼び出し
  - render_success_responseで成功レスポンス
- **17-24行目**: process_embedded_signup - EmbeddedSignupService呼び出し
- **26-29行目**: fetch_and_validate_inbox - 再認可時のインボックス検証
- **31-38行目**: validate_reauthorization_required - 再認可必要性チェック
- **67-76行目**: validate_embedded_signup_params! - パラメータ検証

#### Step 2: Embedded Signupサービスを理解する

認可処理の中核サービスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | embedded_signup_service.rb | `app/services/whatsapp/embedded_signup_service.rb` | サービスの全体構造 |

**主要処理フロー**:
- **11-30行目**: perform - メイン処理
  - validate_parameters!
  - exchange_code_for_token
  - fetch_phone_info
  - validate_token_access
  - create_or_reauthorize_channel
  - setup_webhooks
  - check_channel_health_and_prompt_reauth
- **34-36行目**: exchange_code_for_token - TokenExchangeService呼び出し
- **38-40行目**: fetch_phone_info - PhoneInfoService呼び出し
- **42-44行目**: validate_token_access - TokenValidationService呼び出し
- **46-58行目**: create_or_reauthorize_channel - 作成または再認可

### プログラム呼び出し階層図

```
Api::V1::Accounts::Whatsapp::AuthorizationsController#create
    |
    +-- fetch_and_validate_inbox (inbox_id存在時)
    |       |
    |       +-- validate_reauthorization_required
    |               |
    |               +-- reauthorization_required? or can_upgrade_to_embedded_signup?
    |
    +-- validate_embedded_signup_params!
    |
    +-- process_embedded_signup
    |       |
    |       +-- Whatsapp::EmbeddedSignupService.new.perform
    |               |
    |               +-- validate_parameters!
    |               |
    |               +-- exchange_code_for_token
    |               |       |
    |               |       +-- TokenExchangeService.new(@code).perform
    |               |
    |               +-- fetch_phone_info
    |               |       |
    |               |       +-- PhoneInfoService.new(@waba_id, @phone_number_id, token).perform
    |               |
    |               +-- validate_token_access
    |               |       |
    |               |       +-- TokenValidationService.new(token, @waba_id).perform
    |               |
    |               +-- create_or_reauthorize_channel
    |               |       |
    |               |       +-- ReauthorizationService (inbox_id存在時)
    |               |       +-- ChannelCreationService (新規時)
    |               |
    |               +-- channel.setup_webhooks
    |               |
    |               +-- check_channel_health_and_prompt_reauth
    |                       |
    |                       +-- HealthService.new(channel).fetch_health_status
    |                       +-- channel.prompt_reauthorization! (ペンディング時)
    |
    +-- render_success_response(channel.inbox)
```

### データフロー図

```
[入力]                    [処理]                           [出力]

Embedded Signup      --> AuthorizationsController#create --> チャネル・インボックス
(code, business_id,      |                                  |
 waba_id,                +-- validate_embedded_signup_params!
 phone_number_id)        |                                  |
                         +-- EmbeddedSignupService          +-- Channel::Whatsapp
                         |       |                          +-- Inbox
                         |       +-- TokenExchangeService   +-- Webhook設定
                         |       +-- PhoneInfoService
                         |       +-- TokenValidationService
                         |       +-- ChannelCreationService
                         |           or ReauthorizationService
                         |       +-- setup_webhooks
                         |       +-- HealthService
                         |
                         +-- render_success_response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| authorizations_controller.rb | `app/controllers/api/v1/accounts/whatsapp/authorizations_controller.rb` | コントローラー | 認可エントリーポイント |
| embedded_signup_service.rb | `app/services/whatsapp/embedded_signup_service.rb` | サービス | Embedded Signup処理 |
| token_exchange_service.rb | `app/services/whatsapp/token_exchange_service.rb` | サービス | トークン交換 |
| phone_info_service.rb | `app/services/whatsapp/phone_info_service.rb` | サービス | 電話番号情報取得 |
| token_validation_service.rb | `app/services/whatsapp/token_validation_service.rb` | サービス | トークン検証 |
| channel_creation_service.rb | `app/services/whatsapp/channel_creation_service.rb` | サービス | チャネル作成 |
| reauthorization_service.rb | `app/services/whatsapp/reauthorization_service.rb` | サービス | 再認可処理 |
| health_service.rb | `app/services/whatsapp/health_service.rb` | サービス | ヘルスチェック |
| whatsapp.rb | `app/models/channel/whatsapp.rb` | モデル | WhatsAppチャネルのデータモデル |
