opay-node
Version:
This NodeJS SDK makes it easy to integrate your applications & interact with the [OPay](https://opayweb.com) APIs.
459 lines (397 loc) • 11.5 kB
JavaScript
;
var got = require('got');
var _isEmpty = require('lodash.isempty');
var isObject = require('lodash.isobject');
var some = require('lodash.some');
var alphabetizeObjectKeys = require('alphabetize-object-keys');
var sortBy = require('lodash.sortby');
var getKeys = require('lodash.keys');
var forEach = require('lodash.foreach');
var crypto = require('crypto');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var got__default = /*#__PURE__*/_interopDefaultLegacy(got);
var _isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(_isEmpty);
var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
var some__default = /*#__PURE__*/_interopDefaultLegacy(some);
var alphabetizeObjectKeys__default = /*#__PURE__*/_interopDefaultLegacy(alphabetizeObjectKeys);
var sortBy__default = /*#__PURE__*/_interopDefaultLegacy(sortBy);
var getKeys__default = /*#__PURE__*/_interopDefaultLegacy(getKeys);
var forEach__default = /*#__PURE__*/_interopDefaultLegacy(forEach);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
var checkout = {
/**
* Initialize Transaction
*/
initializeTransaction: {
method: 'post',
path: `cashier/initialize`,
authorization: 'PUBLIC_KEY',
body: {
amount$: String,
callbackUrl$: String,
currency: String,
expireAt$: String,
mchShortName$: String,
payMethods: Array,
payTypes: Array,
productDesc$: String,
productName$: String,
reference$: String,
returnUrl$: String,
userPhone$: String,
userRequestIp$: String,
},
default_body: {
currency: 'NGN',
payMethods: ['account', 'qrcode', 'bankCard', 'bankAccount'],
payTypes: ['BalancePayment', 'BonusPayment', 'OWealth'],
},
},
/**
* Cashier Status
*/
cashierStatus: {
method: 'post',
path: `cashier/status`,
authorization: 'PUBLIC_KEY',
body: { orderNo$: String, reference$: String },
},
/**
* Close Transaction
*/
closeStatus: {
method: 'post',
path: `cashier/close`,
authorization: 'PUBLIC_KEY',
body: { orderNo$: String, reference$: String },
},
};
var inquiry = {
/**
* Query Balance
*/
queryBalance: {
method: 'post',
path: `balances`,
authorization: 'PUBLIC_KEY',
body: null,
},
/**
* Validate OPay User
*/
validateUser: {
method: 'post',
path: `info/user`,
authorization: 'PUBLIC_KEY',
body: { phoneNumber$: String },
},
/**
* Validate OPay Merchant
*/
validateMerchant: {
method: 'post',
path: `info/merchant`,
authorization: 'PUBLIC_KEY',
body: { email$: String },
},
/**
* Validate Bank Account Number
*/
validateBankAccount: {
method: 'post',
path: `verification/accountNumber/resolve`,
authorization: 'PUBLIC_KEY',
body: { bankAccountNo$: String, bankCode$: String, countryCode: String },
default_body: { countryCode: 'NG' },
},
};
var transfers = {
/**
* Transfer to User Wallet
*/
transferToUserWallet: {
method: 'post',
path: `transfer/toWallet`,
authorization: 'SIGNATURE',
body: {
amount$: String,
country: String,
currency: String,
reason$: String,
receiver$: Object,
'receiver.name$': String,
'receiver.phoneNumber$': String,
'receiver.type$': String,
reference$: String,
},
default_body: { country: 'NG', currency: 'NGN' },
},
/**
* Transfer to Merchant Wallet
*/
transferToMerchantWallet: {
method: 'post',
path: `transfer/toWallet`,
authorization: 'SIGNATURE',
body: {
amount$: String,
country: String,
currency: String,
reason$: String,
receiver$: Object,
'receiver.merchantId$': String,
'receiver.name$': String,
'receiver.type$': String,
reference$: String,
},
default_body: { country: 'NG', currency: 'NGN' },
},
/**
* Wallet Trasfer Status
*/
walletTransferStatus: {
method: 'post',
path: `transfer/status/toWallet`,
authorization: 'SIGNATURE',
body: { orderNo$: String, reference$: String },
},
/**
* Get list of banks
*/
getBanks: {
method: 'post',
path: `banks`,
authorization: 'PUBLIC_KEY',
body: { countryCode: String },
default_body: { countryCode: 'NG' },
},
/**
* Get list of countries
*/
getCountries: {
method: 'post',
path: `countries`,
authorization: 'PUBLIC_KEY',
body: null,
},
/**
* Transfer to Bank
*/
transferToBank: {
method: 'post',
path: `transfer/toBank`,
authorization: 'SIGNATURE',
body: {
amount$: String,
country$: String,
currency$: String,
reason$: String,
receiver$: Object,
'receiver.bankAccountNumber$': String,
'receiver.bankCode$': String,
'receiver.name$': String,
reference$: String,
},
default_body: { country: 'NG', currency: 'NGN' },
},
/**
* Bank Transfer status
*/
bankTransferStatus: {
method: 'post',
path: `transfer/status/toBank`,
authorization: 'SIGNATURE',
body: { orderNo$: String, reference$: String },
},
};
const sortObjectAlphabetically = (map) => {
const keys = sortBy__default['default'](getKeys__default['default'](map), (a) => {
return a;
});
const newmap = {};
forEach__default['default'](keys, (k) => {
newmap[k] = map[k];
});
return newmap;
};
const pluckDeep = (obj, key) => key.split('.').reduce((accum, item) => accum[item], obj);
const setDeep = (obj, key, value) => {
var i;
key = key.split('.');
for (i = 0; i < key.length - 1; i++) obj = obj[key[i]];
obj[key[i]] = value;
};
const generatePrivateKey = (key, data) => {
return crypto__default['default'].createHmac('sha512', key).update(JSON.stringify(data)).digest('hex');
};
const isLiteralFalsey = (variable) => {
return variable === '' || variable === false || variable === 0;
};
const checkTypeName = (target, type) => {
let typeName = '';
if (isLiteralFalsey(target)) {
typeName = typeof target;
} else {
typeName = '' + (target && target.constructor.name);
}
return !!(typeName.toLowerCase().indexOf(type) + 1);
};
const isTypeOf = (value, type) => {
let result = false;
type = type || [];
if (typeof type === 'object') {
if (typeof type.length !== 'number') {
return result;
}
let bitPiece = 0;
type = [].slice.call(type);
type.forEach((_type) => {
if (typeof _type === 'function') {
_type = (_type.name || _type.displayName).toLowerCase();
}
bitPiece |= 1 * checkTypeName(value, _type);
});
result = !!bitPiece;
} else {
if (typeof type === 'function') {
type = (type.name || type.displayName).toLowerCase();
}
result = checkTypeName(value, type);
}
return result;
};
const isNullOrUndefined = (value) => {
return isTypeOf(value, ['undefined', 'null']);
};
const getClientBody = (config, inputs) => {
let body = {};
let inputValues = {};
for (var input in config.body) {
if (config.body.hasOwnProperty(input)) {
let key = input.replace('$', '');
let value = pluckDeep(inputs, key);
let type = config.body[input];
let required = false;
if (input.indexOf('$') + 1 === input.length) {
required = true;
}
if ((isNullOrUndefined(value) || value === '') && required) {
throw new Error(`Param: ${key} is required but not provided; please provide as needed`);
} else {
setDeep(body, key, isTypeOf(value, type) ? value : null);
if (body[key] === null) {
throw new Error(`Key: "${key}" is not of type ${type.name || type}; please provided as needed`);
}
}
}
}
inputValues = JSON.stringify(body);
return inputValues;
};
var utils = {
generatePrivateKey,
getClientBody,
sortObjectAlphabetically,
};
const { generatePrivateKey: generatePrivateKey$1, getClientBody: getClientBody$1 } = utils;
const endpoints = Object.assign({}, checkout, inquiry, transfers);
const isEmpty = (value, defined) => {
if (defined && isObject__default['default'](value)) {
return !some__default['default'](value, function (value, key) {
return value !== undefined;
});
}
return _isEmpty__default['default'](value);
};
const createApiFunction = (config) => {
let customConfig = { headers: {} };
return function (params = {}) {
let payload = false;
let inputs = {};
if (config.body !== null) {
if (config.default_body) {
inputs = Object.assign({}, config.default_body, params);
} else {
inputs = Object.assign({}, params);
}
if (!(params instanceof Object)) {
throw new TypeError('Argument: [ params(s) ] Should Be An Object Literal');
}
if (!isEmpty(inputs, true)) {
const body = getClientBody$1(config, alphabetizeObjectKeys__default['default'](inputs));
payload = alphabetizeObjectKeys__default['default'](body);
} else {
throw new TypeError('Argument: [ params(s) ] Not Meant To Be Empty!');
}
}
if (payload === false) {
payload = '{}';
}
if (config.authorization === 'SIGNATURE') {
customConfig.headers.Authorization = `Bearer ${generatePrivateKey$1(this.privateKey, JSON.parse(payload))}`;
}
customConfig.body = payload;
return this.httpClient[config.method](config.path, customConfig);
};
};
function OPayError(message) {
this.name = 'OPayError';
this.message = message || '';
}
OPayError.prototype = Error.prototype;
class OPay {
constructor(publicKey, privateKey, merchantID, appEnv = 'development') {
const environment = /^(?:development|local|dev)$/;
this.privateKey = privateKey;
this.base_url = {
sandbox: 'http://sandbox-cashierapi.opayweb.com/api/v3/',
production: 'https://cashierapi.opayweb.com/api/v3/',
};
this.httpClientOptions = {
prefixUrl: environment.test(appEnv) ? this.base_url.sandbox : this.base_url.production,
headers: {
'Cache-Control': 'no-cache',
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${publicKey}`,
MerchantID: merchantID,
},
mutableDefaults: true,
hooks: {
onError: [
(error) => {
const { response } = error;
if (response && response.body) {
error.name = 'OPayError';
error.message = `${response.body.code}: ${response.body.message} (${error.statusCode})`;
}
return error;
},
],
afterResponse: [
(response) => {
if (response.body.code !== '00000') {
let message = `${response.body.code}: ${response.body.message}`;
throw new OPayError(message);
}
return response;
},
],
},
responseType: 'json',
};
this.httpClient = got__default['default'].extend(this.httpClientOptions);
}
mergeClientOptions(options) {
this.httpClient = this.httpClient.extend(options);
}
}
for (let endpoint in endpoints) {
if (endpoints.hasOwnProperty(endpoint)) {
OPay.prototype[endpoint] = createApiFunction(endpoints[endpoint]);
}
}
var OPay_1 = OPay;
OPay_1.prototype.version = '1.0.2';
var opayNodejsSdk = OPay_1;
module.exports = opayNodejsSdk;