- If you have any questions, always refer back to the API documentation
- https://dinger.asia/developers/eng
- Purpose of this package is
- after creating order, the implemation flow could become very messy because of different payment providers has many different ways
- and not waste a lot of time for the callback implementation
npm install dinger-merchant-pay-api --save
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const PORT = process.env.PORT || 3000;
const DingerMerchantPayApi = require("dinger-merchant-pay-api");
const DingerMerchantPay = new DingerMerchantPayApi(
process.env.DINGER_PROJECT_NAME,
process.env.DINGER_MERCHANT_NAME,
process.env.DINGER_API_KEY,
process.env.DINGER_PUBLIC_KEY,
process.env.DINGER_CALLBACK_KEY,
process.env.DINGER_ENVIRONMENT
)
app.use(bodyParser.json());
// Dinger Merchant API create order endpoint
app.post("/dinger-create-order", async (req, res) => {
let payload = {
'providerName': req.body.providerName,
'methodName': req.body.methodName,
'totalAmount': req.body.totalAmount,
'orderId': req.body.orderId,
'customerPhone': req.body.customerPhone,
"customerName": req.body.customerName,
"description": req.body.description,
"customerAddress": req.body.customerAddress,
"items": req.body.items,
}
let validationResponse = await DingerMerchantPay.validatePayload(payload);
// Do your before hook here
if (validationResponse.pass) {
let payResponse = await DingerMerchantPay.pay(payload);
// Do your after hook here
let flowResponse = await DingerMerchantPay.handleVendorResponse(payload, payResponse);
res.json(flowResponse)
}
if (!validationResponse.pass) {
console.log(validationResponse.message);
return res.status(401).json({ message: "Validation Failed" });
}
res.status(200).json({ message: "Success" });
});
// Dinger Merchant API callback endpoint
app.post("/dinger-callback", async (req, res) => {
try {
let cbResponse = await DingerMerchantPay.verifyCb(req.body);
if (cbResponse.transactionStatus === "SUCCESS") {
// Do your stuffs
}
res.status(200).json({ message: "Success" });
}.catch(( error ) => {
return res.status(403).json({ message: "Unauthorized" });
})
});
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`));
const DingerMerchantPayApi = require("dinger-merchant-pay-api");
const DingerMerchantPay = new DingerMerchantPayApi(
process.env.DINGER_PROJECT_NAME,
process.env.DINGER_MERCHANT_NAME,
process.env.DINGER_API_KEY,
process.env.DINGER_PUBLIC_KEY,
process.env.DINGER_CALLBACK_KEY,
process.env.DINGER_ENVIRONMENT
)
// Please Note: Dinger does not provide UAT environment for credit cards
// MPU / Visa / Master
// There is also no posible way to handle callback in UAT environment
const DingerMerchantPayApi = require("dinger-merchant-pay-api");
const DingerMerchantPay = new DingerMerchantPayApi(
DINGER_PROJECT_NAME,
DINGER_MERCHANT_NAME,
DINGER_API_KEY,
DINGER_PUBLIC_KEY,
DINGER_CALLBACK_KEY,
DINGER_ENVIRONMENT // <<<< 'PRODUCTION' | 'UAT'
)
DingerMerchantPay
.pay({
'providerName': opts.providerName,
'methodName': this.methodName,
'totalAmount': opts.totalAmount,
'orderId': opts.orderId,
'customerPhone': opts.customerPhone,
"customerName": opts.customerName,
"description": opts.description,
"customerAddress": opts.customerAddress,
"items": opts.items,
}).then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
})
Param |
Type |
Required |
Description |
providerName |
string |
true |
'KBZ Pay', 'WAVE PAY', 'MPU', 'KBZ Direct Pay', 'Citizens Pay', 'MAB Bank', 'Mytel', 'TrueMoney', 'CB Pay', 'AYA Pay', 'MPitesan', 'Onepay', 'Sai Sai Pay', 'Visa', 'Master', 'MPT Pay' |
methodName |
string |
true |
'PWA', 'QR', 'PIN', 'OTP' |
totalAmount |
number |
true |
|
orderId |
string |
true |
|
customerPhone |
string |
true |
|
customerName |
string |
true |
|
description |
string |
false |
|
customerAddress |
string |
false |
|
item |
Array |
true |
|
Item Details [MUST_BE_STRINGIFIED]
Param |
Type |
Required |
Description |
name |
string |
true |
|
amount |
string |
true |
|
quantity |
string |
true |
|
4. Handling Create Order Response
- Please Note: that implementation of different method has different responses.
- QR, PIN, OTP, PWA are different ..
- PWA responds redirect link,
- QR responds base64 images, some responds redirect
- OTP also responds redirect link
- MPU, Visa, Master responds >>[portal] redirect link (weird behaviour)
// I created a clean way to handle many different type of responses in 3 simple way.
let payload = {
'providerName': opts.providerName,
'methodName': this.methodName,
'totalAmount': opts.totalAmount,
'orderId': opts.orderId,
'customerPhone': opts.customerPhone,
'customerName': opts.customerName,
'description': opts.description,
'customerAddress': opts.customerAddress,
'items': opts.items,
}
let payResponse = await DingerMerchantPay.pay(payload);
let flowResponse = await DingerMerchantPay.handleVendorResponse(payload, payResponse);
console.log(flowResponse)
// {
// flowOperation: '', << String 'REDIRECT' | 'QR' | 'NOTIFICATION'
// redirectLink: '', << Redirect Link
// qrCode: '' << Base 64 String
// }
// you can respond directly to Front End
res.json(flowResponse)
- This is the idea, to implement your payment flow very clean.
flowOperation |
Key |
Description |
'REDIRECT' |
redirectLink |
open the link on your UI |
'QR' |
qrCode |
show QR code in your application |
'NOTIFICATION' |
|
Do nothing |
- To sum up there are 3 types of operations you need to implement on your front-end.
- Redirect to link
- Show QR code to scan on your application
- Do nothing. just wait for notification from the payment provider application
// Front End Example
// Hopefully this make sense
import axios from 'axios';
//const axios = require('axios'); // legacy way
axios
.post('/createOrder', {
'providerName': opts.providerName,
'methodName': this.methodName,
'totalAmount': opts.totalAmount,
'orderId': opts.orderId,
'customerPhone': opts.customerPhone,
'customerName': opts.customerName,
'description': opts.description,
'customerAddress': opts.customerAddress,
'items': opts.items,
})
.then( (flowResponse) => {
if (flowResponse.flowOperation === "REDIRECT") {
// Do A Redriect
window.open(flowResponse.redirectLink)
}
if (flowResponse.flowOperation === "QR") {
// This is base64 string of QR Code
// Show this on your application
console.log(flowResponse.qrCode)
}
if (flowResponse.flowOperation === "NOTIFICATION") {
// Do Nothing
// Show Pop Up In your front end Order Created & Wait For Nofication
}
})
5. Query Contry Code [Visa / Master / JCB]
let countryResponse = await DingerMerchantPay.queryCountryCode();
// For Visa, Master & JCB, there are additional fields that needs to add
let payResponse = await DingerMerchantPay
.pay({
"providerName": "Visa",
"methodName": "OTP",
"totalAmount" : 2200,
"orderId": "11111",
"email": "info@gmail.com",
"customerPhone" : "09787747310",
"customerName" : "test user name",
"state" : "customer state",
"country" : "customer country", // Must add 'code' value from Country Code List Enquiry API(/countryCodeListEnquiry) from Dinger **
"postalCode" : "customer postal code",
"billAddress" : "customer address",
"billCity" : "customer city",
"items" : "[{‘name':'Mac','amount':'1100','quantity':'2'}]"
});
{
"code": "000",
"message": "Request Success",
"time": "20250201 084550",
"response": [
{
"country": "Afghanistan",
"code": "AF"
},
{
"country": "Aland Islands",
"code": "AX"
},
]
}
6. Check If Users Is Available [Sai Sai Pay & UAB Pay]
DingerMerchantPay
.queryCheckPerson('092400000', 'UAB Pay')
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})
[Response] Valid User Found
{
"code": "000",
"message": "Request Success",
"time": "20221227 165655",
"response": {
"Code": "000",
"Message": "Success"
}
}
[Response] Valid User Not Found
{
"code": "000",
"message": "Request Success",
"time": "20221227 165755",
"response": {
"Code": "021",
"Message": "Invalid Wallet User"
}
}
// This is not offical. I created in this package because this list is very useful.
DingerMerchantPay
.queryAllNameSpace()
.then((response) => {
console.log(response)
})
.catch((error) => {
console.log(error)
})
8. Validating Request Order
// This is validating Logics
let payload = {
"providerName": "Visa",
"methodName": "OTP",
"totalAmount" : 2200,
"orderId": "11111",
"email": "info@gmail.com",
"customerPhone" : "09787747310",
"customerName" : "test user name",
"state" : "customer state",
"country" : "customer country",
"postalCode" : "customer postal code",
"billAddress" : "customer address",
"billCity" : "customer city",
"items" : "[{‘name':'Mac','amount':'1100','quantity':'2'}]"
}
// Putting Everything Together
let validationResponse = await DingerMerchantPay.validatePayload(payload);
if (validationResponse.pass) {
let payResponse = await DingerMerchantPay.pay(payload);
let flowResponse = await DingerMerchantPay.handleVendorResponse(payload, payResponse);
res.json(flowResponse)
}
if (!validationResponse.pass) {
console.log(validationResponse.message)
}
9. Transaction Fee Calculation
// @param {number} amount
// @param {string} vender
// @param {string} digital [yes|no] <<< KBZ Pay, KBZ M Banking takes (15% for virtual goods) (1.9% for non-virtual) >>>
DingerMerchantPay
.orderTransactionFee(5000, 'KBZ Pay', 'yes')
.then(( txFee ) => {
console.log(txFee)
})
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const PORT = process.env.PORT || 3000;
const DingerMerchantPayApi = require("dinger-merchant-pay-api");
const DingerMerchantPay = new DingerMerchantPayApi(
DINGER_PROJECT_NAME,
DINGER_MERCHANT_NAME,
DINGER_API_KEY,
DINGER_PUBLIC_KEY,
DINGER_CALLBACK_KEY,
DINGER_ENVIRONMENT
)
app.use(bodyParser.json());
// Dinger Merchant API callback endpoint
app.post("/dinger-webhook", async (req, res) => {
DingerMerchantPay
.verifyCb(req.body)
.then(( response ) => {
if (response.transactionStatus === "SUCCESS") {
// Do your stuffs
}
})
.catch(( error ) => {
return res.status(403).json({ message: "Unauthorized" });
})
res.status(200).json({ message: "Success" });
});
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`));
- If there are any issue, please feel free to contribute and contact me nawingngan@gmail.com
- If you find this package useful, please buy me a cup of coffee.
