Malaysia
Online banking, e-wallets and DuitNow QR in MYR
Before you start
Authorization
How to sign your requests with the API token.
Create payment
The base order request that this page extends.
This payment method is not enabled for all merchants. Check availability with your manager.
Overview
| Currency | Payment method |
|---|---|
MYR | Online banking, e-wallets, DuitNow QR |
The payer is redirected to paymentLink and completes the payment in their bank's online banking, in an e-wallet app, or by scanning a DuitNow QR code, depending on the selected payment method.
amount is in Malaysian ringgit with up to two decimal places, for example 150.00.
Payment methods
A payment method is defined by two parameters: the bank (a code from the table below) and the channelCode::wayCode pair (payment channel and method). Each bank maps to exactly one pair in the table, so specifying the bank is usually enough.
| Bank code | Bank / wallet | channelCode::wayCode |
|---|---|---|
0001 | Affin Bank | NET_BANKING::BANK_TRANSFER |
0002 | AGRO Bank | NET_BANKING::BANK_TRANSFER |
0003 | Alliance Bank (Personal) | NET_BANKING::BANK_TRANSFER |
0004 | AmBank | NET_BANKING::BANK_TRANSFER |
0005 | Bank Islam | NET_BANKING::BANK_TRANSFER |
0006 | Bank Rakyat | NET_BANKING::BANK_TRANSFER |
0007 | Bank Muamalat | NET_BANKING::BANK_TRANSFER |
0008 | Bank Simpanan Nasional | NET_BANKING::BANK_TRANSFER |
0009 | CIMB Clicks | NET_BANKING::BANK_TRANSFER |
0010 | Hong Leong Bank | NET_BANKING::BANK_TRANSFER |
0011 | HSBC Bank | NET_BANKING::BANK_TRANSFER |
0012 | Kuwait Finance House | NET_BANKING::BANK_TRANSFER |
0013 | Maybank2U | NET_BANKING::BANK_TRANSFER |
0014 | OCBC Bank | NET_BANKING::BANK_TRANSFER |
0015 | Public Bank | NET_BANKING::BANK_TRANSFER |
0016 | RHB Bank | NET_BANKING::BANK_TRANSFER |
0017 | Standard Chartered Bank | NET_BANKING::BANK_TRANSFER |
0018 | UOB Bank | NET_BANKING::BANK_TRANSFER |
0019 | Bank of China | NET_BANKING::BANK_TRANSFER |
0020 | ShopeePay | EWALLET::SHOPPEE_PAY |
0021 | Boost | EWALLET::BOOST |
0022 | Touch 'n Go eWallet | EWALLET::TNG |
0023 | GrabPay | EWALLET::GRAB_PAY |
0024 | DuitNow QR | DNQR::DNQR |
What is different from a regular order
The order is created through the standard POST /v1/orders endpoint. The base fields (amount, currency, successUrl, failUrl, callbackUrl, etc.) are the same as for a regular order; on top of them you pass the customer object with payer details.
| Field | Type | Description |
|---|---|---|
customer | object | Payer details. The required set is listed below |
The externalUserId field is required for this payment method.
Customer fields
| Field | Type | Required | Description |
|---|---|---|---|
phone | string | ✅ Yes | Malaysian mobile number: 10–11 digits starting with 01 (e.g. 0123456789). The +60 country code is accepted and removed automatically |
email | string | ✅ Yes | Payer email |
firstName | string | ✅ Yes | First name, must match the bank account or wallet owner |
lastName | string | ✅ Yes | Last name, must match the bank account or wallet owner |
Pass the payer's real data. The name and phone number are checked against the actual payer on the provider side; mismatches lead to declined payments.
Integration options
The bank and channelCode::wayCode are either set in your terminal settings or passed in the request. Ask your manager which values are fixed on your terminal and which ones you pass yourself.
If the terminal allows several values, they act as an allowlist: the value in the request must be one of them, and the order is rejected without it. If the terminal has a single value, it is applied automatically, and a different value in the request results in an error.
The bank and payment method are fixed on the terminal and are not passed in the request.
Request example
{
"purpose": "Payment for order #1234",
"amount": "150.00",
"currency": "MYR",
"externalId": "23456789",
"externalUserId": "437568",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"callbackUrl": "https://example.com/webhooks/payments",
"customer": {
"lastName": "Rahman",
"firstName": "Amir",
"email": "amir.rahman@example.com",
"phone": "0123456789"
}
}The bank is fixed on the terminal, while the payment channel and method are passed in extraParams. Use this option when one terminal offers several payment methods, for example different e-wallets.
| Field | Type | Required | Description |
|---|---|---|---|
extraParams | string | ✅ Yes | Payment channel and method as channelCode::wayCode, for example EWALLET::TNG |
Request example
{
"purpose": "Payment for order #1234",
"amount": "150.00",
"currency": "MYR",
"externalId": "23456789",
"externalUserId": "437568",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"callbackUrl": "https://example.com/webhooks/payments",
"extraParams": "EWALLET::TNG",
"customer": {
"lastName": "Rahman",
"firstName": "Amir",
"email": "amir.rahman@example.com",
"phone": "0123456789"
}
}The bank is passed in additional.bank; the payment channel and method are derived from it according to the table.
| Field | Type | Required | Description |
|---|---|---|---|
additional.bank | string | ✅ Yes | Bank code from the payment methods table, for example 0022 |
Request example
{
"purpose": "Payment for order #1234",
"amount": "150.00",
"currency": "MYR",
"externalId": "23456789",
"externalUserId": "437568",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"callbackUrl": "https://example.com/webhooks/payments",
"additional": {
"bank": "0022"
},
"customer": {
"lastName": "Rahman",
"firstName": "Amir",
"email": "amir.rahman@example.com",
"phone": "0123456789"
}
}The bank is passed in additional.bank, and the payment channel and method in extraParams. extraParams takes precedence over the table.
| Field | Type | Required | Description |
|---|---|---|---|
extraParams | string | ✅ Yes | Payment channel and method as channelCode::wayCode, for example EWALLET::TNG |
additional.bank | string | ✅ Yes | Bank code from the payment methods table, for example 0022 |
Request example
{
"purpose": "Payment for order #1234",
"amount": "150.00",
"currency": "MYR",
"externalId": "23456789",
"externalUserId": "437568",
"successUrl": "https://example.com/success",
"failUrl": "https://example.com/fail",
"callbackUrl": "https://example.com/webhooks/payments",
"extraParams": "EWALLET::TNG",
"additional": {
"bank": "0022"
},
"customer": {
"lastName": "Rahman",
"firstName": "Amir",
"email": "amir.rahman@example.com",
"phone": "0123456789"
}
}Response
The response is a standard order object. The order is created with the CREATED status; redirect the payer to paymentLink to complete the payment.
Order object fields
If the payer pays less than the order amount, the order still moves to COMPLETED and amount in the order object is updated to the amount actually received. Compare it with the expected amount before fulfilling the order.