# 機能設計書 25-支払方法変更

## 概要

本ドキュメントは、Shopwareストアフロントにおける支払方法変更機能の設計を記述したものである。本機能は、注文確定後に顧客が支払方法を変更するための機能を提供する。

### 本機能の処理概要

支払方法変更機能は、注文編集画面において顧客が別の支払方法を選択し、その選択をコンテキストに適用する機能を提供する。

**業務上の目的・背景**：ECサイトにおいて、注文後に顧客が支払方法を変更したいケースは様々な理由で発生する。例えば、クレジットカードの有効期限切れ、別の決済手段への変更希望、決済エラー後の再試行などがある。顧客自身で支払方法を変更できることで、注文の完了率向上とカスタマーサポートへの問い合わせ削減に寄与する。

**機能の利用シーン**：
- 元の支払方法で決済エラーが発生した場合
- 別の支払方法で支払いたい場合
- クレジットカードの有効期限切れで決済できない場合
- 後払いから前払いに変更したい場合

**主要な処理内容**：
1. 新しい支払方法IDをリクエストから取得
2. SalesChannelContextの支払方法を切り替え
3. 注文編集ページにリダイレクト

**関連システム・外部連携**：
- AbstractContextSwitchRoute: コンテキスト切り替えAPI
- SalesChannelContextService: 販売チャネルコンテキスト管理

**権限による制御**：
- 注文の所有者（顧客本人）のみ変更可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | 注文編集ページ | 主画面 | 注文の支払方法変更（AccountOrderController::orderChangePayment） |

## 機能種別

CRUD操作（Update） / コンテキスト変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| orderId | string | Yes | 対象注文ID（URLパラメータ） | UUID形式 |
| paymentMethodId | string | Yes | 新しい支払方法ID | UUID形式 |

### 入力データソース

- URLルートパラメータ（orderId）
- HTTPリクエストパラメータ（POST: paymentMethodId）
- SalesChannelContext（現在のコンテキスト情報）

## 出力仕様

### 出力データ

出力データはなく、リダイレクトレスポンスのみ返却される。

### 出力先

- リダイレクトレスポンス: `frontend.account.edit-order.page`（注文編集ページ）

## 処理フロー

### 処理シーケンス

