DANA
รับชำระเงินจาก DANA กระเป๋าเงินดิจิทัลชั้นนำของอินโดนีเซียที่มีผู้ใช้งานมากกว่า 150 ล้านรายและได้รับการยอมรับอย่างกว้างขวางทั่วหมู่เกาะ
ภาพรวม
DANA เป็นหนึ่งในกระเป๋าเงินดิจิทัลที่ใหญ่ที่สุดและได้รับความนิยมมากที่สุดในอินโดนีเซีย ได้รับการสนับสนุนจาก Ant Group (บริษัทแม่ของ Alipay) ใช้กันอย่างแพร่หลายสำหรับธุรกรรมประจำวันตั้งแต ่การขนส่งและการจัดส่งอาหารไปจนถึงอีคอมเมิร์ซและการชำระบิล
คุณสมบัติหลัก:
- ✅ การเข้าถึงขนาดใหญ่ - ผู้ใช้งานมากกว่า 150 ล้านรายทั่วอินโดนีเซีย
- ✅ การยืนยันที่รวดเร็ว - การตรวจสอบการชำระเงินแบบเรียลไทม์เกือบทันที (โดยทั่วไปภายในไม่กี่วินาที)
- ✅ การยอมรับสูง - ได้รับการยอมรับที่ร้านค้ามากกว่า 10 ล้านแห่ง
- ✅ มือถือเป็นหลัก - ประสบการณ์สมาร์ทโฟนที่ราบรื่น
- ✅ ความยุ่งยากต่ำ - การยืนยันตัวตนที่รวดเร็วด้วย PIN/ชีวมิติ
- ✅ กรณีการใช้งานที่หลากหลาย - อีคอมเมิร์ซ บริการ การขนส่ง
ภูมิภาคที่รองรับ
| Region | Currency | Min Amount | Max Amount | API Version |
|---|---|---|---|---|
| Indonesia | IDR | Rp1,000 | Rp10,000,000 | 2017-11-02 |
ข้อจำกัดบัญชีตามระดับการยืนยัน
| ระดับการยืนยัน | วงเงินยอดคงเหลือ | ต่อธุรกรรม | วงเงินรายเดือน |
|---|---|---|---|
| Basic (โทรศัพท์เท่านั้น) | Rp 2,000,000 | Rp 2,000,000 | Rp 10,000,000 |
| Premium (ยืนยัน ID) | Rp 10,000,000 | Rp 5,000,000 | Rp 30,000,000 |
| Priority (Premium + อัพเกรด) | Rp 100,000,000 | Rp 10,000,000 | ไม่จำกัด |
วิธีการทำงาน
ประสบการณ์ของลูกค้า:
- ลูกค้าเลือก DANA ที่หน้าชำระเงิน
- ถูกเปลี่ยนเส้นทางไปยังหน้าอนุญาต DANA
- แอป DANA เปิดโดยอัตโนมัติ (deep link)
- ลูกค้าตรวจสอบรายละเอียดการชำระเงิน
- ป้อน PIN หรือใช้การยืนยันตัวตนชีวมิติ
- กลับไปยังเว็บไซต์ผู้ค้า
- ได้รับการยืนยันทันที
เวลาในการดำเนินการโดยทั่วไป: 30-90 วินาที
ตัวอย่างขั้นตอนการชำระเงิน
ขั้นตอนการชำระเงินบนมือถือ:

ประสบการณ์แอปมือถือที่ราบรื่น:
- ❶ เลือก DANA - ลูกค้าเลือกกระเป๋าเงิน DANA ที่หน้าชำระเงิน
- ❷ เปลี่ยนเส้นทางไปยัง DANA - Deep link เปิดแอป DANA โดยอัตโนมัติ
- ❸ ตรวจสอบการชำระเงิน - แสดงรายละเอียดธุรกรรม (ผู้ค้ า, จำนวนเงิน, ID คำสั่งซื้อ)
- ❹ ยืนยันตัวตน - ป้อน DANA PIN หรือใช้การยืนยันตัวตนชีวมิติ
- ❺ ยืนยันการชำระเงิน - แตะปุ่มยืนยันเพื่ออนุญาต
- ❻ การชำระเงินเสร็จสมบูรณ์ - หักเงินจากกระเป๋าเงิน DANA กลับไปยังผู้ค้า
ขั้นตอนการชำระเงินบนเดสก์ท็อป:

