TEXTBOOK SECTION / AI LEARNING

決済システムのセキュリティ

Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装の「実務で必要なセキュリティと運用」より、決済システムのセキュリティを解説。生成AI、AI活用、DX、業務改善を実践しながら学べるオンライン教材です。

1実務で必要なセキュリティと運用EC

OVERVIEW

この節で学べること

概要を表示する
項目内容
教材名Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装
実務で必要なセキュリティと運用
決済システムのセキュリティ
カテゴリEC
学習内容生成AI、AI活用、DX、業務改善を実践しながら理解するための教材です。

TABLE OF CONTENTS

目次

CONTENT

ここから

第20章では、トップページ、商品一覧、購入ボタン、FAQ、LINE、SNSなどをつなげて、売れる導線を設計しました。

ここから第7部では、実務で必要なセキュリティと運用を扱います。

ECでは、商品が売れることも大切です。

しかし、それ以上に大切なのは、安全に売ることです。

決済情報、個人情報、注文情報を扱うECでは、設計を間違えると大きなトラブルになります。

決済情報が漏れる
注文金額を改ざんされる
Webhookを偽装される
管理画面に不正ログインされる
個人情報を必要以上に保存してしまう

この章では、Square APIとNext.jsでECを作るときに、最低限押さえるべきセキュリティの考え方を整理します。

攻略本風に言えば、第21章は**「売れるECを守るための防具をそろえるステージ」**です。


21.1 決済情報を自社サーバーに持たない設計

ECのセキュリティで最も重要なのは、クレジットカード情報を自社サーバーに持たないことです。

クレジットカード番号、有効期限、セキュリティコードなどを自分たちのDBに保存してはいけません。

保存してはいけないもの:
カード番号
有効期限
セキュリティコード
カード名義
磁気データ

初心者が作るECでは、次のような発想になりがちです。

自分のサイトにカード入力フォームを作る
  ↓
入力されたカード情報をサーバーに送る
  ↓
決済処理する

これは危険です。

カード情報を自社サーバーで扱うと、セキュリティ要件が一気に重くなります。

本書では、Squareのホスト型決済やSquareの決済機能を使い、カード情報の入力と処理をSquare側に任せる設計を基本にします。

自社EC:
商品表示
注文作成
在庫管理
メール通知
管理画面

Square:
カード入力
決済処理
決済結果
レシート

SquareのWeb Payments SDKは、オンライン決済を受け付けるためのPCI準拠の入力UIを提供します。Squareのオンライン決済APIについても、Square側がPCI-DSS対応の負担を引き受ける旨が公式に説明されています。(Square)

本書のように、Squareの決済画面やSDKを使う設計では、自社ECが扱うのは次の情報です。

・注文ID
・商品ID
・数量
・合計金額
・Square Payment ID
・Square Order ID
・配送先情報
・注文ステータス

カード番号そのものは扱いません。

この方針を守るだけで、ECのセキュリティリスクは大きく下がります。

決済情報は持たない。
決済結果だけを受け取る。

これが、小規模ECで最初に守るべき基本です。


21.2 Squareに任せるべき領域

ECシステムでは、自分たちで作る部分と、Squareに任せる部分を分けます。

全部を自作しようとすると、危険で複雑になります。

Squareに任せるべき領域は、次の通りです。

・カード情報の入力
・決済処理
・決済ステータスの管理
・決済結果の通知
・レシート
・返金処理の一部

自社ECで担当する領域は、次の通りです。

・商品ページ
・カート
・注文DB
・在庫管理
・配送管理
・メール通知
・管理画面
・SEO
・販売導線

分け方のイメージです。

購入者
  ↓
自社ECで商品を見る
  ↓
Squareで決済する
  ↓
SquareからWebhookが届く
  ↓
自社ECで注文をpaidにする
  ↓
自社ECで配送準備を進める

Squareに任せる理由は、決済まわりが専門性の高い領域だからです。

特にカード情報や決済処理は、自前で作るメリットよりリスクの方が大きくなりやすいです。

自作しない方がよい領域:
カード入力
カード保存
カード認証
決済処理
不正利用判定