```
1. orderChangePayment（POST /account/order/payment/{orderId}）
   └─ paymentMethodIdをリクエストから取得
   └─ RequestDataBagを構築
      └─ PAYMENT_METHOD_ID: 新しい支払方法ID
   └─ AbstractContextSwitchRoute.switchContextを呼び出し
   └─ 注文編集ページにリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[支払方法変更リクエスト] --> B[orderIdをURLから取得]
    B --> C[paymentMethodIdをリクエストから取得]
    C --> D[RequestDataBag構築]
    D --> E[ContextSwitchRoute.switchContext]
    E --> F[コンテキストの支払方法更新]
    F --> G[注文編集ページへリダイレクト]
    G --> H[リダイレクトレスポンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | 所有者確認 | 支払方法を変更できるのは注文を行った顧客本人のみ | 常時 |
| BR-25-02 | 有効な支払方法 | 選択される支払方法は現在のセールスチャネルで有効なものに限る | 常時 |
| BR-25-03 | afterOrderEnabled | 注文後に変更可能な支払方法（afterOrderEnabled=true）のみ選択可能 | 常時 |
| BR-25-04 | コンテキスト更新 | 支払方法の変更はSalesChannelContextに反映される | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| コンテキスト更新 | セッション | UPDATE | 選択された支払方法をセッションに保存 |

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

本機能自体は直接データベースを更新せず、セッションコンテキストのみを変更する。実際のデータベース更新は、注文更新機能（No.26）で行われる。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| PAYMENT_METHOD_NOT_FOUND | 支払方法不在 | 指定されたpaymentMethodIdが存在しない | エラーページ表示 |
| PAYMENT_METHOD_NOT_AVAILABLE | 支払方法無効 | 指定された支払方法が無効または利用不可 | エラーメッセージ表示 |

### リトライ仕様

エラー発生時は注文編集ページに戻り、別の支払方法を選択可能。

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

本機能はセッションコンテキストの更新のみで、トランザクション制御は不要。

## パフォーマンス要件

- コンテキスト切り替え: 500ms以内
- リダイレクト含む全体処理: 1秒以内

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

- POSTメソッドのみ受付（CSRF保護）
- 注文所有者の検証（注文編集ページアクセス時に実施）
- 有効な支払方法のみ選択可能

## 備考

- 本機能は支払方法の「選択」のみを行い、実際の支払処理は注文更新機能（No.26）で実行される
- 注文編集ページへのリダイレクト後、画面上で新しい支払方法が反映された状態で表示される
- コンテキストの変更は一時的なもので、注文更新を行わない限り永続化されない

---

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

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

### 推奨読解順序

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

コンテキスト切り替えに関わるデータ構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SalesChannelContextService.php | `src/Core/System/SalesChannel/Context/SalesChannelContextService.php` | PAYMENT_METHOD_ID定数 |
| 1-2 | SalesChannelContext.php | `src/Core/System/SalesChannel/SalesChannelContext.php` | paymentMethodプロパティ |

**読解のコツ**: SalesChannelContextServiceの定数（PAYMENT_METHOD_ID等）は、コンテキスト切り替え時のキーとして使用される。

#### Step 2: エントリーポイントを理解する

処理の起点となるコントローラーを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AccountOrderController.php | `src/Storefront/Controller/AccountOrderController.php` | orderChangePaymentメソッド |

**主要処理フロー**:
1. **283-300行目**: `orderChangePayment`メソッド - 支払方法変更処理
2. **288行目**: orderIdをURLパラメータから取得
3. **290-295行目**: RequestDataBag構築とContextSwitchRoute呼び出し
4. **299行目**: 注文編集ページへのリダイレクト

#### Step 3: コンテキスト切り替えを理解する

コンテキスト切り替えAPIを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractContextSwitchRoute.php | `src/Core/System/SalesChannel/SalesChannel/AbstractContextSwitchRoute.php` | コンテキスト切り替えAPIの抽象クラス |

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

```
AccountOrderController
    │
    └─ orderChangePayment (POST /account/order/payment/{orderId})
           │
           ├─ RequestParamHelper.get('paymentMethodId')
           │
           ├─ RequestDataBag構築
           │      └─ PAYMENT_METHOD_ID: 新しい支払方法ID
           │
           ├─ AbstractContextSwitchRoute.switchContext
           │      └─ SalesChannelContext更新
           │             └─ paymentMethod切り替え
           │
           └─ redirectToRoute('frontend.account.edit-order.page')
```

### データフロー図

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

POSTリクエスト ─────────────────┬──────────────────────────────────► リダイレクト
(/account/order/payment/{orderId})                                   レスポンス
(paymentMethodId)              │
                               ▼
                    ┌─────────────────────┐
                    │ AccountOrder        │
                    │ Controller          │
                    │ ::orderChangePayment│
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │ ContextSwitchRoute  │
                    │ .switchContext      │─────────────────────────► セッション更新
                    └─────────┬───────────┘                          (paymentMethodId)
                              │
                              ▼
                    ┌─────────────────────┐
                    │ リダイレクト        │
                    │ → edit-order.page   │
                    └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AccountOrderController.php | `src/Storefront/Controller/AccountOrderController.php` | ソース | コントローラー（エントリーポイント） |
| AbstractContextSwitchRoute.php | `src/Core/System/SalesChannel/SalesChannel/AbstractContextSwitchRoute.php` | ソース | コンテキスト切り替えAPI抽象クラス |
| SalesChannelContextService.php | `src/Core/System/SalesChannel/Context/SalesChannelContextService.php` | ソース | コンテキストサービス（定数定義） |
| SalesChannelContext.php | `src/Core/System/SalesChannel/SalesChannelContext.php` | ソース | コンテキストエンティティ |
| RequestDataBag.php | `src/Core/Framework/Validation/DataBag/RequestDataBag.php` | ソース | リクエストデータバッグ |
