Skip to content

Instantly share code, notes, and snippets.

@zb3
Last active February 17, 2025 14:50
Show Gist options
  • Save zb3/6e87e84b302e34b5bdb4e94fc3cd8c2b to your computer and use it in GitHub Desktop.
Save zb3/6e87e84b302e34b5bdb4e94fc3cd8c2b to your computer and use it in GitHub Desktop.
Skrypt sprawdzający poprawność "numerów referencyjnych" z systemu KSeF, obsługuje zarówno numery faktur jak i numery sesji. Bonusową funkcją jest możliwość dopisania sumy kontrolnej dla dowolnego numeru bez niej :)
class KsefIdUtils {
static INVOICE_PATTERN =
/^([1-9]((\d[1-9])|([1-9]\d))\d{7}|M\d{9}|[A-Z]{3}\d{7})-(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-F]{6})-?([0-9A-F]{6})-([0-9A-F]{2})$/;
static SESSION_PATTERN =
/^(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-Z]{2})-([0-9A-F]{10})-([0-9A-F]{10})-([0-9A-F]{2})$/;
static isValid(id) {
if (
!id ||
(!this.INVOICE_PATTERN.test(id) && !this.SESSION_PATTERN.test(id))
) {
return false;
}
const parts = id.split("-");
const partCount = parts.length;
if (partCount !== 5 && partCount !== 4) {
return false;
}
if (partCount === 4 && parts[0].length !== 10) {
return false;
}
const checksumPart = parts[partCount - 1];
const calculatedChecksum = this.calculateChecksum(parts);
return calculatedChecksum === checksumPart.toUpperCase();
}
static calculateChecksum(parts) {
const hasher = new KsefHash();
hasher.addDigitString(parts[0]);
hasher.addDigitString(parts[1]);
if (parts.length === 4) {
hasher.addHexString(parts[2].substring(0, 6));
hasher.addHexString(parts[2].substring(6));
} else {
hasher.addHexString(parts[2]);
hasher.addHexString(parts[3]);
}
let checksumValue = (hasher.value % 256)
.toString(16)
.toUpperCase()
.padStart(2, "0");
return checksumValue;
}
static expand(idWithoutHash) {
return (
idWithoutHash +
"-" +
this.calculateChecksum((idWithoutHash + "-00").split("-"))
);
}
}
class KsefHash {
constructor() {
this.value = 1;
}
addDigitString(digitStr) {
for (let i = 0; i < digitStr.length; i++) {
this.value = 3 * this.value + (digitStr.charCodeAt(i) - 48);
}
}
addHexString(hexStr) {
for (let i = 0; i < hexStr.length; i += 2) {
this.value = 3 * this.value + parseInt(hexStr.substring(i, i + 2), 16);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment