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>タグを閉じる前にこれを追加してください。ライブラリはOmiseとOmiseCardのグローバル変数として利用可能になります。
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が機能します。
関連リソース
- カード情報の収集 - 詳細な統合ガイド
- クレジットカード決済 - サーバーサイドでのチャージ
- セキュリティのベストプラクティス
- テストガイド
- APIリファレンス