直接扣账(Direct Debit)webhook payload
Direct Debit表单会在三个时候发送webhook:顾客申请时、银行批准或拒绝授权(mandate)时,以及之后的每一次扣款。每次都是一个HTTP POST,JSON body包含event和data。本页列出每个栏位。
完整的BCL API,请看API参考文档。
设置你的webhook URL
Section titled “设置你的webhook URL”Webhook是在Direct Debit表单本身设置的:
-
前往Payments → Forms,打开你的Direct Debit表单。
-
点击顶部的Advanced,然后打开Webhook Settings标签页。
-
开启Enable Webhook,输入一个或多个Webhook URLs(最多10个,每个都以
https://开头)。如果没有显示输入框,先点击Add Webhook URL。 -
在Webhook Events下,勾选你需要的事件。请看下一节。

-
点击Save Advanced Settings。
要测试你的endpoint,点击Send Test,并在Event Type选择Direct Debit - When direct debit transactions occur。BCL会发送三个范例请求,每个阶段一个:申请、批准和扣款。

哪个事件在什么时候触发
Section titled “哪个事件在什么时候触发”只勾选Direct Debit复选框并不包括申请。四个事件和授权的对应如下:
| 阶段 | event |
勾选这个事件 | record_type |
|---|---|---|---|
| 顾客提交表单 | form-submit |
Form Submit | DirectDebit |
| 银行批准登记或变更 | payment-success |
Payment Success | DirectDebit |
| 银行拒绝,或失败 | payment-failed |
Payment Failed | DirectDebit |
| 每一次扣款 | direct-debit |
Direct Debit | DirectDebitDeduction |
授权终止时,BCL不会发送webhook。
申请和批准payload
Section titled “申请和批准payload”form-submit、payment-success和payment-failed事件使用同一个结构。这是一个已批准登记的payment-success。数值都是虚构的。
{ "event": "payment-success", "data": { "formable_type": "payment_form", "formable_id": 34, "form_title": "Monthly Fees", "form_url": "https://shop.example.com/form/monthly-fees", "form_featured_image": "", "record_type": "DirectDebit", "record_id": "LINK-00041", "main_data": { "id": "01jfmnrycszgmdhdk78nmtr3gs", "payer_name": "Ali bin Abu", "payer_email": "ali@example.com", "payer_telephone_number": "+60123456789", "order_number": "LINK-00041", "transaction_type": "live", "currency": "MYR", "subtotal_amount": "10.00", "fee_amount": "1.50", "amount": "11.50", "application_type": "Enrolment", "approval_status": "Approved", "bayarcash_mandate_id": "md_AbC123", "mandate_reference_number": "E-20261727400000", "effective_date": "2026-10-01", "frequency_mode": "MT", "created_at": "27/09/2026 10:15:00" }, "tracking_params": null, "custom_fields_data": { "company_name": "Contoh Trading" } }}data对象有这些键:
| 栏位 | 类型 | 意思 |
|---|---|---|
formable_type |
string | 永远是payment_form。取代旧的form_id。 |
formable_id |
number | 表单ID。 |
form_title |
string | 表单标题。 |
form_url |
string | 表单的公开链接,或空值。 |
form_featured_image |
string | 封面图片URL,或空值。 |
record_type |
string | DirectDebit。 |
record_id |
string | 该授权的BCL订单号码。每一次扣款都保持不变。 |
main_data |
object | 授权。请看下面。 |
tracking_params |
null | Direct Debit不记录。 |
custom_fields_data |
object | 表单的自定义栏位,以栏位名称为键。如果没有,就不会出现。 |
Direct Debit没有receipt_url。
在main_data里,BCL会省略空的栏位:
| 栏位 | 类型 | 意思 |
|---|---|---|
id |
string | 内部授权ID。 |
payer_name, payer_email, payer_telephone_number |
string | 顾客的资料。 |
order_number |
string | 与record_id相同。 |
transaction_type |
string | live或test。 |
currency |
string | 通常是MYR。 |
subtotal_amount, fee_amount |
string | 未加手续费的金额,以及手续费。一定会发送。 |
amount |
string | 每期扣除的金额。 |
discount_amount, coupon_code, coupon_usage_id, additional_fee_amount, tax_amount, shipping, classification_code |
various | 只有表单使用时才会发送。意思与付款表单payload相同。 |
application_type |
string | 仅限批准事件:Enrolment或Maintenance(授权的变更)。 |
approval_status |
string | 批准事件时,是New、Waiting Approval、Failed Bank Verification、Active、Terminated、Approved、Rejected、Cancelled或Error其中之一。在form-submit则是原始状态码,或不会出现。 |
bayarcash_mandate_id |
string | 银行回复后的Bayarcash授权ID。 |
mandate_reference_number |
string | 来自银行的授权参考号码。 |
effective_date, expiry_date |
string | 授权的开始和结束日期。 |
frequency_mode |
string | 扣款频率。MT表示每月。 |
created_at |
string | 申请时间,DD/MM/YYYY HH:MM:SS,马来西亚时间。 |
items |
array | 表单上的产品(如果有):index、item、option、quantity、unit_amount、amount、access_url、product_image和protected_content。 |
扣款payload
Section titled “扣款payload”Bayarcash回报的每一个扣款结果,不论成功与否,BCL都会发送direct-debit。这个payload仍然使用form_id。
{ "event": "direct-debit", "data": { "form_id": 34, "form_title": "Monthly Fees", "record_type": "DirectDebitDeduction", "record_id": "LINK-00041", "main_data": { "order_number": "1-727-400-448-141498", "payer_name": "Ali bin Abu", "payer_email": "ali@example.com", "payer_telephone_number": "+60123456789", "mandate_id": "md_AbC123", "mandate_reference_number": "E-20261727400000", "bayarcash_transaction_id": "trx_3qngpY", "batch_number": "HLB1727400000", "amount": "11.50", "status": 3, "status_description": "Successful", "datetime": "2026-10-01 00:00:00", "cycle": 1 }, "custom_fields_data": { "company_name": "Contoh Trading" } }}扣款栏位的意思:
| 栏位 | 类型 | 意思 |
|---|---|---|
form_id |
number | 表单ID。 |
form_title |
string | 表单标题。 |
record_type |
string | DirectDebitDeduction。 |
record_id |
string | 该授权的BCL订单号码。 |
main_data.order_number |
string | 这次扣款的参考号码。 |
payer_name, payer_email, payer_telephone_number |
string | 授权里的顾客资料。 |
mandate_id |
string | Bayarcash授权ID。 |
mandate_reference_number |
string | 来自Bayarcash的授权参考号码。 |
bayarcash_transaction_id |
string | 这次扣款的Bayarcash交易ID。 |
batch_number |
string或null | 银行批次号码。 |
amount |
string | 扣除的金额。 |
status |
number | 扣款状态码。3表示成功。 |
status_description |
string或null | 来自Bayarcash的状态文字。 |
datetime |
string | 扣款日期和时间。 |
cycle |
number或null | 这是第几次扣款,从1开始算。 |
custom_fields_data |
object | 表单的自定义栏位。如果没有,就不会出现。 |
与旧范例的不同
Section titled “与旧范例的不同”如果你是根据旧范例创建整合的,请检查这些变更:
- 申请和批准payload不再有
form_id。使用formable_id。 - 申请和批准的新栏位:
formable_type、form_url、form_featured_image、tracking_params、subtotal_amount、created_at,以及表单有产品时的items。 - 被拒绝或失败的批准现在以
payment-failed发送。 - 扣款payload没有改变。
确认webhook是真的
Section titled “确认webhook是真的”BCL不会为webhook签名,所以没有signature可以检查。在根据webhook采取行动之前,先通过BCL API查找授权或订单,使用难以猜到的URL,并确保同一个事件处理两次也不会出问题。每次尝试都列在Tools → Webhook Logs。BCL不会自动重试失败的发送:打开该行的菜单,点击Resend。在测试模式下,用GET /transaction/{order_number}查找订单,并发送你自己的User-Agent header。
常见问题
我勾选了Direct Debit,但顾客申请时我没有收到webhook。为什么?
Direct Debit事件只包括扣款。申请使用Form Submit,银行批准或拒绝则使用Payment Success或Payment Failed。四个都勾选,就能从头到尾追踪一个授权(mandate)。
怎样把每月扣款对应回顾客的授权?
在direct-debit payload里,record_id是该授权的BCL订单号码,与你在申请时收到的record_id相同。main_data.mandate_id是Bayarcash授权ID,与批准webhook里的bayarcash_mandate_id相同。
为什么测试webhook和真实的不一样?
Direct Debit的Send Test范例在申请和批准payload里仍然使用form_id。真实的申请和批准webhook则改为发送formable_type和formable_id。扣款webhook不论测试或真实,都使用form_id。