オンラインダイレクト・デビット(自動引き落とし)
顧客の銀行口座から直接的に自動で引き落とし、定期的に請求が可能です。タイ国内の事前承認された引き落とし権限により、定期購読や自動請求が実現します。
概要
オンラインダイレクト・デビット(自動引き落とし)を利用することで、顧客の銀行口座から定期的に自動で引き落としできます。顧客が一度承認すれば、その後は定期購読、分割払い、又は定期的なサービス料金に対して自動的に口座から引き落とすことができます。
主な機能:
- ✅ 定期支払い - スケジュール通りに自動請求
- ✅ 事前承認 - 顧客が一度だけ承認
- ✅ 高い成功率 - 銀行口座から直接引き落とし
- ✅ 高額制限 - 1取引につき฿5,000,000以上も対応
- ✅ 返金対応 - 全額及び部分的な返金に対応
- ✅ 複数銀行対応 - タイ主要銀行全て対応
ユースケース
おすすめの利用場面:
- 定期購読 - 月額制SaaS、ストリーミングサービス、会員制
- 分割払い - ローン返済、購入プラン
- 公共料金 - 定期的なサービス料金
- 保険料 - 定期的な保険料支払い
- 寄附 - 定期的な寄附金
不適切な利用場面:
- 一度だけの支払い(モバイルまたはインターネットバンキング をご利用ください)
- ゲストチェックアウト(承認設定が必要)
- 即座の支払い(初期設定に時間がかかります)
対応地域
| 地域 | 通貨 | 最小金額 | 最大金額 | 返金可能 |
|---|---|---|---|---|
| タイ | THB | ฿20.00 | ฿5,000,000+ | ✅ はい |
仕組み
初期設定フロー
定期請求フロー
実装
ステップ1:顧客を作成
- Node.js
- PHP
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});
// 顧客を作成
const customer = await omise.customers.create({
email: 'customer@example.com',
description: '定期購読用顧客',
metadata: {
user_id: '12345'
}
});
console.log('顧客を作成:', customer.id);
<?php
$customer = OmiseCustomer::create(array(
'email' => 'customer@example.com',
'description' => '定期購読用顧客'
));
?>
ステップ2:ダイレクト・デビットソースを作成
// ダイレクト・デビットソースを作成(顧客認証が必要)
const source = await omise.sources.create({
type: 'pay_with_bill_payment',
amount: 50000, // 初期承認金額
currency: 'THB',
customer: customer.id
});
// 顧客を承認ページへリダイレクト
res.redirect(source.authorize_uri);
ステップ3:認可コールバックを処理
app.get('/debit/callback', async (req, res) => {
const sourceId = req.query.source_id;
const source = await omise.sources.retrieve(sourceId);
if (source.flow_status === 'successful') {
// ソースが認可され、請求可能
// 顧客にアタッチ(未設定の場合)
await omise.customers.update(customer.id, {
default_source: source.id
});
res.redirect('/subscription-success');
} else {
res.redirect('/authorization-failed');
}
});
ステップ4:定期請求を作成
// 定期的に顧客に請求
async function chargeSubscription(customerId, amount) {
try {
const charge = await omise.charges.create({
customer: customerId,
amount: amount,
currency: 'THB',
description: '月額定期購読',
metadata: {
billing_period: '2024-02',
subscription_id: 'sub_12345'
}
});
return charge;
} catch (error) {
console.error('請求失敗:', error);
// 失敗を処理(再試行、顧客通知など)
}
}
// 定期請求のスケジュール設定
setInterval(async () => {
const subscriptions = await getActiveSubscriptions();
for (const sub of subscriptions) {
if (sub.next_billing_date === today()) {
await chargeSubscription(sub.customer_id, sub.amount);
}
}
}, 24 * 60 * 60 * 1000); // 毎日確認
完全な実装例
const express = require('express');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
const app = express();
app.use(express.json());
// ステップ1:顧客を登録
app.post('/subscribe', async (req, res) => {
try {
const { email, plan_id, amount } = req.body;
// 顧客を作成
const customer = await omise.customers.create({
email: email,
description: `定期購読: ${plan_id}`
});
// ダイレクト・デビットソースを作成
const source = await omise.sources.create({
type: 'pay_with_bill_payment',
amount: amount,
currency: 'THB',
customer: customer.id
});
// データベースに定期購読を保存
await saveSubscription({
customer_id: customer.id,
source_id: source.id,
plan_id: plan_id,
amount: amount,
status: 'pending_authorization'
});
// 銀行認可ページへリダイレクト
res.json({
authorize_uri: source.authorize_uri,
customer_id: customer.id
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// ステップ2:認可コールバックを処理
app.get('/debit/callback', async (req, res) => {
try {
const sourceId = req.query.source_id;
const source = await omise.sources.retrieve(sourceId);
if (source.flow_status === 'successful') {
// 定期購読ステータスを更新
await updateSubscription(source.id, {
status: 'active',
authorized_at: new Date()
});
// 最初の請求を作成
const charge = await omise.charges.create({
customer: source.customer,
amount: source.amount,
currency: 'THB',
description: '初期定期購読支払い'
});
res.redirect('/subscription-active');
} else {
await updateSubscription(source.id, {
status: 'authorization_failed'
});
res.redirect('/authorization-failed');
}
} catch (error) {
res.redirect('/error');
}
});
// ステップ3:定期請求を処理(cronジョブ)
app.post('/cron/process-subscriptions', async (req, res) => {
try {
const dueSubscriptions = await getDueSubscriptions();
for (const subscription of dueSubscriptions) {
try {
const charge = await omise.charges.create({
customer: subscription.customer_id,
amount: subscription.amount,
currency: 'THB',
description: `定期: ${subscription.plan_id}`,
metadata: {
subscription_id: subscription.id,
billing_period: getCurrentPeriod()
}
});
await recordPayment(subscription.id, charge.id);
} catch (error) {
await handleFailedPayment(subscription.id, error);
}
}
res.sendStatus(200);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Webhookハンドラー
app.post('/webhooks/omise', async (req, res) => {
const event = req.body;
if (event.key === 'charge.complete') {
const charge = event.data;
if (charge.status === 'successful') {
await updateSubscriptionPayment(charge.metadata.subscription_id, 'paid');
await sendReceiptEmail(charge);
} else {
await handleFailedPayment(charge.metadata.subscription_id);
await notifyCustomer(charge);
}
}
res.sendStatus(200);
});
app.listen(3000);
返金対応
// 全額または部分的な返金
const refund = await omise.charges.refund('chrg_test_...', {
amount: 50000 // 全額または部分的
});
ベストプラクティス
1. 明確な承認フロー
<div class="direct-debit-setup">
<h3>ตั้งค่าการหักบัญชีอัตโนมัติ</h3>
<div class="benefits">
<p>✅ ชำระอัตโนมัติทุกเดือน</p>
<p>✅ ไม่ต้องกั งวลเรื่องลืมจ่าย</p>
<p>✅ ยกเลิกได้ทุกเมื่อ</p>
</div>
<p class="amount">จำนวนเงิน: <strong>฿500/เดือน</strong></p>
<button>อนุมัติการหักบัญชี</button>
</div>
2. 失敗した支払いを処理
async function handleFailedPayment(subscriptionId, error) {
// 失敗をログ
await logPaymentFailure(subscriptionId, error);
// 再試行ロジック
const subscription = await getSubscription(subscriptionId);
subscription.retry_count++;
if (subscription.retry_count < 3) {
// 24時間後に再試行
await scheduleRetry(subscriptionId, 24);
} else {
// 定期購読を一時停止
await suspendSubscription(subscriptionId);
await notifyCustomerSuspension(subscription.customer_id);
}
}
3. 顧客への通知
// 請求前に通知
async function sendUpcomingChargeNotification(customerId, amount, dueDate) {
await sendEmail(customerId, {
subject: 'การแจ้งเตือนการหักบัญชี',
body: `บัญชีของคุณจะถูกหัก ฿${amount} ในวันที่ ${dueDate}`
});
}
// 請求成功後に通知
async function sendChargeConfirmation(customerId, charge) {
await sendEmail(customerId, {
subject: 'ยืนยันการหักบัญชี',
body: `การหักบัญชีสำเร็จ ฿${charge.amount / 100}`
});
}
4. キャンセルを許可
app.post('/subscription/cancel', async (req, res) => {
const { subscription_id } = req.body;
// キャンセル済みにマーク(次回請求をしない)
await updateSubscription(subscription_id, {
status: 'canceled',
canceled_at: new Date()
});
// オプション:ソースを削除
// await omise.sources.destroy(source_id);
res.json({ message: 'Subscription canceled' });
});
FAQ
オンラインダイレクト・デビットとは何ですか?
オンラインダイレクト・デビットを使用すると、顧客の銀行口座から定期的に自動で引き落としできます。顧客が一度承認すれば、その後、事業者が請求を開始できます。定期購読と自動請求に最適です。
モバイル/インターネットバンキングとの違いは何ですか?
- モバイル/インターネットバンキング: 一度だけの支払い、顧客が毎回支払いを開始
- ダイレクト・デビット: 定期支払い、加盟店が承認後に請求を開始
顧客は承認をキャンセルできますか?
はい、顧客は銀行を通じて、またはお客様のプラットフォームを通じてダイレクト・デビット権限をキャンセルできます。常に簡単にキャンセルできるオプションを提供してください。
請求に失敗した場合、どうなりますか?
一般的な原因:残高不足、口座閉鎖、権限キャンセル。再試行ロジック(2~3回)を実装し、顧客に支払い方法を更新するよう通知してください。
返金は対応していますか?
はい、ダイレクト・デビットは全額及び部分的な返金に対応しています。
認可にはどのくらい時間がかかりますか?
初期認可には2~5分かかります。認可後、定期請求は1~2営業日以内に処理されます。
関連リソース
次のステップ
- 顧客オブジェクトを作成
- ダイレクト・デビットソースを作成
- 認可コールバックを処理
- 定期請求ロジックを実装
- 再試 行と失敗処理を追加
- 全定期購読フローをテスト
- 本番運用を開始