ข้ามไปยังเนื้อหาหลัก

การสร้างการโอนไปยังบัญชีธนาคาร

การโอนช่วยให้คุณสามารถส่งเงินจากยอดคงเหลือบัญชี Omise ไปยังบัญชีธนาคารของผู้รับ คู่มือนี้อธิบายวิธีการสร้างการโอนเดี่ยวและเป็นกลุ่ม การจัดการค่าธรรมเนียม และการติดตามสถานะการโอน

ภาพรวม

Omise Transfers ช่วยให้คุณสามารถ:

  • ส่งเงินเดือน: โอนเงินไปยังผู้รับ
  • กระบวนการอัตโนมัติ: การโอนทันที่หรือตามกำหนดเวลา
  • การจัดการค่าธรรมเนียม: ทำความเข้าใจโครงสร้างค่าธรรมเนียมที่ชัดเจนต่อการโอน
  • การติดตามสถานะ: ตรวจสอบความคืบหน้าของการโอนแบบเรียลไทม์
  • การดำเนินการแบบกลุ่ม: จัดการการโอนหลายรายการอย่างมีประสิทธิภาพ
  • การจัดการความล้มเหลว: จัดการการโอนที่ล้มเหลวอย่างเหมาะสม

ฟีเจอร์หลัก

  • การโอนทันที่: ส่งเงินโดยทันที่ (อยู่ภายใต้การประมวลผลธนาคาร)
  • ความโปร่งใสค่าธรรมเนียม: โครงสร้างค่าธรรมเนียมที่ชัดเจนต่อการโอน
  • ผู้รับหลายคน: ส่งไปยังผู้รับที่สร้างไว้ก่อนหน้านี้
  • การรองรับข้อมูลเมตา: ติดตามข้อมูลโดยเฉพาะ
  • การแจ้งเตือน Webhook: อัปเดตสถานะแบบเรียลไทม์
  • การตรวจสอบยอดคงเหลือ: ตรวจสอบยอดคงเหลือโดยอัตโนมัติ

ข้อกำหนดการโอน

ก่อนสร้างการโอน:

  1. ยอดคงเหลือเพียงพอ: บัญชีของคุณต้องมีเงินทุนเพียงพอ
  2. ผู้รับที่ใช้งาน: ผู้รับต้องได้รับการตรวจสอบและใช้งานได้
  3. จำนวนขั้นต่ำ: ต้องเป็นไปตามข้อกำหนดการโอนขั้นต่ำ
  4. ความคุ้มครองค่าธรรมเนียม: ยอดคงเหลือต้องครอบคลุมจำนวนการโอน + ค่าธรรมเนียม

ค่าธรรมเนียมการโอน

const TRANSFER_FEES = {
thb: {
domestic: 2500, // 25 THB ต่อการโอน
minimum: 2000 // 20 THB การโอนขั้นต่ำ
}
};

function calculateTransferCost(amount) {
return {
amount: amount,
fee: TRANSFER_FEES.thb.domestic,
total: amount + TRANSFER_FEES.thb.domestic
};
}

// ตัวอย่าง
const cost = calculateTransferCost(100000); // 1,000 THB
console.log(`Amount: ${cost.amount / 100} THB`);
console.log(`Fee: ${cost.fee / 100} THB`);
console.log(`Total deducted: ${cost.total / 100} THB`);

การสร้างการโอนผ่าน API

การโอนขั้นพื้นฐาน

const omise = require('omise')({
secretKey: 'skey_test_123456789',
});

// สร้างการโอน
async function createTransfer(recipientId, amount) {
try {
// ตรวจสอบยอดคงเหลือก่อน
const balance = await omise.balance.retrieve();
const totalCost = amount + 2500; // amount + fee

if (balance.available < totalCost) {
throw new Error(`Insufficient balance. Need ${totalCost}, have ${balance.available}`);
}

// สร้างการโอน
const transfer = await omise.transfers.create({
recipient: recipientId,
amount: amount,
metadata: {
purpose: 'vendor_payment',
invoice_id: 'INV-001',
payment_date: new Date().toISOString()
}
});

console.log('Transfer created:', transfer.id);
console.log('Amount:', transfer.amount / 100, 'THB');
console.log('Fee:', transfer.fee / 100, 'THB');
console.log('Status:', transfer.status);

return transfer;
} catch (error) {
console.error('Transfer failed:', error.message);
throw error;
}
}

