Mobile Banking
Accept payments directly through customers' mobile banking apps with seamless deep linking, instant confirmation, and full refund support.
Overview
Payment method features, limits, user statistics, and fees are subject to change. Information is based on publicly available sources and may not reflect your specific merchant agreement. Always refer to official Omise documentation and your merchant dashboard for current, binding information.
Mobile Banking allows customers to authorize payments directly in their bank's mobile app. When they select their bank at checkout, their banking app opens automatically, they authenticate, approve the payment, and return to your site - all within 30-90 seconds.
Key Features:
- ⚡ Fast - 30-90 second completion time
- 📱 Mobile-first - Seamless app experience
- ✅ Fast confirmation - Near real-time payment verification (typically within seconds)
- 🔄 Refund support - Full and partial refunds
- 🔒 Secure - Bank-grade security
- 💰 High limits - Higher than card limits
Supported Banks
Thailand 🇹🇭
| Bank | Users | Source Type | Refundable | Settlement |
|---|---|---|---|---|
| SCB (Siam Commercial Bank) | 12M+ | mobile_banking_scb | ✅ Yes | 1-3 days |
| Kasikornbank (K-Bank) | 10M+ | mobile_banking_kbank | ✅ Yes | 1-3 days |
| Bangkok Bank (BBL) | 6M+ | mobile_banking_bbl | ✅ Yes | 1-3 days |
| Krungsri (BAY) | 4M+ | mobile_banking_bay | ✅ Yes | 1-3 days |
| Krungthai Bank (KTB) | 5M+ | mobile_banking_ktb | ✅ Yes | 1-3 days |
Singapore 🇸🇬
| Bank | Source Type | Refundable | Settlement |
|---|---|---|---|
| OCBC Bank | mobile_banking_ocbc | ✅ Yes | 1-3 days |
Currency: THB (Thailand), SGD (Singapore) Min Amount: ฿1 / $0.01 Max Amount: ฿2,000,000 / $500,000+ (varies by bank)
How Mobile Banking Works
Customer Experience:
- Select their bank from list
- Banking app opens automatically
- Login if not already authenticated
- Review payment details
- Confirm with biometric/PIN (5 seconds)
- See confirmation
- Return to merchant site
Total time: 30-90 seconds
Implementation
Step 1: Create Mobile Banking Source
- Node.js
- PHP
- Python
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
// Customer selects SCB
const source = await omise.sources.create({
type: 'mobile_banking_scb',
amount: 100000, // ฿1,000
currency: 'THB'
});
<?php
$source = OmiseSource::create(array(
'type' => 'mobile_banking_scb',
'amount' => 100000,
'currency' => 'THB'
));
?>
import omise
source = omise.Source.create(
type='mobile_banking_scb',
amount=100000,
currency='THB'
)
Step 2: Create Charge and Redirect
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
source: source.id,
return_uri: 'https://yourdomain.com/payment/callback',
metadata: {
order_id: 'ORD-12345'
}
});
// Redirect to banking app
res.redirect(charge.authorize_uri);
Step 3: Handle Return and Webhook
// Customer returns here
app.get('/payment/callback', async (req, res) => {
const charge = await omise.charges.retrieve(req.query.charge_id);
if (charge.status === 'successful') {
res.redirect('/success');
} else {
res.redirect('/failed');
}
});
// Webhook for server-side processing
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
// Process order
fulfillOrder(charge.metadata.order_id);
}
res.sendStatus(200);
});
Complete Implementation
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
const app = express();
app.use(express.json());
// Available banks
const BANKS = {
scb: { name: 'SCB', type: 'mobile_banking_scb' },
kbank: { name: 'Kasikornbank', type: 'mobile_banking_kbank' },
bbl: { name: 'Bangkok Bank', type: 'mobile_banking_bbl' },
bay: { name: 'Krungsri', type: 'mobile_banking_bay' },
ktb: { name: 'Krungthai', type: 'mobile_banking_ktb' }
};
// Create payment
app.post('/checkout/mobile-banking', async (req, res) => {
try {
const { bank_code, amount, order_id } = req.body;
const bank = BANKS[bank_code];
if (!bank) {
return res.status(400).json({ error: 'Invalid bank' });
}
// Create source
const source = await omise.sources.create({
type: bank.type,
amount: amount,
currency: 'THB'
});
// Create charge
const charge = await omise.charges.create({
amount: amount,
currency: 'THB',
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: { order_id }
});
res.json({
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
Bank Selector UI
<div class="mobile-banking-selector">
<h3>เลือกธนาคาร (Select Bank)</h3>
<div class="bank-grid">
<button class="bank-button" data-bank="scb">
<img src="/banks/scb.svg" alt="SCB">
<span>SCB</span>
</button>
<button class="bank-button" data-bank="kbank">
<img src="/banks/kbank.svg" alt="Kasikornbank">
<span>Kasikornbank</span>
</button>
<button class="bank-button" data-bank="bbl">
<img src="/banks/bbl.svg" alt="Bangkok Bank">
<span>Bangkok Bank</span>
</button>
<button class="bank-button" data-bank="bay">
<img src="/banks/bay.svg" alt="Krungsri">
<span>Krungsri</span>
</button>
<button class="bank-button" data-bank="ktb">
<img src="/banks/ktb.svg" alt="Krungthai">
<span>Krungthai</span>
</button>
</div>
</div>
<style>
.bank-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 16px;
margin-top: 20px;
}
.bank-button {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
border: 2px solid #e0e0e0;
border-radius: 12px;
background: white;
cursor: pointer;
transition: all 0.2s;
}
.bank-button:hover {
border-color: #1890ff;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.bank-button img {
width: 60px;
height: 60px;
margin-bottom: 12px;
}
</style>
<script>
document.querySelectorAll('.bank-button').forEach(button => {
button.addEventListener('click', async () => {
const bankCode = button.dataset.bank;
const response = await fetch('/checkout/mobile-banking', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
bank_code: bankCode,
amount: 100000,
order_id: 'ORD-12345'
})
});
const data = await response.json();
window.location = data.authorize_uri;
});
});
</script>
Refund Support
All mobile banking payments support full and partial refunds:
// Full refund
const refund = await omise.charges.refund('chrg_test_...', {
amount: 100000
});
// Partial refund
const partialRefund = await omise.charges.refund('chrg_test_...', {
amount: 50000
});
Best Practices
1. Mobile-Only Detection
function isMobileDevice() {
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
}
if (!isMobileDevice()) {
showMessage('Mobile banking requires a mobile device.');
showAlternativePaymentMethods();
}
2. Bank Logo Assets
Use official bank logos (60x60px or 120x120px):
- SCB: Purple logo
- Kasikornbank: Green "K" logo
- Bangkok Bank: Blue logo
- Krungsri: Yellow logo
- Krungthai: Blue/red logo
3. Show Instructions
<div class="instructions">
<h4>วิธีชำระเงิน (How to Pay):</h4>
<ol>
<li>เลือกธนาคารของคุณ (Select your bank)</li>
<li>แอพธนาคารจะเปิดอัตโนมัติ (Banking app will open)</li>
<li>ยืนยันการชำระเงิน (Confirm payment)</li>
<li>กลับมาที่หน้าเว็บ (Return to website)</li>
</ol>
</div>
4. Handle Deep Link Failures
function openBankingApp(authorizeUri) {
window.location = authorizeUri;
// Fallback if app doesn't open
setTimeout(() => {
if (!document.hidden) {
showMessage('แอพธนาคารไม่เปิด? ลองอัปเดทแอพหรือติดตั้งใหม่');
showAlternatives();
}
}, 3000);
}
5. Timeout Handling
// Mobile banking expires after 10 minutes
const TIMEOUT = 10 * 60 * 1000;
setTimeout(() => {
if (!paymentCompleted) {
showMessage('Payment expired. Please try again.');
}
}, TIMEOUT);
Common Issues
Issue: Banking app not opening
Cause: App not installed or outdated
Solution:
- Show app download links
- Offer internet banking alternative
- Display clear error message
Issue: Payment timeout
Cause: Customer didn't complete within 10 minutes
Solution:
- Show clear timeout message
- Allow retry with new charge
- Don't reuse expired charges
Issue: Wrong bank account
Cause: Customer has multiple accounts
Solution:
- Customer selects account in banking app
- Can't control from merchant side
- Show bank name clearly before redirect
FAQ
What is mobile banking payment?
Mobile banking payment allows customers to authorize payments directly in their bank's mobile app. The app opens automatically, customer authenticates, and approves - all in 30-90 seconds.
Which banks are supported?
Thailand: SCB, Kasikornbank, Bangkok Bank, Krungsri, Krungthai Singapore: OCBC
More banks coming soon.
Does it work on desktop?
No, mobile banking requires the bank's mobile app. For desktop users, offer:
- Internet banking
- QR payments
- Credit cards
Can I refund mobile banking payments?
Yes! Mobile banking supports both full and partial refunds, unlike internet banking.
How long does settlement take?
Settlement timing varies by agreement*, depending on your merchant agreement and the bank.
What are the transaction limits?
Limits vary by bank and customer account type:
- Minimum: ฿1 (THB)
- Maximum: ฿2,000,000+ per transaction
Much higher than credit card limits.
*Settlement timing varies by merchant agreement and payment method. Check your Omise merchant dashboard for your specific settlement schedule.
Related Resources
- Bank Transfers Overview - All bank payment methods
- SCB Mobile Banking - SCB integration
- Kasikornbank - K-Bank integration
- Internet Banking - Desktop alternative
- PromptPay - QR alternative
- Testing - Test mobile banking
Next Steps
- Choose your target banks
- Implement bank selector UI
- Create source with selected bank
- Handle redirect and webhooks
- Test with actual mobile devices
- Go live
Ready to integrate? Choose your bank: