feat(ancpi): test EditCartItemJson + SearchEstate with AJAX headers
This commit is contained in:
@@ -77,69 +77,53 @@ export async function GET(req: Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Step: search ──
|
// ── Step: search ──
|
||||||
// SearchEstate.action returns HTML (Angular app), not JSON.
|
// Test EditCartItemJson.action — the real endpoint for configuring cart items
|
||||||
// Need to find the real AJAX endpoints from the Angular JS code.
|
|
||||||
if (step === "search") {
|
if (step === "search") {
|
||||||
const client = await EpayClient.create(username, password);
|
const client = await EpayClient.create(username, password);
|
||||||
|
const BASE = process.env.ANCPI_BASE_URL || "https://epay.ancpi.ro/epay";
|
||||||
|
|
||||||
// Add to cart first
|
// Add to cart
|
||||||
const basketRowId = await client.addToCart(14200);
|
const basketRowId = await client.addToCart(14200);
|
||||||
|
|
||||||
// Load ShowCartItems.action — the Angular form page
|
const results: Record<string, unknown> = { basketRowId };
|
||||||
const cartPageHtml = await client.getRawHtml(
|
|
||||||
`${process.env.ANCPI_BASE_URL || "https://epay.ancpi.ro/epay"}/ShowCartItems.action`,
|
// Test 1: Set county via EditCartItemJson to get UAT list
|
||||||
|
try {
|
||||||
|
const body1 = new URLSearchParams();
|
||||||
|
body1.set("basketId", String(basketRowId));
|
||||||
|
body1.set("metadate.judet", "13"); // CLUJ
|
||||||
|
|
||||||
|
const resp1 = await client.postRaw(
|
||||||
|
`${BASE}/EditCartItemJson.action`,
|
||||||
|
body1.toString(),
|
||||||
);
|
);
|
||||||
|
results["setCounty_type"] = typeof resp1;
|
||||||
// Extract Angular AJAX endpoints and form structure
|
results["setCounty_len"] = typeof resp1 === "string" ? resp1.length : JSON.stringify(resp1).length;
|
||||||
// Look for: SearchEstate, EpayJsonInterceptor, ng-controller, $http
|
results["setCounty_sample"] = (typeof resp1 === "string" ? resp1 : JSON.stringify(resp1)).slice(0, 1000);
|
||||||
const patterns = [
|
} catch (e) {
|
||||||
/SearchEstate[^"'\s]*/g,
|
results["setCounty_error"] = (e as Error).message;
|
||||||
/EpayJsonInterceptor[^"'\s]*/g,
|
|
||||||
/EditCartItem[^"'\s]*/g,
|
|
||||||
/\$http\.(post|get)\s*\(\s*['"]([^'"]+)['"]/g,
|
|
||||||
/action\s*[:=]\s*['"]([^'"]*)['"]/g,
|
|
||||||
/url\s*[:=]\s*['"]([^'"]*?\.action[^'"]*)['"]/g,
|
|
||||||
/ng-controller\s*=\s*["']([^"']+)["']/g,
|
|
||||||
/searchEstate|SearchEstate|cautaImobil/gi,
|
|
||||||
];
|
|
||||||
|
|
||||||
const found: Record<string, string[]> = {};
|
|
||||||
for (const pat of patterns) {
|
|
||||||
const matches = cartPageHtml.match(pat);
|
|
||||||
if (matches && matches.length > 0) {
|
|
||||||
found[pat.source.slice(0, 40)] = [...new Set(matches)].slice(0, 10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also extract any inline JSON data (Angular scope initialization)
|
// Test 2: Try SearchEstate via the Angular way (maybe it's inside EditCartItemJson)
|
||||||
const jsonMatches = cartPageHtml.match(/ng-init\s*=\s*["']([^"']{10,500})["']/g);
|
try {
|
||||||
|
const body2 = new URLSearchParams();
|
||||||
|
body2.set("basketId", String(basketRowId));
|
||||||
|
body2.set("identifier", "345295");
|
||||||
|
body2.set("countyId", "13");
|
||||||
|
|
||||||
// Find county/UAT dropdown references
|
const resp2 = await client.postRaw(
|
||||||
const selectMatches = cartPageHtml.match(/<select[^>]*(?:judet|county|uat)[^>]*>/gi);
|
`${BASE}/SearchEstate.action`,
|
||||||
|
body2.toString(),
|
||||||
// Look for the specific search function
|
{ "X-Requested-With": "XMLHttpRequest", Accept: "application/json" },
|
||||||
const searchFuncMatch = cartPageHtml.match(
|
|
||||||
/function\s+\w*[Ss]earch\w*\s*\([^)]*\)\s*\{[^}]{0,500}/g,
|
|
||||||
);
|
);
|
||||||
|
results["searchAjax_type"] = typeof resp2;
|
||||||
|
results["searchAjax_len"] = typeof resp2 === "string" ? resp2.length : JSON.stringify(resp2).length;
|
||||||
|
results["searchAjax_sample"] = (typeof resp2 === "string" ? resp2 : JSON.stringify(resp2)).slice(0, 1000);
|
||||||
|
} catch (e) {
|
||||||
|
results["searchAjax_error"] = (e as Error).message;
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({ step: "search", results });
|
||||||
step: "search",
|
|
||||||
basketRowId,
|
|
||||||
pageLength: cartPageHtml.length,
|
|
||||||
angularEndpoints: found,
|
|
||||||
ngInit: jsonMatches?.slice(0, 5) ?? [],
|
|
||||||
selectDropdowns: selectMatches?.slice(0, 5) ?? [],
|
|
||||||
searchFunctions: searchFuncMatch?.slice(0, 3) ?? [],
|
|
||||||
// Also check: does the page contain "SearchEstate" anywhere?
|
|
||||||
hasSearchEstate: cartPageHtml.includes("SearchEstate"),
|
|
||||||
hasJsonInterceptor: cartPageHtml.includes("EpayJsonInterceptor"),
|
|
||||||
// Sample of any .action URLs in the page
|
|
||||||
actionUrls: [...new Set(
|
|
||||||
(cartPageHtml.match(/['"][^'"]*\.action[^'"]*['"]/g) ?? [])
|
|
||||||
.map((s: string) => s.replace(/['"]/g, ""))
|
|
||||||
.filter((s: string) => s.length < 100),
|
|
||||||
)].slice(0, 20),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Step: order ── (USES 3 CREDITS!)
|
// ── Step: order ── (USES 3 CREDITS!)
|
||||||
|
|||||||
@@ -256,6 +256,22 @@ export class EpayClient {
|
|||||||
return String(response.data ?? "");
|
return String(response.data ?? "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Raw POST (for endpoint discovery) ──────────────────── */
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
async postRaw(url: string, body: string, extraHeaders?: Record<string, string>): Promise<any> {
|
||||||
|
const response = await this.client.post(url, body, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
...extraHeaders,
|
||||||
|
},
|
||||||
|
timeout: DEFAULT_TIMEOUT_MS,
|
||||||
|
maxRedirects: 5,
|
||||||
|
validateStatus: () => true,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Credits ───────────────────────────────────────────────── */
|
/* ── Credits ───────────────────────────────────────────────── */
|
||||||
|
|
||||||
async getCredits(): Promise<number> {
|
async getCredits(): Promise<number> {
|
||||||
|
|||||||
Reference in New Issue
Block a user