// สร้างการโอนด้วยการตรวจสอบแบบเต็ม
async function createValidatedTransfer(recipientId, amount, metadata = {}) {
// ตรวจสอบผู้รับ
const recipient = await omise.recipients.retrieve(recipientId);

if (!recipient.active) {
throw new Error('Recipient is not active');
}

if (!recipient.verified) {
throw new Error('Recipient is not verified');
}

// ตรวจสอบจำนวน
if (amount < 2000) { // จำนวนการโอนขั้นต่ำ 20 THB
throw new Error('Amount below minimum transfer amount');
}

// ตรวจสอบยอดคงเหลือ
const balance = await omise.balance.retrieve();
const totalCost = amount + 2500;

if (balance.available < totalCost) {
return {
success: false,
reason: 'insufficient_balance',
available: balance.available,
required: totalCost,
shortfall: totalCost - balance.available
};
}

// สร้างการโอน
const transfer = await omise.transfers.create({
recipient: recipientId,
amount: amount,
metadata: metadata
});

return {
success: true,
transfer: transfer,
recipient_name: recipient.name,
bank: recipient.bank_account.brand
};
}

// ตัวอย่างการใช้งาน
createTransfer('recp_test_123456789', 100000); // 1,000 THB

createValidatedTransfer('recp_test_123456789', 500000, {
payment_type: 'monthly_salary',
employee_id: 'EMP-042',
period: '2024-01'
}).then(result => {
if (result.success) {
console.log(`✓ Transfer ${result.transfer.id} created`);
console.log(` To: ${result.recipient_name}`);
console.log(` Bank: ${result.bank}`);
} else {
console.log(`✗ Transfer failed: ${result.reason}`);
}
});
import omise
from datetime import datetime

omise.api_secret = 'skey_test_123456789'

TRANSFER_FEE = 2500 # 25 THB
MIN_AMOUNT = 2000 # 20 THB

def create_transfer(recipient_id, amount):
"""สร้างการโอนไปยังผู้รับ"""
try:
# ตรวจสอบยอดคงเหลือ
balance = omise.Balance.retrieve()
total_cost = amount + TRANSFER_FEE

if balance.available < total_cost:
raise ValueError(f"Insufficient balance. Need {total_cost}, have {balance.available}")

# สร้างการโอน
transfer = omise.Transfer.create(
recipient=recipient_id,
amount=amount,
metadata={
'purpose': 'vendor_payment',
'invoice_id': 'INV-001',
'payment_date': datetime.now().isoformat()
}
)

print(f"Transfer created: {transfer.id}")
print(f"Amount: {transfer.amount / 100} THB")
print(f"Fee: {transfer.fee / 100} THB")
print(f"Status: {transfer.status}")

return transfer
except omise.errors.BaseError as e:
print(f"Transfer failed: {str(e)}")
raise

def create_validated_transfer(recipient_id, amount, metadata=None):
"""สร้างการโอนด้วยการตรวจสอบแบบเต็ม"""

# ตรวจสอบผู้รับ
recipient = omise.Recipient.retrieve(recipient_id)

if not recipient.active:
raise ValueError('Recipient is not active')

if not recipient.verified:
raise ValueError('Recipient is not verified')

# ตรวจสอบจำนวน
if amount < MIN_AMOUNT:
raise ValueError(f'Amount below minimum transfer amount of {MIN_AMOUNT}')

# ตรวจสอบยอดคงเหลือ
balance = omise.Balance.retrieve()
total_cost = amount + TRANSFER_FEE

if balance.available < total_cost:
return {
'success': False,
'reason': 'insufficient_balance',
'available': balance.available,
'required': total_cost,
'shortfall': total_cost - balance.available
}

