'error', 'message' => 'Only POST allowed.']); exit; } // استقبال البيانات $json_input = file_get_contents('php://input'); $requestData = json_decode($json_input, true); $target = $requestData['target'] ?? null; $title = $requestData['title'] ?? null; $body = $requestData['body'] ?? null; $isTopic = $requestData['isTopic'] ?? false; $tone = $requestData['tone'] ?? 'default'; $customData = $requestData['data'] ?? []; if (!$target) { http_response_code(400); echo json_encode(['status' => 'error', 'message' => 'Missing: target, title, or body.']); exit; } // ============================================================================ // دالة Base64 URL-Safe Encoding (ضرورية للـ JWT) // ============================================================================ function base64UrlEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } // ============================================================================ // دالة المصادقة (Google OAuth2) // ============================================================================ function getAccessToken($credentialsPath) { if (!file_exists($credentialsPath)) return null; $credentials = json_decode(file_get_contents($credentialsPath), true); $clientEmail = $credentials['client_email']; $privateKey = $credentials['private_key']; $now = time(); $header = base64UrlEncode(json_encode(['alg' => 'RS256', 'typ' => 'JWT'])); $claim = base64UrlEncode(json_encode([ 'iss' => $clientEmail, 'scope' => 'https://www.googleapis.com/auth/firebase.messaging', 'aud' => 'https://oauth2.googleapis.com/token', 'exp' => $now + 3600, 'iat' => $now ])); $signature = ''; openssl_sign("$header.$claim", $signature, $privateKey, 'SHA256'); $jwt = "$header.$claim." . base64UrlEncode($signature); $ch = curl_init("https://oauth2.googleapis.com/token"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $res = curl_exec($ch); curl_close($ch); return json_decode($res, true)['access_token'] ?? null; } // الحصول على Access Token $accessToken = getAccessToken($serviceAccountFile); if (!$accessToken) { http_response_code(500); echo json_encode(['status' => 'error', 'message' => 'Failed to get Access Token.']); exit; } // جلب Project ID $creds = json_decode(file_get_contents($serviceAccountFile), true); $projectId = $creds['project_id']; $fcmUrl = "https://fcm.googleapis.com/v1/projects/$projectId/messages:send"; // ============================================================================ // بناء هيكل الرسالة // ============================================================================ $messagePayload = [ 'message' => [ 'notification' => [ 'title' => $title, 'body' => $body ], 'android' => [ 'priority' => 'HIGH', 'notification' => [ 'sound' => $tone, 'channel_id' => 'high_importance_channel' // تأكد من تطابقه مع Android ] ], 'apns' => [ 'headers' => ['apns-priority' => '10'], 'payload' => [ 'aps' => [ 'sound' => $tone . '.caf', 'content-available' => 1 ] ] ] ] ]; // تحديد الهدف (Topic أو Token) if ($isTopic) { $messagePayload['message']['topic'] = $target; } else { $messagePayload['message']['token'] = $target; } // ============================================================================ // 🔥 معالجة Data Payload (يجب أن تكون String: String فقط) // ============================================================================ if (!empty($customData)) { $processedData = []; foreach ($customData as $key => $val) { if (is_array($val) || is_object($val)) { // تحويل المصفوفات/الكائنات إلى JSON String $processedData[$key] = json_encode($val, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } else { // تحويل أي قيمة أخرى إلى String $processedData[$key] = (string)$val; } } $messagePayload['message']['data'] = $processedData; } // ============================================================================ // الإرسال الفعلي إلى FCM // ============================================================================ $ch = curl_init($fcmUrl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $accessToken, 'Content-Type: application/json; charset=UTF-8' ]); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($messagePayload, JSON_UNESCAPED_UNICODE)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // الرد if ($httpCode == 200) { echo json_encode([ 'status' => 'success', 'message' => 'Notification sent successfully', 'fcm_response' => json_decode($result) ], JSON_UNESCAPED_UNICODE); } else { http_response_code($httpCode); echo json_encode([ 'status' => 'error', 'message' => 'FCM request failed', 'fcm_response' => json_decode($result) ], JSON_UNESCAPED_UNICODE); } ?>