反対に、自社ECで作る価値があるのは、商品やブランド体験に関わる部分です。

自作する価値がある領域:
商品ページの見せ方
ギフト導線
FAQ
SEO記事
在庫表示
注文管理
配送管理

つまり、設計方針は次の通りです。

危険で専門性が高い決済部分
  → Squareに任せる

ブランド体験と販売導線
  → 自社ECで作る

この分担が、小規模事業者にとって現実的で安全な構成です。


21.3 Access Tokenの管理

Access Tokenは、Square APIを呼び出すための重要な鍵です。

このTokenが漏れると、Square APIへ不正にアクセスされる危険があります。

Squareの公式ドキュメントでは、Personal access tokenはSquareアカウント内のリソースへ広くアクセスできる認証情報として説明されています。また、OAuth access tokenは、Square販売者が許可したスコープに基づいてAPIアクセスするためのTokenです。(Square)

Access Tokenは、絶対にフロントエンドへ出してはいけません。

出してはいけない場所:
Client Component
ブラウザのJavaScript
GitHub
公開リポジトリ
HTML内
console.log

Next.jsでは、Square APIを呼び出す処理はサーバー側に置きます。

よい場所:
Route Handler
Server Action
サーバー側のlib関数
Webhook処理

環境変数の例です。

SQUARE_ACCESS_TOKEN=
SQUARE_LOCATION_ID=
SQUARE_WEBHOOK_SIGNATURE_KEY=

悪い例です。

NEXT_PUBLIC_SQUARE_ACCESS_TOKEN=

NEXT_PUBLIC_が付いた環境変数は、ブラウザ側に公開される可能性があります。

そのため、秘密情報には使ってはいけません。

Access Tokenの扱いで守るべきことは、次の通りです。

・GitHubに書かない
・クライアント側に出さない
・ログに出さない
・人に共有しない
・Sandboxと本番を分ける
・不要になったTokenは無効化する

特に、開発中にやりがちなミスはこれです。

console.log(process.env.SQUARE_ACCESS_TOKEN);

これは避けます。

Tokenは鍵です。

鍵を画面に表示したり、ログに残したり、公開リポジトリに置いたりしてはいけません。


21.4 環境変数の分離

ECでは、Sandbox環境と本番環境を分けます。

Sandboxはテスト用です。

本番は実際のお金が動く環境です。

Sandbox:
テスト用

Production:
本番用

この2つを混ぜると危険です。

本番Tokenを開発環境で使う
テスト決済のつもりが本番決済になる
SandboxのWebhook URLを本番に設定する
本番の注文DBにテスト注文が混ざる

そのため、環境変数を明確に分けます。

.env.local
  → ローカル開発用

Vercel Preview Environment
  → 確認用

Vercel Production Environment
  → 本番用

環境変数の例です。

# Sandbox
SQUARE_ENVIRONMENT=sandbox
SQUARE_ACCESS_TOKEN=sandbox_xxxxx
SQUARE_LOCATION_ID=xxxxx

# Production
SQUARE_ENVIRONMENT=production
SQUARE_ACCESS_TOKEN=production_xxxxx
SQUARE_LOCATION_ID=xxxxx

本番環境では、本番用のAccess Tokenだけを使います。

Sandbox用Tokenを本番に入れても、正しい決済はできません。

反対に、本番Tokenを開発環境に入れると危険です。

開発環境:
Sandboxだけ

本番環境:
Productionだけ

Next.jsでは、サーバー側で環境変数を読み込み、環境に応じてSquareクライアントを切り替えます。

type SquareEnvironment = 'sandbox' | 'production';

type SquareConfig = {
  environment: SquareEnvironment;
  accessToken: string;
  locationId: string;
};

/**
 * 役割: サーバー側の環境変数からSquare接続設定を取得する
 * 入力: なし
 * 出力: Square接続に必要な設定
 */