# สร้างการโอน
transfer = omise.Transfer.create(
recipient=recipient_id,
amount=amount,
metadata=metadata or {}
)

return {
'success': True,
'transfer': transfer,
'recipient_name': recipient.name,
'bank': recipient.bank_account.brand
}

def calculate_transfer_cost(amount):
"""คำนวณต้นทุนรวมรวมค่าธรรมเนียม"""
return {
'amount': amount,
'fee': TRANSFER_FEE,
'total': amount + TRANSFER_FEE,
'amount_formatted': f"{amount / 100:.2f} THB",
'fee_formatted': f"{TRANSFER_FEE / 100:.2f} THB",
'total_formatted': f"{(amount + TRANSFER_FEE) / 100:.2f} THB"
}

# ตัวอย่างการใช้งาน
create_transfer('recp_test_123456789', 100000)

result = create_validated_transfer('recp_test_123456789', 500000, {
'payment_type': 'monthly_salary',
'employee_id': 'EMP-042',
'period': '2024-01'
})

if result['success']:
print(f"✓ Transfer {result['transfer'].id} created")
print(f" To: {result['recipient_name']}")
print(f" Bank: {result['bank']}")
else:
print(f"✗ Transfer failed: {result['reason']}")

ตอบสนอง API

{
"object": "transfer",
"id": "trsf_test_5xyz789abc",
"livemode": false,
"location": "/transfers/trsf_test_5xyz789abc",
"recipient": "recp_test_123456789",
"bank_account": {
"object": "bank_account",
"brand": "bbl",
"last_digits": "7890",
"name": "John Doe"
},
"sent": true,
"paid": false,
"amount": 100000,
"currency": "thb",
"fee": 2500,
"failure_code": null,
"failure_message": null,
"transaction": "trxn_test_5xyz789abc",
"created": "2024-01-15T10:30:00Z",
"metadata": {
"purpose": "vendor_payment",
"invoice_id": "INV-001"
}
}

การติดตามสถานะการโอน

วงจรชีวิตสถานะ

const TRANSFER_STATUSES = {
'pending': 'Transfer created, waiting to be sent',
'sent': 'Transfer sent to bank, waiting for confirmation',
'paid': 'Transfer completed successfully',
'failed': 'Transfer failed',
'reversed': 'Transfer was reversed'
};

async function trackTransferStatus(transferId) {
const transfer = await omise.transfers.retrieve(transferId);

console.log(`Transfer ${transferId}:`);
console.log(` Status: ${transfer.sent ? 'Sent' : 'Pending'}`);
console.log(` Paid: ${transfer.paid ? 'Yes' : 'No'}`);

if (transfer.failure_code) {
console.log(` Failed: ${transfer.failure_message}`);
}

return {
id: transfer.id,
sent: transfer.sent,
paid: transfer.paid,
failed: !!transfer.failure_code,
status_description: getStatusDescription(transfer)
};
}

function getStatusDescription(transfer) {
if (transfer.failure_code) return 'Failed';
if (transfer.paid) return 'Completed';
if (transfer.sent) return 'Processing';
return 'Pending';
}

ตัวอย่างกรณีการใช้งาน

1. การประมวลผลเงินเดือน

class PayrollProcessor:
def __init__(self):
self.transfer_fee = 2500

def process_payroll(self, employees):
"""ประมวลผลเงินเดือนสำหรับพนักงานหลายคน"""
results = {
'processed': [],
'failed': [],
'total_amount': 0,
'total_fees': 0
}

# ตรวจสอบยอดคงเหลือรวมที่ต้องการ
total_needed = sum(emp['salary'] for emp in employees)
total_fees = len(employees) * self.transfer_fee
grand_total = total_needed + total_fees

balance = omise.Balance.retrieve()
if balance.available < grand_total:
raise ValueError(f"Insufficient balance for payroll. Need {grand_total}, have {balance.available}")

