Snap has various optional parameters. These optional parameters can be utilized for more advanced use cases that can help your integration.
You can include more information such as customer_details
, item_details
, and so on along side transaction_details
. While sending API requests, it is recommended to send more details regarding the transaction, so that these details will be captured on the transaction record. Which can be viewed on the Midtrans Dashboard.
The recommended JSON parameters for general use are given below. These parameters are used during backend API request step.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"credit_card": {
"secure": true
},
"item_details": [
{
"id": "a01",
"price": 7000,
"quantity": 1,
"name": "Apple"
},
{
"id": "b02",
"price": 3000,
"quantity": 2,
"name": "Orange"
}
],
"customer_details": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "+628123456789",
"billing_address": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "08123456789",
"address": "Sudirman No.12",
"city": "Jakarta",
"postal_code": "12190",
"country_code": "IDN"
},
"shipping_address": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "0812345678910",
"address": "Sudirman",
"city": "Jakarta",
"postal_code": "12190",
"country_code": "IDN"
}
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"credit_card": {
"secure": true
},
"item_details": [
{
"id": "a01",
"price": 7000,
"quantity": 1,
"name": "Apple"
},
{
"id": "b02",
"price": 3000,
"quantity": 2,
"name": "Orange"
}
],
"customer_details": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "+628123456789",
"billing_address": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "08123456789",
"address": "Sudirman No.12",
"city": "Jakarta",
"postal_code": "12190",
"country_code": "IDN"
},
"shipping_address": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "0812345678910",
"address": "Sudirman",
"city": "Jakarta",
"postal_code": "12190",
"country_code": "IDN"
}
}
}'
For more details, refer to Snap Docs.
You can also add fee, tax, discount, etc. to item_details if you need.
Redirect URL is used to redirect your customer after the payment process is complete through Snap.
This is the default method. In this method, payment page is embedded in merchant website/app. To set your redirect URL, in pop-up mode, go to Settings - Snap Preference - System Settings.
The diagram given below explains the working of redirect URL.
In this method, the customer will be redirected to Midtrans hosted payment page. To set your redirect URL in redirect mode, go to Settings - Configuration.
The diagram given below explains the working of redirection URLs.
?> Note:
The final redirect URL is appended with query parameter like ?order_id=xxx&status_code=xxx&transaction_status=xxx
.
For example the final redirect URL may look like this: https://tokoecommerce.com/finish_payment/?order_id=CustOrder-102123123&status_code=200&transaction_status=capture
.
You may use this information to display custom message to your customer on your finish URL.
Note: Specific if the payment method is Credit Card & processed via 3DS 2 (when the acquiring bank and the MID support), there's small possibility of the transaction is still waiting for the card's 3DS provider to process/verify it, which then Snap will trigger redirect with ?transaction_status=pending
instead of capture/settlement
. To handle the payment success update, as usual you should handle HTTP Notification.
Snap.js supports various useful options, such as specifying language, specifying GoPay payment mode to deeplink, and so on. You can use these options according to your requirement.
For more details, refer to Snap Docs.
?>Note: If you are using Snap Redirect mode, you can append options as Query parameter at the end of the Snap redirect_url
:
[redirect_url]?[options1]=[value]&[options2]=[value]
Which for example (using both language=en
& gopayMode=deeplink
options) the final result url as shown below.
https://app.sandbox.midtrans.com/snap/v2/vtweb/cf9534e3-ddf7-43f9-a1b7-5f618d2d1c96?language=en&gopayMode=deeplink
Including Snap.js on your frontend will expose snap
object as global JS object accessible with window.snap
. These are some main functions that you can access from your frontend codes:
window.snap.pay('SNAP_TRANSACTION_TOKEN', options)
: Will open payment page for that specific Snap Token, which is tied to specific Order ID. Also useful if you want to re-open that same payment page again e.g. when you allow another attempt of payment for that same Order ID, in case of closed earlier. Second parameter is optionaloptions
object explained further here.window.snap.hide()
: Will close the Snap payment page popup. Useful if you want to close the payment page from customers, e.g. when you/customers want to cancel the payment.
For more details, refer to Snap Docs.
Snap.js supports callbacks. It can be used to trigger your custom JavaScript implementation on each event. The available callbacks are given below.
onSuccess
: Function that will be triggered when payment is successful.onPending
: Function that will be triggered when payment is pending, which is for payment that requires further customer action, such as bank transfer / VA, or waiting for 3DS/OTP process*.onError
: Function that will be triggered when there is a payment failure after several attempts.onClose
: Function that will be triggered when customer has closed the Snap popup.
Example of the Snap.js callback option usage while calling window.snap.pay(...)
is given below. This parameter is used during Snap frontend implementation.
window.snap.pay('SNAP_TRANSACTION_TOKEN', {
onSuccess: function(result){
/* You may add your own implementation here */
alert("payment success!"); console.log(result);
},
onPending: function(result){
/* You may add your own implementation here */
alert("wating your payment!"); console.log(result);
},
onError: function(result){
/* You may add your own implementation here */
alert("payment failed!"); console.log(result);
},
onClose: function(){
/* You may add your own implementation here */
alert('you closed the popup without finishing the payment');
}
})
For more details on Snap JS callback's result JSON properties & the samples, refer to this section of Snap Docs.
*Specific if the payment method is Credit Card & processed via 3DS 2 (when the acquiring bank and the MID support), there's small possibility of the transaction is still waiting for the card's 3DS provider to process/verify it, which then Snap will trigger onPending
callback instead of onSuccess
. To handle the payment success update, as usual you should handle HTTP Notification.
By default, Snap will redirect the customer to Finish Redirect URL configured on Dashboard. But you can override that configuration by specifying callbacks.finish
parameter. This will allow you to have specific redirect for each specific payment.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"callbacks": {
"finish": "https://tokoecommerce.com/my_custom_finish/?name=Customer01"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"callbacks": {
"finish": "https://tokoecommerce.com/my_custom_finish/?name=Customer01"
}
}'
On Snap payment selection screen, all available payments for the merchant are activated by default. Under some conditions, you may need to display only some of the payment methods available. There are two ways to achieve this, which are given below.
You can configure Enable Payment with Snap Preference on Midtrans Dashboard. This will apply to all Snap transactions for the Merchant account.
- Login to your Midtrans Dashboard.
- Go to Settings - Snap Preferences - Payment Channels Tab
- Click [x] icon to disable payment channel.
- Click [+] icon To enable payment channel.
- Click Apply Recommended Sorting to use Midtrans recommended sorting. Or drag/drop manually to sort payment channel.
- Click Save.
?> Note: the configuration that is set using this method will only be applied to Snap payment transaction that is being opened via Snap Popup method (frontend javascript implementation method with snap.js). If your implementation is via Snap Redirect mode, please use configuration on the next section.
You can add and customize enabled_payments
parameter. That will apply specifically for the transaction.
Example of the JSON parameters used during backend API request step is given below.
...
"enabled_payments": [
"credit_card",
"gopay",
"shopeepay",
"permata_va",
"bca_va",
"bni_va",
"bri_va",
"echannel",
"other_va",
"danamon_online",
"mandiri_clickpay",
"cimb_clicks",
"bca_klikbca",
"bca_klikpay",
"bri_epay",
"xl_tunai",
"indosat_dompetku",
"kioson",
"Indomaret",
"alfamart",
"akulaku"
]
...
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"enabled_payments": [
"credit_card",
"gopay",
"shopeepay",
"permata_va",
"bca_va",
"bni_va",
"bri_va",
"echannel",
"other_va",
"danamon_online",
"mandiri_clickpay",
"cimb_clicks",
"bca_klikbca",
"bca_klikpay",
"bri_epay",
"xl_tunai",
"indosat_dompetku",
"kioson",
"Indomaret",
"alfamart",
"akulaku"
],
"credit_card": {
"secure": true
},
"customer_details": {
"first_name": "Budi",
"last_name": "Susanto",
"email": "[email protected]",
"phone": "+628123456789"
}
}'
enabled_payments
also support alias, which refers to a list of payment types. Adding an alias is the equivalent of adding all the payment types it refers to. Supported aliases:
bank_transfer
=permata_va, bca_va, bni_va, bri_va, echannel
store
=kioson, indomaret, alfamart
.
Use of enabled_payments
is shown in the sample CURL request shown below.
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"enabled_payments": [
"credit_card"
],
"credit_card": {
"secure": true
}
}'
This code will display only the credit card payment method on Snap as shown below.
Custom Expiry feature enables you to set an expiry time of payment for each transaction. When the time elapses, customer will no longer be able to pay the transaction. There are two ways to configure expiry time, which are given below.
You can set custom expiry with Snap Preference on Midtrans Dashboard. This will apply to all Snap transactions for the Merchant account.
- Login to your MAP account.
- On the home page, go to Settings- Snap Preferences. Snap Preferences page is displayed.
- Select System Settings tab.
- Select Default check box.
- Select duration unit from the drop-down menu.
- Click Save.
This method is used to configure expiry time for a specific transaction.
Example of the JSON parameters used during backend API request step is given below.
...
"expiry": {
"start_time": "2020-04-13 18:11:08 +0700",
"unit": "minutes",
"duration": 180
}
...
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"expiry": {
"start_time": "2020-04-13 18:11:08 +0700",
"unit": "minutes",
"duration": 180
}
}'
Parameter | Description | Type | Required |
---|---|---|---|
start_time |
Timestamp in YYYY-MM-DD HH:MM:SS +0700 .If not specified, transaction time will be used as start time (when customer confirm payment channel). Time Zone is Western Indonesian Time (WIT). |
String(255) | Optional* |
duration |
Expiry duration | Integer | Required |
unit |
Expiry unit. Options: day, hour, minute (plural term also accepted). |
String | Required |
*The start_time
parameter is optional, but if you don’t include it, asynchronous payment methods like Bank Transfer, Gopay, etc. (payment methods that have pending
status) will start the expiry duration only when the customer has proceeded to select & confirm payment on Snap payment screen. Thus the total expiry duration may not be as you were expecting due to Snap payment screen not immediately completed by customer. To avoid this, it is recommended to include the start_time
on the API request.
Custom fields allow you to send your own (custom) data to Snap API, and then it will be sent back from Midtrans to your backend on HTTP notification. It will be displayed on Dashboard under the order detail.
Example of the JSON parameters used during backend API request step is given below.
...
"custom_field1": "this is custom text defined by merchant",
"custom_field2": "order come from web",
"custom_field3": "customer selected blue color variant"
...
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 13000
},
"custom_field1": "this is custom text defined by merchant",
"custom_field2": "order come from web",
"custom_field3": "customer selected blue color variant"
}'
Parameter | Description | Type | Required |
---|---|---|---|
custom_field1 | Custom field 1 for custom parameter from merchant. Input any information you want. |
String(255) | Optional |
custom_field2 | Custom field 2 for custom parameter from merchant. Input any data you want. |
String(255) | Optional |
custom_field3 | Custom field 3 for custom parameter from merchant. Input any data you want. |
String(255) | Optional |
Three Domain Secure (3DS) feature can be enabled/disabled for specific transactions on Snap. By default you should always enable 3DS whenever possible, to prevent unnecessary security and chargeback risks. Understand the risks in disabling 3DS. To disable 3DS for specific business needs, you require agreement and approval. Consult Midtrans Activation team to allow disabling 3DS.
- To enable 3DS, set the
secure
value totrue
. - To disable 3DS, set the
secure
value tofalse
.
Example of the JSON parameters used during backend API request step is given below.
...
"credit_card": {
"secure": true
}
...
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true
}
}'
You can allow customer to save their card credentials within Snap payment page, for easier and faster future transactions. Card credentials will be saved securely on Midtrans side, and will not require merchant to manage the card data.
Merchant will only need to store and associate each unique customer with unique user_id
defined by merchant.
- Add
"save_card" : true
anduser_id
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"save_card": true
},
"user_id": "budiSusanto201"
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"save_card": true
},
"user_id": "budiSusanto201"
}'
?> Note: During the first payment when a customer is intended to save their card, they must tick the “Save this card” check box on Snap payment page, in order for the card to be saved. This is to ensure that the customer explicitly gives consent that they are ok that their card will be securely saved.
Use the same user_id
API params for that particular customer on future transactions. Their card will be previewed on Snap card payment page, on future transactions.
For more use cases, refer to One Click, Two Click, and Recurring Transaction.
?> This feature is also known as Card Tokenization. Which simply means a method to replace sensitive information value (card credentials) with a token
(a placeholder) value, but also allowing it to still be associated with the actual value. Generally to keep sensitive information safely kept within secure environments, but still accessible for authorized parties.
Snap can be utilized to initialize subscription or recurring payment flow. Note that:
- You will require Core API to do the recurring charge.
- The recurring charge should be scheduled & triggered by your (merchant's) system/backend.
- Currently, recurring transaction supports only card transactions.
Please refer to the sequence diagram given below to understand the recommended flow.
Example of the JSON param for the first or initial transaction is given below. This param is used during backend API request step.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"save_card": true
},
"user_id": "budiSusanto201"
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"save_card": true
},
"user_id": "budiSusanto201"
}'
Then you will proceed with displaying Snap payment page as usual. After customer proceed with payment and result in successful first transaction, you will receive saved_token_id
& saved_token_id_expired_at
in the JSON of HTTP notification. saved_token_id
is unique for each customer's card. Store this saved_token_id
in your database and associate that card token to your customer.
!> Important: Be sure to store the card's saved_token_id_expired_at
. When that date time has been surpassed, the card's saved_token_id
will be no longer usable, it means the card is expired. In that case you will need to ask your customer to re-do the card saving process with their re-newed card.
{
"saved_token_id":"481111xDUgxnnredRMAXuklkvAON1114",
"saved_token_id_expired_at": "2020-12-31 07:00:00",
"status_code": "200",
"status_message": "Success, Credit Card transaction is successful",
...
}
When you want to charge that particular customer, you will need to proceed with Charge API request via Core API. The recurring transaction is non 3DS and will directly deduct customer's fund associated with the card.
?> Note: This feature requires special MID from acquiring bank, this utilize what bank usually call as "recurring MID". Which may means additional business agreement with the acquiring bank, you should consult Midtrans Activation team to activate this feature.
For more use cases, refer to One Click, Two Click, and Recurring Transaction.
Note that the Recurring / Subscription mentioned above is relying on your system/backend to schedule and trigger the recurring charges. Additionally, Midtrans also support automatically charge recurring for you based on your specified schedule.
Follow the same implementation as mentioned above, to the point your system retrieved the saved_token_id
. Then you can proceed with Core API's Recurring API feature here. To specify the schedule of when Midtrans should charge recurringly to your customer.
?> Note: This feature requires special MID from acquiring bank, this utilize what bank usually call as "recurring MID". Which may means additional business agreement with the acquiring bank, you should consult Midtrans Activation team to activate this feature.
This method also support GoPay payment method. Please contact Midtrans Activation Team or your Sales Representative before using this feature.
You can specify the preferred Acquiring Bank for specific Snap transaction. Transaction fund will be routed to that specific acquiring bank. Consult Midtrans Activation team to get information about the availability of the Acquiring Bank.
- Specify the bank name inside the
bank
parameter.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"bank": "bca"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"bank": "bca"
}
}'
BIN (Bank Identification Number) filter is a feature that allows the merchant to accept only Credit Cards within specific set of BIN numbers. It is useful for certain bank promo/discount payment by accepting only credit cards issued by that bank. BIN (Bank Identification Number) is the first 1-8 digits of a card number, which identifies the bank that issues the card. A bank generally has more than one BIN.
To use this feature, you need to accumulate the list of BIN that accepts the promotion or uses the issuing bank's name. This list of BIN or issuing bank name will then become a transaction parameter whitelist_bins
. This transaction can only be performed exclusively by using the credit card that is included in the BIN list or BIN under the particular defined issuing bank.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"whitelist_bins": [
"48111111",
"41111111",
"bni"
]
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"whitelist_bins": [
"48111111",
"41111111",
"bni"
]
}
}'
?> Note: We already pre-populate BIN number for BNI, Mandiri, CIMB, BCA, and other partner banks. You can add the bank name as whitelist bins value.
The sample Snap payment page with BIN Filter feature is displayed below.
This is the type of installment where the Card Issuer and Acquiring Bank is the same entity. For example, if a customer makes an installment payment using BNI Card, then Acquiring Bank is also BNI.
For online installments, the bank will issue special MID for installment. This installment MID is used to automatically convert the transaction into installments. To activate the installment feature, you are required to have agreement with the bank. Please consult Midtrans Activation Team for installment MID. If MID is ready, merchant simply needs to add the installment
parameter.
...
"credit_card": {
"secure": true,
"installment": {
// set to `true` to force customer pay with installment for this transaction
// set to `false` to add option for customer to pay with regular fullpayment
"required": true,
"terms": {
// input the desired bank & installment terms
"<bank-name>": [ <installment terms as array of integers> ]
}
}
}
...
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"installment": {
"required": true,
"terms": {
"bca": [3,6,12],
"bni": [3,6,12],
"mandiri": [3,6,12],
"cimb": [3,6,12],
"bri": [3,6,12],
"maybank": [3,6,12],
"mega": [3,6,12]
}
}
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"installment": {
"required": true,
"terms": {
"bca": [6,12],
"bni": [6,12],
"mandiri": [3,6,12]
}
}
}
}'
The sample Snap payment page with online installment feature is displayed below.
?> Note: Installment term will show in the Snap payment page after the customer enters the installment-compatible credit card number. For testing this method, refer to Sandbox test card.
Offline Installment is the type of payment where Card Issuing Bank used for making an installment payment and the Acquiring Bank need not be the same. For example, a customer makes an installment payment using BNI Card and the Acquiring Bank is Mandiri.
To allow installment feature with banks which do not issue Installment MID, merchant can use offline installment feature. With offline installment feature, the transaction will initially be charged in full amount and will be converted into installment later. To activate the installment feature, you are required to have agreement with the bank. Please consult Midtrans Activation Team for installment MID.
You have to add the installment
parameter with combination of whitelist_bins
feature. The purpose of Whitelist BIN is to allow only certain acceptable cards to proceed with offline installment payment, based on the agreement between you and issuing banks.
Usually you will also need to add bank
parameter to specify which card acquirer bank should be used for the offline installment payment.
...
"credit_card": {
"secure": true,
"installment": {
// set to `true` to force customer pay with installment for this transaction
// set to `false` to add option for customer to pay with regular fullpayment
"required": true,
"terms": {
// input the desired installment terms
"offline": [ <installment terms as array of integers> ]
}
},
"whitelist_bins": [ <card BINs as array of strings> ],
"bank": <specify acquirer bank> // input the destination card acquirer bank that will be used
}
...
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"installment": {
"required": true,
"terms": {
"offline": [3,6,12]
}
},
"whitelist_bins": [
"481111",
"410505"
],
"bank": "mandiri"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 120000
},
"credit_card": {
"secure": true,
"installment": {
"required": true,
"terms": {
"offline": [3,6,12]
}
},
"whitelist_bins": [
"481111",
"410505"
],
"bank": "mandiri"
}
}'
The sample Snap payment page with offline installment feature is displayed below.
Parameter | Description |
---|---|
required |
If true , the customer must pay as installment for that specific transaction. If false , the customer can choose to pay as installment or regular full payment for that specific transaction. |
terms |
under terms array, on online installment, you can specify the bank name (For example- BNI, BCA, CIMB, Mandiri, and so on) |
!> Important: When you use whitelist_bins
to create a Snap transaction, it will be applied to all card transaction for that Snap transaction. It could means that you will not be able to mix offline installment with online installment or regular full payment into one Snap transaction. Read further recommendations here.
Pre-authorization feature means customer's fund will not be directly deducted after transaction, but its amount/limit will be temporary reserved (blocked). Then you can initiate "capture" action later via Core API. By default, if there is no "capture" action for the transaction for 7 days, reserved fund will be released after 7 days.
To use this feature, you need to add "type": "authorize"
parameter.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"type": "authorize"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"credit_card": {
"secure": true,
"type": "authorize"
}
}'
After completing payment using GoPay payment method, by default, the customer will remain on Gojek app. They need to manually close Gojek app to switch back to merchant website or application. The gopay.callback_url
parameter will allow customers to be automatically redirected from the Gojek app to the merchant website/application.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"gopay": {
"enable_callback": true,
"callback_url": "https://tokoecommerce.com/gopay_finish"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"gopay": {
"enable_callback": true,
"callback_url": "https://tokoecommerce.com/gopay_finish"
}
}'
You can input callback_url
value with http/https URL protocol for website, or deeplink protocol for mobile App. For example, you can specify deeplink to your app: "callback_url": "tokoecommerce://gopay_finish/"
?>Note:
The final redirect URL will be appended with query parameter like ?order_id=xxx&result=xxx
.
For example the final redirect URL might look like this:
https://tokoecommerce.com/gopay_finish/?order_id=CustOrder-102123123&
result=success
Query Parameter | Description | Type |
---|---|---|
order_id | Order ID sent on the Charge Request. | String |
result | Result of the transaction to decide what kind of page to show to customer. Possible values: success or failure . |
String |
You could utilize those information to display custom message to your customer on your finish URL.
?>Note: gopay.callback_url
will only affect customer who pays with deeplink mode. Customer who pays with QR scan mode, will be redirected to Snap finish redirect URL, which you can specify here.
Snap payment screen by default will automatically detect customer device being used for transaction. If the device is detected as a mobile device, Snap will use deeplink mode to redirect customer to Gojek app (if installed on the device). If the device is detected as a non mobile device, Snap will use QR mode to display QR Code for customer to be paid from their mobile device.
You can specify options gopayMode
on Snap.js to force Snap to use QR or deeplink as specified.
Option | Description | Type | Required |
---|---|---|---|
gopayMode | Choose the UI mode for GoPay. Supported values are deeplink , qr , and auto . Set to auto by default. |
String | Optional |
Example of the Snap.js callback option usage (this parameter is used during Snap frontend implementation), while calling window.snap.pay(...)
is given below.
window.snap.pay('SNAP_TRANSACTION_TOKEN', {
gopayMode: "deeplink"
})
If you are using Snap Redirect Mode, you can append options as Query parameter ?gopayMode=deeplink
at the end of the Snap redirect_url
, which for example the final result url as shown below.
https://app.sandbox.midtrans.com/snap/v2/vtweb/cf9534e3-ddf7-43f9-a1b7-5f618d2d1c96?gopayMode=deeplink
For more details, refer to GoPay.
By default Midtrans will randomize VA number used for bank transfer transaction. In some cases, you might want to specify/customize VA Number for Bank Transfer payment channels. You can do that with the following parameters.
Example of the JSON parameter used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"bca_va": {
"va_number": "12345678901",
"sub_company_code": "00000" //NOTE: Don't send this field unless BCA give you sub company code
},
"bni_va": {
"va_number": "12345678"
},
"bri_va": {
"va_number": "12345678"
},
"permata_va": {
"va_number": "1234567890"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"bca_va": {
"va_number": "12345678901",
"sub_company_code": "00000"
},
"bni_va": {
"va_number": "12345678"
},
"bri_va": {
"va_number": "12345678"
},
"permata_va": {
"va_number": "1234567890"
}
}'
Virtual Account number displayed to customer contains two parts. for example, in {91012}{12435678}
, the company-prefix-number and the second part is a unique-va-number. The second part is the part that can be customized.
- Only digits are allowed.
- Different banks have different specifications on their custom VA numbers. Please see the documentation of the respective banks. Note: for Permata, only B2B VA type support custom VA numbers.
- 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.
Parameter | Description | Type | Required |
---|---|---|---|
BCA va_number |
Length should be within 1 to 11. | String | Optional |
BCA sub_company_code |
BCA sub company code directed for this transactions. NOTE: Don't use it if you don't know. |
String | Optional |
Permata va_number |
Length should be 10. Only supported for B2B VA type. | String | Optional |
BNI va_number |
Length should be within 1 to 8. | String | Optional |
?>Note: In Production mode, each and every bank may not support custom VA number. It depends on the agreement. Please consult Midtrans Activation team for further information.
Some VA description and recipient name can be customized.
Example of the JSON param for the first or initial transaction is given below. This param is used during backend API request step.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"bca_va": {
"free_text": {
"inquiry": [
{
"en": "Invoice for Order 3123 - Toy Shop",
"id": "Tagihan untuk Order 3123 - Toy Shop"
}
],
"payment": [
{
"en": "Pay Order 3123 - Toy Shop",
"id": "Bayar Order 3123 - Toy Shop"
}
]
}
},
"permata_va": {
"recipient_name": "Budi Susanto"
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"bca_va": {
"free_text": {
"inquiry": [
{
"en": "Invoice for Order 3123 - Toy Shop",
"id": "Tagihan untuk Order 3123 - Toy Shop"
}
],
"payment": [
{
"en": "Pay Order 3123 - Toy Shop",
"id": "Bayar Order 3123 - Toy Shop"
}
]
}
},
"permata_va": {
"recipient_name": "Budi Susanto"
}
}'
BCA VA:
- Inquiry free text is list of text that will be displayed on ATM (if supported) when customer attempts to check/enquire the VA number.
- Payment free text is list of text that will be displayed on ATM (if supported) when customer attempts to pay the VA number.
BCA VA Free Text Array:
Parameter | Description | Type | Required |
---|---|---|---|
inquiry | Max item for array is 10 | Array of FreeTextItem | Optional |
payment | Max item for array is 10 | Array of FreeTextItem | Optional |
BCA VA Free Text Item:
Parameter | Description | Type | Required |
---|---|---|---|
en | Size should not exceed 50 characters. | String | Required |
id | Size should not exceed 50 characters. | String | Required |
Permata VA:
Parameter | Description | Type | Required |
---|---|---|---|
recipient_name | Recipient name shown on the on the bank’s payment prompt. It is shown as 20 character uppercase string. Anything over 20 characters will be truncated. NOTE: Default is merchant name. |
String | Optional |
The text printed on Alfamart receipt can be customized.
Example of the JSON parameters used during backend API request step is given below.
{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"cstore": {
"alfamart_free_text_1" : "Thanks for shopping with Toy Store!",
"alfamart_free_text_2" : "Visit our site at toystore.com",
"alfamart_free_text_3" : "Invite your friend and get discount."
}
}
curl -X POST \
https://app.sandbox.midtrans.com/snap/v1/transactions \
-H 'Accept: application/json'\
-H 'Authorization: Basic U0ItTWlkLXNlcnZlci1UT3ExYTJBVnVpeWhoT2p2ZnMzVV7LZU87' \
-H 'Content-Type: application/json' \
-d '{
"transaction_details": {
"order_id": "CustOrder-102",
"gross_amount": 9000
},
"cstore": {
"alfamart_free_text_1" : "Thanks for shopping with Toy Store!",
"alfamart_free_text_2" : "Visit our site at toystore.com",
"alfamart_free_text_3" : "Invite your friend and get discount."
}
}'
Parameter | Description | Type | Required |
---|---|---|---|
alfamart_free_text_1 | First row of printed receipt description | String(40) | Optional |
alfamart_free_text_2 | Second row of printed receipt description | String(40) | Optional |
alfamart_free_text_3 | Third row of printed receipt description | String(40) | Optional |
There are a few limitations to consider while using Midtrans API. These limitations are given below.
Midtrans API allows maximum size of 16kb per request (~16000 total characters). Please try to keep it under the limit to avoid request failures.
?>Tip: Limit the number of item_details
from your request, or group it into fewer item_details
.
The default lifetime for regular Snap transaction, Snap token
and also the redirect_url
, is 24 hours. It can be customized. To customize Snap token
and redirect_url
, refer to Custom Expiry section.
Within the set time limit, the payment page is available for customer to proceed payment. After the limit exceeds, it will show that the payment page is no longer available.
If your customer journey allow customer to close the payment page, and you want to allow customer to retry payment for that same order, you can follow this tips. When you sent request to Snap API and received Snap Token, you can keep/store that Snap Token associated with your Order ID. You can re-call window.snap.pay(SNAP_TRANSACTION_TOKEN')
again on frontend with that same Snap Token to open the payment page popup, as long as it is not expired.
Alternatively if you prefer to create another Snap Token, you can follow the next section.
At the state of customer have not chosen/proceed with any payment method within the Snap payment page, you can still re-initiate create Snap transaction using the same Order ID, since the Order ID is not yet utilized. New Snap token & url will be generated, and the older token & url will no longer be valid.
But that will no longer work if the customer has proceeded to choose/confirm to pay with certain payment methods, the status may have changed to pending
. This also applies to when the customer has successfully paid the transaction. You will get API error message transaction_details.order_id sudah digunakan
. This is to prevent duplication of payment order id on Midtrans side.
To avoid Order ID duplication, you can also change your implementation logic to allow one Order ID on your system to have-many payment Order ID on Midtrans (one-to-many relationship). e.g. for Order ID: web-order-321
your system can send request to Snap API with timestamp suffix on Order ID param like web-order-321-{$timestamp}
. So that you can have many Snap Token recreated for that one particular order.
Card transaction payment status will become pending
once it is proceeded into 3DS/OTP phase. If the transaction is abandoned or not completed within 10-15 minutes, its status will become expire
. For more details please refer here.
Snap is designed to maximize conversion rate of customer payment, it has built-in behavior:
- In which 1 Snap order-id is allowed to be retried multiple times by the customer as long as it is not yet finally paid or expired.
Example scenario:
- Customer attempted to pay a Snap Order ID using card payment, then his card declined 2x.
- Then he choose another payment method, Akulaku, in which he got 1x another declined payment.
- Then finally he chose another payment method, Gopay, in which his payment is successfully accepted.
- In summary: 3x deny attempts, 1x final success attempt.
Thus may result in:
- On Midtrans dashboard you may see for 1 Snap Order ID, it can have multiple attempts recorded.
- In the example scenario above, you will see 2x denied card transactions + 1x denied Akulaku transactions + finally 1x successful Gopay transactions. This is normal as long as there are only 1 successful transaction for 1 Order ID. It is expected that the multiple failed transactions are also recorded.
- Your backend/system may receive multiple webhook/HTTP Notifications of transaction status for 1 Snap order ID, according to the status of each unique attempts.
- In the example scenario above, your system will get 2x denied card transactions notif + 1x denied Akulaku transactions notif + finally 1x successful Gopay transactions notif. This is normal as long as there are only 1 successful transaction for 1 Order ID. It is expected that the multiple failed transaction notifications are also triggered.
?> Tips: You should implement your backend/system to allow early failed payment attempts & eventually accept notification of payment success.
Due to the focus of Snap to be simple, easy to integrate, and focus on the customer friendly UI; for GoPay, ShopeePay, and QRIS transactions made within Snap payment UI, currently there is no feature to programmatically retrieve the actions[].url
(of the payment deeplink/QR url) value from Snap. In case you need to do that scenario, it is recommended to use Core API instead. Though, we are working to improve this in the future Snap version.
You can alternatively store the Snap payment token
(or redirect_url
), and use it to re-display the Snap payment UI to the customer, so the GoPay, ShopeePay and QRIS payment page will be re-displayed according to the customer's session.
This behavior is applicable to Snap as per changes introduced on 12 September 2022.
Background condition:
- When you enable
gopay
(or other QRIS compatible e-money methods likeshopeepay
) payment method on Snap, by default Snap UI (whenever possible) will automatically decide and show two possible scenario for customer to pay:- A) If the customer is detected using mobile device, App Redirect payment flow will be presented.
- B) If the customer is detected using Desktop/PC, QRIS Scan payment flow will be presented.
Please note the following behavior:
- Depending on which method the customer pay with (A or B), for each payment attempts:
- In scenario A: Midtrans will mark the payment_type of the transaction as
gopay
(or the e-money payment method chosen). - In scenario B: Midtrans will mark the payment_type of the transaction as
qris
.
- In scenario A: Midtrans will mark the payment_type of the transaction as
- This will also impact the following:
- JSON fields sent on Webhook/HTTP Notification of the payment status.
- Get Status API response.
- The
Payment Type
displayed on Midtrans Dashboard, and when you download transactions.
- The JSON fields format (returned on Webhook/HTTP Notifications & Get Status API response) is different between
"payment_type": "qris"
and"payment_type": "gopay"
. Refer to the notification example section for details.
Compared to previous behavior before this change, it was:
- Regardless of scenario A or B, Midtrans will record it as
gopay
(or the e-money payment method chosen). Which was a bit misleading, because it does not exactly give a proper differentiator if the payment was paid via QRIS.
Reasons why this changes was introduced:
- To provide clearer information whether the payment source was made via e-money or QRIS.
- The transaction fee for Gopay (e-money) payment method & QRIS is calculated differently. This change will provide clearer information for the Merchant's side to do reconciliation of transactions fee.
- The previous flow was based on e-money QR, which was still in its early stages & each e-money has its own different QR standard. As of now QRIS is maturing to become the unifying standard, we have to continuously optimize our flow to this latest evolving standard.
Though at first you may find it confusing because you did not explicitly enable qris
on Snap or the customer did not choose it either, but you are receiving qris
on notification.
Recommended action for merchant side:
- Please ensure that your system’s implementation can handle this behavior without breaking your system & its payment flow. Especially on the following parts (if applicable):
- Your Notifications Handler implementation logic.
- Get Status API implementation logic.
- Reconciliation implementation logic.
Tips:
- In terms of payment status, there will be no difference between the mentioned payment_type. Success status will still be
settlement
, unpaid will still beexpire
, waiting will still bepending
, etc.- So it will be safe for you to use the same logic (no changes) to check the payment status.
- It will also generally support the same command such as
refund
,expire
, etc. - So the change in
payment_type
will not affect payment status itself. - If it helps make your implementation transition easier,
- You can disregard the payment_type differences or consider. Or
- You can internally consider both
gopay
andqris
payment_type to be one, just like previously.
When a transaction is created on Snap API, it does not immediately assign any payment status on Core API's Get Status response.
Considering this, you may get 404
or Payment Not Found response upon calling Core API get-status even if the payment page is activated on Snap API.
It is because of customer may not have chosen/proceed with any payment method within the Snap payment page (For example, idling or abandoning the Snap payment page). After customer chooses and proceeds with a payment method, the transaction status will be assigned. It will be available on Core API Get Status response. The possible status is as defined in the table above.
If you are using Content Security Policy (CSP) on your payment web page, please whitelist the domains/URLs given below. This is required by the Snap.js to work properly from within your payment web page.
cloudfront.net
*.midtrans.com
*.veritrans.co.id
*.mixpanel.com
*.google-analytics.com
Please whitelist the above domains/URLs in your CSP header/rule, to ensure proper working of Snap.js.
Avoid displaying Snap payment popup within an iframe from your main checkout page. As it may cause unexpected results (known so far):
- Snap UI size may not perfectly fit the size of the browser/device.
- Snap automatically tries to fit to the webpage’s size, if you put Snap within an iframe, it tries to fit to the iframe size instead. Thus it is not recommended. If you insist on doing it with iframe, you can try to resize the iframe size to fit the main webpage’s.
- Payment methods that require redirect to payment provider's website/app may not work (e.g. Gopay, ShopeePay, etc.).
- This is mainly because of Web Browser's security limitations, to avoid spam and unwanted pop-up most of modern web browser by default will try to block redirection coming from cross-domain iframe.
We always recommend to follow the basic Snap integration:
- Use Snap’s javascript directly on your checkout webpage, and make sure to use meta-viewport tag.
- Or alternatively use Snap’s redirect method.