# 機能設計書 2-ソーシャルログイン

## 概要

本ドキュメントは、ECモバイルアプリケーションにおけるソーシャルログイン機能の設計仕様を定義する。外部サービス（SNS等）のアカウントを利用してユーザー認証を行い、新規ユーザーの場合は自動的にアカウントを作成する。

### 本機能の処理概要

**業務上の目的・背景**：新規ユーザーの登録障壁を下げ、コンバージョン率を向上させるため、既存のSNSアカウントを利用した簡易認証を提供する。ユーザーはパスワードを新たに設定する必要がなく、数タップでアカウント作成とログインが完了する。

**機能の利用シーン**：サインイン画面でソーシャルログインボタンをタップした際に利用される。外部認証プロバイダ（Google、Facebook等）での認証後、取得したユーザー情報をもとにBagistoアカウントを作成またはログインする。

**主要な処理内容**：
1. 外部認証プロバイダからユーザー情報（メール、名前等）を取得
2. 取得した情報をもとにcustomerSocialSignUp mutationを実行
3. 新規ユーザーの場合はアカウント自動作成、既存ユーザーの場合はログイン
4. アクセストークン取得とローカル保存
5. ホーム画面への遷移

**関連システム・外部連携**：Bagisto GraphQL API（customerSocialSignUp mutation）、外部認証プロバイダ（Google、Facebook等）

**権限による制御**：本機能は未ログインユーザーが利用可能。認証成功後は顧客権限でアプリ内機能にアクセスできる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | サインイン画面 | 主画面 | ソーシャルログインボタンの配置、外部認証結果の受信 |
| 2 | ホーム画面 | 遷移先画面 | ソーシャルログイン成功後の遷移先 |

## 機能種別

認証処理 / API連携 / データ保存 / 外部サービス連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| email | String | Yes | 外部プロバイダから取得したメールアドレス | - |
| firstName | String | Yes | 外部プロバイダから取得した名 | - |
| lastName | String | Yes | 外部プロバイダから取得した姓 | - |
| phone | String | No | 電話番号 | - |
| signUpType | String | Yes | 認証プロバイダ種別（google、facebook等） | - |

### 入力データソース

- 外部認証プロバイダ：Google Sign-In、Facebook Login等から取得したユーザー情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| status | bool | 処理成功フラグ |
| success | bool | API成功フラグ |
| accessToken | String | API認証用アクセストークン |
| tokenType | String | トークン種別（Bearer等） |
| expiresIn | int | トークン有効期限（秒） |
| customer.id | String | 顧客ID |
| customer.firstName | String | 顧客の名 |
| customer.lastName | String | 顧客の姓 |
| customer.name | String | 顧客のフルネーム |
| customer.email | String | 顧客メールアドレス |
| customer.phone | String | 顧客電話番号 |

### 出力先

- SharedPreferences：顧客情報（ログイン状態、名前、メール、トークン、ID）
- 画面遷移：成功時はホーム画面へ遷移

## 処理フロー

### 処理シーケンス

```
1. ユーザーがソーシャルログインボタンをタップ
   └─ 外部認証プロバイダの認証画面へ遷移

2. 外部プロバイダでの認証完了
   └─ ユーザー情報（email, firstName, lastName等）を取得

3. SocialLoginEventをSignInBlocへ送信
   └─ signInBloc?.add(SocialLoginEvent(...))

4. SignInBlocがSignInRepositoryを通じてAPI呼び出し
   └─ repository!.socialLogin(email, firstName, lastName, phone, signUpType)

5. ApiClientがGraphQL mutationを実行
   └─ mutation.getSocialLoginResponse(...)

6. レスポンス処理
   └─ 成功: SocialLoginState.success発行
   └─ 失敗: SocialLoginState.fail発行

7. 成功時、3秒後にユーザー情報を保存
   └─ appStoragePref.setCustomerLoggedIn(true)等

8. 指紋認証設定確認（オプション）
   └─ checkFingerprint()

9. ホーム画面へ遷移
   └─ Navigator.of(context).pushNamedAndRemoveUntil(home, ...)
```

### フローチャート

