はじめてのPAY.JP - テスト環境で作る最小限の決済フォーム実装

# はじめに

PAY.JPは開発者向けのオンライン決済サービスで、APIを通じてクレジットカード決済を簡単に実装できます。
この記事では、テスト環境を使って最小限の決済フォームを実装する手順を説明します。

## 1. 環境構築

### 1.1 アカウント作成とAPIキーの取得

1. [PAY.JPの登録ページ](https://pay.jp/)でアカウントを作成
2. ダッシュボードにログイン後、「テストモード」のAPIキーを取得
   - 公開キー（pk_test_で始まる）
   - 秘密キー（sk_test_で始まる）

### 1.2 テスト用クレジットカード

テスト環境では以下のカード番号が利用可能です：
- 正常系テスト: `4242 4242 4242 4242`
- 期限切れ: `4242 4242 4242 4241`
- セキュリティコードエラー: `4242 4242 4242 4240`

## 2. フロントエンド実装

### 2.1 基本的なHTML構造

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>PAY.JP Sample Payment Form</title>
    <script src="https://js.pay.jp/v2/pay.js"></script>
    <style>
        .form-group { margin-bottom: 15px; }
        .error { color: red; display: none; }
    </style>
</head>
<body>
    <form id="payment-form">
        <div class="form-group">
            <label for="card-number">カード番号</label>
            <div id="card-number"></div>
            <div class="error" id="card-number-error"></div>
        </div>
        
        <div class="form-group">
            <label for="card-expiry">有効期限</label>
            <div id="card-expiry"></div>
            <div class="error" id="expiry-error"></div>
        </div>
        
        <div class="form-group">
            <label for="card-cvc">CVC</label>
            <div id="card-cvc"></div>
            <div class="error" id="cvc-error"></div>
        </div>
        
        <button type="submit">支払う</button>
    </form>
</body>
</html>
```

### 2.2 JavaScript実装

```javascript
// PAY.JPの公開キーを設定
const payjp = Payjp('pk_test_YOUR_PUBLIC_KEY');

// Elements インスタンスを生成
const elements = payjp.elements();

// 各フォームエレメントを生成
const cardNumber = elements.create('cardNumber');
const cardExpiry = elements.create('cardExpiry');
const cardCvc = elements.create('cardCvc');

// DOMに追加
cardNumber.mount('#card-number');
cardExpiry.mount('#card-expiry');
cardCvc.mount('#card-cvc');

// エラーハンドリング
const displayError = (elementId, message) => {
    const errorElement = document.getElementById(elementId);
    errorElement.textContent = message;
    errorElement.style.display = message ? 'block' : 'none';
};

cardNumber.on('change', (event) => {
    displayError('card-number-error', event.error ? event.error.message : '');
});

cardExpiry.on('change', (event) => {
    displayError('expiry-error', event.error ? event.error.message : '');
});

cardCvc.on('change', (event) => {
    displayError('cvc-error', event.error ? event.error.message : '');
});

// フォーム送信時の処理
document.getElementById('payment-form').addEventListener('submit', async (event) => {
    event.preventDefault();
    
    const { token, error } = await payjp.createToken(cardNumber);
    
    if (error) {
        displayError('card-number-error', error.message);
        return;
    }
    
    // トークンをサーバーに送信する処理
    console.log('Generated token:', token.id);
    // ここで実際のサーバーにトークンを送信
});
```

## 3. バックエンド実装 (Node.js例)

```javascript
const express = require('express');
const payjp = require('payjp')('sk_test_YOUR_SECRET_KEY');
const app = express();

app.post('/charge', async (req, res) => {
    try {
        const charge = await payjp.charges.create({
            amount: 1000,
            currency: 'jpy',
            card: req.body.token,
            capture: true,
        });
        
        res.json({ success: true, charge });
    } catch (error) {
        res.status(400).json({
            success: false,
            message: error.message
        });
    }
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});
```

## 4. 動作確認とテスト

1. フォームの表示確認
   - 各フィールドが正しくレンダリングされていることを確認
   - スタイリングが適切に適用されていることを確認

2. バリデーション確認
   - 不正なカード番号入力時のエラー表示
   - 期限切れカードでのエラー処理
   - CVCの桁数チェック

3. 決済フロー確認
   - テストカードでの正常決済
   - エラーケースの確認
   - 決済完了後の画面遷移

## 5. 本番環境への移行時の注意点

1. APIキーの切り替え
   - テストモードのキーから本番モードのキーへの切り替え
   - 本番環境での再テスト実施

2. セキュリティ対策
   - SSL/TLS対応の確認
   - クロスサイトスクリプティング対策
   - CSRF対策

3. エラーハンドリング
   - ユーザーフレンドリーなエラーメッセージ
   - ログ収集と監視体制の整備

## おわりに

この実装例は最小限の機能に絞っていますが、実際のサービスでは以下の機能も検討すると良いでしょう：

- カード情報の保存機能
- 定期課金の実装
- 決済後のメール通知
- 管理画面での決済状況確認
- 売上レポート機能

## 参考リンク

- [PAY.JP API Documentation](https://pay.jp/docs/api/)
- [PAY.JP テスト用カード番号一覧](https://pay.jp/docs/testcard)