Installment Payments
An installment payment plan allows customers to split a full payment into smaller amounts paid off at regular intervals over a fixed period. Omise provides a set of APIs that allow you to offer your customers this convenient payment method. Currently, you can offer payment plans of up to 36 monthly installments with a minimum total charge amount of 3000 THB (available term lengths and monthly minimum payments vary per card).
The following applies to merchants with accounts registered in Thailand.
Supported Cards
Credit Card | Source type |
installment_term Lengths (months) |
Monthly Minimum (THB) |
---|---|---|---|
Krungsri | installment_bay |
3, 4, 6, 9, 10 | 500 |
Bangkok Bank | installment_bbl |
4, 6, 8, 9, 10 | 500 |
Krungsri First Choice | installment_first_choice |
3, 4, 6, 9, 10, 12, 18, 24, 36 | 300 |
Kasikorn Bank | installment_kbank |
3, 4, 6, 10 | 300 |
Krungthai Card (KTC) | installment_ktc |
3, 4, 5, 6, 7, 8, 9, 10 | 300 |
Payment Flow
Customers who choose to pay using an installment payment plan go through a redirect
payment flow. This means that they are redirected from your website to a external, bank-operated webpage to authorize and confirm the payment amount. Upon completion, the customer is redirected back to your website.
The following screenshots demonstrate this payment flow. At checkout, the customer selects the installment payment method.
After choosing the bank with which they would like to pay, the customer is redirected to the external, bank-operated webpage. The payment amount and any reference numbers should already be filled out on the authorization page.
The customer only has to review the information and confirm the payment. Upon confirmation, the customer will be redirected to your website via the specified return_uri
.
Implementation
Typically, creating an installment payment charge involves:
- Creating a new payment source using the Source API
- Creating a new charge using the Charge API and passing the
id
of the source created in the first step.
This assumes that the installment payment source creation (step 1) happens client-side (e.g. on a user's browser or mobile phone) using a public key while charge creation (step 2) happens server-side using a secret key. We recommend using Omise.js or one of our mobile SDKs to implement the client side of this flow.
Alternatively, if both the creation and charge of a source must happen server-side (not recommended), then the Charge API can be used to both create and charge the source.
Setting Who Pays Installment Interest
Before creating a source, you will need to set which party absorbs the interest for installment payments. This can either be you (Merchant
) or the customer (Customer
). This value can be set on the Dashboard.
Creating a Source Client-side
Installment payment methods are implemented as types of sources. Valid values for the type
and installment_term
parameters are listed in the table above. Keep in mind that the effective valid values for installment_term
depend on the amount
and monthly minimum. The following code demonstrates how to create a new source.
Note: for the following example, you must have already set your $OMISE_PUBLIC_KEY
environment variable to contain your public key.
curl https://api.omise.co/sources \
-X POST \
-u $OMISE_PUBLIC_KEY: \
-d "description=Installment Payment Source" \
-d "amount=500000" \
-d "currency=THB" \
-d "type=installment_kbank" \
-d "installment_term=4" \
-H "Omise-Version: 2019-05-29"
{
"object": "source",
"id": "src_test_5g2hvadpm5ucvap2a6n",
"livemode": false,
"location": "/sources/src_test_5g2hvadpm5ucvap2a6n",
"type": "installment_kbank",
"flow": "redirect",
"amount": 500000,
"currency": "THB",
"installment_term": 4,
"zero_interest_installments": true
}
The returned source object reflects the parameters passed at source creation in addition to the zero_interest_installments
attribute. This will be set to true if you set Merchant
to absorb installment interest in the Dashboard earlier.
Creating an Installment Payment Charge
Use the value of the id
attribute of the returned object above to pass as the value of the source
parameter for a new charge. Because this charge involves the customer leaving the site to authorize the charge, we must also pass the parameter return_uri
. This is the URI on your site to which the customer is redirected upon charge completion.
Note: for this example, you must have already set your $OMISE_SECRET_KEY
environment variable to contain your secret key, and $SOURCE_ID
must contain the value of the id
attribute above.
curl https://api.omise.co/charges \
-X POST \
-u $OMISE_SECRET_KEY: \
-d "source=$SOURCE_ID" \
-d "description=Installment Payment Charge" \
-d "amount=500000" \
-d "currency=THB" \
-d "return_uri=https://example.com/orders/345678/complete" \
-H "Omise-Version: 2019-05-29"
{
"object": "charge",
"id": "chrg_test_5g2hvak2zoseiam51ps",
"livemode": false,
"location": "/charges/chrg_test_5g2hvak2zoseiam51ps",
"created_at": "2019-05-30T07:43:46Z",
"amount": 500000,
"currency": "THB",
"funding_amount": 500000,
"funding_currency": "THB",
"fee": 18250,
"fee_vat": 1278,
"interest": 13000,
"interest_vat": 910,
"net": 466562,
"description": "Installment Payment Charge",
"metadata": {
},
"status": "pending",
"capture": true,
"authorized": false,
"schedule": null,
"reversed": false,
"reversed_at": null,
"expires_at": "2019-06-06T07:43:46Z",
"expired": false,
"expired_at": null,
"voided": false,
"paid": false,
"paid_at": null,
"transaction": null,
"refunded_amount": 0,
"refunds": {
"object": "list",
"from": "1970-01-01T00:00:00Z",
"to": "2019-05-30T07:43:47Z",
"offset": 0,
"limit": 20,
"total": 0,
"order": "chronological",
"location": "/charges/chrg_test_5g2hvak2zoseiam51ps/refunds",
"data": [
]
},
"link": null,
"return_uri": "https://example.com/orders/345678/complete",
"failure_code": null,
"failure_message": null,
"card": null,
"customer": null,
"ip": null,
"dispute": null,
"source": {
"object": "source",
"id": "src_test_5g2hv9yy2k9n0640fox",
"livemode": false,
"location": "/sources/src_test_5g2hv9yy2k9n0640fox",
"type": "installment_kbank",
"flow": "redirect",
"amount": 500000,
"currency": "THB"
},
"disputable": false,
"capturable": false,
"reversible": false,
"refundable": false,
"authorize_uri": "https://pay.omise.co/offsites/ofsp_test_5g2hvak9ayf70bg0gm6/pay"
}
Creating a Source and Charge Server-side
Alternatively, if the source must be specified at charge creation time (i.e. server-side), the Charge API can be used to create and charge a source using one API request.
curl https://api.omise.co/charges \
-X POST \
-u $OMISE_SECRET_KEY: \
-d "amount=500000" \
-d "currency=THB" \
-d "return_uri=http://example.com/orders/345678/complete" \
-d "source[type]=installment_kbank" \
-d "source[installment_term]=4" \
-H "Omise-Version: 2019-05-29"
Authorization
The charge object created from the above API call contains the attribute authorize_uri
. This is the URI for the bank-operated webpage to which you should redirect the customer to review and authorize the charge.
In test mode, you can simulate this behavior by visiting the URI to manually mark the charge as successful or failed.
Checking the Status
Automatic via Webhooks
Use the Events API to get notified when a charge completes. Once configured, a request with the event key
charge.complete
will be sent to your configured webhook endpoint whenever an installment payment charge is completed. See Webhooks for more information.
Charge objects can have the following values for status
: failed
, expired
, pending
, or successful
. If the charge status
is successful
, the value of authorized
and paid
should be true
.
If the charge status is failed
or expired
, check the failure_code
and failure_message
attributes in the charge object for an explanation of the reason. Here are the possible values for failure_code
and a description for each.
failure_code |
Description |
---|---|
insufficient_balance |
Insufficient funds in the account or the card has reached the credit limit. |
payment_cancelled |
Payment cancelled by payer. |
timeout |
Payer did not take action before charge expiration. |
failed_processing |
General payment processing failure. |
Manual
You can check any attribute of the charge by retrieving it via its id
as described in Charges API. Here is an example using a JSON filter tool jq:
curl -s https://api.omise.co/charges/$CHARGE_ID \
-u $OMISE_SECRET_KEY: | jq -M .status
"pending"
Refunds
See the Refunds API documentation for information on how to refund an installment payment charge.
Note: installment payment charges cannot be partially refunded. Only full refunds are supported.
Enabling Installment Payments
You will be required to review additional Terms & Conditions before using the API for live transactions.
The minimum API version required is 2017-11-02
. See API Versioning for guidance on updating your API version.