Card Installments
Allow customers to split card payments into interest-free or low-interest monthly installments with major banks in Thailand and Japan.
Overview
Card installments let customers pay for purchases in monthly installments directly through their credit card issuer. This is a popular payment method in Thailand and Japan for larger purchases, providing customers with flexible payment options while merchants receive the full payment amount upfront.
Key Features:
- ✅ Interest-free options - Many banks offer 0% interest plans
- ✅ Major banks - Supported by leading Thai and Japanese banks
- ✅ Flexible terms - 3, 4, 6, 9, 10, 12+ months
- ✅ Merchant funded - Merchant receives full amount upfront (minus fees)
- ✅ Customer convenience - Payments managed through bank
- ✅ White-label ready - Embed installment form in your checkout
Contact support@omise.co to enable installment payments for your merchant account. Separate approvals may be required for each bank.
Supported Regions
| Region | Currency | Min Amount | Max Amount | API Version |
|---|---|---|---|---|
| Thailand | THB | ฿3,000 | ฿2,000,000 | 2017-11-02 |
| Japan | JPY | ¥10,000 | ¥10,000,000 | 2017-11-02 |
Supported Banks
Thailand
| Bank | Code | 3M | 4M | 6M | 9M | 10M | 12M |
|---|---|---|---|---|---|---|---|
| Kasikornbank (K-Bank) | kbank | ✅ | ✅ | ✅ | ✅ | ✅ | - |
| Bangkok Bank (BBL) | bbl | ✅ | ✅ | ✅ | ✅ | ✅ | - |
| Siam Commercial Bank (SCB) | scb | ✅ | - | ✅ | ✅ | ✅ | - |
| Krungthai Bank (KTB) | ktc | ✅ | ✅ | ✅ | ✅ | - | - |
| Krungsri (Bank of Ayudhya) | bay | ✅ | ✅ | ✅ | - | ✅ | - |
| CIMB Thai | first_choice | ✅ | ✅ | ✅ | ✅ | - | ✅ |
| Citibank | citi | ✅ | ✅ | ✅ | ✅ | - | ✅ |
| TTB (TMB Thanachart) | ttb | ✅ | ✅ | ✅ | ✅ | ✅ | - |
| UOB Thailand | uob | ✅ | ✅ | ✅ | ✅ | ✅ | - |
Japan
| Bank/Provider | Code | 3M | 6M | 10M | 12M | 15M | 18M | 20M | 24M |
|---|---|---|---|---|---|---|---|---|---|
| Major Credit Cards | installment_mcc | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
How It Works
Payment Flow:
- Customer selects installment payment at checkout
- Customer chooses their bank and preferred term (3, 6, 9, 10 months, etc.)
- Customer enters credit card details
- Card is tokenized securely via Omise.js
- Merchant creates charge with
installment_termsparameter - Bank verifies and approves installment plan
- Merchant receives full payment (minus installment fee)
- Customer pays monthly installments to their bank
Typical completion time: 1-2 minutes
Implementation
Step 1: Display Bank & Term Selection
<div class="installment-selection">
<h3>เลือกผ่อนชำระ</h3>
<label for="bank">ธนาคาร:</label>
<select id="installment-bank" name="bank">
<option value="">-- เลือกธนาคาร --</option>
<option value="kbank">กสิกรไทย (K-Bank)</option>
<option value="bbl">กรุงเทพ (BBL)</option>
<option value="scb">ไทยพาณิชย์ (SCB)</option>
<option value="ktc">กรุงไทย (KTC)</option>
<option value="bay">กรุงศรี (BAY)</option>
<option value="first_choice">CIMB Thai</option>
<option value="citi">Citibank</option>
<option value="ttb">ทีทีบี (TTB)</option>
<option value="uob">UOB</option>
</select>
<label for="terms">จำนวนงวด:</label>
<select id="installment-terms" name="terms">
<option value="3">3 เดือน</option>
<option value="4">4 เดือน</option>
<option value="6">6 เดือน</option>
<option value="9">9 เดือน</option>
<option value="10">10 เดือน</option>
</select>
<div class="monthly-payment">
<p>ยอดชำระต่อเดือน: <strong id="monthly-amount">฿0.00</strong></p>
</div>
</div>
<script>
// Calculate monthly payment
function calculateMonthly(total, terms) {
return (total / terms).toFixed(2);
}
document.getElementById('installment-terms').addEventListener('change', function() {
const total = 30000; // Order total
const terms = parseInt(this.value);
document.getElementById('monthly-amount').textContent =
'฿' + calculateMonthly(total, terms);
});
</script>
Step 2: Create Token with Omise.js
- Omise.js
Omise.setPublicKey('pkey_test_YOUR_PUBLIC_KEY');
// Tokenize card
Omise.createToken('card', {
name: document.getElementById('card-name').value,
number: document.getElementById('card-number').value,
expiration_month: document.getElementById('card-exp-month').value,
expiration_year: document.getElementById('card-exp-year').value,
security_code: document.getElementById('card-cvc').value
}, function(statusCode, response) {
if (statusCode === 200) {
// Send token to server
submitToServer(response.id);
} else {
console.error('Token error:', response.message);
}
});
Step 3: Create Charge with Installment Terms
- cURL
- Node.js
- PHP
- Python
curl https://api.omise.co/charges \
-u $OMISE_SECRET_KEY: \
-d "amount=3000000" \
-d "currency=THB" \
-d "card=tokn_test_xxx" \
-d "installment_terms=6"
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
const charge = await omise.charges.create({
amount: 3000000, // ฿30,000.00
currency: 'THB',
card: 'tokn_test_xxx',
installment_terms: 6, // 6-month installment
metadata: {
order_id: 'ORD-12345'
}
});
console.log('Charge status:', charge.status);
console.log('Installment terms:', charge.installment_terms);
<?php
$charge = OmiseCharge::create([
'amount' => 3000000,
'currency' => 'THB',
'card' => 'tokn_test_xxx',
'installment_terms' => 6,
'metadata' => [
'order_id' => 'ORD-12345'
]
]);
echo 'Charge status: ' . $charge['status'];
?>
import omise
omise.api_secret = 'skey_test_YOUR_SECRET_KEY'
charge = omise.Charge.create(
amount=3000000, # ฿30,000.00
currency='THB',
card='tokn_test_xxx',
installment_terms=6,
metadata={
'order_id': 'ORD-12345'
}
)
print('Charge status:', charge.status)
Step 4: Handle Webhook
app.post('/webhooks/omise', (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.status === 'successful') {
// Payment successful
fulfillOrder(charge.metadata.order_id);
console.log(`Installment payment successful: ${charge.id}`);
console.log(`Terms: ${charge.installment_terms} months`);
} else if (charge.status === 'failed') {
// Payment failed
handleFailedPayment(charge);
console.log(`Installment payment failed: ${charge.failure_code}`);
}
}
res.status(200).send('OK');
});
White-Label Installments
Omise supports white-label installment payments, allowing you to embed a fully customizable installment form directly in your checkout page without redirecting customers to a bank page.
White-Label Benefits
- Seamless checkout - Customer stays on your site
- Customizable UI - Match your brand design
- Better conversion - Reduce cart abandonment
- Unified experience - Same flow as regular card payments
White-Label Implementation
// Create installment charge with white-label
const charge = await omise.charges.create({
amount: 3000000,
currency: 'THB',
card: 'tokn_test_xxx',
installment_terms: 6,
// White-label specific: no redirect needed
return_uri: 'https://yourdomain.com/payment/complete'
});
// Handle response
if (charge.status === 'successful') {
// Direct success - no redirect needed
showSuccess();
} else if (charge.authorize_uri) {
// OTP required - redirect to bank
window.location.href = charge.authorize_uri;
}
Charge Status Values
| Status | Description |
|---|---|
pending | Awaiting bank authorization or OTP |
successful | Installment approved and charged |
failed | Installment declined by bank |
Failure Codes
| Code | Description |
|---|---|
insufficient_fund | Card doesn't have enough credit limit |
invalid_card_token | Card token expired or invalid |
stolen_or_lost_card | Card reported stolen or lost |
failed_processing | Bank processing error |
invalid_account_number | Card number invalid |
installment_not_allowed | Card not eligible for installments |
Refunds
Installment charges can be partially or fully refunded:
// Full or partial refund
const refund = await omise.charges.refund('chrg_test_xxx', {
amount: 1500000 // Partial refund of ฿15,000
});
Refunds for installment payments may take longer to process as the bank needs to recalculate the installment schedule. The customer's bank will handle the adjustment of remaining installments.
Interest Rates
Interest rates vary by bank and promotion:
| Type | Description | Merchant Fee |
|---|---|---|
| 0% Interest | Bank promotional rate | Higher MDR (typically 3-5%) |
| Low Interest | Reduced customer interest | Lower MDR |
| Standard | Bank's standard rate | Lowest MDR |
Contact your bank or Omise support for current rates and promotions.
Best Practices
1. Show Monthly Payment
// Always show monthly breakdown
function displayInstallmentDetails(amount, terms) {
const monthly = amount / terms;
const interestRate = getInterestRate(bank, terms); // Get from bank
return {
monthly: monthly.toFixed(2),
total: (monthly * terms).toFixed(2),
interest: interestRate
};
}
2. Validate Minimum Amount
// Enforce minimum amounts by bank
const minimumAmounts = {
'kbank': 300000, // ฿3,000
'bbl': 300000,
'scb': 300000,
'ktc': 300000,
'bay': 300000,
'first_choice': 300000,
'citi': 300000,
'ttb': 300000,
'uob': 300000
};
function validateAmount(amount, bank) {
const minimum = minimumAmounts[bank] || 300000;
return amount >= minimum;
}
3. Show Available Terms Per Bank
// Terms vary by bank - show only valid options
const bankTerms = {
'kbank': [3, 4, 6, 9, 10],
'bbl': [3, 4, 6, 9, 10],
'scb': [3, 6, 9, 10],
'ktc': [3, 4, 6, 9],
'bay': [3, 4, 6, 10],
'first_choice': [3, 4, 6, 9, 12],
'citi': [3, 4, 6, 9, 12],
'ttb': [3, 4, 6, 9, 10],
'uob': [3, 4, 6, 9, 10]
};
function getAvailableTerms(bank) {
return bankTerms[bank] || [];
}
Testing
Test Mode
Use test API keys with any valid card number format:
Test Card:
- Number:
4242424242424242 - Expiry: Any future date
- CVC: Any 3 digits
Test Scenarios:
- Amount ≥ ฿3,000 with valid terms: Success
- Amount < ฿3,000: Failure (below minimum)
- Invalid terms for bank: Failure
// Test installment payment
const charge = await omise.charges.create({
amount: 3000000, // ฿30,000
currency: 'THB',
card: 'tokn_test_xxx',
installment_terms: 6
});
console.log('Test charge:', charge.status);
FAQ
What is card installment payment?
Card installment allows customers to split their credit card payment into monthly installments (3, 6, 9, 10+ months) directly through their issuing bank. The merchant receives the full payment upfront, while the customer pays their bank in monthly installments.
Which banks support installments?
Thailand: Kasikornbank (K-Bank), Bangkok Bank (BBL), Siam Commercial Bank (SCB), Krungthai (KTC), Krungsri (BAY), CIMB Thai, Citibank, TTB, and UOB.
Japan: Major credit card issuers supporting installment terms.
What is the minimum amount for installments?
- Thailand: ฿3,000 minimum per transaction
- Japan: ¥10,000 minimum per transaction
Some banks may have higher minimums for specific promotions.
Who pays the interest?
This depends on the promotion and agreement:
- 0% Interest Plans: Merchant absorbs the cost through higher MDR
- Customer-Paid Interest: Customer pays interest to their bank
- Mixed: Interest split between merchant and customer
Contact Omise or your bank for current promotional rates.
Can I refund installment payments?
Yes, both full and partial refunds are supported. The customer's bank will recalculate their remaining installments after the refund is processed.
What is white-label installments?
White-label installments allow you to embed the entire installment payment form directly in your checkout page. Customers enter their card details and select installment terms without being redirected to a bank page, providing a seamless checkout experience.
How do I know which terms are available?
Available terms vary by bank. Use the bank's supported terms list when displaying options to customers. Not all banks support all terms (e.g., SCB doesn't offer 4-month terms).
When do I receive the payment?
You receive the full payment amount (minus fees) in your next settlement, regardless of the installment term chosen by the customer. The bank handles collecting monthly payments from the customer.
Related Resources
- Credit/Debit Cards - Standard card payments
- Atome - Third-party BNPL
- Omise.js - Frontend tokenization
- Webhooks - Handle payment events
- Testing - Test your integration