メインコンテンツへスキップ

Omise.js

ブラウザ内で直接決済をトークン化する安全なクライアントサイドJavaScriptライブラリ。カードデータをサーバーから遠ざけ、PCI準拠要件を軽減します。

概要

Omise.jsは、ブラウザ内で決済収集とトークン化を完全に処理するJavaScriptライブラリです。機密性の高いカードデータは、顧客のデバイスからOmiseのPCI認証サーバーに直接送信され、バックエンドに触れることはありません。

主な機能:

  • PCI準拠が簡単に - カードデータがサーバーに到達しません
  • 事前構築済み決済フォーム - バリデーション付きのすぐに使用可能なUI
  • カスタム統合 - UIとUXを完全にコントロール
  • 50以上の決済方法 - カード、ウォレット、QR、バンキングなど
  • モバイル最適化 - すべてのデバイスで動作
  • デフォルトで安全 - HTTPS必須、自動バリデーション

仕組み

Omise.jsは、カードデータがサーバーに触れることなく決済情報を収集する安全なフローを提供します:

トークンとソースを収集する安全なフロー

カードデータは顧客のブラウザからOmiseのサーバーに直接送信され、バックエンドで安全に使用できるセキュアトークンが返されます。

インストール

CDN(推奨)

<script src="https://cdn.omise.co/omise.js"></script>

</body>タグを閉じる前にこれを追加してください。ライブラリはOmiseOmiseCardのグローバル変数として利用可能になります。

HTTPS必須

Omise.jsはHTTPSページでのみ動作します。TLS 1.2以上を使用してください。

統合方法

Omise.jsは2つの統合アプローチを提供します:

1. 事前構築済み決済フォーム(最速)

組み込みバリデーション付きのすぐに使える決済フォームにはOmiseCardを使用します:

データ属性メソッド

<form id="checkoutForm">
<script
src="https://cdn.omise.co/omise.js"
data-key="pkey_test_YOUR_PUBLIC_KEY"
data-amount="10025"
data-currency="THB"
data-default-payment-method="credit_card"
data-button-label="Pay Now">
</script>
</form>

JavaScriptメソッド

OmiseCard.configure({
publicKey: "pkey_test_YOUR_PUBLIC_KEY",
amount: 10025,
currency: "THB",
defaultPaymentMethod: "credit_card",
onCreateTokenSuccess: (nonce) => {
if (nonce.startsWith('tokn_')) {
// カードトークンが作成されました
submitPayment(nonce);
} else {
// ソースが作成されました(カード以外の決済用)
submitPayment(nonce);
}
},
onFormClosed: () => {
console.log('決済フォームが閉じられました');
}
});

OmiseCard.open();

結果: プロフェッショナルな決済フォームモーダルが表示されます:

  • バリデーション付きカード入力フィールド
  • 決済方法の選択
  • セキュアなスタイリング
  • モバイルレスポンシブデザイン
  • 組み込みエラーハンドリング

クレジットカード決済フォームの例

2. カスタム統合(完全なコントロール)

UIを完全にコントロールするにはOmiseオブジェクトを使用します:

<form id="payment-form">
<input type="text" id="card-name" placeholder="Card Holder Name" />
<input type="text" id="card-number" placeholder="1234 5678 9012 3456" />
<input type="text" id="expiry-month" placeholder="MM" maxlength="2" />
<input type="text" id="expiry-year" placeholder="YYYY" maxlength="4" />
<input type="text" id="cvv" placeholder="123" maxlength="4" />
<button type="submit">Pay</button>
</form>

<script src="https://cdn.omise.co/omise.js"></script>
<script>
Omise.setPublicKey("pkey_test_YOUR_PUBLIC_KEY");

document.getElementById('payment-form').addEventListener('submit', function(e) {
e.preventDefault();

Omise.createToken("card", {
name: document.getElementById('card-name').value,
number: document.getElementById('card-number').value,
expiration_month: parseInt(document.getElementById('expiry-month').value),
expiration_year: parseInt(document.getElementById('expiry-year').value),
security_code: document.getElementById('cvv').value
}, function(statusCode, response) {
if (statusCode === 200) {
// Success - send token to server
submitTokenToServer(response.id);
} else {
// Error
alert(response.message);
}
});
});
</script>

コアメソッド

setPublicKey()

公開鍵でOmise.jsを初期化します:

Omise.setPublicKey("pkey_test_YOUR_PUBLIC_KEY");

createToken()

カードトークンを作成します:

Omise.createToken("card", {
name: "John Doe",
number: "4242424242424242",
expiration_month: 12,
expiration_year: 2027,
security_code: "123",
// オプションですが推奨
city: "Bangkok",
postal_code: "10110",
country: "TH"
}, function(statusCode, response) {
if (statusCode === 200) {
console.log('トークン:', response.id);
// response.id = "tokn_test_..."
} else {
console.error('エラー:', response.message);
}
});

createSource()

代替決済方法用のソースを作成します:

Omise.createSource("truemoney", {
amount: 35000,
currency: "THB",
phone_number: "+66876543210"
}, function(statusCode, response) {
if (statusCode === 200) {
console.log('Source:', response.id);
// response.id = "src_test_..."
}
});

サポートされている決済方法

クレジット/デビットカード

Omise.createToken("card", cardData, callback);

デジタルウォレット

// Google Pay
Omise.createToken("tokenization", {
method: "googlepay",
data: googlePayToken
}, callback);

// Apple Pay
Omise.createToken("tokenization", {
method: "applepay",
data: applePayToken
}, callback);

QR決済

// PromptPay
Omise.createSource("promptpay", {
amount: 50000,
currency: "THB"
}, callback);

// PayNow
Omise.createSource("paynow", {
amount: 5000,
currency: "SGD"
}, callback);

電子ウォレット

// TrueMoney
Omise.createSource("truemoney", {
amount: 30000,
currency: "THB",
phone_number: "+66876543210"
}, callback);

// GrabPay
Omise.createSource("grabpay", {
amount: 10000,
currency: "SGD"
}, callback);

// ShopeePay
Omise.createSource("shopeepay", {
amount: 25000,
currency: "THB"
}, callback);

Omise.jsは、タイと東南アジアで人気のある幅広い代替決済方法をサポートしています:

代替決済方法フォーム

モバイルバンキング

// KBank (Thailand)
Omise.createSource("mobile_banking_kbank", {
amount: 40000,
currency: "THB"
}, callback);

// SCB Easy
Omise.createSource("mobile_banking_scb", {
amount: 40000,
currency: "THB"
}, callback);

完全な実装例

<!DOCTYPE html>
<html>
<head>
<title>Omise.js Payment</title>
<style>
.payment-form {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.btn-pay {
width: 100%;
padding: 12px;
background: #1e3a8a;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
}
.btn-pay:hover {
background: #1e40af;
}
.btn-pay:disabled {
background: #ccc;
cursor: not-allowed;
}
.error {
color: #c92a2a;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="payment-form">
<h2>Checkout</h2>
<p>Amount: <strong>฿100.25</strong></p>

<form id="payment-form">
<div class="form-group">
<label for="card-name">Cardholder Name</label>
<input type="text" id="card-name" required />
</div>

<div class="form-group">
<label for="card-number">Card Number</label>
<input type="text" id="card-number" placeholder="4242 4242 4242 4242" required />
</div>

<div class="form-group">
<label>Expiration Date</label>
<div style="display: flex; gap: 10px;">
<input type="text" id="expiry-month" placeholder="MM" maxlength="2" style="width: 70px;" required />
<input type="text" id="expiry-year" placeholder="YYYY" maxlength="4" style="width: 100px;" required />
</div>
</div>

<div class="form-group">
<label for="cvv">CVV</label>
<input type="text" id="cvv" placeholder="123" maxlength="4" style="width: 100px;" required />
</div>

<button type="submit" class="btn-pay" id="pay-button">
Pay ฿100.25
</button>

<div id="error-message" class="error"></div>
</form>
</div>

<script src="https://cdn.omise.co/omise.js"></script>
<script>
// Initialize
Omise.setPublicKey("pkey_test_YOUR_PUBLIC_KEY");

// Format card number input
document.getElementById('card-number').addEventListener('input', function(e) {
let value = e.target.value.replace(/\s/g, '');
let formatted = value.match(/.{1,4}/g)?.join(' ') || value;
e.target.value = formatted;
});

// Handle form submission
document.getElementById('payment-form').addEventListener('submit', async function(e) {
e.preventDefault();

// Disable button
const payButton = document.getElementById('pay-button');
const originalText = payButton.textContent;
payButton.disabled = true;
payButton.textContent = 'Processing...';

// Clear previous errors
document.getElementById('error-message').textContent = '';

// Create token
Omise.createToken("card", {
name: document.getElementById('card-name').value,
number: document.getElementById('card-number').value.replace(/\s/g, ''),
expiration_month: parseInt(document.getElementById('expiry-month').value),
expiration_year: parseInt(document.getElementById('expiry-year').value),
security_code: document.getElementById('cvv').value
}, async function(statusCode, response) {
if (statusCode === 200) {
// Success - send to server
try {
const result = await fetch('/process-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: response.id,
amount: 10025
})
});

const data = await result.json();

if (data.success) {
window.location.href = '/payment-success';
} else {
document.getElementById('error-message').textContent = data.error;
payButton.disabled = false;
payButton.textContent = originalText;
}
} catch (error) {
document.getElementById('error-message').textContent = 'Network error. Please try again.';
payButton.disabled = false;
payButton.textContent = originalText;
}
} else {
// Token creation failed
document.getElementById('error-message').textContent = response.message;
payButton.disabled = false;
payButton.textContent = originalText;
}
});
});
</script>
</body>
</html>

