---
title: 複合払い（ポイント＋カード）の返金処理
description: 返金ルールは経理・税務方針で決まる。冪等性キーで二重返金を防ぐ設計を実装前に
sidebar:
  label: 複合払いの返金
---

| 項目 | 内容 |
|---|---|
| **疑うべき法令・基準** | 会計基準 |
| **確認タイミング** | DB・API設計時（実装前） |

## なにが問題になるか

「ポイント500円分＋クレジットカード1,000円で合計1,500円の商品を購入」した後のキャンセルで、どう返金するかのルールが決まっていないと経理上のトラブルに直結します。返金ルールは一般的に2パターンです。

- **ポイント先返還**：チャージ型ポイントを500円分復元し、カード返金を1,000円とする。前受金の復活もあわせて処理する。
- **比例按分**：支払い比率に応じてポイントとカードを按分して返金。端数処理のルールが別途必要。

どちらを採用するかは**経理・税務の方針で決まります**。エンジニアが独自に決めるものではなく、実装前に確認が必要です。ルールが決まったら**コードにハードコーディングせず、設定テーブルかドキュメントに明文化**してください。「なぜこの計算式なのかコードを読んでも不明」という状態は、監査に耐えられないコードを生みます。

もう1つの落とし穴が**二重返金**です。ネットワークの再試行やユーザーの重複操作により、同じ返金リクエストを複数回受信することがあります。

```sql
ALTER TABLE point_transactions
  ADD COLUMN idempotency_key VARCHAR(64) UNIQUE;
```

`idempotency_key` には「注文ID＋返金種別」など同一リクエストを一意に識別できる値をセットします。UNIQUE制約により二重実行時にDBがエラーを返すため、アプリ側で冪等性を保証できます。返金処理は金額に直結するため、この設計を省略すると二重返金が発生し、経理上の不整合につながります。

## 確認すべきこと

- [ ] 複合払いの返金ルール（ポイント先返還か比例按分か）を経理・税務と確認してから実装に入った
- [ ] 返金ルールを設定テーブルまたはドキュメントに明文化した（ハードコーディングしていない）
- [ ] 複合払いの返金処理に冪等性キー（`idempotency_key`）を設計している
- [ ] `idempotency_key` カラムにUNIQUE制約を設け、バグや通信リトライによる二重計上をDB側でも防いでいる
- [ ] 返金時の前受金の復活（`refund` イベント）が記録される設計になっている

## こんな仕様が出たらアラート

- 複合払い（ポイント＋カード）の返金ルールが未定義のまま実装に入る
- 返金処理のルールがコードにハードコーディングされている
- 返金APIにリトライ・重複リクエスト対策がない

## あわせて確認

- 前提となる履歴テーブル設計 → [ポイント・電子マネーの残高DB設計](/features/accounting/balance-db)

{/* 実務メモ: 書籍にない独自の追加情報はこの下に追記していく */}
