125 lines
3.9 KiB
PHP
125 lines
3.9 KiB
PHP
<?php
|
|
/**
|
|
* GET /api/pending-call
|
|
*
|
|
* Called by Caller Android App every 3 seconds to fetch the next pending flash call task.
|
|
*
|
|
* Query params:
|
|
* device_id — Registered device identifier
|
|
* app_key — Device authentication key
|
|
*/
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type, X-App-Key');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
http_response_code(204);
|
|
exit;
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
|
http_response_code(405);
|
|
echo json_encode(['success' => false, 'message' => 'method_not_allowed']);
|
|
exit;
|
|
}
|
|
|
|
require_once __DIR__ . '/../includes/Database.php';
|
|
require_once __DIR__ . '/../includes/Auth.php';
|
|
require_once __DIR__ . '/../includes/Logger.php';
|
|
|
|
// Authenticate — requires device key (Caller Android App)
|
|
Auth::requireAuth('device');
|
|
|
|
$deviceId = $_GET['device_id'] ?? null;
|
|
|
|
if (!$deviceId) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'message' => 'missing_device_id']);
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 400, 'missing_device_id');
|
|
exit;
|
|
}
|
|
|
|
$db = Database::getInstance();
|
|
|
|
try {
|
|
// Verify device exists and is active
|
|
$stmt = $db->prepare(
|
|
"SELECT id, device_id, is_active FROM caller_devices WHERE device_id = ?"
|
|
);
|
|
$stmt->execute([$deviceId]);
|
|
$device = $stmt->fetch();
|
|
|
|
if (!$device || !$device['is_active']) {
|
|
http_response_code(403);
|
|
echo json_encode(['success' => false, 'message' => 'device_not_registered_or_inactive']);
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 403, 'invalid_device');
|
|
exit;
|
|
}
|
|
|
|
// Update last_seen
|
|
$stmt = $db->prepare("UPDATE caller_devices SET last_seen = NOW() WHERE device_id = ?");
|
|
$stmt->execute([$deviceId]);
|
|
|
|
// Find oldest pending flash call task
|
|
// Priority: tasks assigned to this device first, then unassigned tasks
|
|
$stmt = $db->prepare(
|
|
"SELECT id, phone, caller_id, expires_at
|
|
FROM otp_requests
|
|
WHERE method = 'flash_call'
|
|
AND status = 'pending'
|
|
AND expires_at > NOW()
|
|
AND (device_id IS NULL OR device_id = ?)
|
|
ORDER BY
|
|
CASE WHEN device_id = ? THEN 0 ELSE 1 END,
|
|
created_at ASC
|
|
LIMIT 1"
|
|
);
|
|
$stmt->execute([$deviceId, $deviceId]);
|
|
$task = $stmt->fetch();
|
|
|
|
if (!$task) {
|
|
echo json_encode(['success' => true, 'task_id' => null]);
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 200);
|
|
exit;
|
|
}
|
|
|
|
// Claim this task — update status and assign device
|
|
$stmt = $db->prepare(
|
|
"UPDATE otp_requests
|
|
SET status = 'calling', device_id = ?, updated_at = NOW()
|
|
WHERE id = ? AND status = 'pending'"
|
|
);
|
|
$stmt->execute([$deviceId, $task['id']]);
|
|
|
|
// Check if update affected any row (race condition handling)
|
|
if ($stmt->rowCount() === 0) {
|
|
// Another device claimed it first
|
|
echo json_encode(['success' => true, 'task_id' => null]);
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 200);
|
|
exit;
|
|
}
|
|
|
|
// Calculate remaining timeout
|
|
$expiresAt = new \DateTime($task['expires_at']);
|
|
$now = new \DateTime();
|
|
$timeoutSeconds = max(10, $expiresAt->getTimestamp() - $now->getTimestamp());
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'task_id' => (int) $task['id'],
|
|
'phone' => $task['phone'],
|
|
'caller_id' => $task['caller_id'],
|
|
'timeout_seconds' => $timeoutSeconds,
|
|
]);
|
|
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 200);
|
|
|
|
} catch (\Throwable $e) {
|
|
error_log('pending-call error: ' . $e->getMessage());
|
|
http_response_code(500);
|
|
echo json_encode(['success' => false, 'message' => 'internal_error']);
|
|
RequestLogger::log('pending-call', 'GET', $_GET, 500, $e->getMessage());
|
|
}
|