サイトのAPI図鑑B版
掲載情報が正確でない可能性があります。
セキュリティ・コンプライアンス

PCI DSS準拠のAPIセキュリティガイド【決済API・カードデータ保護】

決済APIを扱う際のPCI DSS(Payment Card Industry Data Security Standard)準拠要件の理解と、カードデータの非保持・トークナイゼーション・暗号化・ログ管理の実装方法を解説します。

#PCI DSS#決済セキュリティ#トークナイゼーション#コンプライアンス

PCI DSSとは

PCI DSS(Payment Card Industry Data Security Standard)は、Visa・Mastercard・American Express等のカードブランドが共同で策定したクレジットカードデータの取り扱いに関するセキュリティ基準です。クレジットカードの決済処理・送信・保存を行う全ての事業者が準拠する義務があります。

カードデータの非保持(最も重要)

最もシンプルなPCI DSS対策は「カードデータを自社サーバーに保持しないこと」です。

// Stripe.jsでカードデータをStripeのサーバーに直接送信
// フロントエンド(React)
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

const PaymentForm = () => {
  const stripe = useStripe();
  const elements = useElements();
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    
    // カードデータはStripeのサーバーにのみ送信
    // 自社サーバーにはPaymentIntentIdのみ送信
    const { paymentMethod, error } = await stripe.createPaymentMethod({
      type: 'card',
      card: elements.getElement(CardElement)
    });
    
    if (error) return setError(error.message);
    
    // 自社バックエンドにはPaymentMethodIdのみ送る(カード番号は含まない)
    await fetch('/api/payments', {
      method: 'POST',
      body: JSON.stringify({ paymentMethodId: paymentMethod.id, amount: 1000 })
    });
  };
};

バックエンドでのトークン処理

// バックエンドはStripeのPaymentMethodIdのみ扱う
app.post('/api/payments', authenticate, async (req, res) => {
  const { paymentMethodId, amount } = req.body;
  
  // カード番号は一切保存・ログ出力しない
  // Stripeトークン(PaymentMethodId)のみ使用
  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency: 'jpy',
    payment_method: paymentMethodId,
    confirm: true
  });
  
  // ログにはPaymentIntentのIDのみ記録(カード番号は含まない)
  logger.info('payment_created', {
    userId: req.user.id,
    paymentIntentId: paymentIntent.id,
    amount,
    status: paymentIntent.status
  });
  
  res.json({ status: paymentIntent.status });
});

PCI DSS 12の要件の概要

  • 要件1-2:ネットワークセキュリティ(ファイアウォール・デフォルト設定変更)
  • 要件3-4:カードデータの保護(暗号化・トークナイゼーション)
  • 要件5-6:脆弱性管理(ウイルス対策・セキュアな開発)
  • 要件7-8:アクセス制御(最小権限・ID管理・MFA)
  • 要件9:物理的セキュリティ
  • 要件10:ログ・監視(全アクセスログの保存・レビュー)
  • 要件11:セキュリティテスト(脆弱性スキャン・ペンテスト)
  • 要件12:情報セキュリティポリシー

カード番号のマスキング

// カード番号はPAN全体を保存しない(最後の4桁のみ表示)
const maskCardNumber = (cardNumber) => {
  return '*'.repeat(cardNumber.length - 4) + cardNumber.slice(-4);
};

// DBには最後の4桁のみ保存(確認用)
await db.paymentMethods.create({
  data: {
    userId: req.user.id,
    brand: paymentMethod.card.brand,
    last4: paymentMethod.card.last4, // 末尾4桁のみ
    expMonth: paymentMethod.card.exp_month,
    expYear: paymentMethod.card.exp_year,
    stripePaymentMethodId: paymentMethod.id
  }
});

まとめ

決済APIを扱う際のPCI DSS準拠はビジネスの信頼性を守るための義務です。Stripe・Square等の決済サービスのホスト型フォームを使って自社サーバーにカードデータを渡さない実装を選択することで、準拠の負荷を最小化できます。カードデータのログ出力禁止・暗号化・アクセス制御・監査ログを徹底してください。

よくある質問

Q.PCI DSSに準拠しないとどうなりますか?

PCI DSS非準拠の場合、カードブランド(Visa・Mastercard等)から罰金・取引手数料の引き上げ・最悪の場合はクレジットカード決済の停止処分を受ける可能性があります。データ漏洩が発生した場合は損害賠償・ブランドイメージの損害も生じます。

Q.Stripeを使えばPCI DSSへの準拠は不要ですか?

Stripe.js・Stripe Elementsを使ってカード情報を直接Stripeに送信する実装にすれば、自社のサーバーにカードデータが渡らないため、最も低いPCI DSS適合レベル(SAQ-A)での準拠が可能になり、要件が大幅に軽減されます。ただし完全に不要というわけではありません。

Q.カード番号をログに出力してはいけない理由は?

PCI DSS要件3.3でCANは(カード認証コード)、要件3.4でPAN(プライマリアカウント番号)の保護が義務付けられています。ログにPANを出力するとログファイルがスコープに入りPCIの準拠要件が大幅に増加します。StripeやPaymentIntentのIDのみログに記録してください。

関連記事