Recurring PaymentsและSubscriptions
ใช้งาน subscription billing, recurring paymentsและ scheduled chargesอัตโนมัติด้วยบัตรที่บันทึกไว้โดยใช้ Customers APIและSchedulesของ Omise
ภาพรวม
Recurring paymentsช่วยให้คุณเรียกเก็บเงินจากลูกค้าโด ยอัตโนมัติตามกำหนดเวลาปกติสำหรับ subscriptions, memberships, ผลิตภัณฑ์ SaaSหรือบริการที่มีการเรียกเก็บเงินซ้ำ Omiseมีสองวิธีการ: recurring chargesแบบ manualโดยใช้ Customers APIหรือ recurring chargesแบบอัตโนมัติโดยใช้ Schedules
คุณสมบัติหลัก:
- ✅ บัตรที่บันทึกไว้ - เก็บวิธีการชำระเงินของลูกค้าอย่างปลอดภัย
- ✅ Schedulesที่ยืดหยุ่น - รายวัน รายสัปดาห์ รายเดือน รายปี
- ✅ การเรียกเก็บเงินอัตโนมัติ - การจัดการ subscriptionแบบตั้งค่าแล้วทิ้งไว้
- ✅ การควบคุมแบบ manual - เรียกเก็บเงินลูกค้าด้วยโปรแกรม
- ✅ ตรรกะการลองใหม่ - ลองชำระเงินที่ล้มเหลวอีกครั้งโดยอัตโนมัติ
- ✅ การเรียกเก็บเงินแบบ prorated - การเปลี่ยน subscriptionกลางรอบ
- ✅ หลายบัตร - ลูกค้าสามารถบันทึกวิธีการชำระเงินหลายวิธี
การเปรียบเทียบวิธีการ
| คุณสมบัติ | Customers API (Manual) | Schedules (อัตโนมัติ) |
|---|---|---|
| การควบคุม | ควบคุมเต็มรูปแบบ | อัตโนมัติ |
| ความยืดหยุ่น | ยืดหยุ่นมาก | Schedulesคงที่ |
| ตรรกะการลองใหม่ | คุณต้องใช้งาน | มีในตัว |
| ความซับซ้อน | โค้ดมากขึ้น | โค้ดน้อยลง |
| กรณีการใช้งาน | การเรียกเก็บเงินแบบกำหนดเอง | Subscriptionsมาตรฐาน |
| การคำนวณ Proration | คุณคำนวณ | คุณต้องใช้งาน |
| เหมาะที่สุดสำหรับ | กฎการเรียกเก็บเงินที่ซับซ้อน | Recurring chargesแบบง่าย |
วิธีการทำงาน
วิธี Customers API
วิธี Schedules
Customers API (Manual Recurring)
ขั้นตอนที่ 1: สร้าง Customerพร้อมบัตร
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
// สร้าง customerพร้อมบัตรเริ่มต้น
const customer = await omise.customers.create({
email: 'user@example.com',
description: 'John Doe - Premium Plan',
card: tokenId, // จาก Omise.jsหรือ mobile SDK
metadata: {
plan: 'premium',
billing_cycle: 'monthly',
signup_date: new Date().toISOString()
}
});
console.log('ลูกค้า ID:', customer.id);
console.log('Default card:', customer.default_card);
ขั้นตอนที่ 2: บันทึก ลูกค้า ID
// บันทึกในฐานข้อมูลของคุณ
await db.users.update({
user_id: userId,
omise_customer_id: customer.id,
subscription_status: 'active',
subscription_plan: 'premium',
next_billing_date: calculateNextBillingDate(),
amount: 29900 // ฿299.00
});
ขั้นตอนที่ 3: เรียกเก็บเงิน Customerแบบ Recurring
// งา นที่กำหนดเวลา (ทำงานทุกวัน)
async function processRecurringBilling() {
const today = new Date().toDateString();
// ค้นหาลูกค้าที่ครบกำหนดชำระเงิน
const dueCustomers = await db.users.find({
subscription_status: 'active',
next_billing_date: today
});
for (const user of dueCustomers) {
try {
// เรียกเก็บเงินจากบัตรที่บันทึกไว้ของลูกค้า
const charge = await omise.charges.create({
amount: user.amount,
currency: 'THB',
customer: user.omise_customer_id,
description: `Subscription renewal - ${user.subscription_plan}`,
metadata: {
user_id: user.user_id,
plan: user.subscription_plan,
billing_period: today
}
});
if (charge.status === 'successful') {
// อัปเดต subscription
await extendSubscription(user.user_id);
await sendReceiptEmail(user.email, charge);
console.log(`✓ Charged ${user.email}: ${charge.amount / 100}`);
} else {
// จัดการความล้มเหลว
await handleFailedPayment(user, charge);
}
} catch (error) {
console.error(`✗ Failed to charge ${user.email}:`, error.message);
await handlePaymentError(user, error);
}
}
}
// กำหนดเวลาให้ทำงานทุกวัน
// ใช้ node-cronหรือ schedulerของคุณ
cron.schedule('0 0 * * *', processRecurringBilling);
ขั้นตอนที่ 4: จัดการการชำระเงินที่ล้มเหลว
async function handleFailedPayment(user, charge) {
// เพิ่มจำนวนการลองใหม่
const retryCount = (user.payment_retry_count || 0) + 1;
await db.users.update({
user_id: user.user_id,
payment_retry_count: retryCount,
last_payment_attempt: new Date(),
last_payment_error: charge.failure_message
});
// ตรรกะการลองใหม่
if (retryCount <= 3) {
// ลองใหม่หลังจาก 3, 5, 7 วัน
const retryDays = [3, 5, 7][retryCount - 1];
const retryDate = new Date();
retryDate.setDate(retryDate.getDate() + retryDays);
await db.users.update({
user_id: user.user_id,
next_billing_date: retryDate.toDateString()
});
// ส่งอีเมลให้ลูกค้า
await sendPaymentFailedEmail(user.email, {
reason: charge.failure_message,
retryDate: retryDate,
updateCardUrl: `https://yoursite.com/billing/update-card`
});
} else {
// ระงับ subscriptionหลังจากลองใหม่ 3 ครั้ง
await db.users.update({
user_id: user.user_id,
subscription_status: 'suspended',
suspended_at: new Date()
});
await sendSubscriptionSuspendedEmail(user.email);
}
}
ขั้นตอนที่ 5: อัปเดตบัตร
// ลูกค้าอัปเดตบัตรของพวกเขา
app.post('/billing/update-card', async (req, res) => {
const { userId, newTokenId } = req.body;
try {
const user = await db.users.findOne({ user_id: userId });
// อัปเดตบัตรเริ่มต้นของลูกค้า
const customer = await omise.customers.update(user.omise_customer_id, {
card: newTokenId
});
// รีเซ็ตจำนวนการลองใหม่
await db.users.update({
user_id: userId,
payment_retry_count: 0,
subscription_status: 'active'
});
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});