# ประมวลผลพนักงานแต่ละคน
for employee in employees:
try:
transfer = omise.Transfer.create(
recipient=employee['recipient_id'],
amount=employee['salary'],
metadata={
'type': 'payroll',
'employee_id': employee['employee_id'],
'employee_name': employee['name'],
'period': employee['pay_period'],
'department': employee['department']
}
)

results['processed'].append({
'employee_id': employee['employee_id'],
'name': employee['name'],
'transfer_id': transfer.id,
'amount': employee['salary'],
'fee': self.transfer_fee
})

results['total_amount'] += employee['salary']
results['total_fees'] += self.transfer_fee

print(f"✓ Processed: {employee['name']} - {employee['salary']/100:.2f} THB")

except Exception as e:
results['failed'].append({
'employee_id': employee['employee_id'],
'name': employee['name'],
'error': str(e)
})
print(f"✗ Failed: {employee['name']} - {str(e)}")

# สร้างรายงาน
print(f"\n{'='*50}")
print(f"Payroll Summary:")
print(f" Processed: {len(results['processed'])}")
print(f" Failed: {len(results['failed'])}")
print(f" Total Amount: {results['total_amount']/100:.2f} THB")
print(f" Total Fees: {results['total_fees']/100:.2f} THB")
print(f" Grand Total: {(results['total_amount'] + results['total_fees'])/100:.2f} THB")

return results

# ตัวอย่างการใช้งาน
processor = PayrollProcessor()
employees = [
{
'employee_id': 'EMP-001',
'name': 'John Doe',
'recipient_id': 'recp_test_111',
'salary': 5000000, # 50,000 THB
'department': 'Engineering',
'pay_period': '2024-01'
},
{
'employee_id': 'EMP-002',
'name': 'Jane Smith',
'recipient_id': 'recp_test_222',
'salary': 4500000, # 45,000 THB
'department': 'Marketing',
'pay_period': '2024-01'
}
]

payroll_results = processor.process_payroll(employees)

วิธีปฏิบัติที่ดีที่สุด

1. ตรวจสอบเสมอก่อนโอน

async function safeTransfer(recipientId, amount, metadata) {
// รายการตรวจสอบการตรวจสอบก่อนการโอน
const validations = [];

// 1. ตรวจสอบผู้รับ
try {
const recipient = await omise.recipients.retrieve(recipientId);
if (!recipient.active) validations.push('Recipient not active');
if (!recipient.verified) validations.push('Recipient not verified');
} catch (error) {
validations.push('Recipient not found');
}

// 2. ตรวจสอบจำนวน
if (amount < 2000) validations.push('Amount below minimum');
if (amount % 1 !== 0) validations.push('Amount must be integer');

// 3. ตรวจสอบยอดคงเหลือ
const balance = await omise.balance.retrieve();
const totalCost = amount + 2500;
if (balance.available < totalCost) {
validations.push(`Insufficient balance: need ${totalCost}, have ${balance.available}`);
}

// 4. ตรวจสอบข้อมูลเมตา
if (metadata && typeof metadata !== 'object') {
validations.push('Metadata must be an object');
}

if (validations.length > 0) {
throw new Error(`Validation failed:\n- ${validations.join('\n- ')}`);
}

// ผ่านการตรวจสอบทั้งหมดแล้ว สร้างการโอน
return await omise.transfers.create({
recipient: recipientId,
amount: amount,
metadata: metadata
});
}

2. ใช้ตรรมชาติการลองใหม่

def create_transfer_with_retry(recipient_id, amount, max_retries=3, metadata=None):
"""สร้างการโอนด้วยตรรมชาติการลองใหม่สำหรับข้อผิดพลาดชั่วคราว"""

for attempt in range(max_retries):
try:
transfer = omise.Transfer.create(
recipient=recipient_id,
amount=amount,
metadata=metadata or {}
)
return transfer

except omise.errors.InvalidRequestError as e:
# ข้อผิดพลาดการตรวจสอบ อย่าลองใหม่
raise