function getSquareConfig(): SquareConfig {
  const environment = process.env.SQUARE_ENVIRONMENT;
  const accessToken = process.env.SQUARE_ACCESS_TOKEN;
  const locationId = process.env.SQUARE_LOCATION_ID;

  if (environment !== 'sandbox' && environment !== 'production') {
    throw new Error('SQUARE_ENVIRONMENT is invalid');
  }

  if (!accessToken) {
    throw new Error('SQUARE_ACCESS_TOKEN is missing');
  }

  if (!locationId) {
    throw new Error('SQUARE_LOCATION_ID is missing');
  }

  return {
    environment,
    accessToken,
    locationId,
  };
}

環境変数の分離は地味ですが、決済システムでは非常に重要です。

テストはテスト。
本番は本番。
絶対に混ぜない。

21.5 Webhook署名検証

Webhookは、Squareから自社ECへ決済結果を知らせる仕組みです。

しかし、Webhook URLはインターネット上に公開されます。

そのため、誰かが偽のリクエストを送ってくる可能性があります。

攻撃者:
偽のWebhookを送る

自社EC:
決済完了だと勘違いする

結果:
未決済の商品を発送してしまう

これを防ぐために、Webhook署名検証を行います。

Squareの公式ドキュメントでは、Webhook通知の検証方法として、通知URL、署名キー、リクエストのraw bodyを使ってHMAC-SHA-256署名を生成し、x-square-hmacsha256-signatureヘッダーと比較する方法が説明されています。(Square)

Webhook署名検証の考え方は、次の通りです。

Webhookを受け取る
  ↓
署名ヘッダーを確認する
  ↓
自分の署名キーで署名を計算する
  ↓
Squareから届いた署名と比較する
  ↓
一致した場合だけ処理する

重要なのは、検証前に注文処理を進めないことです。

悪い例:
Webhookを受け取ったらすぐpaidにする

よい例:
署名検証OK
  ↓
イベント種別確認
  ↓
決済ステータス確認
  ↓
paidにする

Webhook処理では、次の順番を守ります。

1. raw bodyを取得する
2. 署名ヘッダーを取得する
3. Webhook署名を検証する
4. イベント種別を確認する
5. Payment IDやOrder IDを確認する
6. 注文DBを更新する

署名検証に失敗した場合は、処理を止めます。

署名検証失敗
  ↓
注文処理しない
  ↓
ログに残す
  ↓
403などで返す

Webhookは、決済完了処理の入口です。

入口で本人確認をしないと、EC全体が危険になります。


21.6 金額改ざん対策

ECで非常に重要なのが、金額改ざん対策です。

購入者のブラウザから送られてきた金額を、そのまま信用してはいけません。

ブラウザ上の情報は、ユーザーが変更できる可能性があります。

商品価格:5,400円
  ↓
ブラウザ上で100円に改ざん
  ↓
そのままサーバーに送信
  ↓
100円で決済される危険

これを防ぐには、サーバー側で正しい金額を計算します。

危険な設計:
クライアントからpriceを受け取る

安全な設計:
クライアントからproductIdとquantityだけ受け取る
サーバー側でDBから価格を取得する

安全な流れは次の通りです。

購入ボタンを押す
  ↓
商品IDと数量を送る
  ↓
サーバー側で商品価格を取得
  ↓
在庫と送料を確認
  ↓
合計金額を計算
  ↓
Squareへ正しい金額を送る

TypeScriptで考えると、次のようになります。

type CheckoutItemInput = {
  productId: string;
  quantity: number;
};

type CalculatedCheckoutAmount = {
  subtotalAmount: number;
  shippingFee: number;
  totalAmount: number;
};

/**
 * 役割: 商品IDと数量から、サーバー側で正しい決済金額を計算する
 * 入力: 商品IDと数量の配列
 * 出力: 小計、送料、合計金額
 */
async function calculateCheckoutAmount(
  items: CheckoutItemInput[]
): Promise<CalculatedCheckoutAmount> {
  // 実際の実装では、productIdをもとにDBから価格を取得する
  // クライアントから送られた価格は使わない

  return {
    subtotalAmount: 5400,
    shippingFee: 800,
    totalAmount: 6200,
  };
}

