using System.Net; using System.Text; using System.Text.Json; namespace PesaplexZk4500Bridge; internal class Program { private const string Host = "http://127.0.0.1:5055/"; static void Main() { Console.Title = "Pesaplex ZK4500 Bridge"; Console.WriteLine("Starting Pesaplex ZK4500 Bridge..."); Console.WriteLine("Listening on " + Host); var scanner = new Zk4500Scanner(); if (!scanner.Initialize()) { Console.WriteLine("WARNING: ZK4500 scanner not initialized."); Console.WriteLine("Check driver, SDK DLL files, and USB connection."); } using var listener = new HttpListener(); listener.Prefixes.Add(Host); listener.Start(); Console.WriteLine("Bridge ready."); Console.WriteLine("Test URL: " + Host + "status"); while (true) { var context = listener.GetContext(); HandleRequest(context, scanner); } } private static void HandleRequest(HttpListenerContext context, Zk4500Scanner scanner) { try { AddCorsHeaders(context.Response); string path = context.Request.Url?.AbsolutePath.ToLower() ?? "/"; if (context.Request.HttpMethod == "OPTIONS") { context.Response.StatusCode = 204; context.Response.Close(); return; } if (path == "/status") { WriteJson(context.Response, new { success = true, service = "Pesaplex ZK4500 Bridge", scannerReady = scanner.IsReady }); return; } if (path == "/capture") { if (!scanner.IsReady) { WriteJson(context.Response, new { success = false, message = "ZK4500 scanner is not ready." }, 400); return; } string template = scanner.CaptureTemplate(); if (string.IsNullOrWhiteSpace(template)) { WriteJson(context.Response, new { success = false, message = "Fingerprint capture failed." }, 400); return; } WriteJson(context.Response, new { success = true, template = template, message = "Fingerprint captured successfully." }); return; } WriteJson(context.Response, new { success = false, message = "Route not found." }, 404); } catch (Exception ex) { WriteJson(context.Response, new { success = false, message = ex.Message }, 500); } } private static void AddCorsHeaders(HttpListenerResponse response) { response.Headers.Add("Access-Control-Allow-Origin", "https://vote.pesaplex.com"); response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); response.Headers.Add("Access-Control-Allow-Headers", "Content-Type"); } private static void WriteJson(HttpListenerResponse response, object data, int statusCode = 200) { string json = JsonSerializer.Serialize(data); byte[] buffer = Encoding.UTF8.GetBytes(json); response.StatusCode = statusCode; response.ContentType = "application/json"; response.ContentEncoding = Encoding.UTF8; response.ContentLength64 = buffer.Length; response.OutputStream.Write(buffer, 0, buffer.Length); response.Close(); } } public class Zk4500Scanner { public bool IsReady { get; private set; } public bool Initialize() { /* IMPORTANT: This is where you connect the official ZKTeco SDK. After installing ZKFinger SDK for Windows, add the SDK DLL/reference. The SDK package normally includes driver files, demo files, and development documents. */ try { // TODO: Replace this with real SDK initialization. // Example depends on the SDK version: // // zkfp2.Init(); // zkfp2.OpenDevice(0); // // OR older SDK: // ZKFPEngX.InitEngine(); IsReady = true; return true; } catch { IsReady = false; return false; } } public string CaptureTemplate() { /* TODO: Replace this method with real ZK4500 capture code. The real method should: 1. Wait for finger placement. 2. Capture fingerprint image. 3. Extract fingerprint template. 4. Return template as Base64 string. */ Console.WriteLine("Waiting for fingerprint..."); // Temporary test template so the website can test connection. // Remove this after SDK code is added. return Convert.ToBase64String( Encoding.UTF8.GetBytes("TEMP_ZK4500_TEMPLATE_" + DateTime.UtcNow.Ticks) ); } }