This section will explain how merchant can initiate GoPay Tokenization (non Pre-Auth) transactions using SNAP-based CoreAPI specification.
- In order to do GoPay Tokenization transaction, merchant should link the customer's GoPay account first by initiating the Account Linking API.
- Once linked, merchant can create a transaction by calling Direct Debit Payment API.
- Merchant can also do other subsequent actions such as Cancel, Refund, and Get Status.
- To receive payment notification from Midtrans, merchant will need to also implement Payment Notification API.
GoPay Tokenization in BI-SNAP flow can also support both GoPay & GoPay Later payment. Merchant should pass the corresponding payment option token as payOptionDetails.additionalInfo.paymentoptiontoken in the request body. The payment option token can be retrieved from Binding Inquiry API.
Creating GoPay Tokenization transaction
![](https://files.readme.io/b5860ab-SNAP_based_account_linking_flow-Copy_of_Page-1.png)
GoPay Tokenization - Direct Debit Payment API
Path | /{version}/debit/payment-host-to-host |
---|---|
HTTP Method | POST |
Version | v1.0 |
SNAP service code | 54 |
Request Header
Field Name | Field Type | Mandatory | Field Description |
---|---|---|---|
Content-type | String | M | Media type of the resource, i.e. application/json. |
X-TIMESTAMP | String | M | Client’s current local time in ISO-8601 format. |
X-SIGNATURE | String | M | Created using symmetric signature HMAC_SHA512 algorithm. |
Authorization | String | M | Represents access_token of a request; string starts with keyword “Bearer ” followed by access_token. Can get this token from Access Token B2B API response. |
Authorization-Customer | String | M | Represents access_token of a request; string starts with keyword “Bearer ” followed by access_token from Binding API response. |
X-PARTNER-ID | String | M | Unique identifier for merchant. Provided by Midtrans. |
X-EXTERNAL-ID | String | M | Numeric string. Preferably UUID. Reference number that should be unique in the same day or 1 day idempotency key. In case of timeout, merchant can do: 1. Use this value in get status API to get status transaction or 2. Retry this request with the same X-EXTERNAL-ID and request body to avoid creating duplicate transaction |
CHANNEL-ID | String | M | Mandatory field from Bank Indonesia that can take any value with correct format 5 digits numeric string |
X-DEVICE-ID | String | M | Device identification on which the API services are currently being accessed by the end user (customer). Sample: Web Application: Mozilla / 5.0(Windows NT 10.0; Win64; x64)AppleWebKit / 537.36(KHTML, like Gecko)Chrome / 75.0.3770.100 Safari / 537.36 OPR / 62.0.3331.99 Mobile Application: Android: android-20013adf6cdd8123f iOS: 72635bdfd223yvjm7246nsdj34hd4559393kjh42 |
Content-type:application/json
X-TIMESTAMP:2024-03-19T14:30:00+07:00
X-SIGNATURE: da1fa417c72d6b91c257e01e54fac824
Authorization: Bearer gp9HjjEj813Y9JGoqwOeOPWbnt4CupvIJbU1Mmu4a11MNDZ7Sg5u9a
Authorization-Customer: Bearer gp9HjjEj813Y9JGoqwOeOPWbnt4CupvIJbU1Mmu4a11MNDZ7Sg5u9a
X-PARTNER-ID: G123456
X-DEVICE-ID: 0987ADCASA
X-EXTERNAL-ID:12345678901234567890
CHANNEL-ID:12345
Request Body
Field Name | Field Type | Mandatory | Field Description | |
partnerReferenceNo | String (64) | M | Merchant order id
Only used for debugging purpose in server side |
|
chargeToken | String | M | The account token used to represent the account binding between merchant and GoPay.
We are not sharing accountToken/accessToken with Merchant. Merchant needs to call the Bind Account API to fetch the accountToken/accessToken. |
|
urlParam | Array of Object | O | Merchant redirect URL.
After completing payment, user will be redirected back to this URL |
|
urlParam.url | String(512) | M | URL value (need to be whitelisted as part of GoPay Tokenization onboarding process) | |
urlParam.type | String(32) | M | Possible value : PAY_RETURN | |
urlParam.isDeeplink | String(1) | M | Is Deeplink or not (Y/N) | |
validUpTo | String(25) | O | The time when the payment will be automatically expired. Using ISO 8601 format.
(Maximum value: 180 days from transaction time, minimum value: 20 seconds, default value: 15 minutes) |
|
payOptionDetails | Array of Object | M | Payment option that will be used for this payment
Currently only accept 1 payOptions |
|
payOptionDetails.payMethod | String (64) | M | Payment method. Possible value: `GOPAY` | |
payOptionDetails.payOption | String (64) | M | Payment option which shows the provider of this payment
Possible value: `GOPAY_WALLET`, `PAY_LATER` (Value can be acquired from additionalInfo.paymentOptions.name in Account Binding Inquiry API response) |
|
payOptionDetails.transAmount | Object | O | Payment transaction amount | |
payOptionDetails.transAmount.value | String (16,2) | M | Transaction amount that will be paid using this payment method. If it's IDR then value includes 2 decimal digits.
e.g. IDR 10.000 will be placed as 10000.00 Minimum value: 1.00 Maximum value : 99999999999.00
(item price * item quantity should be the same amount as transAmount) | |
payOptionDetails.transAmount.currency | String (3) | M | IDR | |
payOptionDetails.additionalInfo | Object | M | Additional information field which merchants need to pass to support current API contracts. | |
payOptionDetails.additionalInfo.recurring | String | O | Recurring flag
Possible value : Y/N If recurring: Y then we will treat this transaction as recurring transaction and bypass PIN challenge. Only applies if recurring feature has already been enabled, please talk to your Midtrans sales representative to have this feature enabled. |
|
payOptionDetails.additionalInfo.promotionIds | Array of String | O | List of promotion ID
Promotion ID can be obtained from Get Promotion API. |
|
payOptionDetails.additionalInfo.paymentOptionToken | String | M | Can get this from Account Binding Inquriy API response. | |
additionalInfo | Object | O | Additional Information | |
additionalInfo.customerDetails | Object | O | Customer detail information | |
additionalInfo.customerDetails.phone | String(15) | O | Customer phone number | |
additionalInfo.customerDetails.email | String(255) | O | Customer email | |
additionalInfo.customerDetails.firstName | String(255) | O | Customer first name | |
additionalInfo.customerDetails.lastName | String(255) | O | Customer last name | |
additionalInfo.customerDetails.billingAddress | Object | O | ||
additionalInfo.customerDetails.billingAddress.firstName | String(255) | O | Billing address first name | |
additionalInfo.customerDetails.billingAddress.lastName | String(255) | O | Billing address last name | |
additionalInfo.customerDetails.billingAddress.phone | String(15) | O | Billing address phone number | |
additionalInfo.customerDetails.billingAddress.address | String(255) | O | Billing address detail | |
additionalInfo.customerDetails.billingAddress.city | String(255) | O | Billing address city | |
additionalInfo.customerDetails.billingAddress.postalCode | String(255) | O | Billing address postal code | |
additionalInfo.customerDetails.billingAddress.countryCode | String(15) | O | Billing address country code | |
additionalInfo.customerDetails.shippingAddress | Object | O | ||
additionalInfo.customerDetails.shippingAddress.firstName | String(255) | O | Shipping address first name | |
additionalInfo.customerDetails.shippingAddress.lastName | String(255) | O | Shipping address last name | |
additionalInfo.customerDetails.shippingAddress.phone | String(15) | O | Shipping address phone number | |
additionalInfo.customerDetails.shippingAddress.address | String(255) | O | Shipping address detail | |
additionalInfo.customerDetails.shippingAddress.city | String(255) | O | Shipping address city | |
additionalInfo.customerDetails.shippingAddress.postalCode | String(255) | O | Shipping address postal code | |
additionalInfo.customerDetails.shippingAddress.countryCode | String(15) | O | Shipping address country code | |
additionalInfo.items | Array Of Object | O | ||
additionalInfo.items.id | String(32) | O | Item ID
Shall merchant intent to apply SKU based promotion, merchant should pass the agreed item ID value for promotion. |
|
additionalInfo.items.price | Object | M | ||
additionalInfo.items.price.value | String (ISO4217) | M | Item price value (item price * item quantity should be the same amount as transAmount) | |
additionalInfo.items.price.currency | String | M | Item price currency | |
additionalInfo.items.quantity | String(16) | M | Item quantity (item price \* item quantity should be the same amount as transAmount) | |
additionalInfo.items.name | String(64) | M | Item name | |
additionalInfo.items.merchantName | String(64) | O | Name of the merchant selling the item | |
additionalInfo.items.brand | String(64) | O | Brand name of the item | |
additionalInfo.items.category | String(64) | O | Category of the item | |
additionalInfo.metadata | Object | O | Merchant's metadata | |
additionalInfo.paymentProviderMetadata | Object | C | Object containing the payment provider’s metadata parameter. This is used whenever merchant needs to pass additional information to payment provider. In the case of GoPay Later Multi Month transaction, merchant needs to pass the required risk data information as agreed with GoPay Later team. |
{
"partnerReferenceNo": "merchant-order-id",
"chargeToken": "accessToken",
"validUpTo": "2023-07-03T10:36:17+07:00",
"payOptionDetails": [
{
"payMethod": "GOPAY",
"payOption": "GOPAY_WALLET",
"transAmount": {
"value": "12345678.00",
"currency": "IDR"
},
"additionalInfo": {
"paymentOptionToken": "aGoPayWalletToken / aPayLaterToken"
}
}
],
"urlParam": {
"url": "www.merchant.com",
"type": "PAY_RETURN",
"isDeeplink": "Y/N"
},
"additionalInfo": {
"customerDetails": {
"phone": "81234532422",
"firstName": "farz",
"lastName": "zsasa",
"email": "[email protected]",
"billingAddress": {
"firstName": "billingFirstName",
"lastName": "billingLastName",
"phone": "billingPhone",
"address": "billingAddress",
"city": "billingCity",
"postalCode": "12790",
"countryCode": "CZH"
},
"shippingAddress": {
"firstName": "shippingFirstName",
"lastName": "shippingLastName",
"phone": "shippingPhone",
"address": "shippingAddress",
"city": "shippingCity",
"postalCode": "12790",
"countryCode": "CZH"
},
},
"items": [
{
"id": "8za1ieleavwusxn6u5re60ri",
"price": {
"value": "12345678.00",
"currency": "IDR"
},
"quantity": “1”,
"name": "Video A",
"brand": "Some Brand",
"category": "Subsciption",
"merchantName": "Amazon Prime"
}
],
"metadata": {},
"paymentProviderMetadata": {
"subOrders": [
{
"subOrderId": "subOrderId001",
"periodType": 3,
"mainOrderId": <string>,
"skuId": "sku2",
"skuName": "rice",
"categoryId": "categoryId2",
"categoryOneName": "mock1",
"categoryTwoName": "mock2",
"categoryCodes": [],
"quantity": 2,
"amount": 100000,
"discounts": {
"funder": <string>,
"totalTenor": <int>,
"discountDetails": [
"tenor": <int>
"discountType": <string> [DISCOUNT_INTEREST_AMOUNT / DISCOUNT_INTEREST_PERCENTAGE]
"discountAmount": <int>,
"discountRate": <float>,
"extendInfo": {}
]
},
"merchantId": <string>,
"merchantRegisterTime": <long>,
"merchantGrade": <string>,
"transactionTimestamp": <long>,
"merchantName": <string>,
"externalMerchantId": <string>,
"transactionId": <string>,
"serviceType" <int>,
"extendInfo": {},
"platformInformation": {
"merchantUserId": <string>,
"firstTransactionDate": "2024/4/12",
"latestTransactionDate": "2024/4/12",
"successTransactionCount": 30,
"successTransactionAmount": 30000000,
"successTransactionCountMonthly": 30,
"successTransactionAmountMonthly": 30000000,
"successCodTransactionCountMonthly": 15,
"successCodTransactionAmountMonthly": 30000000,
"paidByCreditCard": true/false,
"paidByOther": true/false,
"paidByEWallet": true/false,
"inPayLaterWhitelist": true/false,
"inPayLaterBlacklist": true/false,
"creditApplicationScore": 501.58,
"trxnBehaviorScore: 684.29
},
"itemInformation": {
"itemName": <string>,
"categoryName": <string>
}
}
],
"extendInfo": {
"address": {
"address": <string>,
"addressId": <string>,
"state": <string>,
"city": <string>,
"shippingName": <string>
"shippingPhoneNo": <string>
},
"ecommerceOrder": {
"orderAmount": 100000,
"ecommerceSubOrders": [
{
"periodType": 3,
"subOrderId": "GTF_MOCK",
"skuId": "GTF_MOCK",
"skuName": "GTF_MOCK",
"categoryId": "GTF_MOCK",
"categoryOneName": "GTF_MOCK",
"categoryTwoName": "GTF_MOCK",
"categoryCodes": [
"GTF_MOCK"
],
"quantity": 1,
"amount": 100000,
"merchantId": "BLIBLI",
"merchantRegisterTime": 0,
"merchantGrade": "GTF_MOCK",
"transactionTimeStamp": 1674703781574,
"extendInfo": {}
}
]
},
"deviceInfo": {
"platform": "string",
"gps": {
"longitudeHashed": "string",
"latitudeHashed": "string",
"longitude": "string",
"latitude": "string",
"time": null
},
"device": {
"deviceId": "string",
"isRoot": true,
"androidId": "string",
"build": {
"board": "string",
"brand": "string",
"cpuAbi": "string",
"device": "string",
"manufacturer": "string",
"model": "string",
"product": "string"
},
"isTampered": true,
"isHooked": true,
"isEmulators": true
},
"wifiList": [
{
"ssid": "string"
}
],
"ipAddress": {
"ethIp": "string",
"trueIp": "string"
},
"appVersion": "string",
"advertisingId": "string",
"usedByStreamingApps": "string",
"widevineId": "string",
"dexguardId": "string",
"uuid": "string",
"deviceIdInUuid": "string"
}
}
}
}
}
Response Header
Field Name | Field Type | Mandatory | Field Description |
---|---|---|---|
Content-type | String | M | Media type of the resource, i.e. application/json. |
X-TIMESTAMP | String | M | Client’s current local time in ISO-8601 format. |
Content-type: application/json
X-TIMESTAMP: 2020-01-01T00:00:00+07:00
Response Body
Field Name | Field Type | Mandatory | Field Description | |
responseCode | String (7) | M | Error code to specify the error returned. | |
responseMessage | String (150) | M | Debug message to provide more information. | |
referenceNo | String (256) | M | Unique transaction identifier from payment provider system e.g : Gopay order ID. (Only filled if transaction created successfully) |
|
partnerReferenceNo | String (32) | O | Unique transaction identifier from Merchant (Merchant order ID). | |
webRedirectUrl | String (2048) | M |
|
|
appRedirectUrl | String (2048) | M | This will return a universal link to the Gojek/GoPay app. Use this link to redirect user to GoPay PIN page on Gojek/GoPay app for them to complete payment. Merchant should refer to this field if merchant is onboarded to Tokenization app redirection flow. | |
additionalInfo | Object | O | Additional information | |
additionalInfo.amount | String (ISO4217) | M | Amount value | |
additionalInfo.currency | String | M | Amount currency | |
additionalInfo.status | String | M | Midtrans legacy transaction status | |
additionalInfo.expiryTime | String (ISO8601) | M | Midtrans legacy expiry transaction time | |
additionalInfo.paymentType | String | M | Payment type used | |
additionalInfo.gross_amount | Object | M | ||
additionalInfo.gross_amount.value | String (ISO4217) | M | Gross amount value | |
additionalInfo.gross_amount.currency | String | M | Gross amount currency | |
additionalInfo.payOptionDetails | Array of Object | M | Payment option detail | |
additionalInfo.payOptionDetails.payMethod | String | M | Possible value: `GOPAY` | |
additionalInfo.payOptionDetails.payOptions | String | M | Gopay payment option used. . Possible value: `GOPAY_WALLET`, `PAY_LATER`. | |
additionalInfo.transactionTime | String | O | Timestamp of transaction in ISO 8601 format. Time zone: GMT+7. | |
additionalInfo.transactionStatus | String | O | Transaction status
Possible Values:
|
|
additionalInfo.fraudStatus | String | O | Fraud status from Midtrans. Possible values: - accept --> Transaction is safe to proceed. It is not considered as a fraud. - deny --> Transaction is considered as fraud. It is rejected by Midtrans. |
|
additionalInfo.validUpTo | String(25) | O | The time when the payment will be automatically expired. Using ISO 8601 format. |
{
"responseCode":"20054000",
"responseMessage":"Request has been processed successfully",
"referenceNo":"gopay-order-id",
"partnerReferenceNo":"merchant-order-id",
"webRedirectUrl":"https://pjsp.com/universal?bizNo=REF993883&...",
"appRedirectUrl":"https://pjsp.com/universal?bizNo=REF993883&...",
"additionalInfo":{
"grossAmount":{
"value": "12345678.00",
"currency": "IDR"
},
"currency":"IDR",
"amount": "12345678.00",
"status": "PENDING",
"expiryTime": "2024-03-28T07:49:09.00Z"
"paymentType": "GOPAY",
"payOptionDetails" : [{
"payMethod":"GOPAY",
"payOption": "GOPAY_WALLET"
}],
"transactionTime":"2024-03-19T14:30:00+07:00",
"transactionStatus":"03",
"fraudStatus":"accept" ,
"validUpTo":"2023-07-03T10:36:17+07:00"
}
}
{
"responseCode":"4001001",
"responseMessage":"There is some issue with the transaction request",
"originalExternalId": "merchant-order-id",
}
List of response code
Response Code | HTTP Status Code | Response Message |
2005400 | 200 | Successful |
4005402 | 400 | Invalid Mandatory Field chargeToken , partnerReferenceNo |
4015400 | 401 | Unauthorized. Auth token required |
4015401 | 401 | Invalid Token (B2B) |
4015402 | 401 | Invalid Customer Token |
4035403 | 403 | Suspected Fraud |
4035414 | 403 | Insufficient Funds |
4035415 | 403 | Transaction Not Permitted. Url not whitelisted. |
5005401 | 500 | Internal Server Error |
5045400 | 504 | Timeout |