2018-05-17 15:03:59 +00:00
|
|
|
'use strict';
|
|
|
|
|
2018-06-01 13:16:43 +00:00
|
|
|
const $request = require('request');
|
2018-05-17 15:03:59 +00:00
|
|
|
|
2018-06-20 09:20:03 +00:00
|
|
|
const constants = require('./consts');
|
|
|
|
const Keys = require('./keymanagers/Keys');
|
|
|
|
const defaultKeyEncryptor = require('./keymanagers/defaultKeyEncryptor');
|
|
|
|
|
2018-06-15 06:33:41 +00:00
|
|
|
const signer = require('./middleware/signer');
|
|
|
|
const serializer = require('./middleware/serializer');
|
|
|
|
const response = require('./middleware/response');
|
2018-06-11 08:38:32 +00:00
|
|
|
|
2018-06-27 11:21:49 +00:00
|
|
|
const stringifyKeys = (keys) => {
|
|
|
|
Object.keys(keys).map((key) => {
|
|
|
|
keys[key] = keys[key] === null ? null : keys[key].toPem();
|
|
|
|
|
|
|
|
return key;
|
|
|
|
});
|
|
|
|
|
|
|
|
return JSON.stringify(keys);
|
|
|
|
};
|
|
|
|
|
2018-05-17 15:03:59 +00:00
|
|
|
module.exports = class Client {
|
2018-06-20 09:20:03 +00:00
|
|
|
constructor({
|
|
|
|
url,
|
|
|
|
partnerId,
|
|
|
|
userId,
|
|
|
|
hostId,
|
|
|
|
passphrase,
|
|
|
|
keyStorage,
|
|
|
|
}) {
|
|
|
|
if (!url)
|
|
|
|
throw new Error('EBICS URL is requierd');
|
|
|
|
if (!partnerId)
|
|
|
|
throw new Error('partnerId is requierd');
|
|
|
|
if (!userId)
|
|
|
|
throw new Error('userId is requierd');
|
|
|
|
if (!hostId)
|
|
|
|
throw new Error('hostId is requierd');
|
|
|
|
if (!passphrase)
|
|
|
|
throw new Error('passphrase is requierd');
|
|
|
|
|
|
|
|
if (!keyStorage || typeof keyStorage.read !== 'function' || typeof keyStorage.write !== 'function')
|
|
|
|
throw new Error('keyStorage implemntation missing or wrong');
|
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
this.url = url;
|
2018-06-20 09:20:03 +00:00
|
|
|
this.partnerId = partnerId;
|
|
|
|
this.userId = userId;
|
|
|
|
this.hostId = hostId;
|
|
|
|
this.keyStorage = keyStorage;
|
|
|
|
this.keyEncryptor = defaultKeyEncryptor({ passphrase });
|
|
|
|
}
|
|
|
|
|
2018-06-27 14:59:35 +00:00
|
|
|
async send(order) {
|
2018-06-20 09:20:03 +00:00
|
|
|
const isInObject = ('operation' in order);
|
|
|
|
|
|
|
|
if (!isInObject) throw new Error('Operation for the order needed');
|
|
|
|
|
|
|
|
if (order.operation.toUpperCase() === constants.orderOperations.ini) return this.initialization(order);
|
2018-06-27 11:21:49 +00:00
|
|
|
|
2018-06-27 14:59:35 +00:00
|
|
|
const keys = await this.keys();
|
|
|
|
if (keys === null) throw new Error('No keys provided. Can not send the order or any other order for that matter.');
|
2018-06-27 11:21:49 +00:00
|
|
|
|
2018-06-20 09:20:03 +00:00
|
|
|
if (order.operation.toUpperCase() === constants.orderOperations.upload) return this.upload(order);
|
|
|
|
if (order.operation.toUpperCase() === constants.orderOperations.download) return this.download(order);
|
|
|
|
|
|
|
|
throw new Error('Wrong order operation provided');
|
2018-06-01 13:16:43 +00:00
|
|
|
}
|
2018-05-17 15:03:59 +00:00
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
async initialization(order) {
|
2018-06-27 14:59:35 +00:00
|
|
|
const keys = await this.keys();
|
|
|
|
if (keys === null) this._generateKeys();
|
2018-06-27 11:21:49 +00:00
|
|
|
|
2018-06-11 12:25:07 +00:00
|
|
|
const res = await this.ebicsRequest(order);
|
2018-06-11 08:38:32 +00:00
|
|
|
const xml = res.orderData();
|
2018-06-01 13:16:43 +00:00
|
|
|
|
2018-07-03 09:48:00 +00:00
|
|
|
const returnedTechnicalCode = res.technicalCode();
|
|
|
|
const returnedBusinessCode = res.businessCode();
|
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
return {
|
2018-07-04 13:30:16 +00:00
|
|
|
orderData: xml.length ? xml.toString() : xml,
|
2018-06-11 08:38:32 +00:00
|
|
|
orderId: res.orderId(),
|
2018-07-03 09:48:00 +00:00
|
|
|
|
|
|
|
technicalCode: returnedTechnicalCode,
|
|
|
|
technicalCodeSymbol: res.technicalSymbol(),
|
|
|
|
technicalCodeShortText: res.technicalShortText(returnedTechnicalCode),
|
|
|
|
technicalCodeMeaning: res.technicalMeaning(returnedTechnicalCode),
|
|
|
|
|
|
|
|
businessCode: returnedBusinessCode,
|
|
|
|
businessCodeSymbol: res.businessSymbol(returnedBusinessCode),
|
|
|
|
businessCodeShortText: res.businessShortText(returnedBusinessCode),
|
|
|
|
businessCodeMeaning: res.businessMeaning(returnedBusinessCode),
|
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
bankKeys: res.bankKeys(),
|
|
|
|
};
|
2018-05-17 15:03:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async download(order) {
|
2018-06-11 12:25:07 +00:00
|
|
|
const res = await this.ebicsRequest(order);
|
2018-05-17 15:03:59 +00:00
|
|
|
|
|
|
|
order.transactionId = res.transactionId();
|
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
if (res.isSegmented() && res.isLastSegment())
|
2018-06-11 12:25:07 +00:00
|
|
|
await this.ebicsRequest(order);
|
2018-05-17 15:03:59 +00:00
|
|
|
|
2018-07-03 09:48:00 +00:00
|
|
|
const returnedTechnicalCode = res.technicalCode();
|
|
|
|
const returnedBusinessCode = res.businessCode();
|
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
return {
|
|
|
|
orderData: res.orderData(),
|
|
|
|
orderId: res.orderId(),
|
2018-07-03 09:48:00 +00:00
|
|
|
|
|
|
|
technicalCode: returnedTechnicalCode,
|
|
|
|
technicalCodeSymbol: res.technicalSymbol(),
|
|
|
|
technicalCodeShortText: res.technicalShortText(returnedTechnicalCode),
|
|
|
|
technicalCodeMeaning: res.technicalMeaning(returnedTechnicalCode),
|
|
|
|
|
|
|
|
businessCode: returnedBusinessCode,
|
|
|
|
businessCodeSymbol: res.businessSymbol(returnedBusinessCode),
|
|
|
|
businessCodeShortText: res.businessShortText(returnedBusinessCode),
|
|
|
|
businessCodeMeaning: res.businessMeaning(returnedBusinessCode),
|
2018-06-11 08:38:32 +00:00
|
|
|
};
|
2018-06-01 13:16:43 +00:00
|
|
|
}
|
2018-05-17 15:03:59 +00:00
|
|
|
|
2018-05-31 09:08:07 +00:00
|
|
|
async upload(order) {
|
2018-06-11 12:25:07 +00:00
|
|
|
let res = await this.ebicsRequest(order);
|
2018-06-11 08:38:32 +00:00
|
|
|
const transactionId = res.transactionId();
|
|
|
|
const orderId = res.orderId();
|
|
|
|
|
|
|
|
order.transactionId = transactionId;
|
2018-05-31 09:08:07 +00:00
|
|
|
|
2018-06-11 12:25:07 +00:00
|
|
|
res = await this.ebicsRequest(order);
|
2018-05-31 09:08:07 +00:00
|
|
|
|
2018-06-11 08:38:32 +00:00
|
|
|
return [transactionId, orderId];
|
2018-05-31 09:08:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-11 12:25:07 +00:00
|
|
|
ebicsRequest(order) {
|
2018-06-27 14:59:35 +00:00
|
|
|
return new Promise(async (resolve, reject) => {
|
2018-06-20 09:20:03 +00:00
|
|
|
const { version } = order;
|
2018-06-27 14:59:35 +00:00
|
|
|
const keys = await this.keys();
|
2018-06-20 09:20:03 +00:00
|
|
|
|
2018-05-17 15:03:59 +00:00
|
|
|
$request.post({
|
2018-06-01 13:16:43 +00:00
|
|
|
url: this.url,
|
2018-06-27 14:59:35 +00:00
|
|
|
body: signer.version(version).sign((await serializer.use(order, this)).toXML(), keys.x()),
|
2018-06-01 13:16:43 +00:00
|
|
|
headers: { 'content-type': 'text/xml;charset=UTF-8' },
|
2018-06-15 06:33:41 +00:00
|
|
|
}, (err, res, data) => (err ? reject(err) : resolve(response.version(version)(data, keys))));
|
2018-05-17 15:03:59 +00:00
|
|
|
});
|
2018-06-01 13:16:43 +00:00
|
|
|
}
|
2018-05-17 15:03:59 +00:00
|
|
|
|
2018-06-27 14:59:35 +00:00
|
|
|
async keys() {
|
2018-06-28 08:34:14 +00:00
|
|
|
try {
|
|
|
|
const keysString = await this._readKeys();
|
2018-06-27 14:59:35 +00:00
|
|
|
|
2018-06-28 08:34:14 +00:00
|
|
|
return new Keys(JSON.parse(this.keyEncryptor.decrypt(keysString)));
|
|
|
|
} catch (err) {
|
|
|
|
return null;
|
|
|
|
}
|
2018-06-27 11:21:49 +00:00
|
|
|
}
|
2018-06-20 09:20:03 +00:00
|
|
|
|
2018-06-27 11:21:49 +00:00
|
|
|
_generateKeys() {
|
|
|
|
const keysObject = Keys.generate();
|
|
|
|
|
|
|
|
this._writeKeys(keysObject);
|
2018-06-20 09:20:03 +00:00
|
|
|
}
|
|
|
|
|
2018-06-27 14:59:35 +00:00
|
|
|
async setBankKeys(bankKeys) {
|
|
|
|
const keysObject = await this.keys();
|
2018-06-20 09:20:03 +00:00
|
|
|
|
|
|
|
keysObject.setBankKeys(bankKeys);
|
2018-06-27 14:59:35 +00:00
|
|
|
await this._writeKeys(keysObject);
|
2018-06-27 11:21:49 +00:00
|
|
|
}
|
2018-06-20 09:20:03 +00:00
|
|
|
|
2018-06-28 08:34:14 +00:00
|
|
|
_readKeys() {
|
|
|
|
return this.keyStorage.read();
|
2018-06-27 11:21:49 +00:00
|
|
|
}
|
2018-06-20 09:20:03 +00:00
|
|
|
|
2018-06-28 08:34:14 +00:00
|
|
|
_writeKeys(keysObject) {
|
|
|
|
return this.keyStorage.write(this.keyEncryptor.encrypt(stringifyKeys(keysObject.keys)));
|
2018-06-20 09:20:03 +00:00
|
|
|
}
|
2018-05-17 15:03:59 +00:00
|
|
|
};
|