การสร้าง Refunds
Refunds ช่วยให้คุณคืนเงินให้กับลูกค้าสำหรับธุรกรรมที่ charge สำเร็จแล้ว คู่มือนี้ครอบคลุมวิธีการสร้าง refunds เต็มจำนวนผ่านทั้ง API และ Dashboard
ภาพรวม
Refunds เป็นสิ่งจำเป็นสำหรับการจัดการการคืนสินค้า การยกเลิก ข้อพิพาทของลูกค้า และสถานการณ์อื่นๆ ที่คุ ณต้องการกลับรายการการชำระเงิน เมื่อคุณสร้าง refund:
- จำนวน charge เต็มจำนวนจะถูกคืนให้กับวิธีการชำระเงินของลูกค้า
- เงินทุนมักจะถูกคืนภายใน 5-10 วันทำการ (แตกต่างกันตามผู้ออกบัตร)
- สถานะ refund สามารถติดตามได้ตลอดกระบวนการ
- ค่าธรรมเนียมธุรกรรมเดิมจะไม่ถูกคืนตามค่าเริ่มต้น
- Charge จะยังคงอยู่ในประวัติธุรกรรมของคุณด้วยสถานะ refunded
คุณสมบัติหลัก
- การประมวลผลทันที: Refunds ถูกประมวลผลทันทีผ่าน API
- วิธีการชำระเงินหลายแบบ: รองรับ refunds บัตรและวิธีการชำระเงินทางเลือก
- การติดตามสถานะ: การอัปเดตสถานะ refund แบบเรียลไทม์
- การแจ้งเตือนอัตโนมัติ: การแจ้งเตือนลูกค้า (ถ้ามีการกำหนดค่า)
- รองรับ Metadata: เพิ่ม metadata แบบกำหนดเองเพื่อติดตามเหตุผลของ refund
- Webhook Events: รับการแจ้งเตือนเมื่อสถานะ refund เปลี่ยนแปลง
เมื่อใดควรใช้ Refunds
สถานการณ์ทั่วไปสำหรับการสร้าง refunds:
- การคืนสินค้า: ลูกค้าคืนสินค้า
- การยกเลิกบริการ: ลูกค้ายกเลิกบริการหรือการสมัครสมาชิก
- Charges ซ้ำซ้อน: การ charge ซ้ำโดยไม่ตั้งใจ
- ข้อพิพาทของลูกค้า: แก้ไขข้อร้องเรียนของลูกค้า
- สินค้าที่มีข้อบกพร่อง: รายการที่ไม่ตรงตามมาตรฐานคุณภาพ
- สินค้าหมด: ไม่สามารถดำเนินการตามคำสั่งซื้อได้
- การปรับราคา: แก้ไขข้อผิดพลาดในการเรียกเก็บเงิน
การสร้าง Refunds ผ่าน API
Refund เต็มจำนวน
สร้าง refund เต็มจำนวนโดยไม่ระบุจำนวน:
- Node.js
- Python
- PHP
const omise = require('omise')({
secretKey: 'skey_test_123456789',
});
// Create a full refund
async function createFullRefund() {
try {
const refund = await omise.charges.createRefund('chrg_test_123456789', {
metadata: {
reason: 'Customer requested refund',
order_id: 'ORD-12345',
refund_type: 'product_return'
}
});
console.log('Refund created:', refund.id);
console.log('Amount refunded:', refund.amount);
console.log('Status:', refund.status);
console.log('Created at:', new Date(refund.created * 1000));
return refund;
} catch (error) {
console.error('Refund failed:', error.message);
throw error;
}
}
createFullRefund();
import omise
from datetime import datetime
omise.api_secret = 'skey_test_123456789'
def create_full_refund(charge_id):
"""Create a full refund for a charge"""
try:
refund = omise.Charge.retrieve(charge_id).refund(
metadata={
'reason': 'Customer requested refund',
'order_id': 'ORD-12345',
'refund_type': 'product_return'
}
)
print(f"Refund created: {refund.id}")
print(f"Amount refunded: {refund.amount}")
print(f"Status: {refund.status}")
return refund
except omise.errors.BaseError as e:
print(f"Refund failed: {str(e)}")
raise
create_full_refund('chrg_test_123456789')
<?php
require_once 'vendor/autoload.php';
define('OMISE_SECRET_KEY', 'skey_test_123456789');
function createFullRefund($chargeId) {
try {
$charge = OmiseCharge::retrieve($chargeId);
$refund = $charge->refund([
'metadata' => [
'reason' => 'Customer requested refund',
'order_id' => 'ORD-12345',
'refund_type' => 'product_return'
]
]);
echo "Refund created: {$refund['id']}\n";
echo "Amount refunded: {$refund['amount']}\n";
echo "Status: {$refund['status']}\n";
return $refund;
} catch (Exception $e) {
echo "Refund failed: {$e->getMessage()}\n";
throw $e;
}
}
createFullRefund('chrg_test_123456789');
?>
API Response
การสร้าง refund ที่สำเร็จจะคืนค่า:
{
"object": "refund",
"id": "rfnd_test_5xyz789abc",
"location": "/charges/chrg_test_123456789/refunds/rfnd_test_5xyz789abc",
"amount": 100000,
"currency": "thb",
"charge": "chrg_test_123456789",
"transaction": "trxn_test_5xyz789abc",
"created": "2024-01-15T10:30:00Z",
"status": "pending",
"metadata": {
"reason": "Customer requested refund",
"order_id": "ORD-12345",
"refund_type": "product_return"
}
}
การสร้าง Refunds ผ่าน Dashboard
กระบวนการทีละขั้นตอน
-
ไปที่ธุรกรรม
- ล็อกอินเข้า Omise Dashboard
- ไปที่ "Transactions" > "Charges"
-
ค้นหา Charge
- ใช้แถบค้นหาเพื่อค้นหา charge ID
- หรือกรองตามวันที่ จำนวน หรือสถานะ
- คลิกที่ charge เพื่อดูรายละเอียด
-
เริ่ม Refund
- คลิกปุ่ม "Refund"
- จำนวน charge เต็มจำนวนจะถูกกรอกล่วงหน้า
- คุณสามารถแก้ไขจำนวนสำหรับ refunds บางส่วน
-
เพิ่มรายละเอียด Refund (ไม่บังคับ)
- ป้อนเหตุผลสำหรับ refund
- เพิ่มบันทึกภายใน
- เลือกหมวดหมู่ refund (การคืนสินค้า การยกเลิก ฯลฯ)
-
ยืนยัน Refund
- ตรวจสอบรายละเอียด refund
- คลิก "Confirm Refund"
- Refund จะถูกประมวลผลทันที
-
ติดตามสถานะ
- ดูสถานะ refund บนหน้ารายละเอียด charge
- ตรวจสอบส่วน "Refunds" สำหรับความพยายาม refund ทั้งหมด
- ติดตาม webhook events สำหรับการอัปเดตสถานะ
วงจรชีวิตสถานะ Refund
เข้าใจสถานะ refund:
Pending
- Refund ถูกสร้างและกำลังถูกประมวลผล
- โดยทั่วไปใช้เวลาสองสาม นาที
- ลูกค้ายังไม่ได้รับเงิน
Successful
- Refund เสร็จสมบูรณ์
- เงินทุนถูกส่งไปยังผู้ให้บริการการชำระเงิน
- ลูกค้าควรได้รับเงินภายใน 5-10 วันทำการ
Failed
- Refund ไม่สามารถประมวลผลได้
- เหตุผลทั่วไป: ยอดเงินไม่เพียงพอ บัตรไม่ถูกต้อง บัตรหมดอายุ
- ติดต่อฝ่ายสนับสนุนหากปัญหายังคงอยู่
กรณีการใช้งานทั่วไป
1. ขั้นตอนการคืนสินค้า
async function handleProductReturn(orderId, chargeId) {
// อัปเดตสถานะคำสั่งซื้อ
await updateOrderStatus(orderId, 'return_requested');
// สร้าง refund
const refund = await omise.charges.createRefund(chargeId, {
metadata: {
reason: 'product_return',
order_id: orderId,
return_tracking: 'TRACK123456',
warehouse_received: 'pending'
}
});
// ส่งการแจ้งเตือนลูกค้า
await sendCustomerEmail({
template: 'refund_initiated',
orderId: orderId,
refundId: refund.id,
estimatedDays: '5-10 business days'
});
return refund;
}
2. การยกเลิกบริการ
def handle_subscription_cancellation(subscription_id, charge_id, prorate=True):
"""Handle subscription cancellation with optional proration"""
# คำนวณจำนวน refund ถ้ามีการคำนวณตามสัดส่วน
if prorate:
charge = omise.Charge.retrieve(charge_id)
days_used = calculate_days_used(subscription_id)
days_in_period = 30
refund_amount = int(charge.amount * (days_in_period - days_used) / days_in_period)
else:
refund_amount = None # Full refund
# สร้าง refund
refund = omise.Charge.retrieve(charge_id).refund(
amount=refund_amount,
metadata={
'reason': 'subscription_cancellation',
'subscription_id': subscription_id,
'prorated': prorate
}
)
# ยกเลิกการสมัครสมาชิก
cancel_subscription(subscription_id)
return refund
แนวปฏิบัติที่ดีที่สุด
1. เพิ ่ม Metadata เสมอ
รวมบริบทสำหรับทุก refund:
const refund = await omise.charges.createRefund(chargeId, {
metadata: {
reason: 'customer_request',
category: 'product_return',
requested_by: 'customer_service_rep_42',
ticket_id: 'SUPPORT-12345',
timestamp: new Date().toISOString()
}
});
2. ใช้การจัดการข้อผิดพลาดที่เหมาะสม
def safe_refund(charge_id, reason):
"""สร้าง refund ด้วยการจัดการข้อผิดพลาดที่ครอบคลุม"""
try:
refund = omise.Charge.retrieve(charge_id).refund(
metadata={'reason': reason}
)
return {'success': True, 'refund_id': refund.id}
except omise.errors.InvalidRequestError as e:
return {'success': False, 'error': 'invalid_request', 'message': str(e)}
except omise.errors.AuthenticationError as e:
return {'success': False, 'error': 'authentication', 'message': str(e)}
except omise.errors.BaseError as e:
return {'success': False, 'error': 'api_error', 'message': str(e)}
except Exception as e:
return {'success': False, 'error': 'unknown', 'message': str(e)}
3. ติดตามสถานะ Refund
async function trackRefundStatus(chargeId, refundId) {
const charge = await omise.charges.retrieve(chargeId);
const refund = charge.refunds.data.find(r => r.id === refundId);
switch (refund.status) {
case 'pending':
console.log('Refund กำลังถูกประมวลผล');
break;
case 'successful':
console.log('Refund เสร็จสมบูรณ์เรียบร้อย');
await notifyCustomerRefundComplete(charge.customer);
break;
case 'failed':
console.log(`Refund ล้มเหลว: ${refund.failure_message}`);
await escalateToSupport(refundId);
break;
}
return refund;
}
การจัดการข้อผิดพลาด
ข้อผิดพลาดทั่วไป
Refund แล้ว
// Error: charge_already_refunded
try {
const refund = await omise.charges.createRefund(chargeId);
} catch (error) {
if (error.code === 'charge_already_refunded') {
console.log('Charge นี้ถูก refund แล้ว');
// ตรวจสอบ refunds ที่มีอยู่
const charge = await omise.charges.retrieve(chargeId);
console.log('Existing refunds:', charge.refunds.data);
}
}
ยอดเงินไม่เพียงพอ
try:
refund = omise.Charge.retrieve(charge_id).refund()
except omise.errors.InvalidRequestError as e:
if 'insufficient' in str(e).lower():
print("ยอดเงินไม่เพียงพอในการประมวลผล refund")
notify_finance_team(charge_id)
Webhook Integration
จัดการ refund webhook events:
app.post('/webhooks/omise', async (req, res) => {
const event = req.body;
if (event.key === 'refund.create') {
const refund = event.data;
console.log(`Refund created: ${refund.id}`);
await updateRefundStatus(refund.charge, refund.id, 'pending');
} else if (event.key === 'refund.success') {
const refund = event.data;
console.log(`Refund successful: ${refund.id}`);
await updateOrderStatus(refund.metadata.order_id, 'refunded');
await notifyCustomer(refund.charge, 'refund_complete');
} else if (event.key === 'refund.fail') {
const refund = event.data;
console.log(`Refund failed: ${refund.id}`);
await createSupportTicket({
type: 'refund_failed',
refundId: refund.id,
chargeId: refund.charge
});
}
res.sendStatus(200);
});
การทดสอบ Refunds
Test Mode
ใช้ test API keys เพื่อทดสอบ refund flows:
// ทดสอบการสร้าง refund
const testRefund = await omise.charges.createRefund('chrg_test_123', {
metadata: { test: true }
});
// ตรวจสอบรายละเอียด refund
console.assert(testRefund.status === 'pending');
console.assert(testRefund.amount === testCharge.amount);
FAQ
ฉันสามารถ refund charge ได้ทันทีหลังจากสร้างหรือไม่?
ได้ คุณสามารถ refund charge ได้ทันทีที่มีสถานะ successful อย่างไรก็ตาม ถ้า charge ยังอยู่ในสถานะ pending คุณควรรอให้เสร็จสมบูรณ์ก่อนที่จะเริ่ม refund
ใช้เวลานานแค่ไหนที่ลูกค้าจะได้รับ refunds?
เวลา refund ขึ้นอยู่กับวิธีการชำระเงินและผู้ออกบัตร:
- บัตรเครดิต: โดยทั่วไป 5-10 วันทำการ
- บัตรเดบิต: โดยทั่วไป 5-10 วันทำการ
- วิธีการชำระเงินทางเลือก: แตกต่างกันตามวิธี
Refund ถูกประมวลผลทันทีในฝั่ง Omise แต่เครดิตจริงในบัญชีลูกค้าขึ้นอยู่กับธนาคารหรือผู้ออกบัตร
ค่าธรรมเนียม refund ถูกคืนหรือไม่?
ไม่ ค่าธรรมเนียมธุรกรรมเดิมที่ Omise เรียกเก็บจะไม่ถูก refund คุณจะยังคงถูกเรียกเก็บค่าธรรมเนียมธุรกรรมสำหรับ charge เดิม แม้ว่าคุณจะ refund นี่เป็นแนวปฏิบัติมาตรฐานในผู้ประมวลผลการชำระเงินทั้งหมด
ฉันสามารถ refund ไปยังบัตรอื่นได้หรือไม่?
ไม่ได้ refunds ต้องถูกคืนไปยังวิธีการชำระเงินเดิมที่ใช้สำหรับ charge นี่เป็นข้อกำหนดด้านความปลอดภัยและไม่สามารถหลีกเลี่ยงได้
แหล่งข้อมูลที่เกี่ยวข้อง
- Refunds บางส่วน - สร้าง refunds บางส่วน
- ข้อจำกัดของ Refund - เข้าใจข้อจำกัดและข้อจำกัดของ refund
- ประวัติธุรกรรม - ดูและติดตาม refunds ทั้งหมด
- คู่มือ Webhooks - จัดการ refund events
- การจัดการข้อผิดพลาด - จัดการ refund errors อย่างเหมาะสม
ขั้นตอนถัดไป
- เรียนรู้เกี่ยวกับ refunds บางส่วน
- เข้าใจ ข้อจำกัดของ refund และข้อจำกัด
- ตั้งค่า webhook listeners สำหรับการอัปเดตสถานะ refund
- สำรวจ ประวัติธุรกรรม เพื่อติดตาม refunds
- ตรวจสอบ การกระทบยอด สำหรับการจับคู่ refunds กับการโอนเงิน