Bank Transfer Integration

One of the payment method offered by Midtrans is Bank Transfer. By using this payment method, customers will have the option to make a payment via bank transfer and Midtrans will send real time notification when the customer complete the payment.

At this moment, Midtrans has integrated with 4 different bank transfer payment methods:

  1. Permata Virtual Account
  2. BCA Virtual Account
  3. Mandiri Bill Payment
  4. BNI Virtual Account

Basic integration process of Bank Transfer will be explained below.

Sandbox Environment

All the steps below are using Midtrans Sandbox environment, not Production, to easily test the integration process. Make sure you are switching to Sandbox mode on your Midtrans account dashboard while retrieving Server Key and Client Key. Explained in Getting Started - Preparation.

Server Key and Client Key can be retrieved on menu Settings > Access Keys.

Testing Payment

Here is a list of a test transaction that can be used in the Sandbox Environment, please note that this simulator will not work on Production mode.

Payment Methods Description
BCA Virtual Account Midtrans will generate a dummy BCA Virtual Account Number. To perform a test transaction, use the BCA Virtual Account Simulator.
Mandiri Bill Payment Midtrans will generate a Payment Code to complete payment via Mandiri e-channel (Internet Banking, SMS Banking, Mandiri ATM). To perform a test transaction, use the Mandiri Bill Payment Simulator.
BNI Virtual Account Midtrans will generate a dummy BNI Virtual Account Number. To perform a test transaction, use the BNI Virtual Account Simulator.
Permata Virtual Account Midtrans will generate a dummy Permata Virtual Account Number. To perform a test transaction, use the Permata Virtual Account Simulator.



Diagram

Overview of the transaction flow in sequence diagram:
bank transfer transaction flow .

Integration Step

  1. Send transaction data to API Charge.
  2. Display virtual account number and expiry time.
  3. Handle transaction notification.

1. Send Transaction Data to API Charge

Charge API request should be done from Merchant's backend. Server Key (from your account's Dashboard) will be needed to authenticate the request.

Charge API request

This is example of basic /charge API request in Curl, please implement according to your backend language (you can also check our available language libraries).

# sample charge in CURL
curl -X POST \
  https://api.sandbox.midtrans.com/v2/charge \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic <YOUR SERVER KEY ENCODED in Base64>' \
  -H 'Content-Type: application/json' \
  -d '{
  "payment_type": "bank_transfer",
  "transaction_details": {
      "order_id": "order-101",
      "gross_amount": 44000
  }
  "bank_transfer":{
      "bank": "bca"
  }
}'
# sample charge in CURL
curl -X POST \
  https://api.sandbox.midtrans.com/v2/charge \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic <YOUR SERVER KEY ENCODED in Base64>' \
  -H 'Content-Type: application/json' \
  -d '{
  "payment_type": "echannel",
  "transaction_details": {
      "order_id": "order-101",
      "gross_amount": 44000
  }
}'
# sample charge in CURL
curl -X POST \
  https://api.sandbox.midtrans.com/v2/charge \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic <YOUR SERVER KEY ENCODED in Base64>' \
  -H 'Content-Type: application/json' \
  -d '{
  "payment_type": "bank_transfer",
  "transaction_details": {
      "order_id": "order-101",
      "gross_amount": 44000
  }
  "bank_transfer":{
      "bank": "bni"
  }
}'
# sample charge in CURL
curl -X POST \
  https://api.sandbox.midtrans.com/v2/charge \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic <YOUR SERVER KEY ENCODED in Base64>' \
  -H 'Content-Type: application/json' \
  -d '{
  "payment_type": "permata",
  "transaction_details": {
      "order_id": "order-101",
      "gross_amount": 44000
  }
}'

Optional: you can customize transaction_details data. To include data like customer_details, item_details, etc. It's recommended to send as much detail so on report/dashboard those information will be included.

Charge API response

You will get the API response like the following.

