テスト
全支払い方法をサポートするテストモード、テストカード、シミュレートされた支払いシナリオを使用したOmise統合のテストに関する包括的なガイド。
概要
Omiseは、実際のトランザクションを処理せずに本番環境の動作をミラーリングする完全なテスト環境を提供します。テストモードにより、統合を検証し、エラー処理をテストし、本番環境に移行する前にさまざまな支払いシナリオをシミュレートできます。
主な機能:
- ✅ 独立したテストキー - テスト専用の専用APIキー
- ✅ テストカード - 成功、拒否、エラーシナリオをシミュレート
- ✅ すべての支払い方法 - QR、ウォレット、 銀行などをテスト
- ✅ Webhookテスト - テストWebhookを受信
- ✅ 実際のお金なし - 安全なテスト環境
- ✅ 完全機能パリティ - テスト環境が本番環境をミラーリング
テストモード対ライブモード
| 機能 | テストモード | ライブモード |
|---|---|---|
| APIキー | pkey_test_..., skey_test_... | pkey_..., skey_... |
| 実際のお金 | いいえ | はい |
| テストカード | 受け入れ済み | 拒否 |
| 実際のカード | 拒否 | 受け入れ済み |
| Webhook | 配信済み | 配信済み |
| ダッシュボード | テストデータのみ | ライブトランザクション |
重要
テストモードとライブモードは完全に分離されています。テストキーは実際 のトランザクションを処理できず、ライブキーはテストデータを使用できません。
テストAPIキーの取得
ダッシュボードから
- Omiseダッシュボードにログイン
- テストモードに切り替えるためにトグルを使用
- 設定 → APIキーに移動
- テストキーをコピー:
- 公開キー:
pkey_test_...(クライアント側) - 秘密キー:
skey_test_...(サーバー側)
- 公開キー:
テストキー形式
# 公開キー (クライアント側で安全に使用)
pkey_test_5rt6s9vah5lkvi1rh9c
# 秘密キー (サーバー側のみ、決してExposeしない)
skey_test_5rt6s9vah5lkvi1rh9c
セキュリティ
テストキーを公開リポジトリにコミットしたり、クライアント側のコードにExposeしたりしないでください。テストキーは実際のお金を処理しませんが、機密テストデータにアクセスできます。
テストカード
成功シナリオ
| カード番号 | ブランド | 3DS | 結果 |
|---|---|---|---|
| 4242 4242 4242 4242 | Visa | いいえ | 成功 |
| 4242 4242 4242 4242 | Visa | はい | 成功 (3DS) |
| 5555 5555 5555 4444 | Mastercard | いいえ | 成功 |
| 5555 5555 5555 4444 | Mastercard | はい | 成功 (3DS) |
| 3566 1111 1111 1111 | JCB | いいえ | 成功 |
| 3782 822463 10005 | Amex | いいえ | 成功 |
拒否シナリオ
| カード番号 | エラーコード | メッセージ |
|---|---|---|
| 4000 0000 0000 0002 | payment_rejected | チャージが拒否されました |
| 4000 0000 0000 0010 | insufficient_fund | 資金不足 |
| 4000 0000 0000 0028 | stolen_or_lost_card | カードが盗まれた/紛失 |
| 4000 0000 0000 9995 | failed_processing | 処理エラー |
不正検出
| カード番号 | 不正結果 | 動作 |
|---|---|---|
| 4000 0000 0000 0101 | フラグ付き | 手動レビュー対象としてマーク |
| 4000 0000 0000 0044 | ブロック | トランザクショ ンがブロック |
3D Secureテスト
注記
3DSテストでは3DS対応テストアカウントが必要です。有効にするにはsupport@omise.coにお問い合わせください。
| カード番号 | 3DS動作 | 結果 |
|---|---|---|
| 4242 4242 4242 4242 | フリクションレス (チャレンジなし) | 成功 |
| 4111 1111 1115 0002 | 登録失敗 | 拒否 |
| 4111 1111 1114 0003 | 認証失敗 | 拒否 |
3DS認証のテスト:
- 将来の有効期限は機能します
- 任意の3-4桁のCVVを使用
- 任意のカードホルダー名を使用
テスト用カード詳細
// 成功カード
{
name: "John Doe",
number: "4242424242424242",
expiration_month: 12,
expiration_year: 2027,
security_code: "123"
}
// 拒否カード
{
name: "Jane Smith",
number: "4000000000000002",
expiration_month: 12,
expiration_year: 2027,
security_code: "123"
}
有効期限
テストカードでは有効期限を使用できます。少なくとも1年先の日付を使用することをお勧めします。
支払い方法のテスト
クレジット/デビットカード
// Omise.jsを使用
Omise.setPublicKey("pkey_test_YOUR_KEY");
Omise.createToken("card", {
name: "Test Card",
number: "4242424242424242",
expiration_month: 12,
expiration_year: 2027,
security_code: "123"
}, function(statusCode, response) {
if (statusCode === 200) {
console.log('Token created:', response.id);
// チャージを作成するためにトークンを使用
}
});
QR支払い (PromptPay、PayNowなど)
// テスト用PromptPayソースを作成
const source = await omise.sources.create({
type: 'promptpay',
amount: 35000,
currency: 'THB'
});
// QRコードが生成されます
console.log('QR Code URL:', source.scannable_code.image.download_uri);
// ダッシュボードで支払いをシミュレート
// 1. ダッシュボード → チャージに移動
// 2. 保留中のチャージを検索
// 3. [成功にマーク] または [失敗にマーク] をクリック
電子ウォレット (TrueMoney、GrabPayなど)
// テストウォレットソースを作成
const source = await omise.sources.create({
type: 'truemoney',
amount: 50000,
currency: 'THB',
phone_number: '+66876543210' // テストではタイ番号を使用可能
});
// ダッシュボードでシミュレート
// ダッシュボード → チャージ → 成功にマーク
モバイルバンキング
// テスト用モバイルバンキングソースを作成
const source = await omise.sources.create({
type: 'mobile_banking_kbank',
amount: 100000,
currency: 'THB'
});
// ダッシュボードでシミュレート
// ダッシュボード → チャージ → アクション → 成功にマーク
支払い結果のシミュレート
ダッシュボード経由
- テストダッシュボードにログイン
- テストモードが有効になっていることを確認
- チャージに移動
- 保留中のチャージを検索
- アクションドロップダウンをクリック
- 以下を選択:
- 成功にマーク - 成功した支払いをシミュレート
- 失敗にマーク - 支払い失敗をシミュレート
API経由 (テストWebhook)
// チャージは自動的にWebhookをトリガー
// Webhookエンドポ イントログを確認
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
console.log('Test webhook received:', event.key);
console.log('Charge ID:', event.data.id);
console.log('Status:', event.data.status);
res.sendStatus(200);
});
Webhookのテスト
ngrokを使用したローカルテスト
# ngrokをインストール
npm install -g ngrok
# ローカルサーバーを起動
node server.js # ポート3000で実行
# トンネルを作成
ngrok http 3000
# 出力:
# Forwarding https://abc123.ngrok.io -> http://localhost:3000
ダッシュボードでWebhookを構成:
- ngrok HTTPS URLをコピー
- 設定 → Webhookに移動
- エンドポイントを追加:
https://abc123.ngrok.io/webhooks/omise - テストイベントを選択
- 保存
テストWebhook配信
// Webhookハンドラー
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
// デバッグ用にログ
console.log('=== Webhook受信 ===');
console.log('Event:', event.key);
console.log('Object:', event.object);
console.log('Data:', JSON.stringify(event.data, null, 2));
// シグネチャを検証 (重要!)
if (!verifyWebhookSignature(req)) {
console.error('Invalid signature!');
return res.sendStatus(401);
}
// イベントを処理
switch (event.key) {
case 'charge.complete':
handleChargeComplete(event.data);
break;
case 'charge.failed':
handleChargeFailed(event.data);
break;
}
res.sendStatus(200);
});
手動Webhookテスト
# cURLを使用してWebhookをシミュレート
curl -X POST http://localhost:3000/webhooks/omise \
-H "Content-Type: application/json" \
-d '{
"object": "event",
"id": "evnt_test_123",
"key": "charge.complete",
"data": {
"object": "charge",
"id": "chrg_test_123",
"status": "successful",
"amount": 100000
}
}'
払戻のテスト
全額払戻
// テストモードでチャージを作成
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: testTokenId
});
// 成功ステータスを待機
// その後払戻
const refund = await omise.charges.refund(charge.id, {
amount: 100000
});
console.log('Refund status:', refund.status);
部分払戻
// 部分払戻 (50%)
const partialRefund = await omise.charges.refund(charge.id, {
amount: 50000
});
// 複数の部分払戻 (チャージあたり最大15)
const refund2 = await omise.charges.refund(charge.id, {
amount: 25000
});
無効化対払戻
// 無効化 (24時間以内) - 即座にキャンセル
const voidRefund = await omise.charges.refund(charge.id, {
amount: 100000
});
if (voidRefund.voided) {
console.log('Charge was voided (no settlement)');
} else {
console.log('Charge was refunded (settled then refunded)');
}
3D Secureのテスト
テストで3DSを有効化
// return_uriを含めて3DSをトリガー
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: tokenId,
return_uri: 'http://localhost:3000/payment/callback'
});
if (charge.authorize_uri) {
console.log('3DS required, redirect to:', charge.authorize_uri);
// ブラウザで: window.location = charge.authorize_uri
}
3DSフローのテスト
// フリクショ ンレスフロー (チャレンジなし)
const token = await Omise.createToken("card", {
number: "4242424242424242", // チャレンジなしでパス
// ... その他の詳細
});
// チャレンジフロー (認証が必要)
const token2 = await Omise.createToken("card", {
number: "4000000000003220", // 認証が必要
// ... その他の詳細
});
// 認証失敗
const token3 = await Omise.createToken("card", {
number: "4000000000003238", // 3DSに失敗
// ... その他の詳細
});
エラー処理のテスト
ネットワークエラー
async function createChargeWithRetry(chargeData, maxRetries = 3) {
let attempt = 0;
while (attempt < maxRetries) {
try {
const charge = await omise.charges.create(chargeData);
return charge;
} catch (error) {
attempt++;
if (error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT') {
console.log(`Network error, retry ${attempt}/${maxRetries}`);
await sleep(1000 * attempt); // 指数バックオフ
} else {
throw error; // 他のエラーは再試行しない
}
}
}
throw new Error('Max retries exceeded');
}
APIエラー
try {
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
card: invalidToken
});
} catch (error) {
// 特定のエラーを処理
switch (error.code) {
case 'authentication_failure':
console.error('Invalid API key');
break;
case 'invalid_card':
console.error('Card declined');
showCardError(error.message);
break;
case 'insufficient_fund':
console.error('Insufficient funds');
offerAlternativeMethod();
break;
default:
console.error('Payment error:', error.message);
}
}
検証エラー
// 必須フィールドが見つからないテスト
try {
const charge = await omise.charges.create({
amount: 100000
// 通貨と支払いソースが見つかりません
});
} catch (error) {
console.log('Validation error:', error.message);
// Error: currency is required
}
// 無効な金額をテスト
try {
const charge = await omise.charges.create({
amount: -100, // 負の金額
currency: 'THB',
card: tokenId
});
} catch (error) {
console.log('Invalid amount:', error.message);
}