payfrit-api/api/beacon-sharding/verify_beacon_broadcast.php
John Mizerek 1f81d98c52 Initial PHP API migration from CFML
Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3.
Shared helpers in api/helpers.php (DB, auth, request/response, security).
PDO prepared statements throughout. Same JSON response shapes as CFML.
2026-03-14 14:26:59 -07:00

68 lines
2.6 KiB
PHP

<?php
require_once __DIR__ . '/../helpers.php';
runAuth();
$data = readJsonBody();
$hardwareId = trim($data['HardwareId'] ?? '');
if ($hardwareId === '') apiAbort(['OK' => false, 'ERROR' => 'missing_hardware_id', 'MESSAGE' => 'HardwareId is required']);
$beaconUUID = trim($data['UUID'] ?? '');
if ($beaconUUID === '') apiAbort(['OK' => false, 'ERROR' => 'missing_uuid', 'MESSAGE' => 'UUID is required']);
$major = (int) ($data['Major'] ?? 0);
$minor = (int) ($data['Minor'] ?? 0);
$rssi = isset($data['RSSI']) && is_numeric($data['RSSI']) ? (int) $data['RSSI'] : null;
$seenAt = date('Y-m-d H:i:s');
if (!empty($data['SeenAt'])) {
try { $seenAt = (new DateTime($data['SeenAt']))->format('Y-m-d H:i:s'); } catch (Exception $e) {}
}
try {
$qHW = queryOne("
SELECT ID, BusinessID, ServicePointID, ShardUUID, Major, Minor, Status
FROM BeaconHardware WHERE HardwareId = ? LIMIT 1
", [$hardwareId]);
if (!$qHW) {
apiAbort(['OK' => false, 'ERROR' => 'hardware_not_found', 'MESSAGE' => 'Beacon hardware not registered']);
}
if (strcasecmp($qHW['ShardUUID'], $beaconUUID) !== 0) {
apiAbort(['OK' => false, 'ERROR' => 'uuid_mismatch', 'MESSAGE' => 'Beacon is broadcasting wrong UUID',
'ExpectedUUID' => $qHW['ShardUUID'], 'BroadcastUUID' => $beaconUUID]);
}
if ((int) $qHW['Major'] !== $major) {
apiAbort(['OK' => false, 'ERROR' => 'major_mismatch', 'MESSAGE' => 'Beacon is broadcasting wrong Major',
'ExpectedMajor' => (int) $qHW['Major'], 'BroadcastMajor' => $major]);
}
if ((int) $qHW['Minor'] !== $minor) {
apiAbort(['OK' => false, 'ERROR' => 'minor_mismatch', 'MESSAGE' => 'Beacon is broadcasting wrong Minor',
'ExpectedMinor' => (int) $qHW['Minor'], 'BroadcastMinor' => $minor]);
}
$setClauses = ["Status = 'verified'", "VerifiedAt = ?", "LastSeenAt = ?", "UpdatedAt = NOW()"];
$params = [$seenAt, $seenAt];
if ($rssi !== null) {
$setClauses[] = "LastRssi = ?";
$params[] = $rssi;
}
$params[] = $hardwareId;
queryTimed("UPDATE BeaconHardware SET " . implode(', ', $setClauses) . " WHERE HardwareId = ?", $params);
jsonResponse([
'OK' => true,
'BeaconHardwareID' => (int) $qHW['ID'],
'HardwareId' => $hardwareId,
'BusinessID' => (int) $qHW['BusinessID'],
'ServicePointID' => (int) $qHW['ServicePointID'],
'Status' => 'verified',
'VerifiedAt' => (new DateTime($seenAt))->format('Y-m-d\TH:i:s\Z'),
]);
} catch (Exception $e) {
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]);
}