決済実装、今は昔
안녕하신게라!パナソニック コネクト株式会社クラウドソリューション部の加賀です。
ECサイト制作、BtoCのカード決済処理、実装したことありますか?
筆者が初めて決済処理を実装したのは、インターネットが普及し始めた20世紀末頃で、セキュリティ対策は現在ほど確立されておらず牧歌的な時代でした。数社のクレジットカード会社と直接契約し、審査を受け改善指摘に苦しみながらも、様々な経験や知見を得ることができました。しかし、21世紀の現在において、同様なスクラッチ開発と運用を経験された方は非常に稀なのではないでしょうか。
なぜなのか、時代の流れを簡単に説明します。
20世紀末からオンラインでのクレジットカード決済が増加し始め、21世紀に入り取引件数も増えるにつれ、不正利用やトラブル数も増えていき、クレジットカード会社単体の対策では太刀打ち出来なくなっていきました。
2004年に国際カード5ブランドで策定したPCI DSS(Payment Card Industry Data Security Standard 現在v4.0が最新版)では、何百項目にもわたるセキュリティ基準が定められており、これに準拠するため、ECサイト側にもサーバ構築からアプリケーション設計、防御装置(WAFやIDS/IPS等)、四半期毎の脆弱性スキャン、運用体制まで含め、システム全体を見通す専門知識と莫大な運用コストが必要となりました。それでも、攻撃者の手口は日々巧妙化し、セキュリティ対策とのいたちごっこが続きました。
2018年6月からの改正割賦販売法で、カード情報の適切な保護が強く求められるようになり、その対応策としてECサイトの事業者側システム上でのクレジットカード情報の非保持化、またはPCI DSSレベルの高度なセキュリティ対策が実質的に必須となり、国内で一定の効果を見ます。これにより実装技術要件のレベルがさらに上昇し、スクラッチ開発はより困難になったと言えるでしょう。
求められる要件レベルは年々上昇しているにも関わらず、ECサイト数はますます増加傾向にあり、クレジットカード決済が出来る場が減少することはありません。
何が起きているのでしょう?
答えは、シンプルにアウトソースです。PAY.JPやStripeのような決済代行サービスを使えば、数十行のコードで、驚くほど簡単に、そしてセキュアに決済機能を実装できてしまいます。
「やった!面倒なセキュリティ対応は決済代行サービスに丸投げだ!」
そう手放しで喜びたくなる気持ち、よく分かります。ですが、本当にそうでしょうか?
この記事では、便利なサービスに潜む 「たった一つの、しかし極めて重大なリスク」 に焦点を当て、私たちがECサイトを作った場合に、本当に集中して防御すべき点はどこなのかを、アドベントカレンダー2025の記事としてPAY.JPを使った際の具体例として取り上げ、確認していきます。(もちろん他の決済代行サービスでも同様のことが言えます)
「丸投げ天国」もうカード情報に触れなくていい
決済代行サービスがもたらした最大の恩恵は、「クレジットカード情報の非保持化」 を手軽に実現できるようになったことです。
PAY.JPが提供するトークン決済の仕組みを使えば、ユーザが入力したカード情報は、ECサイトのサーバを一切経由せず、PCI DSSに準拠したPAY.JPのサーバへ直接送信されます。

