doku nodejs library
npm install doku-nodejs-libraryIf your looking for another language PHP, Go, Python, Java
bash
npm i doku-nodejs-library
`$3
Before using the Doku Snap SDK, you need to initialize it with your credentials:
1. Client ID, Secret Key and DOKU Public Key: Retrieve these from the Integration menu in your Doku Dashboard
2. Private Key and Public Key : Generate your Private Key and Public KeyHow to generate Merchant privateKey and publicKey :
1. generate private key RSA : openssl genrsa -out private.key 2048
2. set passphrase your private key RSA : openssl pkcs8 -topk8 -inform PEM -outform PEM -in private.key -out pkcs8.key -v1 PBE-SHA1-3DES
3. generate public key RSA : openssl rsa -in private.key -outform PEM -pubout -out public.pem
The encryption model applied to messages involves both asymmetric and symmetric encryption, utilizing a combination of Private Key and Public Key, adhering to the following standards:
1. Standard Asymmetric Encryption Signature: SHA256withRSA dengan Private Key ( Kpriv ) dan Public Key ( Kpub ) (256 bits)
2. Standard Symmetric Encryption Signature HMAC_SHA512 (512 bits)
3. Standard Symmetric Encryption AES-256 dengan client secret sebagai encryption key.
| Parameter | Description | Required |
|-----------------|----------------------------------------------------|--------------|
|
privateKey | The private key for the partner service. | ✅ |
| publicKey | The public key for the partner service. | ✅ |
| dokuPublicKey | Key that merchants use to verify DOKU request | ✅ |
| clientId | The client ID associated with the service. | ✅ |
| secretKey | The secret key for the partner service. | ✅ |
| isProduction | Set to true for production environment | ✅ |
| issuer | Optional issuer for advanced configurations. | ❌ |
| authCode | Optional authorization code for advanced use. | ❌ |
`js
const doku = require('doku-nodejs-library');let privateKey =
-----BEGIN PRIVATE KEY-----;
let issuer = "your issuer";
let clientID = "your client id";
let publicKey = -----BEGIN PUBLIC KEY-----;
let dokuPublicKey = -----BEGIN PUBLIC KEY-----;
let secretKey = 'SK-VknOxwR4xZSEPnG7fpJo';
let snap = new doku.Snap({
isProduction : false,
privateKey : privateKey,
clientID : clientID,
publicKey :publicKey,
dokuPublicKey:dokuPublicKey,
issuer:issuer,
secretKey:secretKey
});
`2. Usage
Initialization
Always start by initializing the Snap object.
`js
let snap = new doku.Snap({
isProduction : false,
privateKey : privateKey,
clientID : clientID,
publicKey :publicKey,
dokuPublicKey:dokuPublicKey,
issuer:issuer,
secretKey:secretKey
});
`
$3
#### I. Virtual Account (DGPC & MGPC)
##### DGPC
- Description: A pre-generated virtual account provided by DOKU.
- Use Case: Recommended for one-time transactions.
##### MGPC
- Description: Merchant generated virtual account.
- Use Case: Recommended for top up business model.Parameters for createVA and updateVA
Parameter
Description
Data Type
Required
partnerServiceId
The unique identifier for the partner service.
String(20)
✅
customerNo
The customer's identification number.
String(20)
✅
virtualAccountNo
The virtual account number associated with the customer.
String(20)
✅
virtualAccountName
The name of the virtual account associated with the customer.
String(255)
✅
virtualAccountEmail
The email address associated with the virtual account.
String(255)
❌
virtualAccountPhone
The phone number associated with the virtual account.
String(9-30)
❌
trxId
Invoice number in Merchants system.
String(64)
✅
totalAmount
value: Transaction Amount (ISO 4217)
Example: "11500.00"
String(16.2)
✅
Currency: Currency
Example: "IDR"
String(3)
✅
additionalInfo
channel: Channel that will be applied for this VA
Example: VIRTUAL_ACCOUNT_BANK_CIMB
String(20)
✅
virtualAccountConfig
reusableStatus: Reusable Status For Virtual Account Transaction
value TRUE or FALSE
Boolean
❌
minAmount: Minimum Amount can be used only if virtualAccountTrxType is Open Amount (O).
Example: "10000.00"
String(16.2)
❌
maxAmount: Maximum Amount can be used only if virtualAccountTrxType is Open Amount (O).
Example: "5000000.00"
String(16.2)
❌
virtualAccountTrxType
Transaction type for this transaction. C (Closed Amount), O (Open Amount)
String(1)
✅
expiredDate
Expiration date for Virtual Account. ISO-8601
Example: "2023-01-01T10:55:00+07:00"
String
❌
freeText
English: Free text for additional description.
Example: "Free text"
String(64)
❌
Indonesia: Free text for additional description.
Example: "Tulisan Bebas"
String(64)
❌
1. Create Virtual Account
- Function:
createVa
`js
const CreateVARequestDto = require('doku-nodejs-library/_models/createVaRequestDto');
const VirtualAccountConfig = require('doku-nodejs-library/_models/virtualAccountConfig');
const TotalAmount = require('doku-nodejs-library/_models/totalAmount');
const AdditionalInfo = require('doku-nodejs-library/_models/additionalInfo');
app.post('/create-va', async (req,res) => {
let createVaRequestDto = new CreateVARequestDto();
createVaRequestDto.partnerServiceId = req.body.partnerServiceId;
createVaRequestDto.customerNo =req.body.customerNo;
createVaRequestDto.virtualAccountNo = req.body.partnerServiceId+req.body.customerNo;
createVaRequestDto.virtualAccountName = req.body.virtualAccountName;
createVaRequestDto.virtualAccountEmail = req.body.virtualAccountEmail;
createVaRequestDto.virtualAccountPhone = req.body.virtualAccountPhone;
createVaRequestDto.trxId = req.body.trxId;
let totalAmount = new TotalAmount();
totalAmount.value = req.body.totalAmount.value;
totalAmount.currency = req.body.totalAmount.currency;
createVaRequestDto.totalAmount = totalAmount;
let virtualAccountConfig = new VirtualAccountConfig();
virtualAccountConfig.reusableStatus = req.body.additionalInfo.virtualAccountConfig.reusableStatus;
let additionalInfo = new AdditionalInfo("VIRTUAL_ACCOUNT_BANK_CIMB", virtualAccountConfig);
additionalInfo.channel = req.body.additionalInfo.channel;
additionalInfo.virtualAccountConfig = virtualAccountConfig;
createVaRequestDto.additionalInfo = additionalInfo;
createVaRequestDto.virtualAccountTrxType =req.body.virtualAccountTrxType;
createVaRequestDto.expiredDate = req.body.expiredDate;
await snap.createVa(createVaRequestDto).then(va=>{
res.status(200).send(va);
}).catch(err=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
})
`2. Update Virtual Account
- Function:
updateVa
`js
const UpdateVaVirtualAccountConfigDto = require('doku-nodejs-library/_models/updateVaVirtualAccountConfigDTO');
const VirtualAccountConfig = require('doku-nodejs-library/_models/virtualAccountConfig');
const TotalAmount = require('doku-nodejs-library/_models/totalAmount');
const UpdateVaAdditionalInfoDto = require('doku-nodejs-library/_models/updateVaAdditionalInfoDTO');
app.post('/update-va', async (req,res) => {
let updateVaRequestDto = new UpdateVaDto()
updateVaRequestDto.partnerServiceId = req.body.partnerServiceId;
updateVaRequestDto.customerNo = req.body.customerNo;
updateVaRequestDto.virtualAccountNo = updateVaRequestDto.partnerServiceId+updateVaRequestDto.customerNo;
updateVaRequestDto.virtualAccountName = req.body.virtualAccountName;
updateVaRequestDto.virtualAccountEmail = req.body.virtualAccountEmail;
updateVaRequestDto.trxId = req.body.trxId
let totalAmount = new TotalAmount();
totalAmount.value = req.body.totalAmount.value;
totalAmount.currency = req.body.totalAmount.currency;
updateVaRequestDto.totalAmount = totalAmount;
let virtualAccountConfig = new UpdateVaVirtualAccountConfigDto();
virtualAccountConfig.status = "INACTIVE"; let additionalInfo = new UpdateVaAdditionalInfoDto(req.body.additionalInfo.channel, virtualAccountConfig);
additionalInfo.channel = req.body.additionalInfo.channel;
additionalInfo.virtualAccountConfig = virtualAccountConfig;
updateVaRequestDto.additionalInfo = additionalInfo;
updateVaRequestDto.virtualAccountTrxType = "C";
updateVaRequestDto.expiredDate = req.body.expiredDate;
console.log(updateVaRequestDto)
await snap.updateVa(updateVaRequestDto).then(va=>{
res.status(200).send(va);
}).catch((err)=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
})
`3. Delete Virtual Account
| Parameter | Description | Data Type | Required |
|-----------------------|----------------------------------------------------------------------------|---------------------|--------------|
|
partnerServiceId | The unique identifier for the partner service. | String(8) | ✅ |
| customerNo | The customer's identification number. | String(20) | ✅ |
| virtualAccountNo | The virtual account number associated with the customer. | String(20) | ✅ |
| trxId | Invoice number in Merchant's system. | String(64) | ✅ |
| additionalInfo | channel: Channel applied for this VA.
Example: VIRTUAL_ACCOUNT_BANK_CIMB | String(30) | ✅ |
- Function:
deletePaymentCode
`js
const DeleteVaRequestDto = require('doku-nodejs-library/_models/deleteVaRequestDTO');
const DeleteVaRequestAdditionalInfo = require('doku-nodejs-library/_models/deleteVaRequestAdditionalInfoDTO');
app.post('/delete-va', async (req,res) => {
let deleteVaRequestDto = new DeleteVaRequestDto()
deleteVaRequestDto.partnerServiceId = req.body.partnerServiceId;
deleteVaRequestDto.customerNo = req.body.customerNo;
deleteVaRequestDto.virtualAccountNo = req.body.virtualAccountNo
deleteVaRequestDto.trxId = req.body.trxId
let additionalInfo = new DeleteVaRequestAdditionalInfo(req.body.additionalInfo.channel);
deleteVaRequestDto.additionalInfo = additionalInfo;
await snap.deletePaymentCode(deleteVaRequestDto).then(response=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
})
`
#### II. Virtual Account (DIPC)
- Description: The VA number is registered on merchant side and DOKU will forward Acquirer inquiry request to merchant side when the customer make payment at the acquirer channel
- Function:
directInquiryVa
`js
const InquiryResponseVirtualAccountDataDTO = require('doku-nodejs-library/_models/InquiryResponseVirtualAccountDataDTO');
const InquiryResponseBodyDTO = require('doku-nodejs-library/_models/inquiryResponseBodyDTO');
const TotalAmount = require('doku-nodejs-library/_models/totalAmount');
const InquiryResponseAdditionalInfoDTO = require('doku-nodejs-library/_models/inquiryResponseAdditionalInfoDTO');
const VirtualAccountConfig = require('doku-nodejs-library/_models/virtualAccountConfig');
const InquiryReasonDto = require('doku-nodejs-library/_models/inquiryReasonDTO');
app.post("/v1.1/transfer-va/inquiry",(req,res)=>{
let data = new InquiryRequestDTO();
data.partnerServiceId = req.body.partnerServiceId;
data.customerNo = req.body.customerNo;
data.virtualAccountNo = req.body.virtualAccountNo;
data.trxDateInit = req.body.trxDateInit;
data.inquiryRequestId = req.body.inquiryRequestId;
data.additionalInfo = req.body.additionalInfo;
let isvalid = snap.validateTokenB2B(req.headers['authorization']);
if(isvalid){
let bodyData = new InquiryResponseBodyDTO()
bodyData.responseCode = "2002400";
bodyData.responseMessage = "Successful"
let vaData = new InquiryResponseVirtualAccountDataDTO()
vaData.partnerServiceId = req.body.partnerServiceId;
vaData.customerNo = req.body.customerNo;
vaData.virtualAccountNo = req.body.virtualAccountNo;
vaData.virtualAccountName = "Nama "+Date.now();
vaData.virtualAccountEmail ="email."+Date.now()+"@gmail.com";
vaData.virtualAccountPhone = ${Date.now()};
let totalAmount = new TotalAmount()
totalAmount.currency = "IDR";
totalAmount.value = "25000.00"
vaData.totalAmount = totalAmount;
vaData.virtualAccountTrxType = "C"
let additionalInfo = new InquiryResponseAdditionalInfoDTO()
additionalInfo.channel = req.body.additionalInfo.channel;
additionalInfo.trxId = "INV_MERCHANT_"+Date.now();
let virtualAccountConfig = new VirtualAccountConfig()
virtualAccountConfig.reusableStatus = true;
virtualAccountConfig.maxAmount = "100000.00";
virtualAccountConfig.minAmount = "10000.00"
additionalInfo.virtualAccountConfig = virtualAccountConfig;
vaData.additionalInfo = additionalInfo;
vaData.inquiryStatus ="00";
let inquiryReason = new InquiryReasonDto()
inquiryReason.english = "Success";
inquiryReason.indonesia = "Sukses";
vaData.inquiryReason = inquiryReason;
vaData.inquiryRequestId = req.body.inquiryRequestId;
vaData.freeText = [
{
"english": "Free text",
"indonesia": "Tulisan Bebas"
}
]
bodyData.virtualAccountData = vaData;
}else{
let body ={
"responseCode": "4010000",
"responseMessage": "Unauthorized",
}
res.status(401).send(body);
}})
`#### III. Check Virtual Account Status
| Parameter | Description | Data Type | Required |
|-----------------------|----------------------------------------------------------------------------|---------------------|--------------|
|
partnerServiceId | The unique identifier for the partner service. | String(8) | ✅ |
| customerNo | The customer's identification number. | String(20) | ✅ |
| virtualAccountNo | The virtual account number associated with the customer. | String(20) | ✅ |
| inquiryRequestId | The customer's identification number. | String(128) | ❌ |
| paymentRequestId | The virtual account number associated with the customer. | String(128) | ❌ |
| additionalInfo | The virtual account number associated with the customer. | String | ❌ | - Function:
checkStatusVa
`js
const CheckStatusVARequestDto = require('doku-nodejs-library/_models/checkStatusVARequestDTO');
app.post('/check-status', async (req,res) => {
let checkVaRequestDto = new CheckStatusVARequestDto()
checkVaRequestDto.partnerServiceId = req.body.partnerServiceId;
checkVaRequestDto.customerNo = req.body.customerNo;
checkVaRequestDto.virtualAccountNo = checkVaRequestDto.partnerServiceId+checkVaRequestDto.customerNo;
await snap.checkStatusVa(checkVaRequestDto).then(response=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
})
`$3
The card registration/account binding process must be completed before payment can be processed. The merchant will send the card registration request from the customer to DOKU.Each card/account can only registered/bind to one customer on one merchant. Customer needs to verify OTP and input PIN.
| Services | Binding Type | Details |
|-------------------|-----------------------|-----------------------------------|
| Direct Debit | Account Binding | Supports Allo Bank and CIMB |
| Direct Debit | Card Registration | Supports BRI |
| E-Wallet | Account Binding | Supports OVO |
#### I. Account Binding
1. Binding
Parameter
Description
Data Type
Required
phoneNo
Phone Number Customer.
Format: 628238748728423
String(9-16)
✅
additionalInfo
channel: Payment Channel
String
✅
custIdMerchant: Customer id from merchant
String(64)
✅
customerName: Customer name from merchant
String(70)
❌
email: Customer email from merchant
String(64)
❌
idCard: Customer id card from merchant
String(20)
❌
country: Customer country
String
❌
address: Customer Address
String(255)
❌
dateOfBirth
String(YYYYMMDD)
❌
successRegistrationUrl: Redirect URL when binding is success
String
✅
failedRegistrationUrl: Redirect URL when binding is success fail
String
✅
deviceModel: Device Model customer
String
✅
osType: Format: ios/android
String
✅
channelId: Format: app/web
String
✅
- Function:
doAccountBinding
`js
const AccountBindingRequestDto = require('doku-nodejs-library/_models/accountBindingRequestDTO');
app.post("/account-binding", async (req,res)=>{
let request = new AccountBindingRequestDto()
request.phoneNo = req.body.phoneNo
request.additionalInfo = req.body.additionalInfo;
let ipAddress = req.headers['x-ip-address'];
let deviceId = req.headers['x-device-id'];
await snap.doAccountBinding(request,ipAddress,deviceId).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(parseInt(err.response.data.responseCode.substring(0, 3))).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`1. Unbinding
- Function:
getTokenB2B2C
`js
app.post('/token-b2b2c', async (req,res) => {
let authCode = req.body['authCode'];
await snap.getTokenB2B2c(authCode).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`
- Function: doAccountUnbinding
`js
const {AccountUnbindingRequestDto,AccountUnbindingAdditionalInfo} = require('doku-nodejs-library/_models/accountUnbindingRequestDTO');
app.post("/account-unbinding", async (req,res)=>{
let request = new AccountUnbindingRequestDto()
let additionalInfo = new AccountUnbindingAdditionalInfo(req.body.additionalInfo.channel)
request.tokenId = req.body.tokenId;
request.additionalInfo = additionalInfo;
let ipAddress = req.headers['x-ip-address'];
await snap.doAccountUnbinding(request,ipAddress).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`#### II. Card Registration
1. Registration
- Function:
doCardRegistration
`js
const CardRegistrationRequestDTO = require('doku-nodejs-library/_models/cardRegistrationRequestDTO');
app.post("/card-registration", async (req,res)=>{
let request = new CardRegistrationRequestDTO()
request.cardData = req.body.cardData;
request.custIdMerchant = req.body.custIdMerchant;
request.phoneNo = req.body.phoneNo;
request.additionalInfo = req.body.additionalInfo;
console.log(request)
await snap.doRegistrationCardBind(request).then((response)=>{
res.status(200).send(response.data);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
console.log(err)
res.status(500).send({"message":err.message});
}
})
})
`2. UnRegistration
- Function:
getTokenB2B2C
`js
app.post('/token-b2b2c', async (req,res) => {
let authCode = req.body['authCode'];
await snap.getTokenB2B2c(authCode).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`
- Function: doCardUnbinding
`js
const CardUnRegistUnbindRequestDTO= require('doku-nodejs-library/_models/cardUnregistUnbindRequestDTO');
app.post("/card-unbinding", async (req,res)=>{
let request = new CardUnRegistUnbindRequestDTO(req.body.tokenId,
req.body.additionalInfo
)
await snap.doUnRegistCardUnBind(request).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
console.log(err)
res.status(500).send({"message":err.message});
}
})
})
`$3
#### I. Request Payment
Once a customer’s account or card is successfully register/bind, the merchant can send a payment request. This section describes how to send a unified request that works for both Direct Debit and E-Wallet channels.
| Acquirer | Channel Name |
|-------------------|--------------------------|
| Allo Bank | DIRECT_DEBIT_ALLO_SNAP |
| BRI | DIRECT_DEBIT_BRI_SNAP |
| CIMB | DIRECT_DEBIT_CIMB_SNAP |
| OVO | EMONEY_OVO_SNAP |
##### Common parameter
Parameter
Description
Data Type
Required
partnerReferenceNo
Reference No From Partner
Format: 628238748728423
String(9-16)
✅
amount
value: Transaction Amount (ISO 4217)
Example: "11500.00"
String(16.2)
✅
Currency: Currency
Example: "IDR"
String(3)
✅
additionalInfo
channel: payment channel
String
✅
remarks:Remarks from Partner
String(40)
✅
successPaymentUrl: Redirect Url if payment success
String
✅
failedPaymentUrl: Redirect Url if payment fail
String
✅
##### Allo Bank Specific Parameters
| Parameter | Description | Required |
|--------------------------------------|---------------------------------------------------------------|--------------|
|
additionalInfo.remarks | Remarks from the partner | ✅ |
| additionalInfo.lineItems.name | Item name (String) | ✅ |
| additionalInfo.lineItems.price | Item price (ISO 4217) | ✅ |
| additionalInfo.lineItems.quantity | Item quantity (Integer) | ✅ |
| payOptionDetails.payMethod | Balance type (options: BALANCE/POINT/PAYLATER) | ✅ |
| payOptionDetails.transAmount.value | Transaction amount | ✅ |
| payOptionDetails.transAmount.currency | Currency (ISO 4217, e.g., "IDR") | ✅ |
##### CIMB Specific Parameters
| Parameter | Description | Required |
|--------------------------------------|---------------------------------------------------------------|--------------|
|
additionalInfo.remarks | Remarks from the partner | ✅ |
##### OVO Specific Parameters
| Parameter | Description | Required |
|------------------------------------------|---------------------------------------------------------------|--------------|
|
feeType | Fee type from partner (values: OUR, BEN, SHA) | ❌ |
| payOptionDetails.payMethod | Payment method format: CASH, POINTS | ✅ |
| payOptionDetails.transAmount.value | Transaction amount (ISO 4217) | ✅ |
| payOptionDetails.transAmount.currency | Currency (ISO 4217, e.g., "IDR") | ✅ |
| payOptionDetails.feeAmount.value | Fee amount (if applicable) | ✅ |
| payOptionDetails.feeAmount.currency | Currency for the fee | ✅ |
| additionalInfo.paymentType | Transaction type (values: SALE, RECURRING) | ✅ |
Here’s how you can use the
doPayment function for both payment types:
- Function: doPayment
`js
const { PaymentRequestDto } = require('doku-nodejs-library/_models/paymentRequestDirectDebitDTO');
app.post("/debit-payment", async (req,res)=>{
let request = new PaymentRequestDto()
request.payOptionDetails = req.body.payOptionDetails;
request.partnerReferenceNo = req.body.partnerReferenceNo;
request.amount = req.body.amount;
request.additionalInfo = req.body.additionalInfo;
let ipAddress = req.headers['x-ip-address'];
let authCode = req.body['authCode'];
await snap.doPayment(request,authCode,ipAddress).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`#### II. Request Payment Jump APP
| Acquirer | Channel Name |
|-------------------|--------------------------|
| DANA | EMONEY_DANA_SNAP |
| ShopeePay | EMONEY_SHOPEE_PAY_SNAP |
The following fields are common across DANA and ShopeePay requests:
Parameter
Description
Data Type
Required
partnerReferenceNo
Reference No From Partner
Examplae : INV-0001
String(9-16)
✅
validUpto
Expired time payment url
String
❌
pointOfInitiation
Point of initiation from partner,
value: app/pc/mweb
String
❌
urlParam
url: URL after payment sucess
String
✅
type: Pay Return
always PAY_RETURN
String
✅
isDeepLink: Is Merchant use deep link or not
Example: "Y/N"
String(1)
✅
amount
value: Transaction Amount (ISO 4217)
Example: "11500.00"
String(16.2)
✅
Currency: Currency
Example: "IDR"
String(3)
✅
additionalInfo
channel: payment channel
String
✅
##### DANA
DANA spesific parameters
Parameter
Description
Data Type
Required
additionalInfo
orderTitle: Order title from merchant
String
❌
supportDeepLinkCheckoutUrl : Value 'true' for Jumpapp behaviour, 'false' for webview, false by default
String
❌
For Shopeepay and Dana you can use the doPaymentJumpApp function for for Jumpapp behaviour- Function:
doPaymentJumpApp`js
const PaymentJumpAppRequestDto = require('doku-nodejs-library/_models/paymentJumpAppRequestDTO');
app.post("/payment-jump-app", async (req,res)=>{
let request = new PaymentJumpAppRequestDto()
request.partnerReferenceNo = req.body.partnerReferenceNo;
request.pointOfInitiation = req.body.pointOfInitiation;
request.urlParam = req.body.urlParam;
request.amount = req.body.amount;
request.additionalInfo = req.body.additionalInfo;
request.validUpto = req.body.validUpto;
let ipAddress = req.headers['x-ip-address'];
let deviceId = req.headers['x-device-id'];
await snap.doPaymentJumpApp(request,ipAddress,deviceId).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`
3. Other Operation
$3
`js
const CheckStatusDirectDebitDTO = require('doku-nodejs-library/_models/checkStatusDirectDebitRequestDTO');
app.post('/debit-status', async (req,res) => {
let request = new CheckStatusDirectDebitDTO()
request.originalExternalId = req.body.originalExternalId
request.originalPartnerReferenceNo= req.body.originalPartnerReferenceNo
request.originalReferenceNo = req.body.originalReferenceNo
request.serviceCode = req.body.serviceCode
request.transactionDate= req.body.transactionDate
request.amount = req.body.amount
request.merchantId = req.body.merchantId
request.subMerchantId = req.body.subMerchantId
request.externalStoreId= req.body.externalStoreId
request.additionalInfo= req.body.additionalInfo
await snap.doCheckStatus(request).then(response=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
})
`$3
`js
const RefundRequestDto = require('doku-nodejs-library/_models/refundRequestDTO');
app.post("/refund", async (req,res)=>{
let request = new RefundRequestDto();
request.originalPartnerReferenceNo = req.body.originalPartnerReferenceNo;
request.refundAmount = req.body.refundAmount;
request.partnerRefundNo = req.body.partnerRefundNo;
request.originalExternalId = req.body.originalExternalId;
request.reason = req.body.reason;
request.additionalInfo = req.body.additionalInfo;
let ipAddress = req.headers['x-ip-address'];
let authCode = req.body['authCode'];
let deviceId = req.headers['deviceId'];
await snap.doRefund(request,authCode,ipAddress,deviceId).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`$3
`js
const BalanceInquiryRequestDto = require('doku-nodejs-library/_models/balanceInquiryRequestDTO');
app.post("/balance-inquiry", async (req,res)=>{
let request = new BalanceInquiryRequestDto();
request.additionalInfo = req.body.additionalInfo
let ipAddress = req.headers['x-ip-address'];
let authCode = req.body['authCode'];
await snap.doBalanceInquiry(request,authCode,ipAddress).then((response)=>{
res.status(200).send(response);
}).catch((err)=>{
if(err.response?.data){
res.status(err.response.status).send(err.response.data);
}else{
res.status(500).send({"message":err.message});
}
})
})
`4. Error Handling and Troubleshooting
The SDK throws exceptions for various error conditions. Always wrap your API calls in try-catch blocks:
`js
await snap.createVa(createVaRequestDto).then(va=>{
res.status(200).send(va);
}).catch(err=>{
if(err.response){
res.status(400).send(err.response.data)
}else{
res.status(400).send({
responseCode:"400",
responseMessage:err.message
})
}
})
`This section provides common errors and solutions:
| Error Code | Description | Solution |
|------------|---------------------------------------|----------------------------------------------|
|
4010000 | Unauthorized | Check if Client ID and Secret Key are valid. |
| 4012400 | Virtual Account Not Found | Verify the virtual account number provided. |
| 2002400` | Successful | Transaction completed successfully. |