payfrit-api/api/beacon-sharding/register_beacon_hardware.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

105 lines
4.9 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']);
}
$bizId = (int) ($data['BusinessID'] ?? 0);
if ($bizId <= 0) apiAbort(['OK' => false, 'ERROR' => 'missing_business_id', 'MESSAGE' => 'BusinessID is required']);
$spId = (int) ($data['ServicePointID'] ?? 0);
if ($spId <= 0) apiAbort(['OK' => false, 'ERROR' => 'missing_servicepoint_id', 'MESSAGE' => 'ServicePointID 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);
$txPower = isset($data['TxPower']) && is_numeric($data['TxPower']) ? (int) $data['TxPower'] : null;
$advInterval = isset($data['AdvertisingInterval']) && is_numeric($data['AdvertisingInterval']) ? (int) $data['AdvertisingInterval'] : null;
$firmwareVersion = trim($data['FirmwareVersion'] ?? '');
try {
// Verify business namespace
$qBiz = queryOne("
SELECT b.ID, b.BeaconShardID, b.BeaconMajor, bs.UUID AS ShardUUID
FROM Businesses b LEFT JOIN BeaconShards bs ON b.BeaconShardID = bs.ID
WHERE b.ID = ? LIMIT 1
", [$bizId]);
if (!$qBiz) apiAbort(['OK' => false, 'ERROR' => 'invalid_business', 'MESSAGE' => 'Business not found']);
if (strcasecmp($qBiz['ShardUUID'] ?? '', $beaconUUID) !== 0) {
apiAbort(['OK' => false, 'ERROR' => 'uuid_mismatch', 'MESSAGE' => 'UUID does not match business\'s assigned shard',
'ExpectedUUID' => $qBiz['ShardUUID'], 'ProvidedUUID' => $beaconUUID]);
}
if ((int) $qBiz['BeaconMajor'] !== $major) {
apiAbort(['OK' => false, 'ERROR' => 'major_mismatch', 'MESSAGE' => 'Major does not match business\'s assigned value',
'ExpectedMajor' => (int) $qBiz['BeaconMajor'], 'ProvidedMajor' => $major]);
}
// Verify service point
$qSP = queryOne("SELECT ID, BusinessID, BeaconMinor, Name FROM ServicePoints WHERE ID = ? LIMIT 1", [$spId]);
if (!$qSP) apiAbort(['OK' => false, 'ERROR' => 'invalid_servicepoint', 'MESSAGE' => 'Service point not found']);
if ((int) $qSP['BusinessID'] !== $bizId) {
apiAbort(['OK' => false, 'ERROR' => 'servicepoint_business_mismatch', 'MESSAGE' => 'Service point does not belong to this business']);
}
if ($qSP['BeaconMinor'] === null) {
queryTimed("UPDATE ServicePoints SET BeaconMinor = ? WHERE ID = ?", [$minor, $spId]);
} elseif ((int) $qSP['BeaconMinor'] !== $minor) {
apiAbort(['OK' => false, 'ERROR' => 'minor_mismatch', 'MESSAGE' => 'Minor does not match service point\'s assigned value',
'ExpectedMinor' => (int) $qSP['BeaconMinor'], 'ProvidedMinor' => $minor]);
}
// Upsert BeaconHardware
$qExisting = queryOne("SELECT ID, Status FROM BeaconHardware WHERE HardwareId = ? LIMIT 1", [$hardwareId]);
if ($qExisting) {
$setClauses = ["BusinessID = ?", "ServicePointID = ?", "ShardUUID = ?", "Major = ?", "Minor = ?", "Status = 'assigned'"];
$params = [$bizId, $spId, $beaconUUID, $major, $minor];
if ($txPower !== null) { $setClauses[] = "TxPower = ?"; $params[] = $txPower; }
if ($advInterval !== null) { $setClauses[] = "AdvertisingInterval = ?"; $params[] = $advInterval; }
if ($firmwareVersion !== '') { $setClauses[] = "FirmwareVersion = ?"; $params[] = $firmwareVersion; }
$setClauses[] = "UpdatedAt = NOW()";
$params[] = $hardwareId;
queryTimed("UPDATE BeaconHardware SET " . implode(', ', $setClauses) . " WHERE HardwareId = ?", $params);
$hwId = (int) $qExisting['ID'];
} else {
$cols = ['HardwareId', 'BusinessID', 'ServicePointID', 'ShardUUID', 'Major', 'Minor', 'Status'];
$vals = ['?', '?', '?', '?', '?', '?', "'assigned'"];
$params = [$hardwareId, $bizId, $spId, $beaconUUID, $major, $minor];
if ($txPower !== null) { $cols[] = 'TxPower'; $vals[] = '?'; $params[] = $txPower; }
if ($advInterval !== null) { $cols[] = 'AdvertisingInterval'; $vals[] = '?'; $params[] = $advInterval; }
if ($firmwareVersion !== '') { $cols[] = 'FirmwareVersion'; $vals[] = '?'; $params[] = $firmwareVersion; }
queryTimed("INSERT INTO BeaconHardware (" . implode(', ', $cols) . ") VALUES (" . implode(', ', $vals) . ")", $params);
$hwId = (int) lastInsertId();
}
jsonResponse([
'OK' => true,
'BeaconHardwareID' => $hwId,
'HardwareId' => $hardwareId,
'BusinessID' => $bizId,
'ServicePointID' => $spId,
'ServicePointName' => $qSP['Name'],
'UUID' => $beaconUUID,
'Major' => $major,
'Minor' => $minor,
'Status' => 'assigned',
]);
} catch (Exception $e) {
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage()]);
}