Deploy: 2026-05-22 21:52:51

This commit is contained in:
Hamza-Ayed
2026-05-22 21:52:51 +03:00
parent 5269789b51
commit 8acca92bba
12 changed files with 1938 additions and 285 deletions

View File

@@ -148,5 +148,237 @@ $router->post('/api/external/verify-payment', function ($request, $response) {
});
// REST API for Entaleq Driver OCR Details (GET)
$router->get('/api/external/driver-ocr', function ($request, $response) {
$apiKey = getenv('ENTALEQ_API_KEY');
$incomingKey = $request->getHeader('x-api-key') ?? '';
if (empty($apiKey) || $incomingKey !== $apiKey) {
$response->status(401)->json([
'status' => 'error',
'message' => 'Unauthorized'
]);
return;
}
$phone = $request->get('phone') ?? '';
$companyId = $request->get('company_id') ?? '';
if (empty($phone)) {
$response->status(400)->json([
'status' => 'error',
'message' => 'Missing phone parameter'
]);
return;
}
\App\Models\DriverOcrData::ensureTableExists();
$hash = \App\Core\Security::blindIndex($phone);
if ($companyId) {
$records = \App\Core\Database::select(
"SELECT * FROM driver_ocr_data WHERE company_id = ? AND phone_hash = ?",
[$companyId, $hash]
);
} else {
$records = \App\Core\Database::select(
"SELECT * FROM driver_ocr_data WHERE phone_hash = ?",
[$hash]
);
}
if (empty($records)) {
$response->status(404)->json([
'status' => 'error',
'message' => 'No driver records found for this phone number'
]);
return;
}
$decryptedRecords = [];
$host = ($request->getHeader('x-forwarded-proto') ?: 'http') . '://' . ($request->getHeader('host') ?: 'localhost');
foreach ($records as $record) {
$decrypted = \App\Models\DriverOcrData::decryptRecord($record);
if ($decrypted) {
// Include absolute paths for all document URLs
$urlFields = [
'id_front_url', 'id_back_url',
'driving_license_front_url', 'driving_license_back_url',
'vehicle_license_front_url', 'vehicle_license_back_url',
'criminal_record_url'
];
foreach ($urlFields as $field) {
if (!empty($decrypted[$field])) {
$decrypted[$field . '_absolute'] = $host . $decrypted[$field];
} else {
$decrypted[$field . '_absolute'] = null;
}
}
$decryptedRecords[] = $decrypted;
}
}
$response->json([
'status' => 'success',
'data' => $decryptedRecords
]);
});
// REST API to Mark Driver Registered (POST)
$router->post('/api/external/register-driver', function ($request, $response) {
$apiKey = getenv('ENTALEQ_API_KEY');
$incomingKey = $request->getHeader('x-api-key') ?? '';
if (empty($apiKey) || $incomingKey !== $apiKey) {
$response->status(401)->json([
'status' => 'error',
'message' => 'Unauthorized'
]);
return;
}
$phone = $request->get('phone') ?? '';
$companyId = $request->get('company_id') ?? '';
if (empty($phone)) {
$response->status(400)->json([
'status' => 'error',
'message' => 'Missing phone parameter'
]);
return;
}
\App\Models\DriverOcrData::ensureTableExists();
$hash = \App\Core\Security::blindIndex($phone);
if ($companyId) {
$existing = \App\Core\Database::selectOne(
"SELECT id FROM driver_ocr_data WHERE company_id = ? AND phone_hash = ? LIMIT 1",
[$companyId, $hash]
);
} else {
$existing = \App\Core\Database::selectOne(
"SELECT id FROM driver_ocr_data WHERE phone_hash = ? LIMIT 1",
[$hash]
);
}
if (!$existing) {
$response->status(404)->json([
'status' => 'error',
'message' => 'Driver record not found'
]);
return;
}
\App\Core\Database::execute(
"UPDATE driver_ocr_data SET status = 'registered' WHERE id = ?",
[$existing['id']]
);
$response->json([
'status' => 'success',
'message' => 'Driver status successfully updated to registered'
]);
});
// Cron job endpoint to send pending driver registration reminders
$router->get('/api/external/cron/send-reminders', function ($request, $response) {
$apiKey = getenv('ENTALEQ_API_KEY');
$incomingKey = $request->getHeader('x-api-key') ?? '';
if (empty($apiKey) || $incomingKey !== $apiKey) {
$response->status(401)->json([
'status' => 'error',
'message' => 'Unauthorized'
]);
return;
}
\App\Models\DriverReminder::ensureTableExists();
$now = date('Y-m-d H:i:s');
$reminders = \App\Core\Database::select(
"SELECT * FROM driver_registration_reminders WHERE status = 'pending' AND scheduled_at <= ?",
[$now]
);
$processed = 0;
foreach ($reminders as $reminder) {
$companyId = $reminder['company_id'];
$phone = $reminder['phone'];
// Get company chatbot rule details
$rule = \App\Models\ChatbotRule::findActiveForRule($companyId);
$geminiKey = ($rule && !empty($rule['gemini_api_key'])) ? $rule['gemini_api_key'] : getenv('GEMINI_API_KEY');
$elApiKey = ($rule && !empty($rule['elevenlabs_api_key'])) ? $rule['elevenlabs_api_key'] : getenv('ELEVENLABS_API_KEY');
$elVoiceId = ($rule && !empty($rule['elevenlabs_voice_id'])) ? $rule['elevenlabs_voice_id'] : getenv('ELEVENLABS_VOICE_ID');
// Fetch company WhatsApp session
$session = \App\Models\WhatsAppSession::findByCompany($companyId);
if (!$session || $session['status'] !== 'connected') {
error_log("Cron Reminder: WhatsApp session not connected for company {$companyId}");
continue;
}
// Try to get driver name from active conversation flow state
$driverName = '';
$state = \App\Models\ConversationState::findActive($companyId, $phone);
if ($state) {
$ctx = json_decode($state['context_data'] ?: '{}', true);
$driverName = $ctx['name'] ?? '';
}
$nameStr = $driverName ? " كابتن " . $driverName : " كابتن";
$reminderMsg = "أهلاً بك{$nameStr}، حابين نذكرك تكمل خطوات تسجيلك لتنضم لعائلة انطلق 🚖. بقية الأوراق كتير مهمة لنفعل حسابك ونبدأ سوا. بانتظار إرسالها!";
// Generate Audio voice note if key is present
$audioData = null;
if (!empty($geminiKey)) {
$audioData = \App\Services\GeminiService::generateAudioResponse(
$geminiKey,
"أنت روبوت خدمة العملاء لشركة انطلق، تتحدث باللهجة السورية الودودة.",
$reminderMsg,
'Puck',
$elApiKey ?: null,
$elVoiceId ?: null
);
}
try {
// 1. Send the text reminder
\App\Core\Flows\ConversationFlowEngine::sendReply($session, $phone, $reminderMsg);
// 2. Send the voice note reminder if generated successfully
if ($audioData && !empty($audioData['audio'])) {
\App\Core\Flows\ConversationFlowEngine::sendReply(
$session,
$phone,
'',
null,
$audioData['audio'],
$audioData['mimeType'] ?? 'audio/mp4'
);
}
// 3. Mark the reminder as sent
\App\Models\DriverReminder::update($reminder['id'], [
'status' => 'sent'
]);
$processed++;
} catch (\Exception $ex) {
error_log("Failed to process reminder ID {$reminder['id']}: " . $ex->getMessage());
}
}
$response->json([
'status' => 'success',
'processed_count' => $processed,
'total_pending_due' => count($reminders)
]);
});
// 4. Dispatch the request
$router->dispatch($request, $response);