金額改ざん対策の基本は、次の一言です。

金額はブラウザから受け取らない。
サーバーで決める。

商品価格、送料、割引、合計金額はすべてサーバー側で計算します。

画面に表示されている価格は、あくまで表示です。

決済に使う価格は、必ずサーバー側で確定します。


21.7 注文ID推測対策

注文IDもセキュリティ上の注意点です。

もし注文IDが単純な連番だと、他人の注文ページを推測される可能性があります。

/orders/1
/orders/2
/orders/3

このようなURLは推測しやすいです。

攻撃者が番号を変えるだけで、他人の注文情報にアクセスできる設計は危険です。

自分の注文:
/orders/100

他人の注文:
/orders/101

URLを変えるだけで見えてしまう

注文ID推測対策では、次のようなIDを使います。

・UUID
・ランダムな注文番号
・十分に長いトークン

例です。

/orders/ord_9f3a2c8e7b1d

ただし、ランダムなIDを使うだけでは不十分です。

必ずアクセス権も確認します。

注文IDが正しい
  ↓
このユーザーの注文か確認
  ↓
問題なければ表示

ゲスト購入の場合は、注文確認ページにアクセスするための一時的なトークンを使う方法があります。

/order-complete?token=random_token

このトークンも、推測しにくい値にします。

注文ID設計で避けたいのは、次のようなものです。

ORDER-0001
ORDER-0002
ORDER-0003

管理画面内で使う注文番号としては分かりやすいですが、公開URLにそのまま使うのは避けた方が安全です。

管理用注文番号:
ORDER-0001

公開アクセス用ID:
ランダムなIDやトークン

人が扱いやすい番号と、外部アクセス用の安全なIDは分けて考えます。


21.8 管理画面の認証

管理画面には、注文情報、配送先、メールアドレス、電話番号などが表示されます。

そのため、管理画面の認証は必須です。

管理画面に表示される情報:
注文一覧
購入者名
メールアドレス
電話番号
配送先住所
注文金額
対応履歴

これらは、購入者に関わる重要な情報です。

URLを知っているだけで見られる状態にしてはいけません。

管理画面では、最低限次の対策を行います。

・ログイン必須にする
・管理者だけが入れるようにする
・サーバー側で認証確認する
・権限ごとに見える範囲を分ける
・操作履歴を残す

危険な設計は、画面上だけで制御することです。

危険な例:
Client Componentでログイン状態を見て、表示を隠すだけ

安全な設計では、サーバー側で確認します。

管理画面へアクセス
  ↓
サーバー側でログイン確認
  ↓
管理者権限を確認
  ↓
許可されていれば表示
  ↓
許可されていなければ拒否

ロールも分けます。

admin:
  すべて操作できる

staff:
  注文確認と発送処理ができる

viewer:
  閲覧だけできる

管理画面では、危険な操作にも注意します。

・注文キャンセル
・返金処理
・在庫変更
・価格変更
・CSV出力
・管理者追加

これらは、誰でも実行できるようにしてはいけません。

一般スタッフ:
発送処理のみ

管理者:
価格変更、CSV出力、設定変更

管理画面は、ECの裏口です。

裏口が空いていると、どれだけ表のページをきれいに作っても危険です。


21.9 個人情報の最小化

ECでは、配送や連絡のために個人情報を扱います。

ただし、必要以上に集めたり保存したりしないことが大切です。

個人情報は、持てば持つほど管理責任が増えます。

集める情報が多い
  ↓
漏えい時の影響が大きい
  ↓
管理も難しくなる

ECで必要になりやすい情報は、次の通りです。

・氏名
・メールアドレス
・電話番号
・配送先住所
・注文内容

一方で、通常の物販ECで不要なことが多い情報もあります。

・生年月日
・性別
・職業
・家族構成
・詳細すぎるアンケート

もちろん、商品やサービスによって必要な場合もあります。

しかし、理由がないなら集めない方が安全です。

必要な情報だけ集める
必要な期間だけ保存する
必要な人だけ見られるようにする

管理画面でも、すべてのスタッフに個人情報を見せる必要はありません。