{
    "status_code": "201",
    "status_message": "Success, Bank Transfer transaction is created",
    "transaction_id": "be03df7d-2f97-4c8c-a53c-8959f1b67295",
    "order_id": "1571823229",
    "merchant_id": "G812785002",
    "gross_amount": "44000.00",
    "currency": "IDR",
    "payment_type": "bank_transfer",
    "transaction_time": "2019-10-23 16:33:49",
    "transaction_status": "pending",
    "va_numbers": [
        {
            "bank": "bca",
            "va_number": "812785002530231"
        }
    ],
    "fraud_status": "accept"
}

You will get the va_numbers attribute which can be performed this transaction.

{
    "status_code": "201",
    "status_message": "OK, Mandiri Bill transaction is successful",
    "transaction_id": "abb2d93f-dae3-4183-936d-4145423ad72f",
    "order_id": "1571823332",
    "merchant_id": "G812785002",
    "gross_amount": "44000.00",
    "currency": "IDR",
    "payment_type": "echannel",
    "transaction_time": "2019-10-23 16:35:31",
    "transaction_status": "pending",
    "fraud_status": "accept",
    "bill_key": "778347787706",
    "biller_code": "70012"
}

You will get the bill_key and bill_code attribute which can be performed this transaction.

{
    "status_code": "201",
    "status_message": "Success, Bank Transfer transaction is created",
    "transaction_id": "2194a77c-a412-4fd8-8ec8-121ff64fbfee",
    "order_id": "1571823369",
    "merchant_id": "G812785002",
    "gross_amount": "44000.00",
    "currency": "IDR",
    "payment_type": "bank_transfer",
    "transaction_time": "2019-10-23 16:36:08",
    "transaction_status": "pending",
    "va_numbers": [
        {
            "bank": "bni",
            "va_number": "9888500212345678"
        }
    ],
    "fraud_status": "accept"
}

You will get the va_numbers attribute which can be performed this transaction.

{
    "status_code": "201",
    "status_message": "Success, PERMATA VA transaction is successful",
    "transaction_id": "035ca76c-b814-4264-9e63-68142351df83",
    "order_id": "1571823410",
    "gross_amount": "44000.00",
    "currency": "IDR",
    "payment_type": "bank_transfer",
    "transaction_time": "2019-10-23 16:36:49",
    "transaction_status": "pending",
    "fraud_status": "accept",
    "permata_va_number": "850003072869607",
    "merchant_id": "G812785002"
}

You will get the permata_va_number attribute which can be performed this transaction.

2. Display Virtual Account Number and Expiry Time

To display the virtual account number, use va_number that retrieved from API response.

By default the expiry time for Bank Transfer / VA is 24 hours, please check this section under "Set Custom Expiry" if you wanna customize the expiry time.

3. Handle HTTP Notification

HTTP notification from Midtrans to Merchant backend will also be triggered on event of transaction_status getting updated, to ensure merchant is securely informed. Including if transaction success or expired (not paid). So apart of JSON result above, Merchant backend will be notified by Midtrans.

HTTP POST request with JSON body will be sent to Merchant's notification url configured on dashboard (Settings > Configuration > Notification URL), this is the sample JSON body that will be received by Merchant:

{
  "va_numbers": [
    {
      "va_number": "812785002530231",
      "bank": "bca"
    }
  ],
  "transaction_time": "2019-10-23 16:33:49",
  "transaction_status": "pending",
  "transaction_id": "be03df7d-2f97-4c8c-a53c-8959f1b67295",
  "status_message": "midtrans payment notification",
  "status_code": "201",
  "signature_key": "b07e6b0c6e7786363f9d7c1502e1171143fefe38e1a2bb93bce87e0fb64dd2ddfbbc8c7d60c6dcd7d6d8edb22169fd46e2250a6a547aa9f3f6da206a63334360",
  "payment_type": "bank_transfer",
  "payment_amounts": [

  ],
  "order_id": "1571823229",
  "merchant_id": "G812785002",
  "gross_amount": "44000.00",
  "fraud_status": "accept",
  "currency": "IDR"
}
{
  "transaction_time": "2019-10-23 16:35:31",
  "transaction_status": "pending",
  "transaction_id": "abb2d93f-dae3-4183-936d-4145423ad72f",
  "status_message": "midtrans payment notification",
  "status_code": "201",
  "signature_key": "ac6c542806820cd5abe218fadc4f2d150e6e6c9ea6cc24a56c78f3625c19ae0eb4bbf0e26059d2bc6879752e9a1f2b673c3158a34f7e96651d621a0be8258ca9",
  "payment_type": "echannel",
  "order_id": "1571823332",
  "merchant_id": "G812785002",
  "gross_amount": "44000.00",
  "fraud_status": "accept",
  "currency": "IDR",
  "biller_code": "70012",
  "bill_key": "778347787706"
}
{
  "va_numbers": [
    {
      "va_number": "9888500212345678",
      "bank": "bni"
    }
  ],
  "transaction_time": "2019-10-23 16:36:08",
  "transaction_status": "pending",
  "transaction_id": "2194a77c-a412-4fd8-8ec8-121ff64fbfee",
  "status_message": "midtrans payment notification",
  "status_code": "201",
  "signature_key": "9eea61a37704a010c0665fbd738eade7bb08ecb8096ee4d3f08def1eb4f9e1f86f0717c3b79b3c41ff36c67c17bb0124e9f567589eba341aae1ad899fecf2ef3",
  "payment_type": "bank_transfer",
  "payment_amounts": [

  ],
  "order_id": "1571823369",
  "merchant_id": "G812785002",
  "gross_amount": "44000.00",
  "fraud_status": "accept",
  "currency": "IDR"
}
{
  "transaction_time": "2019-10-23 16:36:49",
  "transaction_status": "pending",
  "transaction_id": "035ca76c-b814-4264-9e63-68142351df83",
  "status_message": "midtrans payment notification",
  "status_code": "201",
  "signature_key": "386ef32b70e611a41062db75ce2d3770a3e9861df50b0f9e49e56f5d64d74fc4acdef5e16a12955bb232b08384eb43aea22400aa591f658197c69f8ffe8e04f3",
  "permata_va_number": "850003072869607",
  "payment_type": "bank_transfer",
  "order_id": "1571823410",https://open.spotify.com/track/7McZS9J6h0SKoZBR6cfcFe
  "merchant_id": "G812785002",
  "gross_amount": "44000.00",
  "fraud_status": "accept",
  "currency": "IDR"
}

Refer here on more details of how to handle HTTP Notification.

Switching To Production

To use Midtrans production environment (accept real payment from real customer), please make sure to:

  1. Switch the API domain URL from api.sandbox.midtrans.com to api.midtrans.com
  2. Switch the Client Key and Server Key from sandbox Dashboard, with keys from production Dashboard.

Done

The Bank Transfer payment integration guide is now complete. Below are some further references.

Custom Virtual Account Number

A virtual account number contains two parts. The first part is the company code and the second part is the unique code. The second part can be customized for BCA, BNI and Permata (Only supported for b2b transactions) payment types.

If the number provided is already utilized for another order, then a different unique number will be used instead.
If the number provided is longer than required, then the unnecessary digits in the end will be trimmed.
If the number provided is shorter than required, then the number will be prefixed with zeros.

Please add bank_transfer parameter in the /charge API request:

"bank_transfer":{
  "bank": "bca",
  "va_number": "12345678911" //Length should be within 1 to 11
}
"bank_transfer":{
  "bank": "bni",
  "va_number": "12345678" //Length should be within 1 to 8
}
"bank_transfer":{
  "bank": "permata",
  "va_number": "1234567890" //Length should be 10. Only supported for b2b transactions
}

Description

transaction_status value description for Bank Transfer transaction:

Transaction Status Description
settlement Transaction successful, customer has been completed the transaction.
pending The transaction has successfully created but has not been completed by the customer.
expire Transaction failure because customer did not complete the payment within allowed time.
cancel Transaction is canceled by trigger from Merchant.
deny The bank rejected the transaction.


Link: More detailed definition of transaction_status

For more detail: Complete Core API documentation