node-idin
Version:
NodeJS Library for iDIN (https://www.idin.nl/)
88 lines • 4.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = require("assert");
const await_to_js_1 = require("await-to-js");
const util_1 = require("util");
const pretty_data_1 = require("pretty-data");
const xml_crypto_1 = require("xml-crypto");
const xml_encryption_1 = require("xml-encryption");
const xml_js_1 = require("xml-js");
const xmldom_1 = require("xmldom");
const idin_protocol_1 = require("./idin-protocol");
const idin_request_1 = require("./idin-request");
function formatStatusProtocolXML({ transactionId, merchantId, merchantSubId, privateKey, publicKeyFingerprint, publicKey }) {
const xml = pretty_data_1.pd.xmlmin(`
<?xml version="1.0" encoding="UTF-8"?>
<AcquirerStatusReq
version="1.0.0"
productID="NL:BVN:BankID:1.0"
xmlns="http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<createDateTimestamp>${new Date().toISOString()}</createDateTimestamp>
<Merchant>
<merchantID>${merchantId}</merchantID>
<subID>${merchantSubId}</subID>
</Merchant>
<Transaction>
<transactionID>${transactionId}</transactionID>
</Transaction>
</AcquirerStatusReq>
`);
return idin_protocol_1.signXml({ xml, publicKey, publicKeyFingerprint, privateKey });
}
async function getStatusResponse({ merchantId, merchantSubId, routingCert, routingEndpoint, privateKey, publicKeyFingerprint, publicKey }, { transactionId }) {
const [err, statusResponse] = await await_to_js_1.default(idin_request_1.fetchResponse({
payload: formatStatusProtocolXML({ merchantId, merchantSubId, transactionId, privateKey, publicKeyFingerprint, publicKey }),
routingEndpoint,
routingCert,
}));
assert_1.ifError(err);
const xpathQuery = '//*[local-name(.)=\'EncryptedData\']';
const xpathRes = xml_crypto_1.xpath(new xmldom_1.DOMParser().parseFromString(statusResponse), xpathQuery);
const pDecrypt = util_1.promisify(xml_encryption_1.decrypt);
const promises = xpathRes.map((res) => pDecrypt(res.toString(), { key: privateKey }));
const [err1, attributes] = await await_to_js_1.default(Promise.all(promises));
assert_1.ifError(err1);
const parsed = JSON.parse(xml_js_1.xml2json(statusResponse, { compact: true }));
if (parsed['awidxma:AcquirerErrorRes']) {
const error = parsed['awidxma:AcquirerErrorRes'];
return {
createDateTimestamp: error['awidxma:createDateTimestamp'],
Error: error['awidxma:Error'],
};
}
try {
const acqStatusRes = parsed['awidxma:AcquirerStatusRes'];
const response = {
createDateTimestamp: acqStatusRes['awidxma:createDateTimestamp']._text,
Acquirer: {
acquirerID: acqStatusRes['awidxma:Acquirer']['awidxma:acquirerID']._text,
},
Transaction: {
transactionID: acqStatusRes['awidxma:Transaction']['awidxma:transactionID']._text,
status: acqStatusRes['awidxma:Transaction']['awidxma:status']._text,
statusDateTimestamp: acqStatusRes['awidxma:Transaction']['awidxma:statusDateTimestamp']._text,
Response: {},
},
};
const container = acqStatusRes['awidxma:Transaction']['awidxma:container'];
const saml = container.hasOwnProperty('samlp:Response') ? '' : '2';
response.Transaction.Response = {
TransactionID: container[`saml${saml}p:Response`]._attributes.ID,
EntranceCode: container[`saml${saml}p:Response`]._attributes.InResponseTo,
StatusCode: container[`saml${saml}p:Response`][`saml${saml}p:Status`][`saml${saml}p:StatusCode`]._attributes.Value.split('status:')[1],
IssuerID: container[`saml${saml}p:Response`][`saml${saml}:Assertion`][`saml${saml}:Issuer`]._text,
Attributes: Object.assign({}, ...attributes.map((a) => JSON.parse(xml_js_1.xml2json(a, { compact: true }))).map((a) => ({
[(a[`saml${saml}:NameID`] && 'NameID') || a[`saml${saml}:Attribute`]._attributes.Name.split('consumer.')[1]]: (a[`saml${saml}:NameID`] && a[`saml${saml}:NameID`]._text) || a[`saml${saml}:Attribute`][`saml${saml}:AttributeValue`]._text,
}))),
};
return response;
}
catch (e) {
console.log(parsed);
assert_1.ifError(e);
}
}
exports.default = getStatusResponse;
//# sourceMappingURL=status-protocol.js.map