Bank Transfers
Accept payments directly from customer bank accounts via mobile banking apps, internet banking, and online direct debit across Thailand, Malaysia, and Singapore.
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.
Bank transfers allow customers to pay directly from their bank accounts without needing a credit card. These methods are highly trusted in Southeast Asia, where bank account penetration is high but credit card usage is lower than Western markets.
Why Bank Transfers?
- 🏦 High trust - Direct from customer's trusted bank
- 📱 Mobile-first - Popular mobile banking apps
- 💳 No card needed - Access customers without credit cards
- 🔒 Secure - Bank-grade security
- 💰 Lower fees - Often cheaper than cards
- 🌏 Wide reach - High bank account penetration in SEA
Payment Methods Available
Mobile Banking (Thailand)
Direct integration with bank mobile apps - customers authorize payment in their banking app.
| Bank | Users | Settlement | Refundable |
|---|---|---|---|
| Bangkok Bank | 6M+ | 1-3 days | ✅ Yes |
| Krungthai Bank (KTB) | 5M+ | 1-3 days | ✅ Yes |
| Kasikornbank (K-Bank) | 10M+ | 1-3 days | ✅ Yes |
| Krungsri (Bank of Ayudhya) | 4M+ | 1-3 days | ✅ Yes |
| Siam Commercial Bank (SCB) | 12M+ | 1-3 days | ✅ Yes |
Mobile Banking (Singapore)
| Bank | Settlement | Refundable |
|---|---|---|
| OCBC | 1-3 days | ✅ Yes |
Internet Banking
| Method | Region | Settlement | Refundable |
|---|---|---|---|
| Internet Banking (Thailand) | Thailand | 1-3 days | ❌ No |
| FPX (Malaysia) | Malaysia | 1-3 days | ❌ No |
Direct Debit
| Method | Region | Settlement | Refundable |
|---|---|---|---|
| Online Direct Debit | Thailand | 1-3 days | ✅ Yes |
Mobile Banking vs Internet Banking
| Feature | Mobile Banking | Internet Banking |
|---|---|---|
| Platform | Mobile app only | Desktop browser |
| Experience | Seamless deep link | Redirect to bank site |
| Speed | Fast (30-60 sec) | Slower (2-3 min) |
| Refunds | ✅ Supported | ❌ Not supported |
| Popular in | 2023+ | 2018-2022 |
| Recommended | ✅ Yes | ⚠️ Legacy |
Use Mobile Banking for new integrations. It offers better UX, faster payments, and refund support. Internet Banking is legacy but still widely used.
How Bank Transfers Work
Mobile Banking Flow
Customer Experience:
- Customer selects their bank at checkout
- Banking app opens automatically
- Customer logs in (if not already)
- Reviews payment details
- Confirms with biometric/PIN
- Returns to merchant site
Typical completion time: 30-90 seconds
Internet Banking Flow
Customer Experience:
- Customer selects bank and clicks pay
- Redirected to bank's internet banking site
- Logs in with username/password
- Reviews and confirms payment
- Receives confirmation
- Redirected back to merchant
Typical completion time: 2-5 minutes
Implementation Overview
Basic Integration (Mobile Banking)
- Node.js
- PHP
- Python
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
// Create source for mobile banking
const source = await omise.sources.create({
type: 'mobile_banking_scb', // or kbank, bbl, bay, ktb
amount: 100000, // Amount in smallest unit
currency: 'THB'
});
// Create charge
const charge = await omise.charges.create({
amount: 100000,
currency: 'THB',
source: source.id,
return_uri: 'https://yourdomain.com/payment/callback'
});
// Redirect customer to banking app
res.redirect(charge.authorize_uri);
<?php
// Create source
$source = OmiseSource::create(array(
'type' => 'mobile_banking_scb',
'amount' => 100000,
'currency' => 'THB'
));
// Create charge
$charge = OmiseCharge::create(array(
'amount' => 100000,
'currency' => 'THB',
'source' => $source['id'],
'return_uri' => 'https://yourdomain.com/payment/callback'
));
// Redirect
header('Location: ' . $charge['authorize_uri']);
?>
import omise
omise.api_secret = 'skey_test_YOUR_SECRET_KEY'
# Create source
source = omise.Source.create(
type='mobile_banking_scb',
amount=100000,
currency='THB'
)
# Create charge
charge = omise.Charge.create(
amount=100000,
currency='THB',
source=source.id,
return_uri='https://yourdomain.com/payment/callback'
)
# Redirect
return redirect(charge.authorize_uri)
Handling Callbacks and Webhooks
// Handle return from bank
app.get('/payment/callback', async (req, res) => {
const charge = await omise.charges.retrieve(req.query.charge_id);
if (charge.status === 'successful') {
res.redirect('/payment-success');
} else {
res.redirect('/payment-failed');
}
});
// Handle webhook (recommended)
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.status === 'successful') {
fulfillOrder(charge.metadata.order_id);
}
}
res.sendStatus(200);
});
Source Types Reference
Thailand Mobile Banking
| Source Type | Bank Name | Code |
|---|---|---|
mobile_banking_scb | Siam Commercial Bank | SCB |
mobile_banking_kbank | Kasikornbank | KBANK |
mobile_banking_bbl | Bangkok Bank | BBL |
mobile_banking_bay | Krungsri (Bank of Ayudhya) | BAY |
mobile_banking_ktb | Krungthai Bank | KTB |
Singapore Mobile Banking
| Source Type | Bank Name |
|---|---|
mobile_banking_ocbc | OCBC Bank |
Internet Banking
| Source Type | Region | Banks |
|---|---|---|
internet_banking_th | Thailand | All major Thai banks |
fpx | Malaysia | 20+ Malaysian banks |
Direct Debit
| Source Type | Region | Description |
|---|---|---|
pay_with_bill_payment | Thailand | Online Direct Debit |
Choosing the Right Method
By Country
Thailand
- Primary: Mobile Banking (SCB, Kasikornbank)
- Alternative: Internet Banking
- Recurring: Direct Debit
Malaysia
- Primary: FPX (Internet Banking)
- Use case: All e-commerce
Singapore
- Primary: OCBC Mobile Banking
- Alternative: PayNow (QR)
By Use Case
One-time Payments
- Mobile Banking (best UX)
- Internet Banking (wider reach)
Recurring Payments
- Direct Debit only
- Requires customer authorization
Large Transactions
- Bank transfers (higher limits than cards)
- Direct Debit (pre-authorized)
Comparison Matrix
| Feature | Mobile Banking | Internet Banking | Direct Debit |
|---|---|---|---|
| Platform | Mobile only | Desktop/mobile | Any |
| Speed | Fast | Moderate | Fast |
| Refunds | ✅ Yes | ❌ No | ✅ Yes |
| Limits | High | High | Very high |
| Recurring | ❌ No | ❌ No | ✅ Yes |
| Setup | None | None | Required |
| Completion | 30-90 sec | 2-5 min | Instant |
Implementation Patterns
Multi-Bank Selector
// Display available banks
const THAI_BANKS = [
{ code: 'scb', name: 'SCB', type: 'mobile_banking_scb', logo: '/banks/scb.svg' },
{ code: 'kbank', name: 'Kasikornbank', type: 'mobile_banking_kbank', logo: '/banks/kbank.svg' },
{ code: 'bbl', name: 'Bangkok Bank', type: 'mobile_banking_bbl', logo: '/banks/bbl.svg' },
{ code: 'bay', name: 'Krungsri', type: 'mobile_banking_bay', logo: '/banks/bay.svg' },
{ code: 'ktb', name: 'Krungthai', type: 'mobile_banking_ktb', logo: '/banks/ktb.svg' }
];
// Create payment with selected bank
async function createBankPayment(bankType, amount, currency) {
const source = await omise.sources.create({
type: bankType,
amount: amount,
currency: currency
});
const charge = await omise.charges.create({
amount: amount,
currency: currency,
source: source.id,
return_uri: `${baseUrl}/payment/callback`
});
return charge.authorize_uri;
}
Mobile Detection
function isMobileBankingAvailable() {
// Mobile banking requires mobile device
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
}
// Show appropriate options
if (isMobileBankingAvailable()) {
showMobileBankingOptions();
} else {
showInternetBankingOptions();
}
Bank Logo Display
<div class="bank-selector">
<h3>เลือกธนาคาร (Select Bank)</h3>
<div class="bank-grid">
<button class="bank-option" data-type="mobile_banking_scb">
<img src="/banks/scb.svg" alt="SCB">
<span>SCB</span>
</button>
<button class="bank-option" data-type="mobile_banking_kbank">
<img src="/banks/kbank.svg" alt="Kasikornbank">
<span>Kasikornbank</span>
</button>
<!-- More banks -->
</div>
</div>
Best Practices
1. Mobile-First for Modern Experience
// Detect device and show appropriate method
if (isMobile()) {
showMobileBankingOptions();
} else {
showInternetBankingOptions();
showMobileQROption(); // Fallback for desktop
}
2. Display Bank Logos
Use official bank logos to build trust and recognition:
<img src="/banks/scb-logo.svg" alt="SCB Bank" class="bank-logo">
3. Show Clear Instructions
<div class="payment-instructions">
<h4>วิธีชำระเงิน (How to Pay):</h4>
<ol>
<li>เลือกธนาคารของคุณ</li>
<li>แอพธนาคารจะเปิดขึ้นอัตโนมัติ</li>
<li>ยืนยันการชำระเงินในแอพ</li>
<li>รอการยืนยันทันที</li>
</ol>
</div>
4. Handle Timeouts
// Mobile banking expires quickly
const TIMEOUT = 10 * 60 * 1000; // 10 minutes
setTimeout(() => {
if (!paymentCompleted) {
showMessage('Payment expired. Please try again.');
enableRetry();
}
}, TIMEOUT);
5. Always Use Webhooks
// Webhook is primary notification
app.post('/webhooks/omise', handleWebhook);
// Callback is for user experience only
app.get('/payment/callback', handleCallback);
Common Issues & Troubleshooting
Issue: App Not Opening
Solution:
// Check if banking app is installed
setTimeout(() => {
if (!document.hidden) {
showMessage('Banking app not opening? Try these:');
showAlternatives([
'Update your banking app',
'Try internet banking instead',
'Use QR payment'
]);
}
}, 3000);
Issue: Payment Timeout
Solution: Set reasonable timeout and show clear message:
if (charge.status === 'expired') {
showMessage('Payment expired. Please start a new transaction.');
}
Issue: Wrong Bank Account
Solution: Allow customers to verify before confirming:
<div class="verification">
<p>Paying from: <strong>SCB Account ***1234</strong></p>
<button>Change Bank</button>
</div>
FAQ
What's the difference between mobile banking and internet banking?
Mobile Banking: Uses the bank's mobile app with deep linking. Faster, modern UX, supports refunds. Recommended for new integrations.
Internet Banking: Redirects to bank's website. Desktop-friendly, wider bank support, but no refunds. Legacy method.
Which payment method should I use?
- Thailand: Mobile Banking (SCB, Kasikornbank) or Internet Banking for wider reach
- Malaysia: FPX Internet Banking (only option)
- Singapore: OCBC Mobile Banking or PayNow
Do bank transfers support refunds?
- Mobile Banking: ✅ Yes, full and partial refunds
- Internet Banking: ❌ No refunds supported
- Direct Debit: ✅ Yes, refunds supported
How long does settlement take?
Most bank transfer payments settle within 1-3 business days. Check your Omise dashboard for specific settlement schedules.
Can I accept recurring payments?
Only Direct Debit supports recurring payments. Mobile and Internet Banking are for one-time payments only.
What are the transaction limits?
Limits vary by bank and customer account type, but generally:
- Minimum: ฿1 (THB), RM1 (MYR), $1 (SGD)
- Maximum: ฿2,000,000+ per transaction
Much higher than card limits.
Related Resources
- Payment Methods Overview - All available methods
- Digital Wallets - Alternative mobile payments
- QR Payments - PromptPay, PayNow, DuitNow
- Accept Payments - Implementation guide
- Webhooks - Handle notifications
- Testing - Test bank transfers
Next Steps
- Choose your market - Thailand, Malaysia, or Singapore
- Pick payment type - Mobile banking, internet banking, or direct debit
- Implement integration - Follow bank-specific guides
- Test thoroughly - Test with each supported bank
- Go live - Enable for production
Ready to start? Choose your bank:
Thailand:
Malaysia:
Singapore: