mirror of
https://github.com/node-ebics/node-ebics-client.git
synced 2024-11-22 06:02:09 +00:00
client and order optimization
This commit is contained in:
parent
187636019c
commit
945499290a
8
index.js
8
index.js
@ -1,15 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Client = require('./lib/Client');
|
const Client = require('./lib/Client');
|
||||||
const OrderBuilder = require('./lib/OrderBuilder');
|
const fsKeysStorage = require('./lib/storages/fsKeysStorage');
|
||||||
const ISO20022Builder = require('./lib/ISO20022OrderBuilder');
|
|
||||||
const keysManager = require('./lib/keymanagers/keysManager');
|
|
||||||
const fsKeysStorage = require('./lib/keymanagers/fsKeysStorage');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Client,
|
Client,
|
||||||
OrderBuilder,
|
|
||||||
ISO20022Builder,
|
|
||||||
keysManager,
|
|
||||||
fsKeysStorage,
|
fsKeysStorage,
|
||||||
};
|
};
|
||||||
|
@ -2,13 +2,55 @@
|
|||||||
|
|
||||||
const $request = require('request');
|
const $request = require('request');
|
||||||
|
|
||||||
|
const constants = require('./consts');
|
||||||
|
const Keys = require('./keymanagers/Keys');
|
||||||
|
const defaultKeyEncryptor = require('./keymanagers/defaultKeyEncryptor');
|
||||||
|
|
||||||
const signer = require('./middleware/signer');
|
const signer = require('./middleware/signer');
|
||||||
const serializer = require('./middleware/serializer');
|
const serializer = require('./middleware/serializer');
|
||||||
const response = require('./middleware/response');
|
const response = require('./middleware/response');
|
||||||
|
|
||||||
module.exports = class Client {
|
module.exports = class Client {
|
||||||
constructor(url) {
|
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');
|
||||||
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.partnerId = partnerId;
|
||||||
|
this.userId = userId;
|
||||||
|
this.hostId = hostId;
|
||||||
|
this.keyStorage = keyStorage;
|
||||||
|
this.keyEncryptor = defaultKeyEncryptor({ passphrase });
|
||||||
|
}
|
||||||
|
|
||||||
|
send(order) {
|
||||||
|
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);
|
||||||
|
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');
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialization(order) {
|
async initialization(order) {
|
||||||
@ -32,7 +74,6 @@ module.exports = class Client {
|
|||||||
if (res.isSegmented() && res.isLastSegment())
|
if (res.isSegmented() && res.isLastSegment())
|
||||||
await this.ebicsRequest(order);
|
await this.ebicsRequest(order);
|
||||||
|
|
||||||
// return res.orderData();
|
|
||||||
return {
|
return {
|
||||||
orderData: res.orderData(),
|
orderData: res.orderData(),
|
||||||
orderId: res.orderId(),
|
orderId: res.orderId(),
|
||||||
@ -55,11 +96,12 @@ module.exports = class Client {
|
|||||||
|
|
||||||
ebicsRequest(order) {
|
ebicsRequest(order) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const { version, keys } = order;
|
const { version } = order;
|
||||||
// const s = signer.version(version).use(serializer.use(order).toXML(), keys).digest().sign().toXML(); // new (signer.version(version))(serializer.use(order).toXML(), keys).digest().sign().toXML();
|
const keys = this.keys();
|
||||||
|
|
||||||
$request.post({
|
$request.post({
|
||||||
url: this.url,
|
url: this.url,
|
||||||
body: signer.version(version).sign(serializer.use(order).toXML(), keys), // s, // new (signer.version(version))(serializer.use(order).toXML(), keys).digest().sign().toXML(),
|
body: signer.version(version).sign(serializer.use(order, this).toXML(), keys.x()), // s, // new (signer.version(version))(serializer.use(order).toXML(), keys).digest().sign().toXML(),
|
||||||
headers: { 'content-type': 'text/xml;charset=UTF-8' },
|
headers: { 'content-type': 'text/xml;charset=UTF-8' },
|
||||||
}, (err, res, data) => (err ? reject(err) : resolve(response.version(version)(data, keys))));
|
}, (err, res, data) => (err ? reject(err) : resolve(response.version(version)(data, keys))));
|
||||||
});
|
});
|
||||||
@ -80,4 +122,25 @@ module.exports = class Client {
|
|||||||
status(order) {
|
status(order) {
|
||||||
return this.download(order);
|
return this.download(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keys() {
|
||||||
|
const keysString = this.keyStorage.read();
|
||||||
|
|
||||||
|
return new Keys(JSON.parse(this.keyEncryptor.decrypt(keysString)));
|
||||||
|
}
|
||||||
|
|
||||||
|
setBankKeys(bankKeys) {
|
||||||
|
const keysObject = this.keys();
|
||||||
|
|
||||||
|
keysObject.setBankKeys(bankKeys);
|
||||||
|
const { keys } = keysObject;
|
||||||
|
|
||||||
|
Object.keys(keys).map((key) => {
|
||||||
|
keys[key] = keys[key] === null ? null : keys[key].toPem();
|
||||||
|
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.keyStorage.write(this.keyEncryptor.encrypt(JSON.stringify(keys)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,9 +4,15 @@ const packageJson = require('../package.json');
|
|||||||
|
|
||||||
const name = 'eCollect Node Ebics Client';
|
const name = 'eCollect Node Ebics Client';
|
||||||
const { version } = packageJson;
|
const { version } = packageJson;
|
||||||
|
const orderOperations = {
|
||||||
|
ini: 'INI',
|
||||||
|
upload: 'UPLOAD',
|
||||||
|
download: 'DOWNLOAD',
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name,
|
name,
|
||||||
version,
|
version,
|
||||||
|
orderOperations,
|
||||||
productString: `${name} ${version}`,
|
productString: `${name} ${version}`,
|
||||||
};
|
};
|
||||||
|
@ -3,26 +3,22 @@
|
|||||||
const BN = require('bn.js');
|
const BN = require('bn.js');
|
||||||
const NodeRSA = require('node-rsa');
|
const NodeRSA = require('node-rsa');
|
||||||
|
|
||||||
module.exports = class Key {
|
const keyOrNull = (encodedKey) => {
|
||||||
constructor(encodedKey/* , passphrase = null */) {
|
if (encodedKey === null) return new NodeRSA();
|
||||||
this._key = (encodedKey instanceof NodeRSA) ? encodedKey : new NodeRSA(encodedKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static generate(keysize = 2048) {
|
return (encodedKey instanceof NodeRSA) ? encodedKey : new NodeRSA(encodedKey);
|
||||||
return new NodeRSA({ b: keysize });
|
};
|
||||||
}
|
|
||||||
|
|
||||||
static importKey({ mod, exp }) {
|
module.exports = encodedKey => ({
|
||||||
const key = new NodeRSA();
|
key: keyOrNull(encodedKey),
|
||||||
|
|
||||||
key.importKey({ n: mod, e: exp }, 'components-public');
|
generate(keySize = 2048) {
|
||||||
|
return new NodeRSA({ b: keySize });
|
||||||
|
},
|
||||||
|
|
||||||
return new Key(key);
|
importKey({ mod, exp }) {
|
||||||
}
|
this.key.importKey({ n: mod, e: exp }, 'components-public');
|
||||||
|
},
|
||||||
get key() {
|
|
||||||
return this._key;
|
|
||||||
}
|
|
||||||
|
|
||||||
n(to = 'buff') {
|
n(to = 'buff') {
|
||||||
const keyN = Buffer.from(this.key.exportKey('components-public').n);
|
const keyN = Buffer.from(this.key.exportKey('components-public').n);
|
||||||
@ -30,7 +26,7 @@ module.exports = class Key {
|
|||||||
return to === 'hex'
|
return to === 'hex'
|
||||||
? keyN.toString('hex', 1)
|
? keyN.toString('hex', 1)
|
||||||
: keyN;
|
: keyN;
|
||||||
}
|
},
|
||||||
|
|
||||||
e(to = 'buff') {
|
e(to = 'buff') {
|
||||||
const eKey = new BN(this.key.exportKey('components-public').e).toBuffer();
|
const eKey = new BN(this.key.exportKey('components-public').e).toBuffer();
|
||||||
@ -38,13 +34,13 @@ module.exports = class Key {
|
|||||||
return to === 'hex'
|
return to === 'hex'
|
||||||
? eKey.toString('hex')
|
? eKey.toString('hex')
|
||||||
: eKey;
|
: eKey;
|
||||||
}
|
},
|
||||||
|
|
||||||
d() {
|
d() {
|
||||||
return this.key.keyPair.d.toBuffer();
|
return this.key.keyPair.d.toBuffer();
|
||||||
}
|
},
|
||||||
|
|
||||||
toPem() {
|
toPem() {
|
||||||
return this.key.isPrivate() ? this.key.exportKey('pkcs1-private-pem') : this.key.exportKey('pkcs8-public-pem');
|
return this.key.isPrivate() ? this.key.exportKey('pkcs1-private-pem') : this.key.exportKey('pkcs8-public-pem');
|
||||||
}
|
},
|
||||||
};
|
});
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Key = require('./Key');
|
const Key = require('./key');
|
||||||
|
|
||||||
const keyOrNull = key => (key ? new Key(key) : null);
|
const keyOrNull = key => (key ? Key(key) : null);
|
||||||
|
|
||||||
module.exports = class Keys {
|
module.exports = class Keys {
|
||||||
constructor({
|
constructor({
|
||||||
@ -32,8 +32,8 @@ module.exports = class Keys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setBankKeys(bankKeys) {
|
setBankKeys(bankKeys) {
|
||||||
this.keys.bankX002 = Key.importKey(bankKeys.bankX002);
|
this.keys.bankX002.importKey(bankKeys.bankX002);
|
||||||
this.keys.bankE002 = Key.importKey(bankKeys.bankE002);
|
this.keys.bankE002.importKey(bankKeys.bankE002);
|
||||||
}
|
}
|
||||||
|
|
||||||
a() {
|
a() {
|
||||||
|
24
lib/keymanagers/defaultKeyEncryptor.js
Normal file
24
lib/keymanagers/defaultKeyEncryptor.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const encrypt = (data, algorithm, passphrase) => {
|
||||||
|
const cipher = crypto.createCipher(algorithm, passphrase);
|
||||||
|
const encrypted = cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
|
||||||
|
return Buffer.from(encrypted).toString('base64');
|
||||||
|
};
|
||||||
|
const decrypt = (data, algorithm, passphrase) => {
|
||||||
|
data = (Buffer.from(data, 'base64')).toString();
|
||||||
|
const decipher = crypto.createDecipher(algorithm, passphrase);
|
||||||
|
const decrypted = decipher.update(data, 'hex', 'utf8') + decipher.final('utf8');
|
||||||
|
|
||||||
|
return decrypted;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ({
|
||||||
|
passphrase,
|
||||||
|
algorithm = 'aes-256-cbc',
|
||||||
|
}) => ({
|
||||||
|
encrypt: data => encrypt(data, algorithm, passphrase),
|
||||||
|
decrypt: data => decrypt(data, algorithm, passphrase),
|
||||||
|
});
|
@ -3,10 +3,10 @@
|
|||||||
const H004Serializer = require('../orders/H004/serializer');
|
const H004Serializer = require('../orders/H004/serializer');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
use(order) {
|
use(order, client) {
|
||||||
const { version } = order;
|
const { version } = order;
|
||||||
|
|
||||||
if (version.toUpperCase() === 'H004') return H004Serializer.use(order);
|
if (version.toUpperCase() === 'H004') return H004Serializer.use(order, client);
|
||||||
|
|
||||||
throw Error('Error middleware/serializer.js: Invalid version number');
|
throw Error('Error middleware/serializer.js: Invalid version number');
|
||||||
},
|
},
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const orders = require('../orders');
|
const constants = require('../../consts');
|
||||||
|
|
||||||
const iniSerializer = require('./serializers/ini');
|
const iniSerializer = require('./serializers/ini');
|
||||||
const downloadSerializer = require('./serializers/download');
|
const downloadSerializer = require('./serializers/download');
|
||||||
const uploadSerializer = require('./serializers/upload');
|
const uploadSerializer = require('./serializers/upload');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
use(order) {
|
use(order, client) {
|
||||||
const { version, orderType } = order;
|
const operation = order.operation.toUpperCase();
|
||||||
|
|
||||||
if (orders.version(version).isIni(orderType)) return iniSerializer.use(order);
|
if (operation === constants.orderOperations.ini) return iniSerializer.use(order, client);
|
||||||
if (orders.version(version).isDownload(orderType)) return downloadSerializer.use(order);
|
if (operation === constants.orderOperations.download) return downloadSerializer.use(order, client);
|
||||||
if (orders.version(version).isUpload(orderType)) return uploadSerializer.use(order);
|
if (operation === constants.orderOperations.upload) return uploadSerializer.use(order, client);
|
||||||
|
|
||||||
throw Error('Error from orders/orders.js: Wrong order version/type.');
|
throw Error('Error from orders/orders.js: Wrong order version/type.');
|
||||||
},
|
},
|
||||||
|
@ -7,14 +7,19 @@ const Crypto = require('../../../crypto/Crypto');
|
|||||||
const genericSerializer = require('./generic');
|
const genericSerializer = require('./generic');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
use(orderBuilder) {
|
use(order, client) {
|
||||||
|
const keys = client.keys();
|
||||||
|
const ebicsAccount = {
|
||||||
|
partnerId: client.partnerId,
|
||||||
|
userId: client.userId,
|
||||||
|
hostId: client.hostId,
|
||||||
|
};
|
||||||
|
const { orderDetails, transactionId } = order;
|
||||||
const {
|
const {
|
||||||
ebicsData, orderDetails, keys, productString, transactionId,
|
rootName, xmlOptions, xmlSchema, receipt, transfer, productString,
|
||||||
} = orderBuilder;
|
} = genericSerializer(client.hostId, transactionId);
|
||||||
const {
|
|
||||||
rootName, xmlOptions, xmlSchema, receipt, transfer,
|
|
||||||
} = genericSerializer(orderBuilder);
|
|
||||||
|
|
||||||
|
this.productString = productString;
|
||||||
this.rootName = rootName;
|
this.rootName = rootName;
|
||||||
this.xmlOptions = xmlOptions;
|
this.xmlOptions = xmlOptions;
|
||||||
this.xmlSchema = xmlSchema;
|
this.xmlSchema = xmlSchema;
|
||||||
@ -26,11 +31,11 @@ module.exports = {
|
|||||||
this.xmlSchema.header = {
|
this.xmlSchema.header = {
|
||||||
'@': { authenticate: true },
|
'@': { authenticate: true },
|
||||||
static: {
|
static: {
|
||||||
HostID: ebicsData.hostId,
|
HostID: ebicsAccount.hostId,
|
||||||
Nonce: Crypto.nonce(),
|
Nonce: Crypto.nonce(),
|
||||||
Timestamp: Crypto.timestamp(),
|
Timestamp: Crypto.timestamp(),
|
||||||
PartnerID: ebicsData.partnerId,
|
PartnerID: ebicsAccount.partnerId,
|
||||||
UserID: ebicsData.userId,
|
UserID: ebicsAccount.userId,
|
||||||
Product: {
|
Product: {
|
||||||
'@': { Language: 'en' },
|
'@': { Language: 'en' },
|
||||||
'#': productString,
|
'#': productString,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const constants = require('../../../consts');
|
||||||
|
|
||||||
const rootName = 'ebicsRequest';
|
const rootName = 'ebicsRequest';
|
||||||
const rootAttributes = {
|
const rootAttributes = {
|
||||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
@ -58,76 +60,75 @@ const xmlOptions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = (orderBuilder) => {
|
module.exports = (hostId, transactionId) => ({
|
||||||
const { ebicsData, transactionId } = orderBuilder;
|
// return {
|
||||||
|
productString: constants.productString,
|
||||||
|
rootName,
|
||||||
|
xmlOptions,
|
||||||
|
xmlSchema: {
|
||||||
|
'@': rootAttributes,
|
||||||
|
header,
|
||||||
|
AuthSignature: authSignature,
|
||||||
|
body,
|
||||||
|
},
|
||||||
|
|
||||||
return {
|
receipt() {
|
||||||
rootName,
|
this.xmlSchema = {
|
||||||
xmlOptions,
|
|
||||||
xmlSchema: {
|
|
||||||
'@': rootAttributes,
|
'@': rootAttributes,
|
||||||
header,
|
|
||||||
|
header: {
|
||||||
|
'@': { authenticate: true },
|
||||||
|
static: {
|
||||||
|
HostID: hostId,
|
||||||
|
TransactionID: transactionId,
|
||||||
|
},
|
||||||
|
mutable: {
|
||||||
|
TransactionPhase: 'Receipt',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
AuthSignature: authSignature,
|
AuthSignature: authSignature,
|
||||||
body,
|
|
||||||
},
|
|
||||||
|
|
||||||
receipt() {
|
body: {
|
||||||
this.xmlSchema = {
|
TransferReceipt: {
|
||||||
'@': rootAttributes,
|
|
||||||
|
|
||||||
header: {
|
|
||||||
'@': { authenticate: true },
|
'@': { authenticate: true },
|
||||||
static: {
|
ReceiptCode: 0,
|
||||||
HostID: ebicsData.hostId,
|
},
|
||||||
TransactionID: transactionId,
|
},
|
||||||
},
|
};
|
||||||
mutable: {
|
|
||||||
TransactionPhase: 'Receipt',
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
transfer(encryptedOrderData) {
|
||||||
|
this.xmlSchema = {
|
||||||
|
'@': rootAttributes,
|
||||||
|
|
||||||
|
header: {
|
||||||
|
'@': { authenticate: true },
|
||||||
|
static: {
|
||||||
|
HostID: hostId,
|
||||||
|
TransactionID: transactionId,
|
||||||
|
},
|
||||||
|
mutable: {
|
||||||
|
TransactionPhase: 'Transfer',
|
||||||
|
SegmentNumber: {
|
||||||
|
'@': { lastSegment: true },
|
||||||
|
'#': 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
|
||||||
AuthSignature: authSignature,
|
AuthSignature: authSignature,
|
||||||
|
|
||||||
body: {
|
body: {
|
||||||
TransferReceipt: {
|
DataTransfer: {
|
||||||
'@': { authenticate: true },
|
OrderData: encryptedOrderData,
|
||||||
ReceiptCode: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
// };
|
||||||
transfer(encryptedOrderData) {
|
});
|
||||||
this.xmlSchema = {
|
|
||||||
'@': rootAttributes,
|
|
||||||
|
|
||||||
header: {
|
|
||||||
'@': { authenticate: true },
|
|
||||||
static: {
|
|
||||||
HostID: ebicsData.hostId,
|
|
||||||
TransactionID: transactionId,
|
|
||||||
},
|
|
||||||
mutable: {
|
|
||||||
TransactionPhase: 'Transfer',
|
|
||||||
SegmentNumber: {
|
|
||||||
'@': { lastSegment: true },
|
|
||||||
'#': 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
AuthSignature: authSignature,
|
|
||||||
|
|
||||||
body: {
|
|
||||||
DataTransfer: {
|
|
||||||
OrderData: encryptedOrderData,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
@ -8,7 +8,7 @@ const Crypto = require('../../../crypto/Crypto');
|
|||||||
|
|
||||||
const genericSerializer = require('./generic');
|
const genericSerializer = require('./generic');
|
||||||
|
|
||||||
const keySignature = (ebicsData, key, xmlOptions) => {
|
const keySignature = (ebicsAccount, key, xmlOptions) => {
|
||||||
const xmlOrderData = {
|
const xmlOrderData = {
|
||||||
'@': {
|
'@': {
|
||||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
@ -24,13 +24,13 @@ const keySignature = (ebicsData, key, xmlOptions) => {
|
|||||||
},
|
},
|
||||||
SignatureVersion: 'A006',
|
SignatureVersion: 'A006',
|
||||||
},
|
},
|
||||||
PartnerID: ebicsData.partnerId,
|
PartnerID: ebicsAccount.partnerId,
|
||||||
UserID: ebicsData.userId,
|
UserID: ebicsAccount.userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return js2xmlparser.parse('SignaturePubKeyOrderData', xmlOrderData, xmlOptions);
|
return js2xmlparser.parse('SignaturePubKeyOrderData', xmlOrderData, xmlOptions);
|
||||||
};
|
};
|
||||||
const orderData = (ebicsData, keys, xmlOptions) => {
|
const orderData = (ebicsAccount, keys, xmlOptions) => {
|
||||||
const xmlOrderData = {
|
const xmlOrderData = {
|
||||||
'@': {
|
'@': {
|
||||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
@ -54,20 +54,20 @@ const orderData = (ebicsData, keys, xmlOptions) => {
|
|||||||
},
|
},
|
||||||
EncryptionVersion: 'E002',
|
EncryptionVersion: 'E002',
|
||||||
},
|
},
|
||||||
PartnerID: ebicsData.partnerId,
|
PartnerID: ebicsAccount.partnerId,
|
||||||
UserID: ebicsData.userId,
|
UserID: ebicsAccount.userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return js2xmlparser.parse('HIARequestOrderData', xmlOrderData, xmlOptions);
|
return js2xmlparser.parse('HIARequestOrderData', xmlOrderData, xmlOptions);
|
||||||
};
|
};
|
||||||
const commonHeader = (ebicsData, orderDetails, productString) => ({
|
const commonHeader = (ebicsAccount, orderDetails, productString) => ({
|
||||||
'@': { authenticate: true },
|
'@': { authenticate: true },
|
||||||
static: {
|
static: {
|
||||||
HostID: ebicsData.hostId,
|
HostID: ebicsAccount.hostId,
|
||||||
Nonce: Crypto.nonce(),
|
Nonce: Crypto.nonce(),
|
||||||
Timestamp: Crypto.timestamp(),
|
Timestamp: Crypto.timestamp(),
|
||||||
PartnerID: ebicsData.partnerId,
|
PartnerID: ebicsAccount.partnerId,
|
||||||
UserID: ebicsData.userId,
|
UserID: ebicsAccount.userId,
|
||||||
Product: {
|
Product: {
|
||||||
'@': { Language: 'en' },
|
'@': { Language: 'en' },
|
||||||
'#': productString,
|
'#': productString,
|
||||||
@ -80,57 +80,61 @@ const commonHeader = (ebicsData, orderDetails, productString) => ({
|
|||||||
const process = {
|
const process = {
|
||||||
INI: {
|
INI: {
|
||||||
rootName: 'ebicsUnsecuredRequest',
|
rootName: 'ebicsUnsecuredRequest',
|
||||||
header: (ebicsData, orderDetails, productString) => {
|
header: (ebicsAccount, orderDetails, productString) => {
|
||||||
const ch = commonHeader(ebicsData, orderDetails, productString);
|
const ch = commonHeader(ebicsAccount, orderDetails, productString);
|
||||||
|
|
||||||
delete ch.static.Nonce;
|
delete ch.static.Nonce;
|
||||||
delete ch.static.Timestamp;
|
delete ch.static.Timestamp;
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
},
|
},
|
||||||
body: (ebicsData, keys, xmlOptions) => ({
|
body: (ebicsAccount, keys, xmlOptions) => ({
|
||||||
DataTransfer: {
|
DataTransfer: {
|
||||||
OrderData: Buffer.from(zlib.deflateSync(keySignature(ebicsData, keys.a(), xmlOptions))).toString('base64'),
|
OrderData: Buffer.from(zlib.deflateSync(keySignature(ebicsAccount, keys.a(), xmlOptions))).toString('base64'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
HIA: {
|
HIA: {
|
||||||
rootName: 'ebicsUnsecuredRequest',
|
rootName: 'ebicsUnsecuredRequest',
|
||||||
header: (ebicsData, orderDetails, productString) => {
|
header: (ebicsAccount, orderDetails, productString) => {
|
||||||
const ch = commonHeader(ebicsData, orderDetails, productString);
|
const ch = commonHeader(ebicsAccount, orderDetails, productString);
|
||||||
|
|
||||||
delete ch.static.Nonce;
|
delete ch.static.Nonce;
|
||||||
delete ch.static.Timestamp;
|
delete ch.static.Timestamp;
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
},
|
},
|
||||||
body: (ebicsData, keys, xmlOptions) => ({
|
body: (ebicsAccount, keys, xmlOptions) => ({
|
||||||
DataTransfer: {
|
DataTransfer: {
|
||||||
OrderData: Buffer.from(zlib.deflateSync(orderData(ebicsData, keys, xmlOptions))).toString('base64'),
|
OrderData: Buffer.from(zlib.deflateSync(orderData(ebicsAccount, keys, xmlOptions))).toString('base64'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
HPB: {
|
HPB: {
|
||||||
rootName: 'ebicsNoPubKeyDigestsRequest',
|
rootName: 'ebicsNoPubKeyDigestsRequest',
|
||||||
header: (ebicsData, orderDetails, productString) => commonHeader(ebicsData, orderDetails, productString),
|
header: (ebicsAccount, orderDetails, productString) => commonHeader(ebicsAccount, orderDetails, productString),
|
||||||
body: () => ({}),
|
body: () => ({}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
use(orderBuilder) {
|
use(order, client) {
|
||||||
const { xmlOptions, xmlSchema } = genericSerializer(orderBuilder);
|
const keys = client.keys();
|
||||||
const {
|
const { orderDetails, transactionId } = order;
|
||||||
ebicsData, orderDetails, keys, productString,
|
const { xmlOptions, xmlSchema, productString } = genericSerializer(client.host, transactionId);
|
||||||
} = orderBuilder;
|
|
||||||
const orderType = orderDetails.OrderType.toUpperCase();
|
const orderType = orderDetails.OrderType.toUpperCase();
|
||||||
|
const ebicsAccount = {
|
||||||
|
partnerId: client.partnerId,
|
||||||
|
userId: client.userId,
|
||||||
|
hostId: client.hostId,
|
||||||
|
};
|
||||||
|
|
||||||
this.rootName = process[orderType].rootName;
|
this.rootName = process[orderType].rootName;
|
||||||
this.xmlOptions = xmlOptions;
|
this.xmlOptions = xmlOptions;
|
||||||
this.xmlSchema = xmlSchema;
|
this.xmlSchema = xmlSchema;
|
||||||
|
|
||||||
this.xmlSchema.header = process[orderType].header(ebicsData, orderDetails, productString);
|
this.xmlSchema.header = process[orderType].header(ebicsAccount, orderDetails, productString);
|
||||||
this.xmlSchema.body = process[orderType].body(ebicsData, keys, this.xmlOptions);
|
this.xmlSchema.body = process[orderType].body(ebicsAccount, keys, this.xmlOptions);
|
||||||
|
|
||||||
if (orderType !== 'HPB' && Object.prototype.hasOwnProperty.call(this.xmlSchema, 'AuthSignature'))
|
if (orderType !== 'HPB' && Object.prototype.hasOwnProperty.call(this.xmlSchema, 'AuthSignature'))
|
||||||
delete this.xmlSchema.AuthSignature;
|
delete this.xmlSchema.AuthSignature;
|
||||||
|
@ -9,12 +9,14 @@ const Crypto = require('../../../crypto/Crypto');
|
|||||||
|
|
||||||
const downloadSerializer = require('./download');
|
const downloadSerializer = require('./download');
|
||||||
|
|
||||||
|
const transKey = crypto.randomBytes(16);
|
||||||
|
|
||||||
const signatureValue = (document, key) => {
|
const signatureValue = (document, key) => {
|
||||||
const digested = Crypto.digestWithHash(document.replace(/\n|\r/g, ''));
|
const digested = Crypto.digestWithHash(document.replace(/\n|\r/g, ''));
|
||||||
|
|
||||||
return Crypto.sign(key, digested);
|
return Crypto.sign(key, digested);
|
||||||
};
|
};
|
||||||
const orderSignature = (ebicsData, document, key, xmlOptions) => {
|
const orderSignature = (ebicsAccount, document, key, xmlOptions) => {
|
||||||
const xmlObj = {
|
const xmlObj = {
|
||||||
'@': {
|
'@': {
|
||||||
xmlns: 'http://www.ebics.org/S001',
|
xmlns: 'http://www.ebics.org/S001',
|
||||||
@ -24,15 +26,15 @@ const orderSignature = (ebicsData, document, key, xmlOptions) => {
|
|||||||
OrderSignatureData: {
|
OrderSignatureData: {
|
||||||
SignatureVersion: 'A006',
|
SignatureVersion: 'A006',
|
||||||
SignatureValue: signatureValue(document, key),
|
SignatureValue: signatureValue(document, key),
|
||||||
PartnerID: ebicsData.partnerId,
|
PartnerID: ebicsAccount.partnerId,
|
||||||
UserID: ebicsData.userId,
|
UserID: ebicsAccount.userId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return js2xmlparser.parse('UserSignatureData', xmlObj, xmlOptions);
|
return js2xmlparser.parse('UserSignatureData', xmlObj, xmlOptions);
|
||||||
};
|
};
|
||||||
const encryptedOrderSignature = (ebicsData, document, transactionKey, key, xmlOptions) => {
|
const encryptedOrderSignature = (ebicsAccount, document, transactionKey, key, xmlOptions) => {
|
||||||
const dst = zlib.deflateSync(orderSignature(ebicsData, document, key, xmlOptions));
|
const dst = zlib.deflateSync(orderSignature(ebicsAccount, document, key, xmlOptions));
|
||||||
const cipher = crypto.createCipheriv('aes-128-cbc', transactionKey, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])).setAutoPadding(false);
|
const cipher = crypto.createCipheriv('aes-128-cbc', transactionKey, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])).setAutoPadding(false);
|
||||||
|
|
||||||
return Buffer.concat([cipher.update(Crypto.pad(dst)), cipher.final()]).toString('base64');
|
return Buffer.concat([cipher.update(Crypto.pad(dst)), cipher.final()]).toString('base64');
|
||||||
@ -45,23 +47,28 @@ const encryptedOrderData = (document, transactionKey) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
use(orderBuilder) {
|
use(order, client) {
|
||||||
|
const keys = client.keys();
|
||||||
|
const ebicsAccount = {
|
||||||
|
partnerId: client.partnerId,
|
||||||
|
userId: client.userId,
|
||||||
|
hostId: client.hostId,
|
||||||
|
};
|
||||||
const {
|
const {
|
||||||
ebicsData, keys, transactionId, transactionKey, document,
|
transactionId, document,
|
||||||
} = orderBuilder;
|
} = order;
|
||||||
const {
|
const {
|
||||||
rootName, xmlOptions, xmlSchema, transfer,
|
rootName, xmlOptions, xmlSchema, transfer,
|
||||||
} = downloadSerializer.use(orderBuilder);
|
} = downloadSerializer.use(order, client);
|
||||||
|
|
||||||
this.rootName = rootName;
|
this.rootName = rootName;
|
||||||
this.xmlOptions = xmlOptions;
|
this.xmlOptions = xmlOptions;
|
||||||
this.xmlSchema = xmlSchema;
|
this.xmlSchema = xmlSchema;
|
||||||
this.transfer = transfer;
|
this.transfer = transfer;
|
||||||
|
|
||||||
if (transactionId) return this.transfer(encryptedOrderData(document, transactionKey));
|
if (transactionId) return this.transfer(encryptedOrderData(document, transKey));
|
||||||
|
|
||||||
this.xmlSchema.header.static.NumSegments = 1;
|
this.xmlSchema.header.static.NumSegments = 1;
|
||||||
|
|
||||||
this.xmlSchema.body = {
|
this.xmlSchema.body = {
|
||||||
DataTransfer: {
|
DataTransfer: {
|
||||||
DataEncryptionInfo: {
|
DataEncryptionInfo: {
|
||||||
@ -70,11 +77,11 @@ module.exports = {
|
|||||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||||
'#': Crypto.digestPublicKey(keys.bankE()),
|
'#': Crypto.digestPublicKey(keys.bankE()),
|
||||||
},
|
},
|
||||||
TransactionKey: Crypto.publicEncrypt(keys.bankE(), transactionKey).toString('base64'),
|
TransactionKey: Crypto.publicEncrypt(keys.bankE(), transKey).toString('base64'),
|
||||||
},
|
},
|
||||||
SignatureData: {
|
SignatureData: {
|
||||||
'@': { authenticate: true },
|
'@': { authenticate: true },
|
||||||
'#': encryptedOrderSignature(ebicsData, document, transactionKey, keys.a(), this.xmlOptions),
|
'#': encryptedOrderSignature(ebicsAccount, document, transKey, keys.a(), this.xmlOptions),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -41,8 +41,7 @@ const sign = (doc, key) => {
|
|||||||
const toXML = doc => new XMLSerializer().serializeToString(doc);
|
const toXML = doc => new XMLSerializer().serializeToString(doc);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
sign(data, keys) {
|
sign(data, keyX) {
|
||||||
const keyX = keys.x();
|
|
||||||
const doc = new DOMParser().parseFromString(data, 'text/xml');
|
const doc = new DOMParser().parseFromString(data, 'text/xml');
|
||||||
|
|
||||||
return toXML(sign(digest(doc), keyX));
|
return toXML(sign(digest(doc), keyX));
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const orders = {
|
|
||||||
H004: {
|
|
||||||
ini: ['INI', 'HIA', 'HPB'],
|
|
||||||
download: ['HAA', 'HTD', 'XTD', 'HPD', 'HKD', 'PTK', 'HAC', 'STA', 'VMK', 'C52', 'C53', 'C54', 'Z01'],
|
|
||||||
upload: ['AZV', 'CD1', 'CDB', 'CDD', 'CDS', 'CCT', 'CCS', 'XE3'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
version(v) {
|
|
||||||
this.orders = orders[v.toUpperCase()];
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
isIni(orderType) {
|
|
||||||
const { ini } = this.orders;
|
|
||||||
|
|
||||||
return ini.includes(orderType.toUpperCase());
|
|
||||||
},
|
|
||||||
|
|
||||||
isDownload(orderType) {
|
|
||||||
const { download } = this.orders;
|
|
||||||
|
|
||||||
return download.includes(orderType.toUpperCase());
|
|
||||||
},
|
|
||||||
|
|
||||||
isUpload(orderType) {
|
|
||||||
const { upload } = this.orders;
|
|
||||||
|
|
||||||
return upload.includes(orderType.toUpperCase());
|
|
||||||
},
|
|
||||||
};
|
|
@ -7,12 +7,13 @@ module.exports = (pathToFile) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
read() {
|
read() {
|
||||||
|
if (!fs.existsSync(path))
|
||||||
|
return null;
|
||||||
return fs.readFileSync(path, { encoding: 'utf8' });
|
return fs.readFileSync(path, { encoding: 'utf8' });
|
||||||
},
|
},
|
||||||
|
|
||||||
save(data) {
|
write(data) {
|
||||||
fs.writeFileSync(path, data, { encoding: 'utf8' });
|
fs.writeFileSync(path, data, { encoding: 'utf8' });
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user