XBPx Portfolio · Japan
Contact
Lesson 05 / Database × PayPay

第五回
データベース × PayPay

Database テーブル設計 主キー・外部キー PayPay API

CH 014つのテーブルで読み解く全体像

ECサイトやスマホ決済を扱うシステムの裏側では、データベースが大量のデータを整理して保存している。といっても構造は意外とシンプルで、ユーザー・店舗・商品・購入履歴の 4 テーブルが基本形。今回は PayPay 決済を題材に、この 4 つがどう設計され、どうつながるかを読み解いていく。

01 · User

誰が買ったか。アプリにログインするユーザーの情報を管理する。

02 · Company

どこが売ったか。商品を販売する企業・店舗の情報を管理する。

03 · Product

何が売れたか。商品の名称・価格・在庫を管理する。

04 · Purchase

いつ・いくらで。購入の記録を持ち、全テーブルを結ぶ。

読み進める前に:基本用語

データベースはテーブル(表)の集まりでできている。横 1 行分のデータがレコード、縦の項目がカラム。そしてテーブル同士をつなぐ鍵になるのが、次の 2 種類の「キー」だ。

用語意味
主キー (PK)レコードを一意に区別するための、重複しない番号。例:user_id
外部キー (FK)他のテーブルの主キーを参照して、テーブル同士をつなぐ項目。
Point PayPay の決済 API は、Purchase(購入日時)テーブルpaypay_transaction_id という決済 ID を保存することでデータベースと紐づく。外部サービスとの連携も、結局は「テーブルに ID を 1 つ持つ」ことから始まる。

CH 02User — ユーザー管理テーブル

誰が」を管理する中核テーブル。アプリにログインする全ユーザーの基本情報を保持し、決済時には本人の PayPay アカウントと紐づける。

設計のポイント

  • user_id は他テーブルから参照される主キー。ここが全ての起点になる
  • PayPay アカウント情報は paypay_account_id として別カラムで保持する
  • 個人情報を扱うため、パスワードの hash 化・暗号化が必須

スキーマ:users

カラム説明
PKuser_idBIGINTユーザーを一意に識別する主キー
nameVARCHAR(50)ユーザー名
emailVARCHAR(255)メールアドレス(ログインに使用)
password_hashVARCHAR(255)hash 化したパスワード
phoneVARCHAR(20)電話番号
paypay_account_idVARCHAR(64)本人の PayPay アカウントとの紐づけ
created_atDATETIME登録日時
Security パスワードは平文では絶対に保存しない。カラム名が password ではなく password_hash になっているのは、「hash 化した値しか入れない」という設計意図の表明でもある。

CH 03Company — 会社・店舗管理テーブル

どこが」を管理するテーブル。商品を販売する企業や店舗の情報を保持し、PayPay 加盟店 ID によって決済時に売上の振込先を特定する。

設計のポイント

  • Product テーブルから参照される側になる(1 店舗 : N 商品 の関係)
  • paypay_merchant_id で「どの加盟店への支払いか」を識別する
  • 1 つの店舗は複数の商品を持てる。商品側に店舗情報を書き写さないのがコツ

スキーマ:companies

カラム説明
PKcompany_idBIGINT店舗を一意に識別する主キー
nameVARCHAR(100)企業・店舗名
paypay_merchant_idVARCHAR(64)PayPay 加盟店 ID(売上の振込先を特定)
addressVARCHAR(255)所在地
contact_emailVARCHAR(255)連絡先メールアドレス
phoneVARCHAR(20)電話番号
created_atDATETIME登録日時
Point User テーブルの paypay_account_id が「払う側」の紐づけなら、Company テーブルの paypay_merchant_id は「受け取る側」の紐づけ。決済には必ず両方の ID が関わっている。

CH 04Product — 商品管理テーブル

何を」を管理するテーブル。販売する商品の名称・価格・在庫を保持し、どの会社が販売しているかを外部キーで紐づける。

設計のポイント

  • company_id で店舗テーブルを参照する。ここで初めて外部キー (FK) が登場
  • price は決済金額の根拠になる値。型は誤差の出ない DECIMAL を使う
  • 在庫(stock)は規模が大きくなったら別テーブルに切り出すことも検討する

スキーマ:products

カラム説明
PKproduct_idBIGINT商品を一意に識別する主キー
FKcompany_idBIGINT→ companies。販売元の店舗を参照
nameVARCHAR(100)商品名
priceDECIMAL(10,2)価格。決済金額の根拠になる
stockINT在庫数
descriptionTEXT商品説明
created_atDATETIME登録日時
Point 商品側に店舗名や住所をコピーせず、company_id という 1 つの外部キーで参照する。店舗情報が変わっても Company テーブルを 1 か所直すだけで済む——これが「関係で持つ」設計の強さ。

CH 05Purchase — 購入日時テーブル × PayPay

いつ・いくらで」を記録し、4 テーブルすべてを結ぶハブ。User・Company・Product への外部キーを 3 本持ち、さらに PayPay の決済 ID がここに保存されることで、決済システムとデータベースが連動する。

スキーマ:purchases

カラム説明
PKpurchase_idBIGINT購入レコードを一意に識別する主キー
FKuser_idBIGINT→ users。誰が買ったか
FKproduct_idBIGINT→ products。何を買ったか
FKcompany_idBIGINT→ companies。どこから買ったか
amountDECIMAL(10,2)決済金額
paypay_transaction_idVARCHAR(64)PayPay API が返す決済 ID
payment_statusENUM決済状態(成功・失敗・返金など)
purchased_atDATETIME購入日時
PayPay 連携 決済が完了すると PayPay API が transaction_id を返し、それを paypay_transaction_id カラムに保存する。以降の返金・照合・問い合わせはすべてこの ID を起点に行われる。外部 API との連携は「相手が発行した ID をこちらのテーブルに持つ」——このシンプルな形が基本。

CH 06まとめ — テーブル同士のつながり

全体を俯瞰すると、Purchase テーブルが 3 つのマスタ(User / Company / Product)をつなぐハブになっていることがわかる。各マスタから見ると Purchase とは 1 : N の関係——1 人のユーザーは何度も買い、1 つの店舗・商品は何度も売れるからだ。

「関係」は SQL でこう辿れる

テーブルを分けて ID でつないでおくと、決済 ID ひとつから「誰が・どこで・何を・いくらで」買ったかを 1 本のクエリで辿れる。

-- 決済IDから購入の全体像を辿る
SELECT u.name, c.name AS shop, p.name AS product, pu.amount, pu.purchased_at
FROM purchases pu
JOIN users     u ON pu.user_id    = u.user_id
JOIN products  p ON pu.product_id = p.product_id
JOIN companies c ON pu.company_id = c.company_id
WHERE pu.paypay_transaction_id = 'pp_8f3a1c…';
学んだこと 決済データの設計は、役割ごとにテーブルを分け、主キーと外部キーでつなぐことに尽きる。Purchase をハブに 3 つのマスタが 1 : N で結ばれ、PayPay のような外部 API も transaction_id を 1 カラム持つだけで連動できる。複雑に見える決済システムも、分解すれば 4 枚の表と数本のキーでできている。
Qiita 原文(データベース入門)を読む