except omise.errors.APIError as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt # การถ่อนความเสี่ยงแบบเลขชี้กำลัง
print(f"Attempt {attempt + 1} failed, retrying in {wait_time}s...")
time.sleep(wait_time)
else:
raise

return None

3. ตรวจสอบและบันทึกการโอน

class TransferLogger
def self.log_transfer(transfer, context = {})
log_entry = {
event: 'transfer_created',
transfer_id: transfer.id,
recipient: transfer.recipient,
amount: transfer.amount,
fee: transfer.fee,
status: transfer.sent ? 'sent' : 'pending',
created_by: context[:user_id],
timestamp: Time.now.iso8601,
metadata: transfer.metadata
}

# บันทึกลงไฟล์บันทึก
File.open('transfers.log', 'a') do |f|
f.puts JSON.generate(log_entry)
end

# บันทึกไปยังฐานข้อมูลเพื่อการรายงาน
save_to_database(log_entry)
end

def self.save_to_database(entry)
# การใช้งานบันทึกฐานข้อมูล
end
end

คำถามที่พบบ่อย

การโอนใช้เวลานานเท่าไหร่?

การโอนโดยปกติเสร็จสิ้นภายในวันธุรกิจ 1-2 วัน เวลาที่แน่นอนขึ้นอยู่กับธนาคารของผู้รับและเวลาที่การโอนเริ่มขึ้น การโอนที่สร้างในช่วงสุดสัปดาห์หรือวันหยุดอาจใช้เวลานานขึ้น

จะเกิดอะไรขึ้นหากการโอนล้มเหลว?

หากการโอนล้มเหลว วัตถุการโอนจะแสดง "failure_code" และ "failure_message" สาเหตุทั่วไปคือรายละเอียดบัญชีที่ไม่ถูกต้องหรือปัญหาของบัญชีผู้รับ จำนวนจะถูกคืนไปยังยอดคงเหลือของคุณโดยอัตโนมัติ

ฉันสามารถยกเลิกการโอนได้หลังจากสร้างแล้วหรือไม่?

ไม่ คุณไม่สามารถยกเลิกการโอนหลังจากสร้างแล้ว หากคุณต้องการดึงเงินคืน คุณจะต้องขอให้ผู้รับส่งเงินคืน

หากการโอนล้มเหลว ค่าธรรมเนียมการโอนจะถูกคืนเงินหรือไม่?

ใช่ หากการโอนล้มเหลว ทั้งจำนวนการโอนและค่าธรรมเนียมจะถูกคืนไปยังยอดคงเหลือที่พร้อมใช้งาน

ฉันสามารถโอนไปยังบัญชีธนาคารระหว่างประเทศได้หรือไม่?

ปัจจุบัน Omise รองรับการโอนไปยังบัญชีธนาคารไทยเท่านั้น สำหรับการส่งเงินระหว่างประเทศ คุณจะต้องใช้วิธีอื่น

จำนวนการโอนสูงสุดคือเท่าไหร่?

ไม่มีจำนวนการโอนสูงสุดที่กำหนดโดย Omise แต่ยอดคงเหลือบัญชีของคุณและข้อจำกัดธนาคารแต่ละแห่งอาจใช้ได้ การโอนจำนวนมากอาจต้องการการยืนยันเพิ่มเติม

ฉันจะรู้ได้อย่างไรว่าการโอนเสร็จสมบูรณ์?

คุณสามารถติดตามสถานะการโอนผ่าน API หรือตั้งค่า Webhook เพื่อรับการแจ้งเตือนเมื่อการโอนส่ง (transfer.send) หรือเสร็จสิ้น (transfer.pay)

ฉันสามารถตั้งกำหนดการโอนสำหรับวันที่ในอนาคตได้หรือไม่?

ใช่ คุณสามารถใช้ ตารางเวลาการโอน เพื่อตั้งกำหนดการโอนเป็นระยะ ๆ หรือตั้งกำหนดสำหรับวันที่เฉพาะเจาะจง

ทรัพยากรที่เกี่ยวข้อง

ขั้นตอนถัดไป