dinger-merchant-pay-api

1.2.8 • Public • Published

Dinger Merchant Pay API

  • 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

Installation

npm install dinger-merchant-pay-api --save

IDEA

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}`));

1. Creating Instance

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
)

2. Switching 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'
)

3. Creating Order [Pay]

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'}]" 
    });
[Response] Country Code
{
  "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"
    }
}

7. Get All Namespaces

// 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)
    })

10. Callback Handling

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}`));

Summary

  • 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.

Package Sidebar

Install

npm i dinger-merchant-pay-api

Weekly Downloads

46

Version

1.2.8

License

ISC

Unpacked Size

40.9 kB

Total Files

4

Last publish

Collaborators

  • nawingngan