From 04135b27cf04a795095d06626290ad565f938243 Mon Sep 17 00:00:00 2001 From: Julian Cuni Date: Tue, 16 Jun 2026 12:30:00 +0200 Subject: [PATCH] qr-reader: register all server-language extensions (reader posts .jsp) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware capture: the GEE/Fondvision reader (serial H05M2AFA) scans + sends + beeps fine — the earlier 'no beep' was just nothing answering :3000. Real request: GET /qa/mcardsea.jsp?cardid=...&cjihao=H05M2AFA&... — the 'server language' setting (JSP here) selects the URL EXTENSION, so it posts .jsp, not .php. Our route was .php-only and would have 404'd it. Register the endpoint at php/jsp/asp/aspx/cgi so it works whatever the device is configured to. cjihao (serial) is the lane key: assign the reader as lane_devices.id = its serial. --- apps/server/src/routes/qr-reader.ts | 14 ++++++++----- wiki/entities/gee-qr-er80.md | 31 +++++++++++++++++++++++------ wiki/log.md | 12 +++++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/apps/server/src/routes/qr-reader.ts b/apps/server/src/routes/qr-reader.ts index 76d0317..6018f0f 100644 --- a/apps/server/src/routes/qr-reader.ts +++ b/apps/server/src/routes/qr-reader.ts @@ -25,8 +25,6 @@ interface ReaderQuery { time?: string; } -const SDK_PATH = "/qa/mcardsea.php"; - export async function qrReaderRoutes(app: FastifyInstance, dispatcher: ReadDispatcher): Promise { // No auth: the reader is a machine on the isolated device subnet and offers no // auth on its side. Public route, like the Dingtian input push. @@ -77,7 +75,13 @@ export async function qrReaderRoutes(app: FastifyInstance, dispatcher: ReadDispa }; }; - // The reader uses GET; accept POST too in case a variant differs. - app.get<{ Querystring: ReaderQuery }>(SDK_PATH, handler); - app.post<{ Querystring: ReaderQuery }>(SDK_PATH, handler); + // The reader's "server language" setting (JSP/PHP/C#/ASP/CGI) selects the URL + // EXTENSION it GETs — verified on hardware: a JSP-configured unit posts + // /qa/mcardsea.jsp. Register every extension so the endpoint works whatever the + // device is set to; accept POST too in case a variant differs. + for (const ext of ["php", "jsp", "asp", "aspx", "cgi"]) { + const path = `/qa/mcardsea.${ext}`; + app.get<{ Querystring: ReaderQuery }>(path, handler); + app.post<{ Querystring: ReaderQuery }>(path, handler); + } } diff --git a/wiki/entities/gee-qr-er80.md b/wiki/entities/gee-qr-er80.md index 7dc46f0..8e56928 100644 --- a/wiki/entities/gee-qr-er80.md +++ b/wiki/entities/gee-qr-er80.md @@ -71,10 +71,29 @@ barrier. ([[device-input-flow]] is the analogous push pattern; this one also ret - Verified via inject: valid permit QR → `status:1` + open; re-scan → permit exit (still valid); unknown QR → `status:0`; reader on a barrier-less lane → `status:0`. -## Open / to confirm on hardware +## Verified on hardware (2026-06-16) -- A **live scan** still hadn't reached the server during bring-up (no beep). With the real endpoint - now replying the verdict, re-test: scan → expect a beep + a GET in the server log. If still - nothing, it's the reader's scan/trigger/mode (not the server). -- **Reader→lane identity:** confirm what the device actually sends as `cjihao`/`mjihao` and align the - `lane_devices` assignment (the wizard doesn't yet capture the reader's serial as its id). +Captured a real scan (vendor-emulator logger on :3000). The reader **does scan, send, and beep** — +the earlier "no beep" was simply that no server was answering on :3000 with valid JSON. Real GET: + +``` +GET /qa/mcardsea.jsp?cardid=52020056&mjihao=1&cjihao=H05M2AFA&status=11&time=1781634494 +from 10.0.10.7 (referer: http://www.fondvision.com — the OEM is Fondvision) +``` + +- **PATH carries the configured "server language" EXTENSION:** this unit is set to **JSP**, so it + GETs **`/qa/mcardsea.jsp`** — NOT `.php`. Our endpoint was registered at `.php` only → it would + have 404'd the real reader. **Fixed:** the route now registers `php/jsp/asp/aspx/cgi`. +- **`cjihao` = `H05M2AFA`** is the device **serial** — the value our endpoint keys the lane on. So + assign the reader with **`lane_devices.id = "H05M2AFA"`** (+ an access device on the same lane). +- **`mjihao` = 1** (device id). `cardid` = the scanned barcode (`52020056`). `status=11`. +- The reader **beeped on the vendor reply with `status:0`** — so it acts on the reply; `0` = + invalid/1-beep as documented. A matching permit/session will return `status:1` → 2-beep accept. + +## Open / next + +- **Assign the reader** as `lane_devices.id = "H05M2AFA"`, category `reader`, on the same lane as an + access device, so the endpoint resolves the lane. (The setup wizard doesn't yet capture a reader's + serial as its id — manual row or a wizard tweak; see [[first-run-setup]].) +- Re-test against the real app endpoint (now `.jsp`-aware): scan → expect the GET to hit + `/qa/mcardsea.jsp` and a `status:1` 2-beep when the credential matches a permit/open session. diff --git a/wiki/log.md b/wiki/log.md index 1b135dd..ed5c140 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -656,3 +656,15 @@ guarantee. Recorded in [[dingtian-relay]] (new Hardening section). - VERIFIED via inject: valid permit QR→status:1+open; re-scan→permit exit; unknown→status:0; reader on barrier-less lane→status:0. Full build 5/5. - Updated [[gee-qr-er80]] (endpoint as-built + hardware open items). + +## [2026-06-16] test+fix | QR reader VERIFIED on hardware; path is .jsp not .php +- Ran a verbatim-vendor logger on :3000 (replies like mcardsea.php: status:0/output:2). Reader + **beeped** → it scans, sends, and acts on the reply. Earlier "no beep" = nothing was answering :3000. +- Real GET captured: `/qa/mcardsea.jsp?cardid=52020056&mjihao=1&cjihao=H05M2AFA&status=11&time=...` + from 10.0.10.7 (OEM = Fondvision, per referer). +- KEY FIX: the "server language" setting selects the URL EXTENSION — this unit is JSP → posts + **`.jsp`**, but our route was `.php` only (would 404 the reader). Route now registers + php/jsp/asp/aspx/cgi. Build green. +- Real serial **cjihao=H05M2AFA** = the lane key → assign reader as lane_devices.id="H05M2AFA". + Reader beeped on status:0 (invalid/1-beep); a matching permit/session → status:1 (2-beep accept). +- Updated [[gee-qr-er80]] (verified-on-hardware).