fix(ancpi): simplify document parsing, avoid catastrophic regex backtracking
This commit is contained in:
@@ -550,82 +550,20 @@ export class EpayClient {
|
|||||||
.replace(/ț/g, "ț")
|
.replace(/ț/g, "ț")
|
||||||
.replace(/ș/g, "ș");
|
.replace(/ș/g, "ș");
|
||||||
|
|
||||||
// Try multiple patterns to find document info in the Angular HTML
|
// Parse solutii JSON from decoded HTML
|
||||||
// Pattern 1: JSON-like in Angular scope
|
// Format: "solutii":[{"idDocument":47301767,"nome":"Extras_Informare_65346.pdf",...}]
|
||||||
const docPattern1 =
|
const solutiiPattern = /"solutii"\s*:\s*\[(\{[^[\]]*\})\]/g;
|
||||||
/"idDocument"\s*:\s*(\d+)[\s\S]*?"nume"\s*:\s*"([^"]+)"[\s\S]*?"dataDocument"\s*:\s*"([^"]+)"[\s\S]*?"linkDownload"\s*:\s*"([^"]*)"/g;
|
let solutiiMatch;
|
||||||
|
while ((solutiiMatch = solutiiPattern.exec(decoded)) !== null) {
|
||||||
// Pattern 2: DownloadFile links in HTML (regular hrefs)
|
|
||||||
const docPattern2 =
|
|
||||||
/DownloadFile\.action\?typeD=4&(?:amp;)?id=(\d+)/g;
|
|
||||||
|
|
||||||
// Pattern 2b: Angular ng-click="downloadFile($event, 4, ID, '')"
|
|
||||||
const docPattern2b =
|
|
||||||
/downloadFile\s*\(\s*\$event\s*,\s*4\s*,\s*(\d+)/g;
|
|
||||||
|
|
||||||
let docMatch;
|
|
||||||
while ((docMatch = docPattern1.exec(decoded)) !== null) {
|
|
||||||
documents.push({
|
|
||||||
idDocument: parseInt(docMatch[1] ?? "0", 10),
|
|
||||||
idTipDocument: null,
|
|
||||||
nume: docMatch[2] ?? "",
|
|
||||||
numar: null,
|
|
||||||
serie: null,
|
|
||||||
dataDocument: docMatch[3] ?? "",
|
|
||||||
contentType: "application/pdf",
|
|
||||||
linkDownload: docMatch[4] ?? "",
|
|
||||||
downloadValabil: true,
|
|
||||||
valabilNelimitat: true,
|
|
||||||
zileValabilitateDownload: -1,
|
|
||||||
transactionId: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If pattern 1 didn't find anything, try pattern 2/2b (DownloadFile links / Angular ng-click)
|
|
||||||
if (documents.length === 0) {
|
|
||||||
// Combine results from both patterns
|
|
||||||
const allDocIds = new Set<number>();
|
|
||||||
|
|
||||||
while ((docMatch = docPattern2.exec(decoded)) !== null) {
|
|
||||||
allDocIds.add(parseInt(docMatch[1] ?? "0", 10));
|
|
||||||
}
|
|
||||||
while ((docMatch = docPattern2b.exec(decoded)) !== null) {
|
|
||||||
allDocIds.add(parseInt(docMatch[1] ?? "0", 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const docId of allDocIds) {
|
|
||||||
if (docId > 0 && !documents.some((d) => d.idDocument === docId)) {
|
|
||||||
documents.push({
|
|
||||||
idDocument: docId,
|
|
||||||
idTipDocument: null,
|
|
||||||
nume: `document_${docId}.pdf`,
|
|
||||||
numar: null,
|
|
||||||
serie: null,
|
|
||||||
dataDocument: new Date().toISOString().slice(0, 10),
|
|
||||||
contentType: "application/pdf",
|
|
||||||
linkDownload: "",
|
|
||||||
downloadValabil: true,
|
|
||||||
valabilNelimitat: true,
|
|
||||||
zileValabilitateDownload: -1,
|
|
||||||
transactionId: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pattern 3: Look for solutii JSON array (in decoded HTML)
|
|
||||||
const solutiiMatch = decoded.match(/solutii['"]\s*:\s*(\[[\s\S]*?\])/);
|
|
||||||
|
|
||||||
// If pattern 3 matched, try to parse JSON
|
|
||||||
if (documents.length === 0 && solutiiMatch) {
|
|
||||||
try {
|
try {
|
||||||
const solutii = JSON.parse(solutiiMatch[1] ?? "[]");
|
const arr = JSON.parse(`[${solutiiMatch[1]}]`);
|
||||||
for (const s of solutii) {
|
for (const s of arr) {
|
||||||
if (s?.idDocument) {
|
if (s?.idDocument && s?.idTipDocument === null) {
|
||||||
|
// idTipDocument=null means it's a soluție (CF extract), not a chitanță (idTipDocument=1)
|
||||||
documents.push({
|
documents.push({
|
||||||
idDocument: s.idDocument,
|
idDocument: s.idDocument,
|
||||||
idTipDocument: s.idTipDocument ?? null,
|
idTipDocument: null,
|
||||||
nume: s.nume ?? `document_${s.idDocument}.pdf`,
|
nume: s.nume ?? "",
|
||||||
numar: s.numar ?? null,
|
numar: s.numar ?? null,
|
||||||
serie: s.serie ?? null,
|
serie: s.serie ?? null,
|
||||||
dataDocument: s.dataDocument ?? "",
|
dataDocument: s.dataDocument ?? "",
|
||||||
@@ -641,28 +579,30 @@ export class EpayClient {
|
|||||||
} catch { /* parse failed */ }
|
} catch { /* parse failed */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug: if no documents found, log relevant HTML sections
|
// Fallback: extract idDocument directly from decoded HTML
|
||||||
|
if (documents.length === 0) {
|
||||||
|
const idPattern = /"idDocument"\s*:\s*(\d+)\s*,\s*"idTipDocument"\s*:\s*null\s*,\s*"nume"\s*:\s*"([^"]+)"\s*,.*?"dataDocument"\s*:\s*"([^"]+)"/g;
|
||||||
|
let idMatch;
|
||||||
|
while ((idMatch = idPattern.exec(decoded)) !== null) {
|
||||||
|
documents.push({
|
||||||
|
idDocument: parseInt(idMatch[1] ?? "0", 10),
|
||||||
|
idTipDocument: null,
|
||||||
|
nume: idMatch[2] ?? "",
|
||||||
|
numar: null,
|
||||||
|
serie: null,
|
||||||
|
dataDocument: idMatch[3] ?? "",
|
||||||
|
contentType: "application/pdf",
|
||||||
|
linkDownload: "",
|
||||||
|
downloadValabil: true,
|
||||||
|
valabilNelimitat: true,
|
||||||
|
zileValabilitateDownload: -1,
|
||||||
|
transactionId: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (documents.length === 0 && status === "Finalizata") {
|
if (documents.length === 0 && status === "Finalizata") {
|
||||||
// Find sections containing "idDocument", "DownloadFile", "solutii", or "Extras"
|
console.warn(`[epay] Order ${orderId}: Finalizata but no documents found`);
|
||||||
const relevantPatterns = [
|
|
||||||
/idDocument[^<]{0,200}/gi,
|
|
||||||
/DownloadFile[^<]{0,200}/gi,
|
|
||||||
/solutii[^<]{0,200}/gi,
|
|
||||||
/Extras_Informare[^<]{0,200}/gi,
|
|
||||||
/downloadFile[^<]{0,200}/gi,
|
|
||||||
/tipFisier[^<]{0,200}/gi,
|
|
||||||
];
|
|
||||||
for (const pat of relevantPatterns) {
|
|
||||||
const matches = html.match(pat);
|
|
||||||
if (matches) {
|
|
||||||
console.log(`[epay] OrderDetails ${orderId} match [${pat.source.slice(0, 20)}]:`, matches.slice(0, 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Also log around "Finalizata" for context
|
|
||||||
const finIdx = html.indexOf("Finalizata");
|
|
||||||
if (finIdx >= 0) {
|
|
||||||
console.log(`[epay] OrderDetails ${orderId} near Finalizata:`, html.slice(finIdx - 100, finIdx + 300).replace(/\s+/g, " "));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { orderId, status, documents };
|
return { orderId, status, documents };
|
||||||
|
|||||||
Reference in New Issue
Block a user