UNPKG

@craynic/qr-platba

Version:

Library to work with Czech QR payments

360 lines (359 loc) 14.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QrRequest = exports.RequestType = void 0; var ibantools_1 = require("ibantools"); var crc_1 = require("crc"); var Dinero = require("dinero.js"); var lodash_1 = require("lodash"); var QrRequestDate_1 = require("./QrRequestDate"); var sanitizeQrString_1 = require("./sanitizeQrString"); var RequestType; (function (RequestType) { RequestType["PaymentRequest"] = "SPD"; RequestType["CollectionRequest"] = "SCD"; })(RequestType = exports.RequestType || (exports.RequestType = {})); var QrRequest = exports.QrRequest = /** @class */ (function () { function QrRequest(account, requestType) { if (requestType === void 0) { requestType = RequestType.PaymentRequest; } this.requestType = requestType; // noinspection TypeScriptFieldCanBeMadeReadonly this.amountInCents = null; this.message = null; this.constantSymbol = null; this.specificSymbol = null; this.variableSymbol = null; this.paymentReference = null; this.receiverName = null; this.dateOfTransaction = null; this.dateOfLastTransaction = null; this.paymentType = null; this.notificationType = null; this.notificationAddress = null; this.frequency = null; this.payAfterDeath = false; this.retryPeriod = null; this.senderID = null; this.url = null; this.senderNote = null; this.account = this.validateAccount(account); } QrRequest.prototype.getAccount = function () { return this.account; }; QrRequest.prototype.setAccount = function (account) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.account = this.validateAccount(account); return newRequest; }; QrRequest.prototype.validateAccount = function (account) { if (isQrPayAccountString(account)) { return [account]; } if (isQrPayAccountArray(account)) { return account; } throw new Error('Invalid account: please provide a string or array of strings (max 3), each containing IBAN or IBAN+BIC.'); }; QrRequest.prototype.getAmount = function () { return this.amountInCents; }; QrRequest.prototype.setAmountInCents = function (amountInCents) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.amountInCents = amountInCents === null ? null : this.validateAmount(amountInCents, 'CZK'); return newRequest; }; QrRequest.prototype.validateAmount = function (amount, currency) { var dinero = Dinero({ amount: amount, currency: currency }); if (!isQrPayAmountInCents(dinero)) { throw new Error('Invalid transfer amount in cents!'); } return dinero; }; QrRequest.prototype.getMessage = function () { return this.message; }; QrRequest.prototype.setMessage = function (value) { if (value === null || isValidStringOfLength(value, 0, 60)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.message = value; return newRequest; } else { throw new Error('Invalid message'); } }; QrRequest.prototype.getConstantSymbol = function () { return this.constantSymbol; }; QrRequest.prototype.setConstantSymbol = function (value) { if (value === null || isValidNumericStringOfLength(value, 0, 10)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.constantSymbol = value; return newRequest; } else { throw new Error('Invalid constant symbol'); } }; QrRequest.prototype.getSpecificSymbol = function () { return this.specificSymbol; }; QrRequest.prototype.setSpecificSymbol = function (value) { if (value === null || isValidNumericStringOfLength(value, 0, 10)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.specificSymbol = value; return newRequest; } else { throw new Error('Invalid specific symbol'); } }; QrRequest.prototype.getVariableSymbol = function () { return this.variableSymbol; }; QrRequest.prototype.setVariableSymbol = function (value) { if (value === null || isValidNumericStringOfLength(value, 0, 10)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.variableSymbol = value; return newRequest; } else { throw new Error('Invalid variable symbol'); } }; QrRequest.prototype.getPaymentReference = function () { return this.paymentReference; }; QrRequest.prototype.setPaymentReference = function (value) { if (value === null || isValidNumericStringOfLength(value, 0, 16)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.paymentReference = value; return newRequest; } else { throw new Error('Invalid payment reference'); } }; QrRequest.prototype.getReceiverName = function () { return this.receiverName; }; QrRequest.prototype.setReceiverName = function (value) { if (value === null || isValidStringOfLength(value, 0, 35)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.receiverName = value; return newRequest; } else { throw new Error('Invalid receiver name'); } }; QrRequest.prototype.getDateOfTransaction = function () { var _a, _b; return (_b = (_a = this.dateOfTransaction) === null || _a === void 0 ? void 0 : _a.date) !== null && _b !== void 0 ? _b : null; }; QrRequest.prototype.setDateOfTransaction = function (value) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.dateOfTransaction = value === null ? null : new QrRequestDate_1.QrRequestDate(value); return newRequest; }; QrRequest.prototype.getDateOfLastTransaction = function () { var _a, _b; return (_b = (_a = this.dateOfLastTransaction) === null || _a === void 0 ? void 0 : _a.date) !== null && _b !== void 0 ? _b : null; }; QrRequest.prototype.setDateOfLastTransaction = function (value) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.dateOfLastTransaction = value === null ? null : new QrRequestDate_1.QrRequestDate(value); return newRequest; }; QrRequest.prototype.getPaymentType = function () { return this.paymentType; }; QrRequest.prototype.setPaymentType = function (value) { if (value === null || isValidStringOfLength(value, 0, 3)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.paymentType = value; return newRequest; } else { throw new Error('Invalid payment type'); } }; QrRequest.prototype.getNotificationType = function () { return this.notificationType; }; QrRequest.prototype.setNotificationType = function (value) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.notificationType = value; return newRequest; }; QrRequest.prototype.getNotificationAddress = function () { return this.notificationAddress; }; QrRequest.prototype.setNotificationAddress = function (value) { if (value === null || isValidStringOfLength(value, 0, 320)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.notificationAddress = value; return newRequest; } else { throw new Error('Invalid notification address!'); } }; QrRequest.prototype.getFrequency = function () { return this.frequency; }; QrRequest.prototype.setFrequency = function (value) { if (value === null || isValidFrequency(value)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.frequency = value; return newRequest; } else { throw new Error('Invalid frequency!'); } }; QrRequest.prototype.isPayAfterDeath = function () { return this.payAfterDeath; }; QrRequest.prototype.setPayAfterDeath = function (value) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.payAfterDeath = value; return newRequest; }; QrRequest.prototype.getRetryPeriod = function () { return this.retryPeriod; }; QrRequest.prototype.setRetryPeriod = function (value) { if (value === null || isValidRetryPeriod(value)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.retryPeriod = value; return newRequest; } else { throw new Error('Invalid retry period!'); } }; QrRequest.prototype.getSenderID = function () { return this.senderID; }; QrRequest.prototype.setSenderID = function (value) { if (value === null || isValidStringOfLength(value, 0, 20)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.senderID = value; return newRequest; } else { throw new Error('Invalid sender ID!'); } }; QrRequest.prototype.getURL = function () { return this.url; }; QrRequest.prototype.setURL = function (value) { if (value === null || isValidStringOfLength(value, 0, 140)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.url = value; return newRequest; } else { throw new Error('Invalid URL!'); } }; QrRequest.prototype.getSenderNote = function () { return this.senderNote; }; QrRequest.prototype.setSenderNote = function (value) { if (value === null || isValidStringOfLength(value, 0, 60)) { var newRequest = (0, lodash_1.cloneDeep)(this); newRequest.senderNote = value; return newRequest; } else { throw new Error('Invalid sender note!'); } }; QrRequest.prototype.toString = function () { return "".concat(this.toStringWithoutChecksum(), "*CRC32:").concat(this.getChecksum()); }; QrRequest.prototype.getChecksum = function () { return (0, crc_1.crc32)(this.toStringWithoutChecksum()).toString(16).padStart(8, '0').toUpperCase(); }; QrRequest.prototype.toStringWithoutChecksum = function () { return "".concat(this.requestType, "*").concat(QrRequest.VERSION, "*").concat(this.getFields() .map(function (field) { return "".concat(field[0], ":").concat(field[1]); }) .join('*')); }; QrRequest.prototype.getFields = function () { var _a, _b; return Array(['ACC', this.getAccount()[0]], ['AM', (_a = this.getAmount()) === null || _a === void 0 ? void 0 : _a.toFormat('0.00')], ['CC', (_b = this.getAmount()) === null || _b === void 0 ? void 0 : _b.getCurrency()], ['MSG', this.getMessage()], ['X-KS', this.getConstantSymbol()], ['X-SS', this.getSpecificSymbol()], ['X-VS', this.getVariableSymbol()], ['ALT-ACC', this.getAccount().length > 1 ? this.getAccount().slice(1).join(',') : null], ['RF', this.getPaymentReference()], ['RN', this.getReceiverName()], ['DT', this.dateOfTransaction], ['DL', this.dateOfLastTransaction], ['PT', this.getPaymentType()], ['NT', this.getNotificationType()], ['NTA', this.getNotificationAddress()], ['FRQ', this.getFrequency()], ['DH', this.isPayAfterDeath() ? '1' : null], ['X-PER', this.getRetryPeriod()], ['X-ID', this.getSenderID()], ['X-URL', this.getURL()], ['X-SELF', this.getSenderNote()]) .filter(function (value) { return value[1] !== null && value[1] !== undefined && value[1] !== ''; }) .map(function (value) { return [ value[0], (0, sanitizeQrString_1.sanitizeQrString)(value[1]), ]; }) .sort(function (a, b) { if (a[0] < b[0]) { return -1; } if (a[0] > b[0]) { return 1; } if (a[1] < b[1]) { return -1; } if (a[1] > b[1]) { return 1; } return 0; }); }; QrRequest.prototype.isAlphanumericQRCode = function () { return /^[0-9A-Z $%*+\-./:]*$/.test(this.toStringWithoutChecksum()); }; QrRequest.VERSION = '1.2'; return QrRequest; }()); // eslint-disable-next-line @typescript-eslint/no-explicit-any var isQrPayAccountString = function (value) { if (typeof value !== 'string') { return false; } var strParts = value.split('+'); return (value.length > 0 && value.length <= 46 && strParts.length <= 2 && (0, ibantools_1.isValidIBAN)(strParts[0]) && (strParts.length === 1 || (0, ibantools_1.isValidBIC)(strParts[1]))); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any var isQrPayAccountArray = function (values) { return Array.isArray(values) && values.length >= 1 && values.length <= 3 && values.reduce(function (previousValue, value) { return isQrPayAccountString(value) && previousValue; }, true); }; var isQrPayAmountInCents = function (value) { return value.getAmount() > 0 && value.getAmount() < 10000000 * 100; }; var isValidStringOfLength = function ( // eslint-disable-next-line @typescript-eslint/no-explicit-any value, min, max) { if (typeof value !== 'string') { return false; } var sanitizedValue = (0, sanitizeQrString_1.sanitizeQrString)(value); return (sanitizedValue.length >= min && sanitizedValue.length <= max && !/[^\u0020-\u007e\u00a0-\u00ff]/g.test(value) && !/^ /.test(value) && !/ $/.test(value)); }; var isValidNumericStringOfLength = function ( // eslint-disable-next-line @typescript-eslint/no-explicit-any value, min, max) { return isValidStringOfLength(value, min, max) && /^\d*$/.test(value); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any var isValidFrequency = function (value) { return /^\d{1,2}[DMY]$/.test(value); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any var isValidRetryPeriod = function (value) { return typeof value === 'number' && value >= 0 && value <= 30; };