206 lines
7.3 KiB
JavaScript
206 lines
7.3 KiB
JavaScript
/**
|
|
* Functions to interact with 3rd party merchanct aquirers
|
|
*/
|
|
'use strict';
|
|
|
|
var Q = require('q');
|
|
var errors = require(global.pathPrefix + '../utils/acquirers/acquirer_errors.js');
|
|
var credorax = require(global.pathPrefix + '../utils/acquirers/credorax.js');
|
|
var utils = require(global.pathPrefix + 'utils.js');
|
|
var config = require(global.configFile);
|
|
var testAcquirer = require(global.pathPrefix + '../utils/acquirers/test_acquirer.js');
|
|
var worldpayAcquirer = require(global.pathPrefix + '../utils/acquirers/worldpay_acquirer.js');
|
|
var demoAcquirer = require(global.pathPrefix + '../utils/acquirers/demo_acquirer.js');
|
|
var forceAcquirer = null; // Set to 'Test' to force use of Test acquirer
|
|
|
|
module.exports = {
|
|
invalidateMerchantAccount: invalidateMerchantAccount,
|
|
payTokenised: payTokenised,
|
|
payTransaction: payTransaction,
|
|
tokeniseCard: tokeniseCard,
|
|
|
|
validateMerchantAccount: validateMerchantAccount,
|
|
|
|
ERRORS: errors
|
|
};
|
|
|
|
/**
|
|
* Define the list of acquirers we have available
|
|
*/
|
|
const ACQUIRERS = {
|
|
Test: testAcquirer,
|
|
Worldpay: worldpayAcquirer,
|
|
Demo: demoAcquirer
|
|
};
|
|
|
|
/**
|
|
* Generic function to call the appropriate implementation based on the given
|
|
* acquirer name and function name.
|
|
*
|
|
* @param {string} acquirer - the acquirer that should be used
|
|
* @param {string} functionName - the name of the function to call
|
|
* @param {any[]} params - array of parameters for the function to be called
|
|
* @returns {Promise} - the result of the function or rejects with UNKNOWN_ACQUIRER
|
|
*/
|
|
function callImplIfExists(acquirer, functionName, params) {
|
|
const acquirerName = forceAcquirer || acquirer;
|
|
const acquirerImpl = ACQUIRERS[acquirerName];
|
|
if (!acquirerImpl || !acquirerImpl[functionName]) {
|
|
return Q.reject({name: errors.UNKNOWN_ACQUIRER});
|
|
}
|
|
|
|
return acquirerImpl[functionName].apply(null, params);
|
|
}
|
|
|
|
/**
|
|
* Attempts to invalidate the token with the merchant enquirer
|
|
*
|
|
* @param {string} acquirer - The merchant acquirer's name
|
|
* @param {string} token - The token to be invalidated
|
|
* @param {string} merchantID - The merchant ID for the merchant account
|
|
* @param {string} cipher - The merchant cipher for the merchant account
|
|
* @param {string} accountID - The accountID for creating a tracking id
|
|
*
|
|
* @returns {promise} - A promise that resolves on success, or rejects on fail
|
|
*/
|
|
function invalidateMerchantAccount(acquirer, token, merchantID, cipher, accountID) {
|
|
const acquirerName = forceAcquirer || acquirer;
|
|
const acquirerImpl = ACQUIRERS[acquirerName];
|
|
if (!acquirerImpl || !acquirerImpl.invalidateMerchantAccount) {
|
|
return Q.reject({name: errors.UNKNOWN_ACQUIRER});
|
|
}
|
|
|
|
return acquirerImpl.invalidateMerchantAccount(token, merchantID, cipher, accountID);
|
|
}
|
|
|
|
/**
|
|
* Makes a payment from customer to merchant using the specified acquirer. This
|
|
* requires the card to be pre-tokenised by the selected acquirer.
|
|
*
|
|
* @param {Object} transaction - The transaction being completed
|
|
* @param {Object} customerAccount - The customer's payment account
|
|
* @param {string} customerIP - The IP address the customer is connected from
|
|
* @param {Object} merchantAccount - The merchant's payment account
|
|
*
|
|
* @returns {Promise} - A promise that resolves on success, or rejects on fail
|
|
*/
|
|
function payTokenised(
|
|
transaction,
|
|
customerAccount,
|
|
customerIP,
|
|
merchantAccount
|
|
) {
|
|
//
|
|
// Check the token exists
|
|
//
|
|
if (!customerAccount.Token) {
|
|
return Q.reject({name: errors.NO_TOKEN});
|
|
}
|
|
|
|
//
|
|
// Check the merchant display name is long enough
|
|
//
|
|
if (utils.MinDisplayNameLength > transaction.MerchantDisplayName.length) {
|
|
return Q.reject({name: errors.INVALID_MERCHANT_NAME});
|
|
}
|
|
|
|
switch (forceAcquirer || merchantAccount.AcquirerName) {
|
|
case 'Credorax':
|
|
return credorax.payTokenised(
|
|
transaction,
|
|
customerAccount,
|
|
customerIP,
|
|
merchantAccount
|
|
);
|
|
|
|
case 'Test':
|
|
// Run the test version. Note that `testAcquirer` will be undefined
|
|
// unless this is in dev mode.
|
|
return testAcquirer.payTokenised(
|
|
transaction,
|
|
customerAccount,
|
|
customerIP,
|
|
merchantAccount
|
|
);
|
|
// Else fall through to default.
|
|
|
|
default:
|
|
return Q.reject({name: errors.UNKNOWN_ACQUIRER});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Makes a payment from customer to merchant using the appropriate acquirer
|
|
*
|
|
* @param {Object} client - the client making the payment
|
|
* @param {Object} device - the device making the payment
|
|
* @param {Object} data - various neccessary data
|
|
* @param {String} data.ClientKey - the client key required to decrypt the payment details
|
|
* @param {String} data.ipAddress - ipAddress of the client
|
|
* @param {Object} [data.cardDetails] - optional decrypted card details
|
|
* @param {Object} transaction - The transaction object with the payment info
|
|
* @param {Object} merchantInfo - Merchant account and address info
|
|
* @param {Object} customerInfo - Customer account and address info
|
|
*
|
|
* @returns {Promise} - Resolves to payment info, or rejects ERRORS value
|
|
*/
|
|
function payTransaction(
|
|
client,
|
|
device,
|
|
data,
|
|
transaction,
|
|
merchantInfo,
|
|
customerInfo
|
|
) {
|
|
//
|
|
// Check the merchant display name is long enough
|
|
//
|
|
if (utils.MinDisplayNameLength > transaction.MerchantDisplayName.length) {
|
|
return Q.reject({name: errors.INVALID_MERCHANT_NAME});
|
|
}
|
|
|
|
const acquirerName = forceAcquirer || merchantInfo.account.AcquirerName;
|
|
const acquirer = ACQUIRERS[acquirerName];
|
|
if (!acquirer || !acquirer.payTransaction) {
|
|
return Q.reject({name: errors.UNKNOWN_ACQUIRER});
|
|
}
|
|
|
|
//
|
|
// Call the specific aquirer to process the transaction
|
|
//
|
|
return acquirer.payTransaction(client, device, data, transaction, merchantInfo, customerInfo);
|
|
}
|
|
|
|
/**
|
|
* Validates that a merchant account is valid with the given acquirer
|
|
*
|
|
* @param {Object} account - the account to validate
|
|
* @returns {Promise} - resolves on succes or rejects with ERRORS value
|
|
*/
|
|
function validateMerchantAccount(account) {
|
|
const acquirerName = forceAcquirer || account.AcquirerName;
|
|
const acquirer = ACQUIRERS[acquirerName];
|
|
if (!acquirer || !acquirer.validateMerchantAccount) {
|
|
return Q.reject({name: errors.UNKNOWN_ACQUIRER});
|
|
}
|
|
|
|
//
|
|
// Call the specific aquirer to process the transaction
|
|
//
|
|
return acquirer.validateMerchantAccount(account);
|
|
}
|
|
|
|
/**
|
|
* Tokenises the card and returns some interesting information about it, along
|
|
* with the encrypted token (assuming the appropriate keys are provided).
|
|
*
|
|
* @param {string} acquirer - the acquirer to use to tokenise
|
|
* @param {Object} cardDetails - the card details to tokenise
|
|
* @param {string?} clientKey - the client Key (to encrypt the token)
|
|
* @param {string?} clientID - the client ID (to encrypt the token)
|
|
* @returns {Promise} - a promise for the successful tokenisation
|
|
*/
|
|
function tokeniseCard(acquirer, cardDetails, clientKey, clientID) {
|
|
return callImplIfExists(acquirer, 'tokeniseCard', [cardDetails, clientKey, clientID]);
|
|
}
|