セキュリティのベストプラクティス

1. カードデータを絶対にサーバーに送信しない

// ❌ 悪い例: これをしないでください
fetch('/checkout', {
body: JSON.stringify({
cardNumber: '4242424242424242', // ダメ!
cvv: '123' // ダメ!
})
});

// ✅ 良い例: トークンのみを送信
fetch('/checkout', {
body: JSON.stringify({
token: 'tokn_test_...' // 安全!
})
});

2. HTTPSを使用する

<!-- ✅ 良い例 -->
<script src="https://cdn.omise.co/omise.js"></script>

<!-- ❌ 悪い例 -->
<script src="http://cdn.omise.co/omise.js"></script>

3. クライアントとサーバーの両方でバリデーション

// クライアントサイドのバリデーション
function validateCard() {
const number = document.getElementById('card-number').value;
const month = parseInt(document.getElementById('expiry-month').value);
const year = parseInt(document.getElementById('expiry-year').value);

if (number.length < 13) {
return 'カード番号が短すぎます';
}

if (month < 1 || month > 12) {
return '無効な有効期限の月';
}

const currentYear = new Date().getFullYear();
if (year < currentYear) {
return 'カードの有効期限が切れています';
}

return null; // 有効
}

4. 機密データをクリアする

function clearForm() {
document.getElementById('card-number').value = '';
document.getElementById('cvv').value = '';
// ユーザーの利便性のため、名前と有効期限は保持
}

5. CSPヘッダーを実装する

<meta http-equiv="Content-Security-Policy"
content="script-src 'self' https://cdn.omise.co;">

よくある問題とトラブルシューティング

問題: "Public key is required"

解決策:

// createTokenの前にsetPublicKeyを呼び出す必要があります
Omise.setPublicKey("pkey_test_YOUR_KEY");

問題: "Invalid card number"

原因:

  • カード番号に数字以外の文字が含まれている
  • 無効なカードブランド
  • 本番モードでテストカードを使用

解決策:

// スペースを削除してバリデーション
const cardNumber = value.replace(/\s/g, '');
if (!/^\d{13,19}$/.test(cardNumber)) {
return '無効なカード番号';
}

問題: トークン作成が400を返す

よくある原因:

  • 必須フィールドが欠落している
  • データ型が間違っている(文字列 vs 整数)
  • 無効な有効期限

解決策:

Omise.createToken("card", {
name: cardName, // 文字列
number: cardNumber.replace(/\s/g, ''), // 文字列
expiration_month: parseInt(month), // 整数!
expiration_year: parseInt(year), // 整数!
security_code: cvv // 文字列
}, callback);

よくある質問

React、Vue、AngularでOmise.jsを使用できますか?

はい!index.htmlでOmise.jsを読み込み、コンポーネントでグローバルOmiseオブジェクトを使用します:

// Reactの例
useEffect(() => {
if (window.Omise) {
window.Omise.setPublicKey(publicKey);
}
}, []);

const handleSubmit = () => {
window.Omise.createToken('card', cardData, callback);
};
トークンは再利用できますか?

いいえ、トークンは1回限りの使用です。各チャージには新しいトークンが必要です。カードを保存するには、顧客APIを使用してください。

トークンはどのくらいの期間有効ですか?

カードトークンは未使用の場合、10分後に期限切れになります。チャージ直前にトークンを作成してください。

事前構築済み決済フォームのスタイルをカスタマイズできますか?

事前構築済みフォームにはスタイリングオプションが限られています。外観を完全にコントロールするには、カスタム統合方法を使用してください。

Omise.jsはオフラインで動作しますか?

いいえ、Omise.jsはトークン化のためにOmiseサーバーと通信するためにインターネット接続が必要です。

Omise.jsをテストするにはどうすればよいですか?

テストカードを使用してテストモードで実行します:

  • 成功: 4242 4242 4242 4242
  • 拒否: 4000 0000 0000 0002

テストモードでは、将来の有効期限とすべてのCVVが機能します。

すべてのテストカードを表示 →

関連リソース

次のステップ

  1. ページにOmise.jsを含める
  2. 統合方法を選択
  3. トークン化を実装
  4. テストカードでテスト
  5. サーバーサイドでのチャージを追加
  6. 本番稼働