@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
398 lines (397 loc) • 19.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@fabrix/fabrix/dist/common");
const errors_1 = require("@fabrix/spool-sequelize/dist/errors");
const enums_1 = require("../../enums");
const enums_2 = require("../../enums");
class PaymentService extends common_1.FabrixService {
publish(type, event, options = {}) {
if (this.app.services.EventsService) {
options.include = options.include || [{
model: this.app.models.EventItem.instance,
as: 'objects'
}];
return this.app.services.EventsService.publish(type, event, options);
}
this.app.log.debug('spool-events is not installed, please install it to use publish');
return Promise.resolve();
}
authorize(transaction, options = {}) {
transaction.description = transaction.description || 'Transaction Authorize';
const Transaction = this.app.models.Transaction;
const paymentProcessor = this.app.config.get(`generics.${transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!(transaction instanceof Transaction.instance)) {
throw new Error('Transaction must be an instance');
}
if (!paymentProcessor || !paymentProcessor.adapter) {
const err = new Error('Payment Processor is unspecified');
return Promise.reject(err);
}
let resTransaction;
return this.app.services.PaymentGenericService.authorize(transaction, paymentProcessor)
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.authorize did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.authorize.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction authorize of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
capture(transaction, options = {}) {
transaction.description = transaction.description || 'Transaction Capture';
const Transaction = this.app.models['Transaction'];
const paymentProcessor = this.app.config.get(`generics.${transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!paymentProcessor || !paymentProcessor.adapter) {
const err = new Error('Payment Processor is unspecified');
return Promise.reject(err);
}
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve a Transaction instance');
}
if (_transaction.kind !== enums_2.TRANSACTION_KIND.AUTHORIZE) {
throw new Error(`Transaction kind must be '${enums_2.TRANSACTION_KIND.AUTHORIZE}' to be captured`);
}
if (_transaction.status !== enums_1.TRANSACTION_STATUS.SUCCESS) {
throw new Error(`Transaction status must be '${enums_1.TRANSACTION_STATUS.SUCCESS}' to be captured`);
}
return this.app.services.PaymentGenericService.capture(_transaction, paymentProcessor);
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.capture did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.capture.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction capture of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
sale(transaction, options) {
options = options || {};
transaction.description = transaction.description || 'Transaction Sale';
const Transaction = this.app.models.Transaction;
const paymentProcessor = this.app.config.get(`generics.${transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!paymentProcessor || !paymentProcessor.adapter) {
const err = new Error('Payment Processor is unspecified');
return Promise.reject(err);
}
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve a Transaction instance');
}
return this.app.services.PaymentGenericService.sale(_transaction, paymentProcessor);
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.sale did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.sale.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction sale of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
manual(transaction, options) {
options = options || {};
const Transaction = this.app.models.Transaction;
if (!(transaction instanceof Transaction.instance)) {
throw new Error('Transaction must be an instance');
}
transaction.status = enums_1.TRANSACTION_STATUS.PENDING;
return transaction.save({ transaction: options.transaction || null })
.then(() => {
const event = {
object_id: transaction.order_id,
object: 'order',
objects: [{
order: transaction.order_id
}, {
transaction: transaction.id
}],
type: `order.transaction.${transaction.kind}.${transaction.status}`,
message: `Order ID ${transaction.order_id} transaction ID ${transaction.id} ${transaction.kind} of ${this.app.services.ProxyCartService.formatCurrency(transaction.amount, transaction.currency)} ${transaction.currency} ${transaction.status}`,
data: transaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return transaction;
});
}
void(transaction, options = {}) {
const Transaction = this.app.models['Transaction'];
const paymentProcessor = this.app.config.get(`generics.${transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!paymentProcessor || !paymentProcessor.adapter) {
const err = new Error('Payment Processor is unspecified');
return Promise.reject(err);
}
transaction.description = transaction.description || 'Transaction Void';
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!_transaction) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Transaction Not Found');
}
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve a Transaction instance');
}
if (_transaction.kind !== enums_2.TRANSACTION_KIND.AUTHORIZE) {
throw new Error(`Transaction kind must be '${enums_2.TRANSACTION_KIND.AUTHORIZE}' to be voided`);
}
if (_transaction.status !== enums_1.TRANSACTION_STATUS.SUCCESS) {
throw new Error(`Transaction status must be '${enums_1.TRANSACTION_STATUS.SUCCESS}' to be voided`);
}
return this.app.services.PaymentGenericService.void(_transaction, paymentProcessor);
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.void did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.void.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction ID ${resTransaction.id} voided of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
refund(transaction, options = {}) {
const Transaction = this.app.models['Transaction'];
const paymentProcessor = this.app.config.get(`generics.${transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!paymentProcessor || !paymentProcessor.adapter) {
const err = new Error('Payment Processor is unspecified');
return Promise.reject(err);
}
transaction.description = transaction.description || 'Transaction Refund';
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!_transaction) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Transaction Not Found');
}
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve a Transaction instance');
}
if ([enums_2.TRANSACTION_KIND.CAPTURE, enums_2.TRANSACTION_KIND.SALE].indexOf(_transaction.kind) === -1) {
throw new Error(`Transaction kind must be '${enums_2.TRANSACTION_KIND.CAPTURE}' or '${enums_2.TRANSACTION_KIND.SALE}' to be refunded`);
}
if (_transaction.status !== enums_1.TRANSACTION_STATUS.SUCCESS) {
throw new Error(`Transaction status must be '${enums_1.TRANSACTION_STATUS.SUCCESS}' to be refunded`);
}
return this.app.services.PaymentGenericService.refund(_transaction, paymentProcessor);
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.refund did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.refund.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction ID ${resTransaction.id} refund of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
retry(transaction, options) {
options = options || {};
const Transaction = this.app.models['Transaction'];
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!_transaction) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Transaction Not Found');
}
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve a Transaction instance');
}
if ([enums_1.TRANSACTION_STATUS.PENDING, enums_1.TRANSACTION_STATUS.FAILURE].indexOf(_transaction.status) === -1) {
throw new Error('Transaction can not be tried if it is not pending or has not failed');
}
const paymentProcessor = this.app.config.get(`generics.${_transaction.gateway}`)
|| this.app.config.get('generics.payment_processor');
if (!paymentProcessor || !paymentProcessor.adapter) {
throw new Error('Payment Processor is unspecified');
}
_transaction.retry();
return this.app.services.PaymentGenericService[_transaction.kind](_transaction, paymentProcessor);
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('PaymentGenericService.retry did not return Transaction instance');
}
return _transaction.save({ transaction: options.transaction || null });
})
.then(_transaction => {
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: `order.transaction.${resTransaction.kind}.${resTransaction.status}`,
message: `Order ID ${resTransaction.order_id} transaction ID ${resTransaction.id} ${resTransaction.kind} of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.currency} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
cancel(transaction, options) {
options = options || {};
const Transaction = this.app.models['Transaction'];
let resTransaction;
return Transaction.resolve(transaction, { transaction: options.transaction || null })
.then(_transaction => {
if (!_transaction) {
throw new errors_1.ModelError('E_NOT_FOUND', 'Transaction Not Found');
}
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not resolve Transaction instance');
}
if ([enums_1.TRANSACTION_STATUS.PENDING, enums_1.TRANSACTION_STATUS.FAILURE].indexOf(_transaction.status) === -1) {
throw new Error('Transaction can not be cancelled if it is not pending or failed');
}
return _transaction.cancel().save({ transaction: options.transaction || null });
})
.then(_transaction => {
if (!(_transaction instanceof Transaction.instance)) {
throw new Error('Did not return Transaction instance');
}
resTransaction = _transaction;
const event = {
object_id: resTransaction.order_id,
object: 'order',
objects: [{
order: resTransaction.order_id
}, {
transaction: resTransaction.id
}],
type: 'order.transaction.cancelled',
message: `Order ID ${resTransaction.order_id} transaction ID ${resTransaction.id} of ${this.app.services.ProxyCartService.formatCurrency(resTransaction.amount, resTransaction.currency)} ${resTransaction.status}`,
data: resTransaction
};
return this.publish(event.type, event, {
save: true,
transaction: options.transaction || null
});
})
.then(event => {
return resTransaction;
});
}
}
exports.PaymentService = PaymentService;