```zip token_management_system/ ├── db.sql ├── api/ │ ├── config.php │ ├── gst.php │ ├── rlt.php │ ├── debug_date.php ├── Token_Management_API.postman_collection.json ``` # db.sql ```sql CREATE DATABASE ultraaud_tms; USE ultraaud_tms; CREATE TABLE tokens ( id BIGINT PRIMARY KEY AUTO_INCREMENT, long_token TEXT NOT NULL, short_token VARCHAR(16) NOT NULL UNIQUE, vehicle_number VARCHAR(50), driver_name VARCHAR(100), event_date DATETIME, location TEXT, duration DATETIME, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); CREATE INDEX idx_short_token ON tokens(short_token); ``` # api/config.php ```php PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); } catch (PDOException $e) { http_response_code(500); echo json_encode(['error' => 'Database connection failed: ' . $e->getMessage()]); exit; } ?> ``` # api/gst.php ```php 'Method not allowed']); exit; } $data = json_decode(file_get_contents('php://input'), true); if (!isset($data['long_token']) || empty(trim($data['long_token']))) { http_response_code(400); echo json_encode(['error' => 'Long token is required']); exit; } function cleanValue($value) { return trim(str_replace(['`', ','], '', $value ?? '')); } function parseDate($date) { if (empty($date)) return null; $date = cleanValue($date); // Handle multiple date formats $formats = [ 'd M Y, h:i A', // e.g., 7 Sep 2025, 5:11 AM 'd M Y h:i A', // e.g., 7 Sep 2025 5:11 AM (no comma) 'Y-m-d H:i:s', // e.g., 2025-09-07 05:11:00 'Y-m-d\\TH:i:s' // e.g., 2025-09-07T05:11:00 ]; foreach ($formats as $format) { $parsed = DateTime::createFromFormat($format, $date, new DateTimeZone('UTC')); if ($parsed !== false) { $parsed->setTimezone(new DateTimeZone('UTC')); $result = $parsed->format('Y-m-d H:i:s'); error_log("Successfully parsed date: $date -> $result"); return $result; } } error_log("Failed to parse date: $date"); throw new Exception("Invalid date format: $date"); } function generateShortToken($pdo) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $length = 16; do { $short_token = ''; for ($i = 0; $i < $length; $i++) { $short_token .= $characters[random_int(0, strlen($characters) - 1)]; } $stmt = $pdo->prepare('SELECT short_token FROM tokens WHERE short_token = ?'); $stmt->execute([$short_token]); } while ($stmt->fetch()); return $short_token; } try { $long_token = cleanValue($data['long_token']); $vehicle_number = isset($data['vehicle_number']) ? cleanValue($data['vehicle_number']) : ''; $driver_name = isset($data['driver_name']) ? cleanValue($data['driver_name']) : ''; $event_date = isset($data['event_date']) ? parseDate($data['event_date']) : null; $location = isset($data['location']) ? cleanValue($data['location']) : ''; $duration = isset($data['duration']) ? parseDate($data['duration']) : null; // Debug logging error_log("Parsed event_date: " . ($event_date ?? 'NULL')); error_log("Parsed duration: " . ($duration ?? 'NULL')); $short_token = generateShortToken($pdo); $stmt = $pdo->prepare(' INSERT INTO tokens ( long_token, short_token, vehicle_number, driver_name, event_date, location, duration ) VALUES (?, ?, ?, ?, ?, ?, ?) '); $stmt->execute([ $long_token, $short_token, $vehicle_number, $driver_name, $event_date, $location, $duration ]); echo json_encode([ 'success' => true, 'short_token' => $short_token ]); } catch (Exception $e) { http_response_code(400); echo json_encode(['error' => 'Operation failed: ' . $e->getMessage()]); } ?> ``` # api/rlt.php ```php 'Method not allowed']); exit; } $short_token = isset($_GET['short_token']) ? trim($_GET['short_token']) : ''; if (empty($short_token)) { http_response_code(400); echo json_encode(['error' => 'Short token is required']); exit; } function cleanValue($value) { return trim(str_replace(['`', ','], '', $value ?? '')); } try { $short_token = cleanValue($short_token); $stmt = $pdo->prepare('SELECT long_token FROM tokens WHERE short_token = ?'); $stmt->execute([$short_token]); $result = $stmt->fetch(); if ($result) { echo json_encode([ 'success' => true, 'long_token' => $result['long_token'] ]); } else { http_response_code(404); echo json_encode(['error' => 'Short token not found']); } } catch (PDOException $e) { http_response_code(500); echo json_encode(['error' => 'Retrieval failed: ' . $e->getMessage()]); } ?> ``` # api/debug_date.php ```php 'Method not allowed']); exit; } $data = json_decode(file_get_contents('php://input'), true); function cleanValue($value) { return trim(str_replace(['`', ','], '', $value ?? '')); } function parseDate($date) { if (empty($date)) return null; $date = cleanValue($date); $formats = [ 'd M Y, h:i A', // e.g., 7 Sep 2025, 5:11 AM 'd M Y h:i A', // e.g., 7 Sep 2025 5:11 AM (no comma) 'Y-m-d H:i:s', // e.g., 2025-09-07 05:11:00 'Y-m-d\\TH:i:s' // e.g., 2025-09-07T05:11:00 ]; foreach ($formats as $format) { $parsed = DateTime::createFromFormat($format, $date, new DateTimeZone('UTC')); if ($parsed !== false) { $parsed->setTimezone(new DateTimeZone('UTC')); $result = $parsed->format('Y-m-d H:i:s'); error_log("Debug parse: $date -> $result"); return $result; } } error_log("Debug parse failed: $date"); return null; } try { $event_date = isset($data['event_date']) ? parseDate($data['event_date']) : null; $duration = isset($data['duration']) ? parseDate($data['duration']) : null; echo json_encode([ 'success' => true, 'event_date' => $event_date, 'duration' => $duration ]); } catch (Exception $e) { http_response_code(400); echo json_encode(['error' => 'Debug failed: ' . $e->getMessage()]); } ?> ``` # Token_Management_API.postman_collection.json ```json { "info": { "_postman_id": "b3g4c7d6-6e8f-4g3h-b4e2-ad1f3g4e8f2c", "name": "Token Management API", "description": "Postman collection to test the Token Management APIs at https://tms.3mtrack.com/api/. Tests generating a 16-character short token, retrieving the long token, and debugging date parsing for event_date and duration.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "Debug Date Parsing", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Debug Date Parsing - Success', function () {", " pm.response.to.have.status(200);", " var jsonData = pm.response.json();", " pm.expect(jsonData.success).to.be.true;", " pm.expect(jsonData.event_date).to.equal('2025-09-07 05:11:00');", " pm.expect(jsonData.duration).to.equal('2025-09-08 05:11:00');", "});" ], "type": "text/javascript" } } ], "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/json", "type": "text" } ], "body": { "mode": "raw", "raw": "{\n \"event_date\": \"7 Sep 2025, 5:11 AM\",\n \"duration\": \"8 Sep 2025, 5:11 AM\"\n}", "options": { "raw": { "language": "json" } } }, "url": { "raw": "{{baseUrl}}/api/debug_date.php", "host": ["{{baseUrl}}"], "path": ["api", "debug_date.php"] }, "description": "Tests date parsing for event_date and duration without inserting into the database." }, "response": [] }, { "name": "Generate Short Token", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Generate Short Token - Success', function () {", " pm.response.to.have.status(200);", " var jsonData = pm.response.json();", " pm.expect(jsonData.success).to.be.true;", " pm.expect(jsonData.short_token).to.be.a('string');", " pm.expect(jsonData.short_token.length).to.equal(16);", " pm.environment.set('shortToken', jsonData.short_token);", "});" ], "type": "text/javascript" } } ], "request": { "method": "POST", "header": [ { "key": "Content-Type", "value": "application/json", "type": "text" } ], "body": { "mode": "raw", "raw": "{\n \"long_token\": \"RzBFAiAv126Nf_7eoPOQ64-tsfmV9ocBtlYeVCd9kIeSsBfy-QIhAKhsCHmhwaDocdY8J3hUohtMrbqGgdwar3pIEshgGPqGeyJ1Ijo2NDk2LCJlIjoiMjAyNS0wOS0wOFQwMDoxMToxOC4zMTcrMDA6MDAifQ\",\n \"vehicle_number\": \"CH04K9236 | truck\",\n \"driver_name\": \"Driver Not Defined\",\n \"event_date\": \"7 Sep 2025, 5:11 AM\",\n \"location\": \"XR87+MM Bhattian, Ludhiana, Punjab, India\",\n \"duration\": \"8 Sep 2025, 5:11 AM\"\n}", "options": { "raw": { "language": "json" } } }, "url": { "raw": "{{baseUrl}}/api/gst.php", "host": ["{{baseUrl}}"], "path": ["api", "gst.php"] }, "description": "Generates a 16-character short token from a long token and stores metadata, including event_date and duration." }, "response": [] }, { "name": "Retrieve Long Token", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Retrieve Long Token - Success', function () {", " pm.response.to.have.status(200);", " var jsonData = pm.response.json();", " pm.expect(jsonData.success).to.be.true;", " pm.expect(jsonData.long_token).to.be.a('string');", "});" ], "type": "text/javascript" } } ], "request": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/api/rlt.php?short_token={{shortToken}}", "host": ["{{baseUrl}}"], "path": ["api", "rlt.php"], "query": [ { "key": "short_token", "value": "{{shortToken}}", "description": "Use the short token from the Generate Short Token response" } ] }, "description": "Retrieves the long token for a given 16-character short token." }, "response": [] }, { "name": "Retrieve Long Token - Invalid Short Token", "event": [ { "listen": "test", "script": { "exec": [ "pm.test('Retrieve Long Token - Invalid Short Token', function () {", " pm.response.to.have.status(404);", " var jsonData = pm.response.json();", " pm.expect(jsonData.error).to.equal('Short token not found');", "});" ], "type": "text/javascript" } } ], "request": { "method": "GET", "header": [], "url": { "raw": "{{baseUrl}}/api/rlt.php?short_token=xxxxxxxxxxxxxxxx", "host": ["{{baseUrl}}"], "path": ["api", "rlt.php"], "query": [ { "key": "short_token", "value": "xxxxxxxxxxxxxxxx", "description": "Invalid short token for testing error response" } ] }, "description": "Tests error handling for an invalid 16-character short token." }, "response": [] } ], "variable": [ { "id": "baseUrl", "key": "baseUrl", "value": "https://tms.3mtrack.com", "description": "Base URL for the Token Management API" }, { "id": "shortToken", "key": "shortToken", "value": "", "description": "Stores the short token from the Generate Short Token response" } ] } ``` ### Changes Made 1. **Updated `gst.php`**: - **Enhanced `parseDate` Function**: - Added support for `d M Y h:i A` (no comma, e.g., `7 Sep 2025 5:11 AM`) to handle variations in input. - Set timezone to UTC explicitly to avoid locale issues. - Throws an exception with the invalid date for better error reporting (returns HTTP 400). - Logs successful and failed parsing attempts with input and output values. - **Debug Logging**: - Logs parsed `event_date` and `duration` values before insertion. - **Error Handling**: - Returns a 400 status with a specific error message if date parsing fails (e.g., `{"error":"Operation failed: Invalid date format: 7 Sep 2025, 5:11 AM"}`). 2. **Added `debug_date.php`**: - A new endpoint to test date parsing without database insertion. - Accepts `event_date` and `duration` in a POST request and returns their parsed values. - Helps isolate whether the issue is in parsing or database insertion. - Example response: `{"success":true,"event_date":"2025-09-07 05:11:00","duration":"2025-09-08 05:11:00"}` 3. **Unchanged Files**: - **db.sql**: Schema is correct with `event_date` and `duration` as nullable `DATETIME` fields. - **config.php**: PDO connection string is correct (`mysql:host=localhost;dbname=ultraaud_tms`). - **rlt.php**: Unaffected by the date issue, as it only retrieves `long_token`. 4. **Postman Collection**: - Updated `_postman_id` for uniqueness. - Added a **Debug Date Parsing** request to test `event_date` and `duration` parsing. - Test script for **Debug Date Parsing** validates that `event_date` and `duration` are parsed as `2025-09-07 05:11:00` and `2025-09-08 05:11:00`. - Retained existing tests for **Generate Short Token**, **Retrieve Long Token**, and **Retrieve Long Token - Invalid Short Token**. - Uses the provided sample data (e.g., `event_date: "7 Sep 2025, 5:11 AM"`). ### Instructions to Use 1. **Setup the System**: - Extract `token_management_system.zip` to your web server’s root (e.g., `/var/www/html/token_management_system`). - Ensure the `api/` folder is accessible at `https://tms.3mtrack.com/api/`. - Verify `config.php` credentials (`username: ultraaud_tms`, `password: Manish`). Update if different: ```php $pdo = new PDO('mysql:host=localhost;dbname=ultraaud_tms', 'your_username', 'your_password', [...]); ``` - Create or verify the database by executing `db.sql` in MySQL: ```bash mysql -u ultraaud_tms -pManish < db.sql ``` - Ensure PHP 7.4 or lower is installed with `PDO` and MySQL support. - Set write permissions for the `api/` directory. 2. **Import the Postman Collection**: - Download `Token_Management_API.postman_collection.json` from the artifact. - In Postman, click **Import**, select the file, and import it. - Verify the `baseUrl` variable is set to `https://tms.3mtrack.com` in the environment settings. 3. **Test the APIs**: - **Debug Date Parsing** (`https://tms.3mtrack.com/api/debug_date.php`): - Send the POST request with the provided JSON (`event_date: "7 Sep 2025, 5:11 AM"`, `duration: "8 Sep 2025, 5:11 AM"`). - Expected response: `{"success":true,"event_date":"2025-09-07 05:11:00","duration":"2025-09-08 05:11:00"}` - If the response shows `null` or an error, check the PHP error log for `Debug parse failed: `. - **Generate Short Token** (`https://tms.3mtrack.com/api/gst.php`): - Send the POST request with the provided JSON payload. - Expected response: `{"success":true,"short_token":"aB3xY7pQz9mW2kL8"}` (example 16-character token). - The Postman test script saves the `short_token` to the `shortToken` variable. - Check the `tokens` table in `ultraaud_tms`: ```sql SELECT * FROM tokens WHERE short_token = 'your_short_token'; ``` - Expected values: - `long_token`: `RzBFAiAv126Nf_7...` - `short_token`: A unique 16-character string. - `vehicle_number`: `CH04K9236 | truck` - `driver_name`: `Driver Not Defined` - `event_date`: `2025-09-07 05:11:00` - `location`: `XR87+MM Bhattian, Ludhiana, Punjab, India` - `duration`: `2025-09-08 05:11:00` - Ensure no backticks or commas in any field. - Check the PHP error log (`/var/log/php_errors.log` or similar) for messages like `Failed to parse date: `. - **Retrieve Long Token** (`https://tms.3mtrack.com/api/rlt.php`): - Ensure the `shortToken` variable is set. - Send the GET request and verify: `{"success":true,"long_token":"RzBFAiAv126Nf_7..."}` - Confirm no metadata is returned. - **Retrieve Long Token - Invalid Short Token**: - Send the GET request with `short_token=xxxxxxxxxxxxxxxx`. - Verify: `{"error":"Short token not found"}` with HTTP 404. 4. **Troubleshooting**: - **If `event_date` or `duration` is still `NULL`**: - Run the **Debug Date Parsing** request to confirm parsing output. - Check the PHP error log for messages like `Failed to parse date: 7 Sep 2025, 5:11 AM`. - Test with an alternative date format in the Postman request for **Generate Short Token**: ```json "event_date": "2025-09-07 05:11:00", "duration": "2025-09-08 05:11:00" ``` - Verify the input JSON matches `7 Sep 2025, 5:11 AM` exactly (check for extra spaces or casing). - **Database Issues**: - Ensure the `ultraaud_tms` database and `tokens` table exist: ```sql SHOW DATABASES; USE ultraaud_tms; SHOW TABLES; ``` - Verify permissions: ```sql GRANT ALL PRIVILEGES ON ultraaud_tms.* TO 'ultraaud_tms'@'localhost' IDENTIFIED BY 'Manish'; FLUSH PRIVILEGES; ``` - **HTTPS Issues**: Ensure `tms.3mtrack.com` has a valid SSL certificate. - **CORS Issues**: The `Access-Control-Allow-*` headers in `config.php` should handle cross-origin requests. 5. **Debugging Steps**: - Check the PHP error log for parsing errors. - Use the **Debug Date Parsing** request to isolate parsing issues. - Query the database after running **Generate Short Token**: ```sql SELECT event_date, duration FROM tokens WHERE short_token = 'your_short_token'; ``` - If parsing fails, share the exact input JSON and error log output. 6. **Notes**: - The `parseDate` function now handles `d M Y, h:i A` and `d M Y h:i A`, with explicit UTC timezone. - The `debug_date.php` endpoint helps verify parsing without affecting the database. - APIs remain at `https://tms.3mtrack.com/api/gst.php`, `https://tms.3mtrack.com/api/rlt.php`, and `https://tms.3mtrack.com/api/debug_date.php`. - Data cleaning (no backticks or commas) is maintained. If the issue persists, please provide: - The exact input JSON used in the **Generate Short Token** request. - PHP error log output (e.g., from `/var/log/php_errors.log`). - The result of `SELECT * FROM tokens;` after running the request. - The response from the **Debug Date Parsing** request. I can also integrate this with the SIM Inventory system or add more robust date validation if needed. Let me know how to proceed!