mirror of
https://github.com/node-ebics/node-ebics-client.git
synced 2025-08-13 19:35:34 +00:00
Major changes. Separating responsibilities. Orders builder, serializer.
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class C52 extends GenericOrder {
|
||||
constructor(client, from, to) {
|
||||
super(client);
|
||||
this._from = from;
|
||||
this._to = to;
|
||||
|
||||
this._schema.header = {
|
||||
'@': {
|
||||
authenticate: true,
|
||||
},
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': {
|
||||
Language: 'de',
|
||||
},
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'C52',
|
||||
OrderAttribute: 'DZHNN',
|
||||
StandardOrderParams: {
|
||||
DateRange: {
|
||||
Start: this._from,
|
||||
End: this._to,
|
||||
},
|
||||
},
|
||||
},
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': {
|
||||
Version: 'X002',
|
||||
Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256',
|
||||
},
|
||||
'#': this.client.bankX().publicDigest(),
|
||||
},
|
||||
Encryption: {
|
||||
'@': {
|
||||
Version: 'E002',
|
||||
Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256',
|
||||
},
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
@@ -1,181 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// const randHex = require('../../lib/utils').randHex;
|
||||
const crypto = require('crypto');
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
const consts = require('../consts');
|
||||
|
||||
const authSignature = () => {
|
||||
return {
|
||||
'ds:SignedInfo': {
|
||||
'ds:CanonicalizationMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/TR/2001/REC-xml-c14n-20010315',
|
||||
},
|
||||
},
|
||||
'ds:SignatureMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
},
|
||||
},
|
||||
'ds:Reference': {
|
||||
'@': { URI: "#xpointer(//*[@authenticate='true'])" },
|
||||
'ds:Transforms': {
|
||||
'ds:Transform': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/TR/2001/REC-xml-c14n-20010315',
|
||||
},
|
||||
},
|
||||
},
|
||||
'ds:DigestMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/2001/04/xmlenc#sha256',
|
||||
},
|
||||
},
|
||||
'ds:DigestValue': {},
|
||||
},
|
||||
},
|
||||
'ds:SignatureValue': {},
|
||||
};
|
||||
};
|
||||
module.exports = class GenericOrder {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
|
||||
this.hostId = client.hostId;
|
||||
this.userId = client.userId;
|
||||
this.partnerId = client.partnerId;
|
||||
|
||||
this.transactionId = '';
|
||||
|
||||
this.xmlOptions = {
|
||||
declaration: {
|
||||
include: true,
|
||||
encoding: 'utf-8',
|
||||
},
|
||||
format: {
|
||||
doubleQuotes: true,
|
||||
indent: '',
|
||||
newline: '',
|
||||
pretty: true,
|
||||
},
|
||||
};
|
||||
|
||||
this._schema = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
|
||||
header: {},
|
||||
|
||||
AuthSignature: authSignature(),
|
||||
|
||||
body: {},
|
||||
};
|
||||
}
|
||||
|
||||
get schema() {
|
||||
return this._schema;
|
||||
}
|
||||
|
||||
static get productString() {
|
||||
return consts.productString;
|
||||
}
|
||||
|
||||
static nonce() {
|
||||
return crypto.randomBytes(16).toString('hex');
|
||||
}
|
||||
|
||||
// TODO: remove eslint-disable-line
|
||||
timestamp() { // eslint-disable-line
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
root() { // eslint-disable-line class-methods-use-this
|
||||
return 'ebicsRequest';
|
||||
}
|
||||
|
||||
toReceiptXML() {
|
||||
const xmlObj = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
TransactionID: this.transactionId,
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Receipt',
|
||||
},
|
||||
},
|
||||
|
||||
AuthSignature: this.authSignature(),
|
||||
|
||||
body: {
|
||||
TransferReceipt: {
|
||||
'@': { authenticate: true },
|
||||
ReceiptCode: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return js2xmlparser.parse(this.root(), xmlObj, this.xmlOptions);
|
||||
}
|
||||
|
||||
toTransferXML() {
|
||||
const xmlObj = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
TransactionID: this.transactionId,
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Transfer',
|
||||
SegmentNumber: {
|
||||
'@': { lastSegment: true },
|
||||
'#': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
AuthSignature: this.authSignature(),
|
||||
|
||||
body: {
|
||||
DataTransfer: {
|
||||
OrderData: this.encryptedOrderData(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return js2xmlparser.parse(this.root(), xmlObj, this.xmlOptions);
|
||||
}
|
||||
|
||||
encryptedOrderData() { // eslint-disable-line class-methods-use-this
|
||||
return null;
|
||||
}
|
||||
|
||||
toXML() {
|
||||
return js2xmlparser.parse(this.root(), this._schema, this.xmlOptions);
|
||||
}
|
||||
};
|
@@ -1,79 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
const pad = (d) => {
|
||||
const dLen = d.length;
|
||||
const len = 16 * (Math.trunc(dLen / 16) + 1);
|
||||
|
||||
return Buffer.concat([d, Buffer.from(Buffer.from([0]).toString().repeat(len - dLen - 1)), Buffer.from([len - dLen])]);
|
||||
};
|
||||
|
||||
module.exports = class GenericUploadOrder extends GenericOrder {
|
||||
constructor(client, document) {
|
||||
super(client);
|
||||
|
||||
this._document = document;
|
||||
this._key = crypto.randomBytes(16);
|
||||
|
||||
this._schema.body = {
|
||||
DataTransfer: {
|
||||
DataEncryptionInfo: {
|
||||
'@': { authenticate: true },
|
||||
EncryptionPubKeyDigest: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
TransactionKey: this.client.bankE().publicEncrypt(this._key).toString('base64'),
|
||||
},
|
||||
SignatureData: {
|
||||
'@': { authenticate: true },
|
||||
'#': this.encryptedOrderSignature(),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
orderSignature() {
|
||||
const xmlObj = {
|
||||
'@': {
|
||||
xmlns: 'http://www.ebics.org/S001',
|
||||
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation': 'http://www.ebics.org/S001 http://www.ebics.org/S001/ebics_signature.xsd',
|
||||
},
|
||||
OrderSignatureData: {
|
||||
SignatureVersion: 'A006',
|
||||
SignatureValue: this.signatureValue(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
},
|
||||
};
|
||||
|
||||
return js2xmlparser.parse('UserSignatureData', xmlObj, this.xmlOptions);
|
||||
}
|
||||
|
||||
signatureValue() {
|
||||
const digested = crypto.createHash('sha256').update(this._document.replace(/\n|\r/g, '')).digest();
|
||||
|
||||
return this.client.a().sign(digested);
|
||||
}
|
||||
|
||||
encryptedOrderData() {
|
||||
const dst = zlib.deflateSync(this._document.replace(/\r|\n/g, ''));
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', this._key, 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(pad(dst)), cipher.final()]).toString('base64');
|
||||
}
|
||||
|
||||
encryptedOrderSignature() {
|
||||
const dst = zlib.deflateSync(this.orderSignature());
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', this._key, 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(pad(dst)), cipher.final()]).toString('base64');
|
||||
}
|
||||
};
|
81
lib/orders/H004/GenericSerializer.js
Normal file
81
lib/orders/H004/GenericSerializer.js
Normal file
@@ -0,0 +1,81 @@
|
||||
'use strict';
|
||||
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const xmlOptions = {
|
||||
declaration: {
|
||||
include: true,
|
||||
encoding: 'utf-8',
|
||||
},
|
||||
format: {
|
||||
doubleQuotes: true,
|
||||
indent: '',
|
||||
newline: '',
|
||||
pretty: true,
|
||||
},
|
||||
};
|
||||
|
||||
const authSignature = ({
|
||||
'ds:SignedInfo': {
|
||||
'ds:CanonicalizationMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/TR/2001/REC-xml-c14n-20010315',
|
||||
},
|
||||
},
|
||||
'ds:SignatureMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
|
||||
},
|
||||
},
|
||||
'ds:Reference': {
|
||||
'@': { URI: "#xpointer(//*[@authenticate='true'])" },
|
||||
'ds:Transforms': {
|
||||
'ds:Transform': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/TR/2001/REC-xml-c14n-20010315',
|
||||
},
|
||||
},
|
||||
},
|
||||
'ds:DigestMethod': {
|
||||
'@': {
|
||||
Algorithm:
|
||||
'http://www.w3.org/2001/04/xmlenc#sha256',
|
||||
},
|
||||
},
|
||||
'ds:DigestValue': {},
|
||||
},
|
||||
},
|
||||
'ds:SignatureValue': {},
|
||||
});
|
||||
|
||||
module.exports = class GenericSerializer {
|
||||
constructor(orderBuilder) {
|
||||
this._order = orderBuilder;
|
||||
this._orderDetails = orderBuilder.orderDetails;
|
||||
this._hostId = orderBuilder.hostId;
|
||||
this._partnerId = orderBuilder.partnerId;
|
||||
this._userId = orderBuilder.userId;
|
||||
this._keys = orderBuilder.keys;
|
||||
this._transactionId = orderBuilder.transactionId;
|
||||
this._rootName = orderBuilder.root.nodeName;
|
||||
this._rootAttributes = orderBuilder.root.nodeAttributes;
|
||||
|
||||
this._xmlOptions = xmlOptions;
|
||||
this._xml = {};
|
||||
}
|
||||
|
||||
static authSignature() {
|
||||
return authSignature;
|
||||
}
|
||||
|
||||
get keys() {
|
||||
return this._keys;
|
||||
}
|
||||
|
||||
toXML() {
|
||||
return js2xmlparser.parse(this._rootName, this._xml, this._xmlOptions);
|
||||
}
|
||||
};
|
128
lib/orders/H004/InitializationSerializer.js
Normal file
128
lib/orders/H004/InitializationSerializer.js
Normal file
@@ -0,0 +1,128 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const consts = require('../../consts');
|
||||
const Crypto = require('../../crypto/Crypto');
|
||||
|
||||
const GenericSerializer = require('./GenericSerializer');
|
||||
|
||||
module.exports = class InitializationSerializer extends GenericSerializer {
|
||||
constructor(order) {
|
||||
super(order);
|
||||
|
||||
this._xml = {
|
||||
'@': this._rootAttributes,
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this._hostId,
|
||||
Nonce: Crypto.nonce(),
|
||||
Timestamp: Crypto.timestamp(),
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
Product: {
|
||||
'@': { Language: 'en' },
|
||||
'#': consts.productString,
|
||||
},
|
||||
OrderDetails: this._orderDetails,
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {},
|
||||
},
|
||||
};
|
||||
|
||||
if (this._isINI() || this._isHIA()) {
|
||||
delete this._xml.header.static.Nonce;
|
||||
delete this._xml.header.static.Timestamp;
|
||||
|
||||
this._xml.body = {
|
||||
DataTransfer: {
|
||||
OrderData: this.orderData(),
|
||||
},
|
||||
};
|
||||
} else {
|
||||
this._rootName = 'ebicsNoPubKeyDigestsRequest';
|
||||
this._xml.AuthSignature = GenericSerializer.authSignature();
|
||||
this._xml.body = {};
|
||||
}
|
||||
}
|
||||
|
||||
orderData() {
|
||||
if (this._isINI()) return this._iniKeySignature();
|
||||
if (this._isHIA()) return this._hiaOrderData();
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
_iniKeySignature() {
|
||||
const xmlOrderData = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'http://www.ebics.org/S001',
|
||||
},
|
||||
SignaturePubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this._keys.a().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': this._keys.a().e().toString('base64'),
|
||||
},
|
||||
TimeStamp: Crypto.timestamp(),
|
||||
},
|
||||
SignatureVersion: 'A006',
|
||||
},
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
};
|
||||
|
||||
const signature = js2xmlparser.parse('SignaturePubKeyOrderData', xmlOrderData, this._xmlOptions);
|
||||
|
||||
return Buffer.from(zlib.deflateSync(signature)).toString('base64');
|
||||
}
|
||||
|
||||
_hiaOrderData() {
|
||||
const xmlOrderData = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
},
|
||||
AuthenticationPubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this._keys.x().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': this._keys.x().e().toString('base64'),
|
||||
},
|
||||
},
|
||||
AuthenticationVersion: 'X002',
|
||||
},
|
||||
EncryptionPubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this.keys.e().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': this._keys.e().e().toString('base64'),
|
||||
},
|
||||
},
|
||||
EncryptionVersion: 'E002',
|
||||
},
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
};
|
||||
|
||||
const order = js2xmlparser.parse('HIARequestOrderData', xmlOrderData, this._xmlOptions);
|
||||
|
||||
return Buffer.from(zlib.deflateSync(order)).toString('base64');
|
||||
}
|
||||
|
||||
_isINI() {
|
||||
return this._orderDetails.OrderType.toUpperCase() === 'INI';
|
||||
}
|
||||
|
||||
_isHIA() {
|
||||
return this._orderDetails.OrderType.toUpperCase() === 'HIA';
|
||||
}
|
||||
|
||||
_isHPB() {
|
||||
return this._orderDetails.OrderType.toUpperCase() === 'HPB';
|
||||
}
|
||||
};
|
78
lib/orders/H004/OrderBuilder.js
Normal file
78
lib/orders/H004/OrderBuilder.js
Normal file
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
|
||||
// const orderTypes = ['ini', 'download', 'upload', 'zip'];
|
||||
|
||||
module.exports = class OrderBuilder {
|
||||
constructor() {
|
||||
this._transactionKey = crypto.randomBytes(16);
|
||||
this._root = {
|
||||
nodeName: 'ebicsRequest',
|
||||
nodeAttributes: {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
};
|
||||
this._body = {};
|
||||
}
|
||||
|
||||
details(data) {
|
||||
this._data = data;
|
||||
this._data.transactionId = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static payment() {
|
||||
const builder = new OrderBuilder();
|
||||
|
||||
builder._type = 'payment';
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
static status() {
|
||||
const builder = new OrderBuilder();
|
||||
|
||||
builder._type = 'status';
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
static ini() {
|
||||
const builder = new OrderBuilder();
|
||||
|
||||
builder._type = 'ini';
|
||||
builder._root.nodeName = 'ebicsUnsecuredRequest';
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
get type() { return this._type; }
|
||||
get root() { return this._root; }
|
||||
get body() { return this._body; }
|
||||
get data() { return this._data; }
|
||||
get orderDetails() { return this._data.orderDetails; }
|
||||
get transactionId() { return this._data.transactionId; }
|
||||
get document() { return this._data.document; }
|
||||
get transactionKey() { return this._transactionKey; }
|
||||
get ebicsData() { return this._data.ebicsData; }
|
||||
get hostId() { return this._data.ebicsData.hostId; }
|
||||
get partnerId() { return this._data.ebicsData.partnerId; }
|
||||
get userId() { return this._data.ebicsData.userId; }
|
||||
get keys() { return this._data.ebicsData.keysManager.keys(); }
|
||||
|
||||
set transactionId(tid) {
|
||||
this._data.transactionId = tid === '' ? null : tid;
|
||||
}
|
||||
|
||||
hasTransactionId() {
|
||||
return this.transactionId !== null;
|
||||
}
|
||||
};
|
15
lib/orders/H004/OrderSerializer.js
Normal file
15
lib/orders/H004/OrderSerializer.js
Normal file
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const InitializationSerializer = require('./InitializationSerializer');
|
||||
const StatusSerializer = require('./StatusSerializer');
|
||||
const PaymentSerializer = require('./PaymentSerializer');
|
||||
|
||||
module.exports = class OrderSerializer {
|
||||
static serialize(order) {
|
||||
if (order.type === 'ini') return new InitializationSerializer(order);
|
||||
if (order.type === 'payment') return new PaymentSerializer(order);
|
||||
if (order.type === 'status') return new StatusSerializer(order);
|
||||
|
||||
throw Error('Incorect order type. Available types: ini, status, payment, statement');
|
||||
}
|
||||
};
|
131
lib/orders/H004/PaymentSerializer.js
Normal file
131
lib/orders/H004/PaymentSerializer.js
Normal file
@@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const consts = require('../../consts');
|
||||
const Crypto = require('../../crypto/Crypto');
|
||||
|
||||
const GenericSerializer = require('./GenericSerializer');
|
||||
|
||||
module.exports = class PaymentSerializer extends GenericSerializer {
|
||||
constructor(order) {
|
||||
super(order);
|
||||
|
||||
this._transactionKey = order.transactionKey;
|
||||
|
||||
this._xml = {
|
||||
'@': this._rootAttributes,
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this._hostId,
|
||||
Nonce: Crypto.nonce(),
|
||||
Timestamp: Crypto.timestamp(),
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
Product: {
|
||||
'@': { Language: 'en' },
|
||||
'#': consts.productString,
|
||||
},
|
||||
OrderDetails: this._orderDetails,
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': Crypto.digestPublicKey(this._keys.bankX()),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': Crypto.digestPublicKey(this._keys.bankE()),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
NumSegments: 1,
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
},
|
||||
AuthSignature: GenericSerializer.authSignature(),
|
||||
body: {
|
||||
DataTransfer: {
|
||||
DataEncryptionInfo: {
|
||||
'@': { authenticate: true },
|
||||
EncryptionPubKeyDigest: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': Crypto.digestPublicKey(this._keys.bankE()),
|
||||
},
|
||||
TransactionKey: Crypto.publicEncrypt(this._keys.bankE(), this._transactionKey).toString('base64'),
|
||||
},
|
||||
SignatureData: {
|
||||
'@': { authenticate: true },
|
||||
'#': this.encryptedOrderSignature(),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (order.hasTransactionId()) {
|
||||
this._xml.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this._hostId,
|
||||
TransactionID: this._transactionId,
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Transfer',
|
||||
SegmentNumber: {
|
||||
'@': { lastSegment: true },
|
||||
'#': 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this._xml.body = {
|
||||
DataTransfer: {
|
||||
OrderData: this.encryptedOrderData(),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
orderSignature() {
|
||||
const xmlObj = {
|
||||
'@': {
|
||||
xmlns: 'http://www.ebics.org/S001',
|
||||
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation': 'http://www.ebics.org/S001 http://www.ebics.org/S001/ebics_signature.xsd',
|
||||
},
|
||||
OrderSignatureData: {
|
||||
SignatureVersion: 'A006',
|
||||
SignatureValue: this.signatureValue(),
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
},
|
||||
};
|
||||
|
||||
return js2xmlparser.parse('UserSignatureData', xmlObj, this._xmlOptions);
|
||||
}
|
||||
|
||||
signatureValue() {
|
||||
const digested = Crypto.digestWithHash(this._order.document.replace(/\n|\r/g, ''));
|
||||
|
||||
return Crypto.sign(this._keys.a(), digested);
|
||||
}
|
||||
|
||||
encryptedOrderData() {
|
||||
const dst = zlib.deflateSync(this._order.document.replace(/\n|\r/g, ''));
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', this._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');
|
||||
}
|
||||
|
||||
encryptedOrderSignature() {
|
||||
const dst = zlib.deflateSync(this.orderSignature());
|
||||
const cipher = crypto.createCipheriv('aes-128-cbc', this._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');
|
||||
}
|
||||
};
|
67
lib/orders/H004/StatusSerializer.js
Normal file
67
lib/orders/H004/StatusSerializer.js
Normal file
@@ -0,0 +1,67 @@
|
||||
'use strict';
|
||||
|
||||
const consts = require('../../consts');
|
||||
const Crypto = require('../../crypto/Crypto');
|
||||
|
||||
const GenericSerializer = require('./GenericSerializer');
|
||||
|
||||
module.exports = class StatusSerializer extends GenericSerializer {
|
||||
constructor(order) {
|
||||
super(order);
|
||||
|
||||
this._xml = {
|
||||
'@': this._rootAttributes,
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this._hostId,
|
||||
Nonce: Crypto.nonce(),
|
||||
Timestamp: Crypto.timestamp(),
|
||||
PartnerID: this._partnerId,
|
||||
UserID: this._userId,
|
||||
Product: {
|
||||
'@': { Language: 'en' },
|
||||
'#': consts.productString,
|
||||
},
|
||||
OrderDetails: this._orderDetails,
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': Crypto.digestPublicKey(this._keys.bankX()),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': Crypto.digestPublicKey(this._keys.bankE()),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
},
|
||||
AuthSignature: GenericSerializer.authSignature(),
|
||||
body: {},
|
||||
};
|
||||
|
||||
if (order.hasTransactionId()) {
|
||||
this._xml.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this._hostId,
|
||||
TransactionID: this._transactionId,
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Receipt',
|
||||
},
|
||||
};
|
||||
|
||||
this._xml.body = {
|
||||
TransferReceipt: {
|
||||
'@': { authenticate: true },
|
||||
ReceiptCode: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
@@ -1,43 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HAA extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HAA',
|
||||
OrderAttribute: 'DZHNN',
|
||||
StandardOrderParams: '',
|
||||
},
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankX().publicDigest(),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
@@ -1,54 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HAC extends GenericOrder {
|
||||
constructor(client, from = null, to = null) {
|
||||
super(client);
|
||||
this._from = from;
|
||||
this._to = to;
|
||||
|
||||
this._schema.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HAC',
|
||||
OrderAttribute: 'DZHNN',
|
||||
StandardOrderParams: this._hasDateRange() ? {
|
||||
DateRange: {
|
||||
Start: this._from,
|
||||
End: this._to,
|
||||
},
|
||||
} : '',
|
||||
},
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankX().publicDigest(),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
_hasDateRange() {
|
||||
return this._from && this._to;
|
||||
}
|
||||
};
|
@@ -1,85 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HIA extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HIA',
|
||||
OrderAttribute: 'DZNNN',
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {},
|
||||
},
|
||||
|
||||
body: {
|
||||
DataTransfer: {
|
||||
OrderData: Buffer.from(zlib.deflateSync(this.orderData())).toString('base64'),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
root() { // eslint-disable-line class-methods-use-this
|
||||
return 'ebicsUnsecuredRequest';
|
||||
}
|
||||
|
||||
orderData() {
|
||||
const xmlOrderData = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
},
|
||||
AuthenticationPubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this.client.x().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': 'AQAB',
|
||||
},
|
||||
},
|
||||
AuthenticationVersion: 'X002',
|
||||
},
|
||||
EncryptionPubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this.client.e().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': 'AQAB',
|
||||
},
|
||||
},
|
||||
EncryptionVersion: 'E002',
|
||||
},
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
};
|
||||
|
||||
return js2xmlparser.parse('HIARequestOrderData', xmlOrderData, this.xmlOptions);
|
||||
}
|
||||
|
||||
toXML() {
|
||||
return js2xmlparser.parse(this.root(), this._schema, this.xmlOptions);
|
||||
}
|
||||
};
|
@@ -1,43 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HKD extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HKD',
|
||||
OrderAttribute: 'DZHNN',
|
||||
StandardOrderParams: '',
|
||||
},
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankX().publicDigest(),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
@@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HPB extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HPB',
|
||||
OrderAttribute: 'DZHNN',
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {},
|
||||
};
|
||||
}
|
||||
|
||||
root() { // eslint-disable-line class-methods-use-this
|
||||
return 'ebicsNoPubKeyDigestsRequest';
|
||||
}
|
||||
};
|
@@ -1,43 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class HTD extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema.header = {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
Nonce: this.nonce(),
|
||||
Timestamp: this.timestamp(),
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'HTD',
|
||||
OrderAttribute: 'DZHNN',
|
||||
StandardOrderParams: '',
|
||||
},
|
||||
BankPubKeyDigests: {
|
||||
Authentication: {
|
||||
'@': { Version: 'X002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankX().publicDigest(),
|
||||
},
|
||||
Encryption: {
|
||||
'@': { Version: 'E002', Algorithm: 'http://www.w3.org/2001/04/xmlenc#sha256' },
|
||||
'#': this.client.bankE().publicDigest(),
|
||||
},
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {
|
||||
TransactionPhase: 'Initialisation',
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
@@ -1,77 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const zlib = require('zlib');
|
||||
const js2xmlparser = require('js2xmlparser');
|
||||
|
||||
const GenericOrder = require('./GenericOrder');
|
||||
|
||||
module.exports = class INI extends GenericOrder {
|
||||
constructor(client) {
|
||||
super(client);
|
||||
|
||||
this._schema = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'urn:org:ebics:H004',
|
||||
Version: 'H004',
|
||||
Revision: '1',
|
||||
},
|
||||
|
||||
header: {
|
||||
'@': { authenticate: true },
|
||||
static: {
|
||||
HostID: this.hostId,
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
Product: {
|
||||
'@': { Language: 'de' },
|
||||
'#': this.productString,
|
||||
},
|
||||
OrderDetails: {
|
||||
OrderType: 'INI',
|
||||
OrderAttribute: 'DZNNN',
|
||||
},
|
||||
SecurityMedium: '0000',
|
||||
},
|
||||
mutable: {},
|
||||
},
|
||||
|
||||
body: {
|
||||
DataTransfer: {
|
||||
OrderData: Buffer.from(zlib.deflateSync(this.keySignature())).toString('base64'),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
root() { // eslint-disable-line class-methods-use-this
|
||||
return 'ebicsUnsecuredRequest';
|
||||
}
|
||||
|
||||
keySignature() {
|
||||
const xmlOrderData = {
|
||||
'@': {
|
||||
'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
xmlns: 'http://www.ebics.org/S001',
|
||||
},
|
||||
SignaturePubKeyInfo: {
|
||||
PubKeyValue: {
|
||||
'ds:RSAKeyValue': {
|
||||
'ds:Modulus': Buffer.from(this.client.a().n(), 'HEX').toString('base64'),
|
||||
'ds:Exponent': 'AQAB',
|
||||
},
|
||||
TimeStamp: this.timestamp(),
|
||||
},
|
||||
SignatureVersion: 'A006',
|
||||
},
|
||||
PartnerID: this.partnerId,
|
||||
UserID: this.userId,
|
||||
};
|
||||
|
||||
return js2xmlparser.parse('SignaturePubKeyOrderData', xmlOrderData, this.xmlOptions);
|
||||
}
|
||||
|
||||
toXML() {
|
||||
return js2xmlparser.parse(this.root(), this._schema, this.xmlOptions);
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user