Online Direct Debit NEW
このページで扱うトピック
Enable secure and seamless purchases directly from your customers' bank accounts using Direct Debit. Customers can link their bank account to your website or application for faster checkout, eliminating the need to enter payment details on future purchases.
How to enable
- Supported Countries: Thailand
- Minimum API version:
2017-11-02
To enable Online Direct Debit, send an email requesting this feature to support@opn.ooo. You will need to review and accept new terms and conditions.
Supported banks
Bank | Linked account type |
---|---|
Bank of Ayudhya | direct_debit_bay |
Kasikorn Bank | direct_debit_kbank |
Krungthai Bank | direct_debit_ktb |
Siam Commercial Bank | direct_debit_scb |
Transaction limits
Country | Currencies | Min. amount | Max. amount |
---|---|---|---|
Thailand | THB |
2000 (THB 20) |
15000000 (THB 150,000) |
Direct Debit charges cannot be refunded.
Payment flow
First, customers need to link their bank account to your platform securely. The steps are as follows:
The customer chooses the bank to link their bank account.
The customer gets redirected to their bank's website or application to authenticate.
The customer selects the bank account they want to link to your platform.
The bank account details are displayed for confirmation.
The customer provides consent.
The customer is redirected to your website with their bank account successfully linked.
Later, customers wishing to make payments can follow these steps:
The customer selects the Direct Debit payment method.
The customer selects the bank from which they would like to pay.
The customer selects the bank account linked to your platform.
The customer sees your payment confirmation page.
Customers only need to link their bank account to your platform once. Afterward, they won't need to authorize future transactions with that linked account.
Implementation
Use the following API requests to link a customer's bank account to your website or application.
Create a linked account.
Redirect the customer to the specified
registration_uri
.Wait for the linked account completion webhook event. You may also retrieve it manually to independently verify its status.
Create a customer and attach the newly successful linked account to it (alternatively, you can also attach the linked account to an existing customer).
Next, create a charge using the customer ID and linked account ID you previously made.
Creating a linked account
When the customer confirms that they wish to link their bank account, create a new linked account specifying the type
and return_uri
.
Parameter | Type | Description |
---|---|---|
type |
string | (required) Linked account type (direct_debit_bay , direct_debit_kbank , direct_debit_ktb , or direct_debit_scb ). |
return_uri |
string | (required) Location on your website to which the customer should be redirected after completing the registration. |
citizen_id |
string | (optional) Customer's citizen ID. If supplied, banks will perform validation before the registration process. For direct_debit_ktb , this field is required if you would like to register the customer using the KTB NEXT app. |
The following examples demonstrate the creation of a new linked account for direct_debit_kbank
. Replace the $OMISE_SECRET_KEY
variable with the test secret key found on your dashboard.
curl https://api.omise.co/linked_accounts \
-u $OMISE_SECRET_KEY: \
-d "type=direct_debit_kbank" \
-d "return_uri=https://example.com/accounts/345678/complete"
{
"object": "linked_account",
"id": "lnac_test_5zr9wnoskjk6g0vpjd3",
"livemode": false,
"location": "/linked_accounts/lnac_test_5zr9wnoskjk6g0vpjd3",
"registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9wnoskjk6g0vpjd3",
"return_uri": "https://example.com/accounts/345678/complete",
"type": "direct_debit_kbank",
"status": "pending",
"last_digits": null,
"metadata": {},
"failure_code": null,
"failure_message": null,
"registered_at": null,
"expires_at": "2024-05-16T10:38:20Z",
"created_at": "2024-05-15T10:38:20Z"
}
The id
attribute is the linked account ID (begins with lnac
).
Completing the registration
You have now created a new linked account with its status set to pending
. Other possible values for the linked account status are successful
, failed
, expired
, and deleted
.
Redirect the customer to the location specified in registration_uri
so they can complete the registration.
You can simulate this registration phase in test mode by visiting registration_uri
to manually mark the linked account as successful
or failed
.
After the customer has completed the registration phase, they will be redirected to the location specified in return_uri
.
Receiving the linked account completion event
The best way to be notified when a linked account is completed is by using webhook events.
Set up a location on the merchant server to receive webhook events and add this location as a webhook endpoint on the dashboard.
Checking the linked account status
After receiving this event, retrieve the linked account using its id
and confirm that its status
matches the status
of the linked account contained in the event.
If the value of status
is successful
, the customer's bank account has been successfully linked.
If the value of status
is failed
, check the failure_code
and failure_message
in the linked account object for an explanation.
Possible failure codes are as follows.
Failure Code | Description |
---|---|
failed_processing |
General linked account processing failure. |
invalid_account |
The customer's account information is invalid or does not exist in the bank system. |
registration_rejected |
The bank rejected the registration. |
rate_limit_exceeded |
There are too many requests for a given period. Please try again. |
Creating a customer
After receiving a successful
linked account, you need to attach it to a customer before using it to create a charge. This will allow for better management and tracking between customers and their linked accounts.
Create a new customer or update the existing one specifying the linked_account
using the desired linked account ID.
One customer can have multiple linked accounts, but a linked account can only be attached to one customer.
The following examples demonstrate creating a new customer. Replace the $OMISE_SECRET_KEY
variable with the test secret key found on your dashboard.
curl https://api.omise.co/customers \
-u $OMISE_SECRET_KEY: \
-d "linked_account=$LINKED_ACCOUNT_ID"
{
"object": "customer",
"id": "cust_test_5zr9wnsj8za8bn31rur",
"livemode": false,
"location": "/customers/cust_test_5zr9wnsj8za8bn31rur",
"deleted": false,
"metadata": {},
"cards": {
"object": "list",
"data": [],
"limit": 20,
"offset": 0,
"total": 0,
"location": "/customers/cust_test_5zr9wnsj8za8bn31rur/cards",
"order": "chronological",
"from": "1970-01-01T00:00:00Z",
"to": "2024-05-15T10:38:20Z"
},
"default_card": null,
"linked_accounts": {
"object": "list",
"data": [
{
"object": "linked_account",
"id": "lnac_test_5zr9527qwb44ad4s9lw",
"livemode": false,
"location": "/linked_accounts/lnac_test_5zr9527qwb44ad4s9lw",
"registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9527qwb44ad4s9lw",
"return_uri": "https://omise.co",
"type": "direct_debit_kbank",
"status": "successful",
"last_digits": "7890",
"metadata": {},
"failure_code": null,
"failure_message": null,
"registered_at": "2024-05-15T09:20:00Z",
"expires_at": "2024-05-16T09:19:56Z",
"created_at": "2024-05-15T09:19:56Z"
}
],
"limit": 20,
"offset": 0,
"total": 1,
"location": "/customers/cust_test_5zr9wnsj8za8bn31rur/linked_accounts",
"order": "chronological",
"from": "1970-01-01T00:00:00Z",
"to": "2024-05-15T10:38:20Z"
},
"description": null,
"email": null,
"created_at": "2024-05-15T10:38:20Z"
}
The id
attribute is the customer ID (begins with cust
).
Creating a charge
Create a charge specifying the parameters amount
, currency
, customer
, and linked_account
.
Parameter | Type | Description |
---|---|---|
amount |
integer | (required) Amount in subunits (see transaction limits) |
currency |
string | (required) Currency as three-letter ISO 4217 code (THB ) |
customer |
string | (required) Customer ID with a linked account from the bank account registration |
linked_account |
string | (required) Linked account ID from the bank account registration |
The following examples demonstrate how to create a new charge. Replace the $OMISE_SECRET_KEY
variable with the test secret key found on your dashboard.
curl https://api.omise.co/charges \
-u $OMISE_SECRET_KEY: \
-d "amount=5000" \
-d "currency=THB" \
-d "customer=$CUSTOMER_ID" \
-d "linked_account=$LINKED_ACCOUNT_ID"
{
"object": "charge",
"id": "chrg_test_5zr9wnvxw05szpqkh9k",
"location": "/charges/chrg_test_5zr9wnvxw05szpqkh9k",
"amount": 5000,
"acquirer_reference_number": null,
"net": 4973,
"fee": 25,
"fee_vat": 2,
"interest": 0,
"interest_vat": 0,
"funding_amount": 5000,
"refunded_amount": 0,
"transaction_fees": {
"fee_flat": "0.0",
"fee_rate": "0.5",
"vat_rate": "7.0"
},
"platform_fee": {
"fixed": null,
"amount": null,
"percentage": null
},
"currency": "THB",
"funding_currency": "THB",
"ip": null,
"refunds": {
"object": "list",
"data": [],
"limit": 20,
"offset": 0,
"total": 0,
"location": "/charges/chrg_test_5zr9wnvxw05szpqkh9k/refunds",
"order": "chronological",
"from": "1970-01-01T00:00:00Z",
"to": "2024-05-15T10:38:22Z"
},
"link": null,
"description": null,
"metadata": {},
"card": null,
"source": null,
"schedule": null,
"linked_account": {
"object": "linked_account",
"id": "lnac_test_5zr9527qwb44ad4s9lw",
"livemode": false,
"location": "/linked_accounts/lnac_test_5zr9527qwb44ad4s9lw",
"registration_uri": "http://test.omise.co/register?ref=lnac_test_5zr9527qwb44ad4s9lw",
"return_uri": "https://omise.co",
"type": "direct_debit_kbank",
"status": "successful",
"last_digits": "7890",
"metadata": {},
"failure_code": null,
"failure_message": null,
"registered_at": "2024-05-15T09:20:00Z",
"expires_at": "2024-05-16T09:19:56Z",
"created_at": "2024-05-15T09:19:56Z"
},
"customer": "cust_test_5zr9nrqgambvlg9bn5y",
"dispute": null,
"transaction": "trxn_test_5zr9wo1aw1wrn49d346",
"failure_code": null,
"failure_message": null,
"status": "successful",
"authorize_uri": null,
"return_uri": null,
"created_at": "2024-05-15T10:38:21Z",
"paid_at": "2024-05-15T10:38:21Z",
"expires_at": "2024-05-22T10:38:21Z",
"expired_at": null,
"reversed_at": null,
"zero_interest_installments": false,
"branch": null,
"terminal": null,
"device": null,
"authorized": true,
"capturable": false,
"capture": true,
"disputable": false,
"livemode": false,
"refundable": false,
"partially_refundable": false,
"reversed": false,
"reversible": false,
"voided": false,
"paid": true,
"expired": false,
"can_perform_void": false,
"approval_code": null
}
Completing the charge
If the payment succeeds, the charge status
will be successful
upon creation. Other possible values for charge status
are failed
and pending
.
In the event of a pending
charge status due to bank processing delays, rest assured that the system is designed to automatically update it to the correct status shortly. No action is needed from your side or the customer. We recommend waiting for the charge.complete
webhook for the finalized charge status.
Receiving the charge completion event
The best way to be notified about the completion of a charge is using webhook events.
Set up a location on the merchant server to receive webhook events, and add this location as a webhook endpoint on the dashboard.
Checking the charge status
After receiving this event, retrieve the charge using its id
and confirm that its status
matches the status
of the charge contained in the event.
If the value of status
is successful
, you got paid.
If the value of status
is failed
, check the failure_code
and failure_message
in the charge object for an explanation.
Possible failure codes are as follows.
Failure Code | Description |
---|---|
failed_processing |
General payment processing failure. |
invalid_account |
Valid account for payment method not found. |
insufficient_fund |
Insufficient funds in the account or the payment method has reached its limit. |
rate_limit_exceeded |
There are too many requests for a given period. Please try again. |
Creating a recurring charge
Most direct debit use cases involve recurring payments, typically requiring setting up a schedule to charge a bank account automatically at specified intervals. You can manage this schedule either by yourself, where you send charge creation requests at selected times, or by leveraging our Schedule API for automated handling.
Follow this guide for examples of creating a charge schedule. Here's an example of how to create a recurring direct debit charge on the first day of every month:
curl https://api.omise.co/schedules \
-u $OMISE_SECRET_KEY: \
-d "every=1" \
-d "period=month" \
-d "on[days_of_month][]=1" \
-d "start_date=2025-01-01" \
-d "end_date=2025-12-31" \
-d "charge[amount]=5000" \
-d "charge[currency]=THB" \
-d "charge[customer]=$CUSTOMER_ID" \
-d "charge[linked_account]=$LINKED_ACCOUNT_ID"
{
"object": "schedule",
"id": "schd_test_60rjgvu1gnr8loh44l0",
"deleted": false,
"livemode": false,
"location": "/schedules/schd_test_60rjgvu1gnr8loh44l0",
"every": 1,
"occurrences": {
"object": "list",
"data": [],
"limit": 20,
"offset": 0,
"total": 0,
"location": "/schedules/schd_test_60rjgvu1gnr8loh44l0/occurrences",
"order": "chronological",
"from": "1970-01-01T00:00:00Z",
"to": "2024-08-16T03:54:32Z"
},
"on": {
"days_of_month": [
1
]
},
"in_words": "Every 1 month(s) on the 1st",
"period": "month",
"status": "running",
"active": true,
"state": "Active",
"charge": {
"object": "scheduled_charge",
"id": "rchg_test_60rjgvu0wxzapqjgvop",
"livemode": false,
"currency": "THB",
"amount": 5000,
"default_card": false,
"card": null,
"customer": "cust_test_60rjevagkj6dqq7zqz4",
"linked_account": "lnac_test_60rjesjp1hjn0hux6re",
"description": null,
"metadata": {},
"created_at": "2024-08-16T03:54:31Z"
},
"next_occurrences_on": [
"2025-01-01",
"2025-02-01",
"2025-03-01",
"2025-04-01",
"2025-05-01",
"2025-06-01",
"2025-07-01",
"2025-08-01",
"2025-09-01",
"2025-10-01",
"2025-11-01",
"2025-12-01"
],
"ended_at": null,
"start_on": "2025-01-01",
"end_on": "2025-12-31",
"created_at": "2024-08-16T03:54:31Z",
"deleted_by": null
}
Removing a linked account
When the customer wants to remove their bank account from your platform, you may do so by removing the linked account.
After the linked account is removed, it will have a deleted
status and no longer be usable for future charges.
Note: Deleting a customer will not remove the attached linked accounts.
For Krungthai Bank, after removing the linked account from your platform, the customer needs to contact their bank to disconnect the bank account completely.
curl https://api.omise.co/linked_accounts/$LINKED_ACCOUNT_ID \
-X DELETE \
-u $OMISE_SECRET_KEY:
{
"object": "linked_account",
"id": "lnac_test_5zrb4qbkn11ogwc221x",
"livemode": false,
"location": "/linked_accounts/lnac_test_5zrb4qbkn11ogwc221x",
"registration_uri": "http://test.omise.co/register?ref=lnac_test_5zrb4qbkn11ogwc221x",
"return_uri": "https://omise.co",
"type": "direct_debit_kbank",
"status": "deleted",
"last_digits": "7890",
"metadata": {},
"failure_code": null,
"failure_message": null,
"registered_at": "2024-05-15T12:43:37Z",
"expires_at": "2024-05-16T12:43:32Z",
"created_at": "2024-05-15T12:43:32Z"
}
Related API documentation
How to check the public key and secret key
For information on how to obtain and check the public and secret keys, please refer to this document.