(PAY.JP公式記事より画像引用) ※筆者注:加盟店=ECサイト
ECサイトのサーバが受け取るのは、カード情報の代わりとなる一度だけしか使えないtok_xxxxxxxxのような文字列の「トークン」だけ。このトークンを使って決済をリクエストすれば完了です。
これにより、ECサイトはカード情報の直接的な保持・処理から解放され「クレジットカード情報の非保持化」の要件を満たすことで、PCI DSSの適用範囲を大幅に縮小し、その重荷の一部をアウトソースできる1ようになり、開発者はプロダクトのコア機能開発に集中できるようになりました。まさに天国です。
手放しで喜べない「たった一つのリスク」
さて、ここからが本題です。
PCI DSS対応の大部分をアウトソースできたとしても、残りのごく一部は依然として私たちの管理下にあります。そして、そのごく一部が、ECサイトのビジネス全てを破壊しうる力を持っています。
それが、 APIの秘密鍵(Secret Key=sk_で始まるキー)です。
sk_live_xxxxxxxxから始まるこの文字列はPAY.JPのAPIを自由に操作できる「鍵」です。
決済代行サービスはこの「秘密鍵」であるAPIキーを発行し、その安全な管理・運用についてはサービス利用者に責任があることを明示しています。
そうです。丸投げではなく、責任分界点への理解が必要なのです。
もし、この秘密鍵が漏洩したらどうなるか?
これはPAY.JPのサーバサイドAPIのほぼ全ての機能にアクセス可能になることを意味します。
悪意のある攻撃者が、あなたのECサイト(加盟店)であるかのように装い、以下のような甚大な被害を引き起こす可能性があります。
1. 金銭的な被害
-
不正な支払い
第三者が架空の不正支払いトランザクションを生成できます。これにより、後々チャージバック(不正利用に伴う返金要求)が発生し、甚大な損害につながる可能性があります。 -
不正な返金処理
既に行われた正当な取引に対して、勝手に返金処理を行うことができます。これにより、本来得られるはずだった売上が失われ、直接的な金銭的損失を被る可能性があります。 -
不正な定期課金の作成・操作
顧客に対して意図しない定期課金を作成したり、既存の定期課金を停止・変更したりすることが可能です。これにより、顧客への不信感や収益の不安定化を招くおそれがあります。
このとき、顧客はチャージバック等により救済される一方、ECサイト(加盟店)は不正取引の損害を負担するケースが多い点にも注意が必要です。(他の決済代行サービスもほぼ同等ですが、3Dセキュア時は免責など条件は異なります、必ず加盟店規約をご確認ください。)
2. 顧客情報・取引情報の漏洩
-
顧客情報・取引履歴の閲覧
あなたのサービスに登録されている全顧客の情報(名前、メールアドレス、住所、メタデータなど)や、過去のすべての取引履歴を閲覧・取得されてしまいます。これは個人情報保護の観点から非常に深刻な事態です。 -
登録カード情報の一部閲覧
顧客が登録しているクレジットカード情報の一部(カードブランド、有効期限、下4桁など)が閲覧される可能性があります。カード番号全体やCVCが漏れることはありませんが、たとえ下4桁でも攻撃者名簿の名寄せに使われるリスクがあり、顧客の不安を煽り、信頼を損なう原因となります。
3. サービスの信頼性失墜
-
顧客データや定期課金の破壊
API経由で顧客情報や定期課金プランを勝手に削除・変更される可能性があります。これにより、あなたのサービスが正常に機能しなくなり、顧客からの信頼を完全に失うことになります。 -
アカウント情報の閲覧
売上残高や振込履歴など、あなたのビジネスに関する機密情報が閲覧される可能性があります。
顧客のカード情報そのものは安全でも、ECサイトのビジネスは一瞬で崩壊します。
面倒なことから解放されたからこそ、私たちは残されたこの一点のリスクに、神経を全集中させるべきなのです。
集中防御! - 「秘密鍵」を守り抜くための具体策
では、この「秘密鍵」をどう守ればよいのでしょうか。「防御」「検知」「対応」の3つのフェーズで、集中して取り組むべきポイントを整理して具体化しましょう。
1.「防御」 - 鍵を安全な場所に保管する
まずは、鍵そのものを漏洩させないための「防御」です。
-
絶対にやってはいけないこと
- ソースコード(特にパブリックリポジトリ)にベタ書きしてしまう
- Slackやメールで安易に共有してしまう
- フロントエンドのJavaScriptに公開鍵ではなく秘密鍵を埋め込んでしまう(と、ブラウザに秘密鍵が配信され、誰でも取得可能な状態となってしまう)
payjp.jsは、秘密鍵の埋め込み利用を検知すると警告を出してくれますが、それに頼るべきではありません。
-
推奨される管理方法
-
環境変数で管理する
サーバの環境変数として設定し、コードと分離します。これは基本的な対策です。 -
シークレット管理サービスで管理する(推奨)
AWS Secrets ManagerやGoogle Secret Managerといった専用サービスを利用します。誰が・いつ・どこから鍵にアクセスしたかを全て記録でき、厳格なアクセス制御とログ監査が可能です。
-
環境変数で管理する
-
管理画面自体の防御
-
二段階認証の強制
APIキーを再発行できる決済代行サービスの管理画面自体も重要な防御対象です。チームメンバー全員のアカウントで二段階認証を必須に設定し、管理画面への不正ログインを防ぎましょう。
-
二段階認証の強制
2.「検知」 - 不正な金庫破りを即座に察知する
それでも完璧な防御を構築することは難しいと考え、万が一、鍵への不正アクセスがあった場合に、それを即座に「検知」する仕組みが不可欠です。
-
PAY.JPのWebhookを活用する
「決済」「返金」「金額変更」など、お金に関わる重要なイベントが発生した際に、PAY.JPからのWebhook通知を基に自社の監視システムやSlackに通知を送るように設定します。特定の顧客への集中した操作、普段利用されないAPIの呼び出しなどを即座に察知できます。
その際、Webhook通知が本当に決済代行サービスから送信されたものであるか、署名の検証も実装し、なりすまし通知による陽動作戦を無効化しておきましょう。 -
シークレット管理サービスのログを監視する(推奨)
AWS Secrets Managerを使っているなら、AWS CloudTrailのログが監視の要です。-
監視対象
秘密鍵へのアクセスログ(例:GetSecretValueイベント) -
検知ルール
- 想定外のIPアドレスからのアクセス(例:ECサイトの内部IPアドレスレンジ外)
- 想定外の実行元からのアクセス(例:本番サーバのIAMロール以外やIAMユーザ)
- 異常な頻度でのアクセス
-
監視対象
これらのルールに違反したら、即座にセキュリティチームにアラートが飛ぶように自動化しておきましょう。
3.「対応」 - 被害を最小限に食い止める
不正アクセスを検知したら、パニックにならず、あらかじめ決めておいた手順で「対応」します。
この「対応」は、攻撃者とのスピード勝負になります。遅れるほど被害が拡大します。
-
APIキーの再発行(無効化と新規作成)
PAY.JPの管理画面にログインし、「APIキー」のメニューから現在使用しているAPIキーを再発行します。古いキーは即座に無効化され、攻撃者はそれ以上APIを操作できなくなります。 -
システムのAPIキーを差し替える
新しい秘密鍵を、あなたのウェブサービスやアプリケーションのサーバ側に安全な方法で差し替えます。(ここに穴があると繰り返し攻撃を受けてしまいます、要注意)
もし古いキーがGitHubのパブリックリポジトリなどにコミットされてしまっていた場合は、差し替え後にリポジトリの履歴からも完全に削除する対応が必要です。(参考: GitHub ドキュメント - リポジトリからの機微なデータの削除) -
被害状況の確認
PAY.JP管理画面の「支払い履歴」や「顧客リスト」などを確認し、不審な取引や操作が行われていないか調査します。不審な点が見つかった場合は、速やかにPAY.JPのサポートに連絡し、状況を報告してください。
もしも、個人情報の漏えいが疑われる場合は、 個人情報保護法(APPI) に沿って、個人情報保護委員会への報告および本人通知の要否を速やかに評価し、必要な手続きを開始する手順を用意しましょう。(海外取引もある場合は、EU一般データ保護規則(GDPR)や各国の漏洩報告期限も確認してください)
「秘密鍵 怪しく感じる? 即ローテ!」を合言葉に、この手順をチームで共有し、怪しいと感じる主観的な判断も尊重しつつ、システムからのアラートやログといった客観的な情報に基づいて迅速に行動できるよう、訓練しておくことが極めて重要です。
楽になったからこそ、本質に集中しよう
- 決済代行サービスのおかげで、ECサイトへの決済実装は驚くほど簡単になった
- PCI DSSの適用範囲を大幅に縮小できるが、責任が完全になくなるわけではない
- 私たちが絶対に守り抜かなければならない 「一点集中のリスク」がAPIの秘密鍵 となる
- 「金銭的被害」「顧客情報の漏洩」「サービスの信頼性失墜」という甚大な結果を招く
- この一点を守り抜く体制として、「防御(保管方法)」「検知(ログ監視)」「対応(キーローテーションと被害調査)」を組織として構築する
便利なツールが複雑な問題を容易に解決してくれる現代だからこそ、私たち開発者は、残された本質的なリスクは何かを見極め、そこにリソースを集中投下するべきです。
この記事が、皆さんの安全なECサイト開発やビジネス運営の一助となれば幸いです。
将来的な改善への期待>PAY.JPさん
私見ですが、漏洩時のリスクを軽減するため、秘密鍵を使用する特定APIのIPアドレス制限や、権限を制限した秘密鍵を発行し、アプリケーションの機能に応じた最小権限の秘密鍵を利用して分散管理できるようになると嬉しいです。
お断り
記事内容は個人の見解であり、所属組織の立場や戦略・意見を代表するものではありません。
あくまでエンジニアとしての経験や考えを発信していますので、ご了承ください。
-
この方式により、PCI DSS準拠で求められる自己問診票(SAQ: Self-Assessment Questionnaire)の適用範囲を大幅に縮小できます。一般的に、このようなJavaScriptを利用したトークン決済は「SAQ A-EP」の対象とされますが、いずれにせよ数百項目に及ぶ要求事項の大部分をアウトソースできることに変わりはありません。 ↩