การสแกน QR code สำหรับผู้ใช้เดสก์ท็อป:
- ❶ เริ่มการชำระเงิน DANA - ลูกค้าเลือก DANA บนเดสก์ท็อป
- ❷ สร้าง QR code - ระบบสร้าง QR การชำระเงิน DANA ที่ไม่ซ้ำกัน
- ❸ แสดง QR - แสดง QR code อย่างเด่นชัดบนหน้าจอ
- ❹ เปิดแอป DANA - ลูกค้าเปิด DANA บนมือถือ
- ❺ สแกน QR - ใช้สแกนเนอร์ QR ในแอปเพื่อจับภาพโค้ด
- ❻ ตรวจสอบและยืนยัน - รายละเอียดการชำระเงินปรากฏขึ้น ยืนยันตัวตนด้ วย PIN
- ❼ สำเร็จ - ประมวลผลการชำระเงิน เดสก์ท็อปแสดงการยืนยัน
การนำไปใช้
ขั้นตอนที่ 1: สร้าง DANA Source
- cURL
- Node.js
- PHP
- Python
- Ruby
- Go
curl https://api.omise.co/sources \
-u skey_test_YOUR_SECRET_KEY: \
-d "type=dana" \
-d "amount=100000" \
-d "currency=IDR"
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
const source = await omise.sources.create({
type: 'dana',
amount: 100000, // Rp 1,000
currency: 'IDR'
});
console.log('DANA source:', source.id);
<?php
$source = OmiseSource::create(array(
'type' => 'dana',
'amount' => 100000,
'currency' => 'IDR'
));
?>
import omise
omise.api_secret = 'skey_test_YOUR_SECRET_KEY'
source = omise.Source.create(
type='dana',
amount=100000,
currency='IDR'
)
require 'omise'
Omise.api_key = 'skey_test_YOUR_SECRET_KEY'
source = Omise::Source.create({
type: 'dana',
amount: 100000,
currency: 'IDR'
})
source, err := client.Sources().Create(&operations.CreateSource{
Type: "dana",
Amount: 100000,
Currency: "IDR",
})
Response:
{
"object": "source",
"id": "src_test_5rt6s9vah5lkvi1rh9c",
"type": "dana",
"flow": "redirect",
"amount": 100000,
"currency": "IDR"
}
ขั้นตอนที่ 2: สร้าง Charge และ Redirect
app.post('/checkout/dana', async (req, res) => {
try {
const { amount, order_id, customer_email } = req.body;
// ตรวจสอบจำนวนเงิน
if (amount < 100000) { // ขั้นต่ำ Rp 1,000
return res.status(400).json({
error: 'Minimum amount is Rp 1,000'
});
}
if (amount > 1000000000) { // สูงสุด Rp 10,000,000
return res.status(400).json({
error: 'Maximum amount is Rp 10,000,000'
});
}
// สร้าง source
const source = await omise.sources.create({
type: 'dana',
amount: amount,
currency: 'IDR'
});
// สร้าง charge
const charge = await omise.charges.create({
amount: amount,
currency: 'IDR',
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id,
customer_email: customer_email,
payment_method: 'dana'
}
});
// Redirect ไปยัง DANA
res.redirect(charge.authorize_uri);
} catch (error) {
console.error('DANA error:', error);
res.status(500).json({ error: error.message });
}
});
ขั้นตอนที่ 3: จัดการ Return Callback
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(`/order-success?order=${charge.metadata.order_id}`);
} else if (charge.status === 'failed') {
res.redirect(`/payment-failed?reason=${charge.failure_message}`);
} else {
res.redirect('/payment-pending');
}
} catch (error) {
res.redirect('/payment-error');
}
});
ขั้นตอนที่ 4: จัดการ Webhook
app.post('/webhooks/omise', async (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.source.type === 'dana') {
if (charge.status === 'successful') {
await fulfillOrder(charge.metadata.order_id);
await sendConfirmationEmail(charge.metadata.customer_email);
} else if (charge.status === 'failed') {
await handleFailedPayment(charge.metadata.order_id);
}
}
}
res.sendStatus(200);
});
ตัวอย่างการนำไปใช้แบบสมบูรณ์
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
const app = express();
app.use(express.json());
// การกำหนดค่า DANA
const DANA_CONFIG = {
currency: 'IDR',
minAmount: 100000, // Rp 1,000
maxAmount: 1000000000, // Rp 10,000,000
displayName: 'DANA',
timeout: 15 * 60 * 1000 // 15 นาที
};
// สร้างการชำระเงิน DANA
app.post('/checkout/dana', async (req, res) => {
try {
const { amount, order_id, customer_email, customer_name } = req.body;
// ตรวจสอบจำนวนเงิน
if (amount < DANA_CONFIG.minAmount) {
return res.status(400).json({
error: `Minimum amount is Rp ${DANA_CONFIG.minAmount / 100}`
});
}
if (amount > DANA_CONFIG.maxAmount) {
return res.status(400).json({
error: `Maximum amount is Rp ${DANA_CONFIG.maxAmount / 100}`
});
}
// สร้าง source
const source = await omise.sources.create({
type: 'dana',
amount: amount,
currency: DANA_CONFIG.currency
});
// สร้าง charge
const charge = await omise.charges.create({
amount: amount,
currency: DANA_CONFIG.currency,
source: source.id,
return_uri: `${process.env.BASE_URL}/payment/callback`,
metadata: {
order_id: order_id,
customer_email: customer_email,
customer_name: customer_name,
payment_method: 'dana'
}
});
// บันทึกสำหรับการติดตาม
console.log(`DANA payment initiated: ${charge.id} for order ${order_id}`);
// ส่งคืน authorization URL
res.json({
authorize_uri: charge.authorize_uri,
charge_id: charge.id
});
} catch (error) {
console.error('DANA error:', error);
res.status(500).json({ error: error.message });
}
});
// Payment callback
app.get('/payment/callback', async (req, res) => {
try {
const charge = await omise.charges.retrieve(req.query.charge_id);
if (charge.status === 'successful') {
res.redirect(`/order-confirmation?order=${charge.metadata.order_id}`);
} else {
res.redirect(`/payment-failed?charge=${req.query.charge_id}`);
}
} catch (error) {
res.redirect('/payment-error');
}
});
// Webhook handler
app.post('/webhooks/omise', async (req, res) => {
const event = req.body;
if (event.key === 'charge.complete' && event.data.source.type === 'dana') {
const charge = event.data;
if (charge.status === 'successful') {
await fulfillOrder(charge.metadata.order_id);
await sendReceipt(charge.metadata.customer_email, charge);
console.log(`DANA payment successful: ${charge.id}`);
} else {
await cancelOrder(charge.metadata.order_id);
console.log(`DANA payment failed: ${charge.id}`);
}
}
res.sendStatus(200);
});
app.listen(3000);
การรองรับการคืนเงิน
DANA รองรับการคืนเงินเต็มจำนวนและบางส่วนภายใน30 วัน:
// คืนเงินเต็มจำนวน
const fullRefund = await omise.charges.refund('chrg_test_...', {
amount: 100000 // จำนวนเงินเต็ม
});
// คืนเงินบางส่วน
const partialRefund = await omise.charges.refund('chrg_test_...', {
amount: 50000 // จำนวนเงินบางส่วน
});
console.log('Refund status:', fullRefund.status);
การคืนเงินจะถูกประมวลผลกลับไปยังกระเป๋าเงิน DANA ของลูกค้าภายใน 3-7 วันทำการ
ปัญหาทั่วไปและการแก้ไขปัญหา
ปัญหา: ลูกค้าไม่มีแอป DANA
สาเหตุ: ลูกค้าเลือก DANA แต่ไม่มีแอปที่ติดตั้ง
วิธีแก้ไข:
// ตรวจจับมือถือและแสดงความต้องการแอป
function checkDANA() {
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (!isMobile) {
alert('DANA is only available on mobile devices. Please use a smartphone.');
return false;
}
// แสดงพร้อมท์การติดตั้งหากจำเป็น
showMessage('DANA app required. Download from:');
showLinks({
android: 'https://play.google.com/store/apps/details?id=id.dana',
ios: 'https://apps.apple.com/id/app/dana-indonesia/id1388056324'
});
return true;
}
ปัญหา: ยอดเงินไม่เพียงพอ
ข้อผิดพลาด: การชำระเงินถูกปฏิเสธ
วิ ธีแก้ไข:
if (charge.failure_code === 'insufficient_balance') {
showMessage('Saldo DANA tidak mencukupi. Silakan top up atau gunakan metode pembayaran lain.');
showAlternativePaymentMethods();
}
ปัญหา: เกินวงเงินบัญชี
ข้อผิดพลาด: เกินวงเงินธุรกรรม
วิธีแก้ไข:
if (charge.failure_code === 'transaction_limit_exceeded') {
showMessage(
'Transaksi melebihi batas akun DANA Anda. ' +
'Tingkatkan verifikasi akun atau gunakan metode pembayaran lain.'
);
}
ปัญหา: หมดเวลาชำระเงิน
สาเหตุ: ลูกค้าไม่ได้ชำระเงินภายใน 15 นาที
วิธีแก้ไข:
const TIMEOUT = 15 * 60 * 1000;
setTimeout(() => {
if (!paymentCompleted) {
showMessage('Waktu pembayaran habis. Silakan coba lagi.');
enableRetry();
}
}, TIMEOUT);
แนวทางปฏิบัติที่ดีที่สุด
1. แสดงเป็นภาษาอินโดนีเซีย
<div class="dana-payment">
<h3>Bayar dengan DANA</h3>
<div class="instructions">
<ol>
<li>Pastikan aplikasi DANA sudah terinstal</li>
<li>Pastikan saldo DANA mencukupi</li>
<li>Anda akan diarahkan ke aplikasi DANA</li>
<li>Masukkan PIN DANA untuk konfirmasi</li>
</ol>
</div>
<p class="help-text">
Belum punya DANA?
<a href="https://dana.id" target="_blank">Download di sini</a>
</p>
</div>
2. การตรวจจับเฉพาะมือถือ
function validateDANAPayment() {
const userAgent = navigator.userAgent;
const isMobile = /Android|iPhone|iPad|iPod/i.test(userAgent);
if (!isMobile) {
return {
valid: false,
message: 'DANA hanya tersedia di perangkat mobile'
};
}
// ตรวจสอบว่าเป็น Android หรือ iOS
const isAndroid = /Android/i.test(userAgent);
const isIOS = /iPhone|iPad|iPod/i.test(userAgent);
return {
valid: true,
platform: isAndroid ? 'android' : (isIOS ? 'ios' : 'unknown')
};
}
3. จัดการ Deep Links
function openDANAApp(authorizeUri) {
// Redirect ไปยัง DANA
window.location = authorizeUri;
// ตรวจสอบว่าแอปเปิด (fallback)
setTimeout(() => {
if (!document.hidden) {
// แอปไม่ได้เปิด
showInstallPrompt();
}
}, 2500);
}
function showInstallPrompt() {
const isAndroid = /Android/i.test(navigator.userAgent);
const downloadUrl = isAndroid
? 'https://play.google.com/store/apps/details?id=id.dana'
: 'https://apps.apple.com/id/app/dana-indonesia/id1388056324';
const message = 'Aplikasi DANA belum terinstal. Download sekarang?';
if (confirm(message)) {
window.location = downloadUrl;
}
}
4. การจัดรูปแบบจำนว นเงิน
function formatIDR(amount) {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(amount / 100);
}
// การใช้งาน
const displayAmount = formatIDR(100000); // "Rp 1.000"
5. ใช้ Webhooks
// Webhook คือแหล่งความจริงหลัก
app.post('/webhooks/omise', handleWebhook);
// Callback คือสำรองสำหรับประสบการณ์ผู้ใช้
app.get('/payment/callback', handleCallback);
การทดสอบ
ข้อมูลรับรองการทดสอบ
ใช้ข้อมูลรับรองโหมดทดสอบ Omise:
- Secret Key:
skey_test_YOUR_SECRET_KEY - Public Key:
pkey_test_YOUR_PUBLIC_KEY
จำนวนเงินทดสอบ
| จำนวนเงิน (IDR) | ผลลัพธ์ที่คาดหวัง |
|---|---|
| 100000 - 999999 | Success |
| 1000000 | Insufficient balance |
| 1000001 | Transaction declined |
ขั้นตอนการทดสอบ
- สร้าง charge ด้วยข้อมูลรับรองการทดสอบ
- ใช้จำนวนเงินทดสอบข้างต้น
- ชำระเงินใน DANA test environment
- ตรวจสอบว่าได้รับ webhook
- ตรวจสอบสถานะ charge
คำถามที่พบบ่อย
DANA คืออะไร?
DANA คือกระเป๋าเงินดิจิทัลชั้นนำของอินโดนีเซียที่มีผู้ใช้งานมากกว่า 150 ล้านราย ได้รับการสนับสนุนจาก Ant Group (บริษัทแม่ของ Alipay) และได้รับการยอมรับอย่างกว้างขวางสำหรับอีคอมเมิร์ซ การขนส่ง และธุรกรรมประจำวัน
ลูกค้าจำเป็นต้องมีบัญชี DANA หรือไม่?
ใช่ ลูกค้าต้องติดตั้งแอปมือถือ DANA และมีบัญชี DANA ที่เปิดใช้งาน แอปฟรีและใช้ได้กับ Android และ iOS
ข้อจำกัดการทำธุรกรรมคืออะไร?
- ขั้นต่ำ: Rp 1,000
- สูงสุด: Rp 10,000,000 ต่อธุรกรรม
ข้อจำกัดยังขึ้นอยู่กับระดับการยืนยันบัญชีของลูกค้า (Basic, Premium, Priority)
การชำระเงินใช้เวลานานเท่าไร?
การชำระเงิน DANA โดยทั่วไปเกิดขึ้นภายใน 1-3 วันทำการ ตรวจสอบแดชบอร์ด Omise ของคุณสำหรับตารางการชำระเงินเฉพาะ
ฉันสามารถคืนเงินการชำระเงิน DANA ได้หรือไม่?
ได้ DANA รองรับการคืนเงินเต็มจำนวนและบางส่วนภายใน 30 วันของธุรกรรมเดิม
จะเกิดอะไรขึ้นหากลูกค้ามียอดเงินไม่เพียงพอ?
การชำระเงินจะถูกปฏิเสธ ลูกค้าสามารถเติมเงินกระเป๋าเงิน DANA ผ่าน:
- การโอนเงินธนาคาร
- ร้านสะดวกซื้อ (Indomaret, Alfamart)
- ตู้ ATM
- วิธีการชำระเงินที่เชื่อมโยงอื่นๆ
ให้ข้อความแสดงข้อผิดพลาดที่ชัดเจนและเสนอวิธีการชำระเงินทางเลือก
DANA ทำงานบนเดสก์ท็อปหรือไม่?
ไม่ DANA ต้องใช้แอปมือถือและเป็นเฉพาะมือถือเท่านั้น ผู้ใช้เดสก์ท็อปควรได้รับแสดงวิธีการชำระเงินทางเลือกเช่นบัตรเครดิตหรือการโอนเงินธนาคาร
ฉันควรแสดงคำแนะนำเป็นภาษาอินโดนีเซียหรือไม่?
ใช่! เนื่องจาก DANA เป็นเฉพาะอินโดนีเซีย ขอแนะนำอย่างยิ่งให้แสดงคำแนะนำการชำระเงินในภาษาบาฮาซาอินโดนีเซียเพื่อประสบการณ์ผู้ใช้ที่ดีขึ้น
การทดสอบ
โหมดทดสอบ
DANA สามารถทดสอบได้โดยใช้ test API keys ของคุณ ในโหมดทดสอบ:
ข้อมูลรับรองการทดสอบ:
- ใช้ test API keys (skey_test_xxx)
- สกุลเงิน: IDR (รูเปียห์อินโดนีเซีย)
- ไม่ต้องมีบัญชี DANA จริงสำหรับการทดสอบ
ขั้นตอนการทดสอบ:
- สร้าง source และ charge ด้วย test API keys
- ลูกค้า redirect ไปยัง test
authorize_uri - หน้า test จำลองการอนุญาต DANA
- ใช้ Actions ของ Omise Dashboard เพื่อทำเครื่องหมาย charge เป็นสำเร็จ/ล้มเหลว
- ตรวจสอบการจัดการ webhook และ return_uri
การนำไปใช้การทดสอบ:
// ทดสอบการชำระเงิน DANA
const source = await omise.sources.create({
type: 'dana',
amount: 10000, // Rp10,000
currency: 'IDR'
});
const charge = await omise.charges.create({
amount: 10000,
currency: 'IDR',
source: source.id,
return_uri: 'https://example.com/callback'
});
console.log('Test authorize URL:', charge.authorize_uri);
สถานการณ์ทดสอบ:
- การชำระเงินสำเร็จ: ตรวจสอบขั้นตอนการทำคำสั่งซื้อให้เสร็จสมบูรณ์
- การชำระเงินล้มเหลว: ทดสอบการจัดการข้อผิดพลาดและการส่งข้อความ
- ข้อจำกัดจำนวนเงิน: ทดสอบจำนวนเงินขั้นต่ำและสูงสุด
- ขั้นตอนมือถือ: ทดสอบการเชื่อมโยงลึกไปยังแอป DANA
- ยอดเงินไม่เพียงพอ: จำลองยอดเงินในกระเป๋าเงินต่ำ
- หมดเวลา: ทดสอบสถานการณ์ก ารชำระเงินที่ถูกละทิ้ง
- การส่ง Webhook: ตรวจสอบการแจ้งเตือน webhook ทั้งหมด
หมายเหตุที่สำคัญ:
- โหมดทดสอบไม่เชื่อมต่อกับเซิร์ฟเวอร์ DANA จริง
- ใช้แดชบอร์ดเพื่อจำลองผลลัพธ์การชำระเงิน
- ทดสอบขั้นตอนแอปมือถืออย่างละเอียด
- ตรวจสอบการจัดการ webhook สำหรับสถานะ charge ทั้งหมด
- ทดสอบการตรวจสอบจำนวนเงินสำหรับ IDR
สำหรับแนวทางการทดสอบที่ครอบคลุม โปรดดูเอกสารการทดสอบ
แหล่งข้อมูลที่เกี่ยวข้อง
- ภาพรวมกระเป๋าเงินดิจิทัล - ตัวเลือกกระเป๋าเงินทั้งหมด
- ShopeePay - กระเป๋าเงินทางเลือกของอินโด นีเซีย
- การชำระเงิน QR - วิธีการชำระเงินตาม QR
- การคืนเงิน - นโยบายการคืนเงิน
- การทดสอบ - ทดสอบการรวม DANA
- Webhooks - นำ webhooks ไปใช้