はじめに
PAY.JPは開発者向けのオンライン決済サービスで、APIを通じてクレジットカード決済を簡単に実装できます。
この記事では、テスト環境を使って最小限の決済フォームを実装する手順を説明します。
1. 環境構築
1.1 アカウント作成とAPIキーの取得
- PAY.JPの登録ページでアカウントを作成
- ダッシュボードにログイン後、「テストモード」のAPIキーを取得
- 公開キー(pk_test_で始まる)
- 秘密キー(sk_test_で始まる)
1.2 テスト用クレジットカード
テスト環境では以下のカード番号が利用可能です:
- 正常系テスト:
4242 4242 4242 4242
- 期限切れ:
4242 4242 4242 4241
- セキュリティコードエラー:
4242 4242 4242 4240
2. フロントエンド実装
2.1 基本的な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実装
// 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例)
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. 動作確認とテスト
-
フォームの表示確認
- 各フィールドが正しくレンダリングされていることを確認
- スタイリングが適切に適用されていることを確認
-
バリデーション確認
- 不正なカード番号入力時のエラー表示
- 期限切れカードでのエラー処理
- CVCの桁数チェック
-
決済フロー確認
- テストカードでの正常決済
- エラーケースの確認
- 決済完了後の画面遷移
5. 本番環境への移行時の注意点
-
APIキーの切り替え
- テストモードのキーから本番モードのキーへの切り替え
- 本番環境での再テスト実施
-
セキュリティ対策
- SSL/TLS対応の確認
- クロスサイトスクリプティング対策
- CSRF対策
-
エラーハンドリング
- ユーザーフレンドリーなエラーメッセージ
- ログ収集と監視体制の整備
おわりに
この実装例は最小限の機能に絞っていますが、実際のサービスでは以下の機能も検討すると良いでしょう:
- カード情報の保存機能
- 定期課金の実装
- 決済後のメール通知
- 管理画面での決済状況確認
- 売上レポート機能