
Security News
Astral Launches pyx: A Python-Native Package Registry
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
doku-nodejs-library
Advanced tools
Welcome to the DOKU NODE JS SDK! This SDK simplifies access to the DOKU API for your server-side NODE JS applications, enabling seamless integration with payment and virtual account services.
If your looking for another language PHP, Go, Python, Java
To install the Doku Snap SDK, use Composer:
npm i doku-nodejs-library
Before using the Doku Snap SDK, you need to initialize it with your credentials:
How to generate Merchant privateKey and publicKey :
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:
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. | ❌ |
const doku = require('doku-nodejs-library');
let privateKey = `-----BEGIN PRIVATE KEY-----
your privatekey
-----END PRIVATE KEY-----`;
let issuer = "your issuer";
let clientID = "your client id";
let publicKey = `-----BEGIN PUBLIC KEY-----
your public key
-----END PUBLIC KEY-----`;
let dokuPublicKey = `-----BEGIN PUBLIC KEY-----
doku public key
-----END 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
});
Initialization Always start by initializing the Snap object.
let snap = new doku.Snap({
isProduction : false,
privateKey : privateKey,
clientID : clientID,
publicKey :publicKey,
dokuPublicKey:dokuPublicKey,
issuer:issuer,
secretKey:secretKey
});
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) | ❌ |
Create Virtual Account
createVa
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
})
}
})
})
Update Virtual Account
updateVa
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
})
}
})
})
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
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
})
}
})
})
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
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){
<!--validate yout virtualAccountNo in your database-->
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);
}})
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 | ❌ |
checkStatusVa
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
})
}
})
})
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 |
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
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});
}
})
})
getTokenB2B2C
app.post('/token-b2b2c', async (req,res) => {
<!--YOUR_AUTH_CODE_FROM_ACCOUNT_BINDING-->
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});
}
})
})
doAccountUnbinding
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});
}
})
})
Registration
doCardRegistration
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});
}
})
})
UnRegistration
getTokenB2B2C
app.post('/token-b2b2c', async (req,res) => {
<!--YOUR_AUTH_CODE_FROM_ACCOUNT_BINDING-->
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});
}
})
})
doCardUnbinding
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});
}
})
})
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 |
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 | ✅ |
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") | ✅ |
Parameter | Description | Required |
---|---|---|
additionalInfo.remarks | Remarks from the partner | ✅ |
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
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});
}
})
})
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 Returnalways PAY_RETURN | String | ✅ | |
isDeepLink : Is Merchant use deep link or notExample: "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 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 | ❌ |
doPaymentJumpApp
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});
}
})
})
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
})
}
})
})
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});
}
})
})
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});
}
})
})
The SDK throws exceptions for various error conditions. Always wrap your API calls in try-catch blocks:
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. |
FAQs
doku nodejs library
The npm package doku-nodejs-library receives a total of 29 weekly downloads. As such, doku-nodejs-library popularity was classified as not popular.
We found that doku-nodejs-library demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.