@craynic/qr-platba
Version:
Library to work with Czech QR payments
360 lines (359 loc) • 14.7 kB
JavaScript
"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; };