発送担当:
配送先住所が必要

商品管理担当:
購入者住所は不要

売上確認担当:
個人名までは不要な場合がある

必要に応じて、表示を制限します。

メールアドレス:
taro@example.com

一部マスク:
ta***@example.com

個人情報の最小化は、セキュリティだけでなく、運用の安心にもつながります。

持たない情報は漏れない。

この考え方が重要です。


21.10 ログに保存してはいけない情報

最後に、ログの扱いを整理します。

ログは、エラー調査や運用確認に役立ちます。

しかし、何でもログに残してよいわけではありません。

特に決済システムでは、ログに秘密情報や個人情報を出さないことが重要です。

保存してはいけない情報は、次の通りです。

・Access Token
・Webhook署名キー
・クレジットカード情報
・セキュリティコード
・認証Cookie
・セッションToken
・パスワード
・個人情報の全文

開発中によくある危険な例です。

console.log(requestBody);
console.log(process.env.SQUARE_ACCESS_TOKEN);
console.log(webhookHeaders);

WebhookのrequestBodyには、注文情報や決済情報が含まれる可能性があります。

環境変数をログに出すのは特に危険です。

安全なログは、調査に必要な最低限の情報にします。

保存してよい情報の例:
注文ID
イベントID
処理結果
エラー種別
発生日時

ログの例です。

2026-07-06 16:30
event_id: evt_xxxxx
order_id: ord_xxxxx
event_type: payment.updated
result: success

エラー時も、詳細を出しすぎないようにします。

悪い例:
Access Tokenがxxxxxで、Square API呼び出しに失敗しました

よい例:
Square API authentication failed

ログは、問題解決のために必要です。

しかし、ログ自体が情報漏えいの原因になることもあります。

ログは便利。
でも、秘密情報を入れると危険。

本番環境では、ログの保存期間や閲覧権限も決めておきます。

・誰がログを見られるか
・どのくらい保存するか
・個人情報を含むログを残していないか
・エラー通知に秘密情報が含まれていないか

ログは、最低限、必要な範囲で、安全に残します。


第21章のまとめ

決済システムのセキュリティでは、難しい技術を大量に覚えるよりも、まず危険な設計を避けることが重要です。

この章で覚えておきたいポイントは、次の通りです。

1. クレジットカード情報を自社サーバーに保存しない
2. カード入力と決済処理はSquareに任せる
3. Access Tokenは絶対にクライアント側へ出さない
4. Sandboxと本番の環境変数を分ける
5. Webhookは署名検証してから処理する
6. 金額はブラウザから受け取らず、サーバー側で計算する
7. 注文IDは推測しにくくし、アクセス権も確認する
8. 管理画面には認証と権限管理を入れる
9. 個人情報は必要最小限だけ持つ
10. ログに秘密情報や個人情報を残さない

セキュリティの基本は、次の一言にまとめられます。

持たなくてよい情報は持たない。
信じてはいけない入力は信じない。

カード情報は持たない。

金額はサーバーで計算する。

Webhookは検証する。

管理画面は守る。

この基本を守るだけで、小規模ECの安全性は大きく上がります。

第22章では、実際の運用で起きるエラーや障害にどう対応するかを整理していきます。

FAQ

よくある質問

決済システムのセキュリティは医療関係者向けだけの内容ですか。
医療分野の例が含まれる場合もありますが、医療関係者だけに限定した内容ではありません。生成AI、AI活用、DX、業務改善、プロトタイプ開発など、一般的なAI学習の事例として読める内容です。
AI初心者でも読めますか。
はい。AIをこれから学ぶ方、数学が苦手な方、仕事でAIを使いたい方にも読み進めやすいように、教材の章と節の流れに沿って整理しています。
サムネイル画像は必ず表示されますか。
はい。教材にcoverUrlが設定されている場合はその画像を表示し、未設定の場合は代替サムネイル画像を表示します。
Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装のほかの章も読めますか。
はい。教材トップから章立てを確認でき、前後の節へもページ下部のナビゲーションから移動できます。