mobilpay-card
Version:
Mobilpay card gateway library
293 lines (277 loc) • 9.21 kB
JavaScript
const rc4 = require('./encrypt');
const fs = require('fs');
const xml2js = require('xml2js');
let builder = new xml2js.Builder({
cdata: true
});
let parser = new xml2js.Parser({
explicitArray:false
});
/**
* MobilPay class.
*
* @constructor
* @param {String} signature - The signature of the account.
*/
class MobilPay {
constructor(signature) {
this.signature = signature;
this.publicKey = null;
this.privateKey = null;
this.clientData = {
billing: null,
shipping: null,
};
this.paymentData = null;
}
/**
* Set the publicKey from path
*
* @param {String} publicPemPath - The path to the public pem file.
*/
setPublicKeyFromPath (publicPemPath) {
try {
this.publicKey = fs.readFileSync(publicPemPath).toString();
} catch (e) {
throw new Error('PUBLIC_CERTIFICATE_MISSING')
}
}
/**
* Set the privateKey from path
*
* @param {String} privateKeyPath - The path to the private key file.
*/
setPrivateKeyFromPath (privateKeyPath) {
try {
this.privateKey = fs.readFileSync(privateKeyPath).toString();
} catch (e) {
throw new Error('PRIVATE_CERTIFICATE_MISSING')
}
}
/**
* Set public key from string
*
* @param {String} publicKey The publicKey contents
*/
setPublicKey (publicKey) {
this.publicKey = publicKey;
}
/**
* Set private key from string
*
* @param {String} privateKey The privateKey contents
*/
setPrivateKey (privateKey) {
this.privateKey = privateKey;
}
/**
* Set the client billing information.
*
* @param {String} firstName The client's first name.
* @param {String} lastName The client's last name.
* @param {String} county The client's county.
* @param {String} city The client's city.
* @param {String} address The client's address.
* @param {String} email The client's email.
* @param {String} phone The client's phone number.
*/
setClientBillingData({firstName, lastName, county, city, address, email, phone}) {
this.clientData.billing = {
first_name: firstName,
last_name: lastName,
address: `${county}, ${city}, ${address}`,
email: email,
mobile_phone: phone
}
}
/**
* Set the client shipping information.
*
* @param {String} firstName The client's first name.
* @param {String} lastName The client's last name.
* @param {String} county The client's county.
* @param {String} city The client's city.
* @param {String} address The client's address.
* @param {String} email The client's email.
* @param {String} phone The client's phone number.
*/
setClientShippingData({firstName, lastName, county, city, address, email, phone}) {
this.clientData.shipping = {
first_name: firstName,
last_name: lastName,
address: `${county}, ${city}, ${address}`,
email: email,
mobile_phone: phone
}
}
/**
* Set the split payment information.
*
* @param {String} destinationId The sac id (signature) of the first recipient.
* @param {Number} destinationAmount The amount for the first recipient.
*/
setSplitPayment(destinationId, destinationAmount) {
this.splitPayment = {
split: {
destination: [
{$: {
id: destinationId, amount: destinationAmount.toString()
}}
]
},
}
}
/**
* Set the client billing information.
*
* @param {String} orderId The id of the order.
* @param {String} amount The amount to be charged.
* @param {String} currency The currency in which to be charged.
* @param {String} details The details about the transaction.
* @param {String} confirmUrl The url which the MobilPay API should call for confirmation.
* @param {String} returnUrl The url which the MobilPay API should return after confirmation.
*/
setPaymentData({orderId, amount, currency, details, confirmUrl, returnUrl}) {
if (!this.clientData.billing) {
throw new Error('BILLING_DATA_MISSING')
}
if (!this.clientData.shipping) {
this.setClientShippingData(this.clientData.billing);
}
if (typeof this.splitPayment === 'undefined') {
this.splitPayment = null
}
this.paymentData = {
order: {
$: {
id: orderId,
timestamp: new Date().getTime(),
type: 'card'
},
...this.splitPayment,
signature: this.signature,
url: {
return: returnUrl,
confirm: confirmUrl
},
invoice: {
$: {
currency: currency.toString().toUpperCase(),
amount: amount,
},
details: details,
contact_info: {
billing: {
$: {
type: 'person'
},
...this.clientData.billing
},
shipping: {
$: {
type: 'person'
},
...this.clientData.shipping
}
}
},
}
}
}
/**
* Build the request for the API call
*
* @param {Boolean} sandbox Use for sandbox
*/
buildRequest (sandbox) {
if (!this.paymentData) {
throw new Error('PAYMENT_DATA_MISSING');
}
let xml = null;
let request = null;
try {
xml = builder.buildObject(this.paymentData)
} catch (e) {
console.log(e);
throw new Error('XML_BUILDER_ERROR');
}
try{
request = rc4.encrypt(this.publicKey, xml)
} catch (e) {
console.log(e);
throw new Error('RC4_BUILDER_ERROR');
}
return {
url: sandbox ? 'http://sandboxsecure.mobilpay.ro' : 'https://secure.mobilpay.ro/en',
env_key: request.envKey,
data: request.envData
}
}
/**
* Get the payment confirmation
*
* @param {String} envKey The env_key.
* @param data The data.
*/
confirmPayment (envKey, data) {
const privateKey = this.privateKey;
return new Promise(function(resolve,reject){
parser.parseString(rc4.decrypt(privateKey, envKey, data),function(err,result){
if(err){
console.log(err);
reject(err);
}
resolve(result);
});
});
}
/**
* Validate a payment
*
* @param {String} envKey The env_key from the Mobilpay request body
* @param data The data from the Mobilpay request body
*/
async validatePayment (envKey, data) {
const confirmedPayment = await this.confirmPayment(envKey, data);
return new Promise(function(resolve, reject) {
if (confirmedPayment.errorType) {
reject(confirmedPayment.errorMessage)
}
const mobilpayAction = confirmedPayment.order.mobilpay.action;
const errorObj = confirmedPayment.order.mobilpay.error;
let errorMessage = errorObj._;
let errorCode = errorObj.$.code;
if (parseInt(errorCode) !== 0) {
resolve({
action: mobilpayAction,
errorMessage: errorMessage,
error: errorObj,
$: confirmedPayment.order.$,
orderInvoice: confirmedPayment.order.invoice,
res: {
set: {
key: 'Content-Type',
value: 'application/xml'
},
send: `<?xml version="1.0" encoding="utf-8" ?><crc error_code="${errorCode}">${errorMessage}</crc>`,
}
});
}
resolve({
action: mobilpayAction,
errorMessage: null,
error: null,
$: confirmedPayment.order.$,
orderInvoice: confirmedPayment.order.invoice,
res: {
set: {
key: 'Content-Type',
value: 'application/xml'
},
send: `<?xml version="1.0" encoding="utf-8" ?><crc>${errorMessage}</crc>`
}
});
})
}
}
module.exports = MobilPay;