```mermaid
flowchart TD
    A[サインイン画面] --> B[ソーシャルログインボタンタップ]
    B --> C[外部認証プロバイダ画面]
    C --> D{外部認証結果}
    D -->|キャンセル| A
    D -->|成功| E[ユーザー情報取得]
    E --> F[GraphQL API呼び出し]
    F --> G{API結果}
    G -->|失敗| H[エラー通知表示]
    H --> I[ダイアログ閉じる]
    I --> A
    G -->|成功| J[ユーザー情報保存]
    J --> K[成功通知表示]
    K --> L[ホーム画面へ遷移]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 自動アカウント作成 | メールアドレスが未登録の場合、新規アカウントを自動作成 | 初回ソーシャルログイン時 |
| BR-002 | 既存アカウント紐付け | 同一メールアドレスが存在する場合、既存アカウントにログイン | ソーシャルログイン時 |
| BR-003 | 認証成功時の自動遷移 | 認証成功後3秒待機してからホーム画面へ遷移 | 認証成功時 |
| BR-004 | セッション管理 | ログイン状態はSharedPreferencesに永続化 | 認証成功時 |

### 計算ロジック

本機能に計算ロジックは存在しない。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アカウント作成/ログイン | customers | INSERT/SELECT | 新規顧客作成または既存顧客照合 |
| トークン生成 | oauth_access_tokens | INSERT | アクセストークンの生成・保存 |

※上記はバックエンド側（Bagisto）での操作。モバイルアプリ側ではSharedPreferencesへの書き込みのみ。

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

#### SharedPreferences（ローカルストレージ）

| 操作 | 項目（キー名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| WRITE | customerLoggedIn | true | ログイン状態フラグ |
| WRITE | customerName | SignInModel.data.name | 顧客名 |
| WRITE | customerEmail | SignInModel.data.email | 顧客メール |
| WRITE | customerToken | "${tokenType} ${token}" | 認証トークン |
| WRITE | customerId | SignInModel.data.id | 顧客ID |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 外部認証エラー | 外部プロバイダでの認証キャンセルまたは失敗 | サインイン画面に戻る |
| - | API認証エラー | Bagisto APIでの認証失敗 | ShowMessage.errorNotificationでエラー表示 |
| - | ネットワークエラー | API通信失敗 | ShowMessage.errorNotificationでエラー表示 |

### リトライ仕様

本機能にリトライ処理は実装されていない。ユーザーは手動で再度ソーシャルログインを試行する必要がある。

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

モバイルアプリ側ではトランザクション管理は行わない。バックエンド側でアカウント作成とトークン生成が一連の処理として実行される。

## パフォーマンス要件

- 外部認証プロバイダの応答時間に依存
- Bagisto API応答時間：3秒以内

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

- 外部認証プロバイダとの通信はOAuth 2.0準拠
- アクセストークンはSharedPreferencesに保存（暗号化なし）
- ソーシャルログインで取得した情報のみでアカウント作成されるため、パスワード設定なし

## 備考

- 本機能はサインイン機能（No.1）と同じBlocを共有している
- 外部認証プロバイダの具体的な実装は本機能スコープ外

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

サインイン機能と同じデータモデルを使用。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | signin_model.dart | `lib/data_model/sign_in_model/signin_model.dart` | SignInModelクラスでソーシャルログインのレスポンス構造も同様に処理 |

#### Step 2: イベント・状態定義を理解する

ソーシャルログイン専用のイベントと状態を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sign_in_event.dart | `lib/screens/sign_in/bloc/sign_in_event.dart` | SocialLoginEvent（26-37行目）でemail, firstName, lastName, phone, signUpTypeを保持 |
| 2-2 | sign_in_state.dart | `lib/screens/sign_in/bloc/sign_in_state.dart` | SocialLoginState（42-55行目）でソーシャルログイン結果の状態管理 |

#### Step 3: ビジネスロジックを理解する

Blocでのソーシャルログインイベント処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sign_in_bloc.dart | `lib/screens/sign_in/bloc/sign_in_bloc.dart` | SocialLoginEvent処理（38-57行目）でAPI呼び出しと状態発行 |

**主要処理フロー**:
- **38行目**: SocialLoginEventの判定
- **40-44行目**: repository.socialLogin()呼び出し
- **48-52行目**: 成功/失敗に応じたState発行

#### Step 4: リポジトリ層を理解する

ソーシャルログインAPI呼び出しの抽象化を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sign_in_repository.dart | `lib/screens/sign_in/bloc/sign_in_repository.dart` | socialLoginメソッド（35-48行目）でApiClientを呼び出し |

#### Step 5: API通信層を理解する

GraphQL通信の実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | api_client.dart | `lib/services/api_client.dart` | socialLoginメソッド（627-646行目）でmutationを実行 |
| 5-2 | mutation_query.dart | `lib/services/mutation_query.dart` | getSocialLoginResponseメソッド（843-885行目）でGraphQL mutation文字列を生成 |

#### Step 6: 画面での結果処理を理解する

サインイン画面でのソーシャルログイン結果処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | BlocConsumer内でSocialLoginState処理（96-119行目） |

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

```
SignInScreen (View)
    │
    ├─ [外部認証プロバイダ] ─── ユーザー情報取得
    │
    ├─ SignInBloc (Business Logic)
    │      │
    │      └─ SignInRepositoryImp (Repository)
    │             │
    │             └─ ApiClient.socialLogin() (API Layer)
    │                    │
    │                    └─ GraphQlApiCalling (GraphQL Client)
    │                           │
    │                           └─ MutationsData.getSocialLoginResponse() (Query Builder)
    │
    └─ appStoragePref (Local Storage)
           └─ SharedPreferences
```

### データフロー図

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

外部認証プロバイダ
       │
       ▼
email, firstName,     ───▶ SocialLoginEvent ───▶ SignInBloc
lastName, phone,                                    │
signUpType                                          ▼
                                            SignInRepository
                                                    │
                                                    ▼
                                                ApiClient ───▶ GraphQL API
                                                    │
                                                    ▼
                                             SignInModel
                                                    │
                                                    ▼
                        SocialLoginState.success ───▶ SignInScreen
                                                     │
                                                     ▼
                                              appStoragePref ───▶ SharedPreferences
                                                     │
                                                     ▼
                                              Navigator.pushNamedAndRemoveUntil(home)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | ソース | サインイン画面UI（ソーシャルログインボタン含む） |
| sign_in_bloc.dart | `lib/screens/sign_in/bloc/sign_in_bloc.dart` | ソース | 状態管理Bloc（SocialLoginEvent処理含む） |
| sign_in_event.dart | `lib/screens/sign_in/bloc/sign_in_event.dart` | ソース | イベント定義（SocialLoginEvent） |
| sign_in_state.dart | `lib/screens/sign_in/bloc/sign_in_state.dart` | ソース | 状態定義（SocialLoginState） |
| sign_in_repository.dart | `lib/screens/sign_in/bloc/sign_in_repository.dart` | ソース | リポジトリ層（socialLoginメソッド） |
| signin_model.dart | `lib/data_model/sign_in_model/signin_model.dart` | ソース | データモデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント（socialLogin） |
| mutation_query.dart | `lib/services/mutation_query.dart` | ソース | GraphQLクエリ定義（getSocialLoginResponse） |
