SCB Mobile Banking (SCB Easy)
タイ最古で3番目に大きな銀行であるSiam Commercial BankのSCB Easyモバイルアプリ経由で、1,400万人以上のアクティブユーザーから即時決済を受け付けます。
決済フロー

モバイルバンキング決済プロセスのステップバイステップ:
❶ 銀行を選択 - 顧客がマーチャントのチェックアウトで銀行を選択
❷ 銀行にリダイレクト - システムが銀行の決済承認ページにリダイレクト
❸ バンキングアプリを開く - ディープリンクが銀行のモバイルアプリを自動的に起動
- iOS: Universal Links経由で開く
- Android: App Links経由で開く
- 顧客に「[銀行]アプリで開く」プロンプトが表示される
❹ 認証 - 顧客がバンキングアプリにログイン(まだログインしていない場合)
- PINの入力(6桁)
- 指紋スキャン
- Face ID認識
❺ 決済を確認 - アプリに取引詳細が表示される:
- マーチャント名
- 決済金額
- 注文参照
- 引き落とし口座
❻ 決済を承認 - 顧客が取引を確認
- 銀行が要求する場合は追加のPIN/OTPを入力
- 「決済を確認」ボタンをタップ
❼ 決済処理 - 銀行が即座に資金を転送
❽ 確認 - アプリに成功画面が表示される
- 取引参照番号
- ダウンロード可能な領収書
❾ マーチャントに戻る - 顧客がマーチャントのウェブサイトにリダイレクトされる
- 自動リダイレクトまたは「マーチャントに戻る」ボタン
- 注文確認ページが表示される
一般的な完了時間: 30〜90秒
概要
SCB Easyは、タイの主 要金融機関の1つであるSiam Commercial Bank(SCB)のモバイルバンキングアプリです。顧客は、PINまたは生体認証を使用してモバイルアプリから直接SCB銀行口座から安全に決済できます。
主な機能:
- ✅ 迅速な確認 - ほぼリアルタイムの決済検証(通常数秒以内)
- ✅ 1,400万人以上のユーザー - タイで大規模な顧客基盤
- ✅ 高額制限 - 1取引あたり最大฿150,000
- ✅ 信頼できる銀行 - タイ初の銀行(1906年設立)
- ✅ 24時間365日利用可能 - いつでも利用可能
- ✅ 安全な認証 - PIN、指紋、またはFace ID
対応地域
| 地域 | 通貨 | 最小金額 | 最大金額 | 1日の制限 |
|---|---|---|---|---|
| タイ | THB | ฿20.00 | ฿150,000 | 銀行により異なる* |
*1日の制限は顧客の銀行口座設定に基づいて異なり、Omiseでは指定されていません
仕組み
顧客体験:
- 顧客がチェックアウトで「SCB Easy」を選択
- SCB決済承認ページにリダイレクト
- ディープリンク経由でSCB Easyアプリを開く
- 取引詳細を確認
- PIN、指紋、またはFace IDで認証
- 決済を確認
- マーチャントのウェブサイトに戻る
一般的な完了時間: 1〜3分
実装
ステップ1: SCBソースを作成
- cURL
- Node.js
- PHP
- Python
- Ruby
- Go
- Java
- C#
curl https://api.omise.co/sources \
-u skey_test_YOUR_SECRET_KEY: \
-d "type=mobile_banking_scb" \
-d "amount=100000" \
-d "currency=THB"
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
const source = await omise.sources.create({
type: 'mobile_banking_scb',
amount: 100000, // THB 1,000.00
currency: 'THB'
});
<?php
$source = OmiseSource::create(array(
'type' => 'mobile_banking_scb',
'amount' => 100000,
'currency' => 'THB'
));
?>
import omise
omise.api_secret = 'skey_test_YOUR_SECRET_KEY'
source = omise.Source.create(
type='mobile_banking_scb',
amount=100000,
currency='THB'
)
require 'omise'
Omise.api_key = 'skey_test_YOUR_SECRET_KEY'
source = Omise::Source.create({
type: 'mobile_banking_scb',
amount: 100000,
currency: 'THB'
})
source, err := client.Sources().Create(&operations.CreateSource{
Type: "mobile_banking_scb",
Amount: 100000,
Currency: "THB",
})
Source source = client.sources().create(new Source.CreateParams()
.type("mobile_banking_scb")
.amount(100000L)
.currency("THB"));
var source = await client.Sources.Create(new CreateSourceRequest
{
Type = "mobile_banking_scb",
Amount = 100000,
Currency = "THB"
});
レスポンス:
{
"object": "source",
"id": "src_test_5rt6s9vah5lkvi1rh9c",
"type": "mobile_banking_scb",
"flow": "redirect",
"amount": 100000,
"currency": "THB"
}
ステップ2: チャージを作成
curl https://api.omise.co/charges \
-u skey_test_YOUR_SECRET_KEY: \
-d "amount=100000" \
-d "currency=THB" \
-d "source=src_test_5rt6s9vah5lkvi1rh9c" \
-d "return_uri=https://yourdomain.com/payment/callback"
ステップ3: 顧客をリダイレクト
app.post('/checkout/scb', async (req, res) => {
try {
const { amount, order_id } = req.body;
// 金額制限を検証
if (amount < 2000 || amount > 200000000) {
return res.status(400).json({
error: '金額は฿20から฿2,000,000の間である必要があります'
});
}
// ソースを作成
const source = await omise.sources.create({
type: 'mobile_banking_scb',
amount: amount,
currency: 'THB'
});
// チャージを作成
const charge = await omise.charges.create({
amount: amount,
currency: 'THB',
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id
}
});
// SCB Easyにリダイレクト
res.redirect(charge.authorize_uri);
} catch (error) {
console.error('SCB Easyエラー:', error);
res.status(500).json({ error: error.message });
}
});
ステップ4: 戻りを処理
app.get('/payment/callback', async (req, res) => {
try {
const chargeId = req.query.charge_id;
const charge = await omise.charges.retrieve(chargeId);
if (charge.status === 'successful') {
// 決済成功
await processOrder(charge.metadata.order_id);
res.redirect('/payment-success');
} else if (charge.status === 'failed') {
// 決済失敗
res.redirect('/payment-failed?reason=' + charge.failure_message);
} else {
// まだ保留中
res.redirect('/payment-pending');
}
} catch (error) {
res.redirect('/payment-error');
}
});
ステップ5: Webhookを処理
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
if (event.key === 'charge.complete' && event.data.source.type === 'mobile_banking_scb') {
const charge = event.data;
if (charge.status === 'successful') {
processOrder(charge.metadata.order_id);
} else if (charge.status === 'failed') {
handleFailedPayment(charge.metadata.order_id);
}
}
res.sendStatus(200);
});
完全な実装例
// Express.jsサーバー
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
const app = express();
app.use(express.json());
// チェックアウトページ
app.post('/checkout/scb', async (req, res) => {
try {
const { amount, order_id } = req.body;
// 金額を検証
if (amount < 2000 || amount > 200000000) {
return res.status(400).json({
error: '金額は฿20から฿2,000,000の間である必要があります'
});
}
// ソースを作成
const source = await omise.sources.create({
type: 'mobile_banking_scb',
amount: amount,
currency: 'THB'
});
// チャージを作成
const charge = await omise.charges.create({
amount: amount,
currency: 'THB',
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id,
payment_method: 'scb_easy'
}
});
// 承認URLを返す
res.json({
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});
} catch (error) {
console.error('SCB Easyエラー:', error);
res.status(500).json({ error: error.message });
}
});
// コールバックハンドラー
app.get('/payment/callback', async (req, res) => {
try {
const chargeId = req.query.charge_id;
const charge = await omise.charges.retrieve(chargeId);
if (charge.status === 'successful') {
res.redirect(`/order-success?order=${charge.metadata.order_id}`);
} else {
res.redirect(`/payment-failed?charge=${chargeId}`);
}
} catch (error) {
res.redirect('/payment-error');
}
});
// Webhookハンドラー
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.source.type === 'mobile_banking_scb') {
if (charge.status === 'successful') {
updateOrderStatus(charge.metadata.order_id, 'paid');
sendConfirmationEmail(charge.metadata.customer_email);
} else {
updateOrderStatus(charge.metadata.order_id, 'failed');
}
}
}
res.sendStatus(200);
});
app.listen(3000);
返金サポート
SCB Easyは180日以内の全額返金のみをサポートしています:
// 全額返金のみ
const refund = await omise.charges.refund('chrg_test_...', {
amount: 100000 // 全額である必要があります
});
SCB Easyは一部返金をサポートしていません。180日以内の全額返金のみが許可されています。
よくある問題とトラブルシューティング
問題: 顧客がSCB Easyアプリを持っていない
原因: 顧客がSCBを選択したがアプリがインストールされていない
解決策:
- 明確な手順を表示
- アプリダウンロードリンクを提供
- 代替決済方法を提供
function isMobile() {
return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
}
if (!isMobile()) {
alert('SCB Easyにはモバイルアプリが必要です。モバイルデバイスを使用するか、別の決済方法を選択してください。');
}
問題: 決済が期限切れになる
原因: 顧客が制限時間内(15分)に決済を完了しなかった
解決策:
// カウントダウンタイマーを表示
const EXPIRY_TIME = 15 * 60 * 1000;
setTimeout(() => {
if (!paymentConfirmed) {
showExpiryMessage();
allowRetry();
}
}, EXPIRY_TIME);
問題: 1日の制限を超過
エラー: 銀行によって取引が拒否される
解決策:
- 顧客がSCB Easyアプリで1日の制限を調整できます
- 複数の日に決済を分割
- 代替決済方法を使用
問題: 顧客がアプリを閉じた
原因: return_uriが呼び出されない
解決策:
- Webhook処理を実装(より信頼性が高い)
- 注文ステータス確認ページを提供
- メール/SMS確認を送信
ベストプラクティス
1. 明確な手順を表示
<div class="scb-instructions">
<h3>SCB Easyで支払 う</h3>
<ol>
<li>SCB Easyアプリがインストールされていることを確認してください</li>
<li>アプリを開くためにリダイレクトされます</li>
<li>PIN、指紋、またはFace IDで認証</li>
<li>決済を確認してください</li>
</ol>
<p><strong>決済は15分以内に完了する必要があります</strong></p>
<a href="https://www.scb.co.th/en/personal-banking/digital-banking/scb-easy.html">
SCB Easyをダウンロード
</a>
</div>
2. ディープリンクを処理
function openSCBApp(authorizeUri) {
// モバイルアプリを開こうとする
window.location = authorizeUri;
// アプリがインストールされていない場合のフォールバック
setTimeout(() => {
if (document.hidden) {
// アプリが正常に開かれた
return;
}
// アプリインストール手順を表示
showInstallAppMessage();
}, 2000);
}
3. タイムアウトを設定
// 15分の決済ウィンドウ
const PAYMENT_TIMEOUT = 15 * 60 * 1000;
setTimeout(() => {
if (!paymentConfirmed) {
showTimeoutMessage();
allowRetry();
}
}, PAYMENT_TIMEOUT);
4. Webhookを使用
// Webhookはコールバックよりも信頼性が高い
app.post('/webhooks/omise', handleWebhook);
app.get('/payment/callback', handleCallback);
5. 金額を検証
function validateSCBAmount(amount) {
const MIN = 2000; // ฿20.00
const MAX = 200000000; // ฿2,000,000.00
if (amount < MIN) {
return `最小金額は฿${MIN / 100}です`;
}
if (amount > MAX) {
return `最大金額は฿${MAX / 100}です`;
}
return null; // 有効
}
FAQ
SCB Easyとは何ですか?
SCB Easyは、タイのSiam Commercial Bankのモバイルバンキングアプリで、1,400万人以上のユーザーがいます。顧客はPINまたは生体認証を使用してSCB銀行口座から直接支払うことができます。
顧客はSCB口座が必要ですか?
はい、顧客はアクティブなSCB銀行口座とSCB Easyアプリがインストールされている必要があります。アプリはiOSとAndroidで無料です。
取引制限は何ですか?
- 1取引あたり: ฿20から฿2,000,000
- 1日の制限: 最大฿5,000,000(顧客設定により異なる)
顧客はSCB Easyアプリで1日の制限を調整できます。
決済にはどのくらい時間がかかりますか?
SCB Easyの決済は通常1〜2営業日以内に行われます。具体的な決済スケジュールについては、Omiseダッシュボードをご確認ください。
SCB Easyの決済を返金できますか?
はい、ただし全額返金のみが180日以内にサポートされています。一部返金は利用できません。
決済が期限切れになったらどうなりますか?
決済は15分後に期限切れになります。顧客が新しいチャージで再試行できるようにします。残り時間を表示するカウントダウンタイマーを表示します。
SCB Easyは24時間365日利用できますか?
はい、SCB Easyは週末や休日を含めて24時間365日利用できます。ただし、決済は営業日のスケジュールに従います。
テスト
テストモード
SCB Mobile BankingはテストAPIキーを使用してテストできます。テストモードでは:
テスト認証情報:
- テストAPIキーを使用(skey_test_xxx)
- 通貨: THB(タイバーツ)
- テストに実際のSCB口座は不要
テストフロー:
- テストAPIキーでソースとチャージを作成
- 顧客をテスト
authorize_uriにリダイレクト - テストページがSCBモバイルバンキング承認をシミュレート
- Omiseダッシュボードアクションを使用してチャージを成功/失敗としてマーク
- WebhookとReturn_uri処理を検証
テスト実装:
// SCB Mobile Bankingをテスト
const source = await omise.sources.create({
type: 'mobile_banking_scb',
amount: 50000, // ฿500.00
currency: 'THB'
});
const charge = await omise.charges.create({
amount: 50000,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/callback'
});
console.log('テスト承認URL:', charge.authorize_uri);
テストシナリオ:
- 決済成功: リダイレクトフローと注文処理を完了
- 決済失敗: エラー処理をテスト
- 金額制限: ฿20の最小値と最大値をテスト
- モバイルフロー: SCB Easyアプリへのディープリンクをテスト
- タイムアウト: 放棄された決済シナリオをテスト
- Return URI: 決済後の適切なリダイレクトを検証
- Webhook配信: すべてのWebhook通知を検証
重要な注意事項:
- テストモードは実際のSCBサーバーに接続しません
- ダッシュボードを使用して決済ステータスの変更をシミュレート
- モバイルアプリのディープリンクをテスト
- すべてのチャージステータスのWebhook処理を検証
- 成功と失敗の両方の決済フローをテスト
包括的なテストガイドラインについては、テストドキュメントを参照してください。
関連リソース
- Mobile Banking概要 - すべてのモバイルバンキングオプション
- KBank Mobile Banking - 代替銀行
- Bangkok Bank Mobile - 別のオプション
- テスト - SCB統合をテスト
- 返金 - 返金ポリシー