daraja
Version:
A NodeJS library to simplify integration with Safaricom's Daraja M-Pesa API
312 lines (311 loc) • 6.86 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
const constants = require('constants');
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const moment = require('moment');
const api = require('./api');
exports.generateToken = async (
environment,
consumerKey,
consumerSecret,
accessToken,
expiryDate
) => {
try {
if (moment().isBefore(expiryDate)) {
return { accessToken, expiryDate };
}
const { access_token, expires_in } = await api.generateToken(
environment,
consumerKey,
consumerSecret
);
return {
accessToken: access_token,
expiryDate: moment().add(expires_in, 'seconds')
};
} catch (error) {
throw error;
}
};
exports.mpesaExpressRequest = async (
environment,
accessToken,
shortcode,
passkey,
transactionType,
amount,
sender,
recipient,
callbackUrl,
accountReference,
transactionDescription
) => {
const timestamp = moment().format('YYYYMMDDHHmmss');
try {
const {
MerchantRequestID: merchantRequestId,
CheckoutRequestID: checkoutRequestId
} = await api.mpesaExpressRequest(
environment,
accessToken,
shortcode,
Buffer.from(`${shortcode}${passkey}${timestamp}`).toString('base64'),
timestamp,
transactionType,
amount,
sender,
recipient,
sender,
callbackUrl,
accountReference,
transactionDescription
);
return { merchantRequestId, checkoutRequestId };
} catch (error) {
throw error;
}
};
exports.mpesaExpressQuery = async (
environment,
accessToken,
shortcode,
passkey,
checkoutRequestId
) => {
const timestamp = moment().format('YYYYMMDDHHmmss');
try {
const {
ResultCode: resultCode,
ResultDesc: resultDescription
} = await api.mpesaExpressQuery(
environment,
accessToken,
shortcode,
Buffer.from(`${shortcode}${passkey}${timestamp}`).toString('base64'),
timestamp,
checkoutRequestId
);
return { resultCode, resultDescription };
} catch (error) {
throw error;
}
};
exports.c2bRegisterUrl = async (
environment,
accessToken,
shortcode,
validationUrl,
confirmationUrl,
responseType
) => {
try {
const {
ResponseDescription: responseDescription
} = await api.c2bRegisterUrl(
environment,
accessToken,
validationUrl,
confirmationUrl,
responseType,
shortcode
);
return { responseDescription };
} catch (error) {
throw error;
}
};
exports.c2bSimulateTransaction = async (
environment,
accessToken,
shortcode,
sender,
amount,
billReference
) => {
if (environment !== 'sandbox') {
throw new Error('Cannot simulate on production environment');
}
try {
const {
ConversationID: conversationId,
OriginatorCoversationID: originatorConversationId,
ResponseDescription: responseDescription
} = await api.c2bSimulateTransaction(
accessToken,
'CustomerPayBillOnline',
amount,
sender,
billReference,
shortcode
);
return { conversationId, originatorConversationId, responseDescription };
} catch (error) {
throw error;
}
};
exports.b2cPaymentRequest = async (
environment,
accessToken,
shortcode,
recipient,
amount,
commandId,
initiatorName,
initiatorPassword,
remarks,
occassion,
timeoutUrl,
resultUrl
) => {
try {
const {
ConversationID: conversationId,
OriginatorConversationID: originatorConversationId,
ResponseDescription: responseDescription
} = await api.b2cPaymentRequest(
environment,
accessToken,
initiatorName,
generateSecurityCredential(environment, initiatorPassword),
commandId,
amount,
shortcode,
recipient,
remarks,
timeoutUrl,
resultUrl,
occassion
);
return { conversationId, originatorConversationId, responseDescription };
} catch (error) {
throw error;
}
};
exports.accountBalanceRequest = async (
environment,
accessToken,
shortcode,
identifierType,
initiatorName,
initiatorPassword,
remarks,
timeoutUrl,
resultUrl
) => {
try {
const {
ConversationID: conversationId,
OriginatorConversationID: originatorConversationId,
ResponseDescription: responseDescription
} = await api.accountBalanceRequest(
environment,
accessToken,
'AccountBalance',
shortcode,
identifierType,
remarks,
initiatorName,
generateSecurityCredential(environment, initiatorPassword),
timeoutUrl,
resultUrl
);
return { conversationId, originatorConversationId, responseDescription };
} catch (error) {
throw error;
}
};
exports.transactionStatusRequest = async (
environment,
accessToken,
shortcode,
identifierType,
initiatorName,
initiatorPassword,
transactionId,
remarks,
occassion,
timeoutUrl,
resultUrl
) => {
try {
const {
ConversationID: conversationId,
OriginatorConversationID: originatorConversationId,
ResponseDescription: responseDescription
} = await api.transactionStatusRequest(
environment,
accessToken,
'TransactionStatusQuery',
shortcode,
identifierType,
remarks,
initiatorName,
generateSecurityCredential(environment, initiatorPassword),
timeoutUrl,
resultUrl,
transactionId,
occassion
);
return { conversationId, originatorConversationId, responseDescription };
} catch (error) {
throw error;
}
};
exports.reversalRequest = async (
environment,
accessToken,
shortcode,
initiatorName,
initiatorPassword,
transactionId,
remarks,
occassion,
timeoutUrl,
resultUrl
) => {
try {
const {
ConversationID: conversationId,
OriginatorConversationID: originatorConversationId,
ResponseDescription: responseDescription
} = await api.reversalRequest(
environment,
accessToken,
'TransactionReversal',
shortcode,
11,
remarks,
initiatorName,
generateSecurityCredential(environment, initiatorPassword),
timeoutUrl,
resultUrl,
transactionId,
occassion
);
return { conversationId, originatorConversationId, responseDescription };
} catch (error) {
throw error;
}
};
const generateSecurityCredential = (environment, password) =>
crypto
.publicEncrypt(
{
key: fs.readFileSync(
path.join(
__dirname,
'..',
'..',
'certificates',
`${environment}.cer`
),
'utf8'
),
padding: constants.RSA_PKCS1_PADDING
},
Buffer.from(password)
)
.toString('base64');
;