Firebase Push Notification in Android using PHP

Jyotishgher Astrology
By -
0

 Send Push Notification in FCM v1 API

To send push notifications using the Firebase Cloud Messaging (FCM) v1 API, you must switch from the deprecated static server key architecture to a secure, short-lived OAuth 2.0 access token model.To use Firebase Cloud Messaging (FCM) for push notifications in Android, you must register your app in the Firebase Console, add the google-services.json file and firebase-messaging dependency to your Android project, implement a service extending FirebaseMessagingService, request notification permissions for Android 13+, and capture the device registration token. In this project i will Show PHP API CODE with all steps.

Send Push Notification in FCM v1 API

To send push notifications to the next stage officer when an approval is completed, you need to integrate Firebase Cloud Messaging (FCM) into your app. Here's how to implement it:

🔧 Step 1: Set Up Firebase in Your Project

Add Firebase Dependencies

In your app/build.gradle:

dependencies {

    // ... existing dependencies ...

    

    // Firebase Cloud Messaging

    implementation 'com.google.firebase:firebase-messaging:23.4.1'

    implementation 'com.google.firebase:firebase-analytics:21.5.1'

}


Add google-services.json

  1. Go to Firebase Console → Create a new project (or use existing)

  2. Add your Android app with your package name

  3. Download google-services.json and place it in your app/ directory

Add this to your root build.gradle:

buildscript {
    dependencies {
        // ... existing ...
        classpath 'com.google.gms:google-services:4.4.0'
    }
}

🔧 Step 2: Add Firebase Service to AndroidManifest.xml

<application>
    <!-- ... existing ... -->
    
    <!-- Firebase Messaging Service -->
    <service
        android:name=".urgency.firebase.MyFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    
    <!-- Default notification icon and color -->
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_notification" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorPrimary" />
</application>

🔧 Step 3: Create Firebase Messaging Service

// MyFirebaseMessagingService.java


public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "FCM_Service";
    private static final String CHANNEL_ID = "approval_channel";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        // Handle Data Payload
        if (remoteMessage.getData().size() > 0) {
            Map<String, String> data = remoteMessage.getData();
            Log.d(TAG, "Message data payload: " + data);

            String title = data.get("title");
            String body = data.get("body");
            String certId = data.get("certId");
            String certNo = data.get("certNo");
            String action = data.get("action");
            String senderEmpNo = data.get("senderEmpNo");

            sendNotification(title, body, certId, certNo, action, senderEmpNo);
        }

        // Handle Notification Payload
        if (remoteMessage.getNotification() != null) {
            String title = remoteMessage.getNotification().getTitle();
            String body = remoteMessage.getNotification().getBody();
            Log.d(TAG, "Notification Body: " + body);

            // Get data from notification payload
            Map<String, String> data = remoteMessage.getData();
            String certId = data.get("certId");
            String certNo = data.get("certNo");
            String action = data.get("action");
            String senderEmpNo = data.get("senderEmpNo");

            sendNotification(title, body, certId, certNo, action, senderEmpNo);
        }
    }

    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        Log.d(TAG, "FCM token refreshed: " + token);

        // Save token locally
        getSharedPreferences("FCM_PREFS", MODE_PRIVATE)
                .edit()
                .putString("fcm_token", token)
                .apply();

        // Get employee number
        String empNo = getSharedPreferences("LOGIN_DATA", MODE_PRIVATE)
                .getString("EMP_NO", "");

        if (empNo != null && !empNo.trim().isEmpty()) {
            FcmTokenManager.saveTokenToServer(getApplicationContext(), empNo, token);
        }
    }

    private void sendNotification(String title, String body, String certId, 
                                   String certNo, String action, String senderEmpNo) {
        
        // ✅ FIX: Create intent with proper extras
        Intent intent = new Intent(this, dashboard.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        
        // ✅ Pass all data as extras
        if (certId != null && !certId.isEmpty()) {
            intent.putExtra("CERT_ID", certId);
        }
        if (certNo != null && !certNo.isEmpty()) {
            intent.putExtra("CERT_NO", certNo);
        }
        if (action != null && !action.isEmpty()) {
            intent.putExtra("ACTION", action);
        }
        if (senderEmpNo != null && !senderEmpNo.isEmpty()) {
            intent.putExtra("SENDER_EMPNO", senderEmpNo);
        }
        
        // ✅ Add a flag to indicate notification click
        intent.putExtra("FROM_NOTIFICATION", true);

        PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                (int) System.currentTimeMillis(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder =
                new NotificationCompat.Builder(this, CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_action_gear)
                        .setContentTitle(title != null ? title : "Urgency Certificate")
                        .setContentText(body != null ? body : "New certificate requires your approval")
                        .setAutoCancel(true)
                        .setSound(defaultSoundUri)
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "Certificate Approvals",
                    NotificationManager.IMPORTANCE_HIGH
            );
            channel.setDescription("Notifications for certificate approvals");
            channel.enableVibration(true);
            channel.enableLights(true);
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build());
    }
}

🔧 Step 4: Save FCM Token on Login

Add this to your login activity to save the token when user logs in:

// In your LoginActivity or DashboardActivity

private void getAndSaveFcmToken() {

    FirebaseMessaging.getInstance().getToken()

        .addOnCompleteListener(task -> {

            if (!task.isSuccessful()) {

                Log.w("FCM_TOKEN", "Fetching FCM token failed", task.getException());

                return;

            }

            

            String token = task.getResult();

            Log.d("FCM_TOKEN", "Token: " + token);

            

            // Save token to your server with employee ID

            saveTokenToServer(token);

        });

}


private void saveTokenToServer(String token) {

    // Call your PHP API to save the token

    String url = "https://www.jyotishgher.in/save_fcm_token.php"; //ADD YOUR SERVER SIDE FILE

    

    RequestQueue queue = Volley.newRequestQueue(this);

    StringRequest stringRequest = new StringRequest(Request.Method.POST, url,

        response -> Log.d("FCM_SAVE", "Token saved: " + response),

        error -> Log.e("FCM_SAVE", "Error saving token", error)

    ) {

        @Override

        protected Map<String, String> getParams() {

            Map<String, String> params = new HashMap<>();

            params.put("empno", empNo); // Your employee ID

            params.put("fcm_token", token);

            return params;

        }

    };

    

    queue.add(stringRequest);

}

🔧 Step 5: Create Database Table for FCM Tokens

-- Add this to your Oracle database
CREATE TABLE FCM_TOKENS (
    TOKEN_ID NUMBER PRIMARY KEY,
    EMPLOYEE_ID VARCHAR2(50) NOT NULL,
    FCM_TOKEN VARCHAR2(500) NOT NULL,
    DEVICE_TYPE VARCHAR2(20) DEFAULT 'ANDROID',
    CREATED_DATE DATE DEFAULT SYSDATE,
    UPDATED_DATE DATE DEFAULT SYSDATE,
    IS_ACTIVE CHAR(1) DEFAULT 'Y',
    CONSTRAINT FK_FCM_USER FOREIGN KEY (EMPLOYEE_ID) REFERENCES USERS(EMPLOYEE_ID)
);

CREATE SEQUENCE SEQ_FCM_TOKEN_ID START WITH 1 INCREMENT BY 1;

🔧 Step 6: PHP API to Save FCM Token | Use your's server end Code

// save_fcm_token.php
<?php
header('Content-Type: application/json');
include 'db_connection.php';

$empno = $_POST['empno'] ?? '';
$fcm_token = $_POST['fcm_token'] ?? '';

if (empty($empno) || empty($fcm_token)) {
    echo json_encode(['success' => false, 'message' => 'Missing parameters']);
    exit;
}

// Check if token exists for this employee
$check_sql = "SELECT TOKEN_ID FROM FCM_TOKENS WHERE EMPLOYEE_ID = :empno";
$check_stmt = oci_parse($conn, $check_sql);
oci_bind_by_name($check_stmt, ':empno', $empno);
oci_execute($check_stmt);

if (oci_fetch($check_stmt)) {
    // Update existing token
    $sql = "UPDATE FCM_TOKENS 
            SET FCM_TOKEN = :token, UPDATED_DATE = SYSDATE 
            WHERE EMPLOYEE_ID = :empno";
} else {
    // Insert new token
    $sql = "INSERT INTO FCM_TOKENS (TOKEN_ID, EMPLOYEE_ID, FCM_TOKEN) 
            VALUES (SEQ_FCM_TOKEN_ID.NEXTVAL, :empno, :token)";
}

$stmt = oci_parse($conn, $sql);
oci_bind_by_name($stmt, ':token', $fcm_token);
oci_bind_by_name($stmt, ':empno', $empno);
oci_execute($stmt);

echo json_encode(['success' => true, 'message' => 'Token saved']);
?>

🔧 Step 7: Send Notification as per your requirement where you need

private void callNormalApproveAPI(String certNo, String remarksParam, String stageParam, ProgressDialog progressDialog) {
    url = awmApprovalEntry_API
            + "?CERT_NO=" + Uri.encode(certNo)
            + "&REMARKS_AWM=" + Uri.encode(remarksParam)
            + "&APRV_BY_AWM=" + Uri.encode(FORWARD_TO)
            + "&CURRENT_STAGE=" + Uri.encode(stageParam)
            + "&DSG=" + Uri.encode(dsg);

    Log.d("APPROVE_API_URL_NORMAL", url);

    JsonObjectRequest request = new JsonObjectRequest(
            Request.Method.GET,
            url,
            null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    progressDialog.dismiss();
                    try {
                        Log.d("APPROVE_RESPONSE_NORMAL", response.toString());
                        boolean success = response.optBoolean("success", false);
                        int status = response.optInt("status", 0);
                        
                        if (success && status == 1) {
                            // Get the next officer's employee ID
                            String forwardedTo = response.optString("forwarded_to", "");
                            
                            // Send push notification to next officer
                            if (!forwardedTo.isEmpty() && !forwardedTo.equals("null")) {
                                sendPushNotification(
                                    forwardedTo,
                                    "Certificate Approved",
                                    "Certificate " + certNo + " forwarded for your approval",
                                    certNo
                                );
                            }
                            
                            Toast.makeText(awm_fp_request_view_for_action.this,
                                    "Certificate APPROVED successfully!", Toast.LENGTH_LONG).show();
                            refreshActivity();
                        } else {
                            String message = response.optString("message", "Unknown error");
                            Toast.makeText(awm_fp_request_view_for_action.this,
                                    "Error: " + message, Toast.LENGTH_SHORT).show();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        Toast.makeText(awm_fp_request_view_for_action.this,
                                "Error parsing approval response", Toast.LENGTH_SHORT).show();
                    }
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    progressDialog.dismiss();
                    handleAPIError("APPROVE_NORMAL", error);
                }
            }
    );

    requestQueue.add(request);
}

// Method to send push notification to next officer
private void sendPushNotification(String targetEmpNo, String title, String body, String certNo) {
    String url = "https://xxxx.xx/send_notification.php";
    
    RequestQueue queue = Volley.newRequestQueue(this);
    StringRequest request = new StringRequest(Request.Method.POST, url,
        response -> Log.d("NOTIFICATION", "Push sent: " + response),
        error -> Log.e("NOTIFICATION", "Error sending push", error)
    ) {
        @Override
        protected Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("target_empno", targetEmpNo);
            params.put("title", title);
            params.put("body", body);
            params.put("cert_id", CERT_ID);
            params.put("cert_no", certNo);
            params.put("sender_empno", FORWARD_TO);
            return params;
        }
    };
    
    queue.add(request);
}

Fix for Notification Builder Error

The error occurs because the method is setContentText(), not setContentBody(). Here's the corrected code:

📄 How to Get Firebase Server Key

For Legacy API (Solution 1):OLD

  1. Go to Firebase Console

  2. Select your project

  3. Click on ⚙️ Project Settings → Cloud Messaging

  4. Under Project Credentials, copy the Server Key

For FCM v1 API (Solution 2): NEW ADVISED

  1. Go to Firebase Console → Project Settings → Service Accounts

  2. Click Generate New Private Key

  3. Save the JSON file as service-account.json in your server

  4. Copy your Project ID from Project Settings → General

🎯 Common Issues & Solutions

IssueSolution
404 ErrorUse correct FCM endpoint or check Project ID
401 UnauthorizedInvalid Server Key - regenerate from Firebase Console
InvalidRegistrationToken is invalid - refresh token on device
NotRegisteredApp uninstalled - remove token from database

Make sure to replace YOUR_FCM_SERVER_KEY with your actual Server Key from Firebase Console!

$serverKey = 'AAAA3xYZ123...'; // Your actual server key

🔧 Step 8: PHP API to Send FCM Notification

send_notification.php

<?php
// send_notification.php - FCM v1 FINAL WORKING VERSION


/*
|--------------------------------------------------------------------------
| Get Parameters
|--------------------------------------------------------------------------
*/

$target_empno = $_REQUEST['target_empno'] ?? '';
$title = $_REQUEST['title'] ?? 'Urgency Certificate';
$body = $_REQUEST['body'] ?? 'Certificate requires your approval';
$cert_id = $_REQUEST['cert_id'] ?? '';
$cert_no = $_REQUEST['cert_no'] ?? '';
$sender_empno = $_REQUEST['sender_empno'] ?? '';

$target_empno = trim($target_empno);
$title = trim($title);
$body = trim($body);
$cert_id = trim($cert_id);
$cert_no = trim($cert_no);
$sender_empno = trim($sender_empno);

/*
|--------------------------------------------------------------------------
| Validate Target Employee
|--------------------------------------------------------------------------
*/

if (empty($target_empno)) {
    echo json_encode([
        'success' => false,
        'message' => 'Target employee ID required'
    ]);
    exit;
}

/*
|--------------------------------------------------------------------------
| Get Active FCM Tokens
|--------------------------------------------------------------------------
*/

$sql = "
    SELECT TOKEN_ID, EMPNO, FCM_TOKEN, DEVICE_TYPE
    FROM IOS.URG_FCM_TOKENS
    WHERE EMPNO = :empno AND IS_ACTIVE = 'Y'
";

$stmt = oci_parse($conn, $sql);
oci_bind_by_name($stmt, ':empno', $target_empno);

if (!oci_execute($stmt)) {
    $error = oci_error($stmt);
    echo json_encode([
        'success' => false,
        'message' => 'Failed to fetch tokens',
        'error' => $error['message']
    ]);
    exit;
}

$tokens = [];
while ($row = oci_fetch_assoc($stmt)) {
    if (!empty($row['FCM_TOKEN'])) {
        $tokens[] = [
            'token_id' => $row['TOKEN_ID'],
            'token' => $row['FCM_TOKEN'],
            'device_type' => $row['DEVICE_TYPE']
        ];
    }
}

if (empty($tokens)) {
    echo json_encode([
        'success' => false,
        'message' => 'No active FCM token found for employee',
        'empno' => $target_empno
    ]);
    exit;
}

/*
|--------------------------------------------------------------------------
| FCM v1 Configuration
|--------------------------------------------------------------------------
*/

// ✅ Your Firebase Project ID
$projectId = ''; // Your actual Project ID

// Get Access Token
$accessToken = getAccessToken();

if (!$accessToken) {
    echo json_encode([
        'success' => false,
        'message' => 'Failed to get FCM access token. Please check service account configuration.',
        'empno' => $target_empno
    ]);
    exit;
}

/*
|--------------------------------------------------------------------------
| Send Notification
|--------------------------------------------------------------------------
*/

$results = [];
$successCount = 0;
$failedCount = 0;

foreach ($tokens as $tokenData) {
    $fcmToken = $tokenData['token'];
    
    $result = sendFCMNotificationV1(
        $fcmToken,
        $title,
        $body,
        $cert_id,
        $cert_no,
        $sender_empno,
        $projectId,
        $accessToken
    );
    
    if ($result['success']) {
        $successCount++;
    } else {
        $failedCount++;
    }
    
    $results[] = [
        'token_id' => $tokenData['token_id'],
        'success' => $result['success'],
        'response' => $result['response'],
        'httpCode' => $result['httpCode']
    ];
}

/*
|--------------------------------------------------------------------------
| Final Response
|--------------------------------------------------------------------------
*/

echo json_encode([
    'success' => $successCount > 0,
    'message' => "Notification sent to $successCount device(s)",
    'target_empno' => $target_empno,
    'total_tokens' => count($tokens),
    'success_count' => $successCount,
    'failed_count' => $failedCount,
    'results' => $results
]);

/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
*/

/**
 * Get OAuth2 Access Token using Service Account
 */
function getAccessToken() {
    // Path to your service account JSON file
    $serviceAccountFile = $_SERVER['DOCUMENT_ROOT'] . '/cmms/service-account.json';
    
    // Try alternative path if not found
    if (!file_exists($serviceAccountFile)) {
        $serviceAccountFile = __DIR__ . '/service-account.json';
    }
    
    if (!file_exists($serviceAccountFile)) {
        error_log("❌ Service account file not found at: " . $serviceAccountFile);
        return null;
    }
    
    $serviceAccount = json_decode(file_get_contents($serviceAccountFile), true);
    
    if (!$serviceAccount || !isset($serviceAccount['client_email']) || !isset($serviceAccount['private_key'])) {
        error_log("❌ Invalid service account file format");
        return null;
    }
    
    // Create JWT
    $now = time();
    $payload = [
        'iss' => $serviceAccount['client_email'],
        'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
        'aud' => 'https://oauth2.googleapis.com/token',
        'exp' => $now + 3600,
        'iat' => $now
    ];
    
    $jwt = generateJWT($payload, $serviceAccount['private_key']);
    
    if (!$jwt) {
        error_log("❌ Failed to generate JWT");
        return null;
    }
    
    // Request access token
    $ch = curl_init('https://oauth2.googleapis.com/token');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
        'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion' => $jwt
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    if ($httpCode == 200) {
        $data = json_decode($response, true);
        if (isset($data['access_token'])) {
            error_log("✅ Access token obtained successfully");
            return $data['access_token'];
        }
    }
    
    error_log("❌ Failed to get access token: HTTP $httpCode - " . $response);
    if (!empty($curlError)) {
        error_log("CURL Error: " . $curlError);
    }
    return null;
}

/**
 * Generate JWT for OAuth2
 */
function generateJWT($payload, $privateKey) {
    $header = ['alg' => 'RS256', 'typ' => 'JWT'];
    
    $base64UrlHeader = rtrim(strtr(base64_encode(json_encode($header)), '+/', '-_'), '=');
    $base64UrlPayload = rtrim(strtr(base64_encode(json_encode($payload)), '+/', '-_'), '=');
    
    $signatureInput = $base64UrlHeader . '.' . $base64UrlPayload;
    
    $key = openssl_pkey_get_private($privateKey);
    if (!$key) {
        error_log("❌ Invalid private key");
        return null;
    }
    
    openssl_sign($signatureInput, $signature, $key, OPENSSL_ALGO_SHA256);
    $base64UrlSignature = rtrim(strtr(base64_encode($signature), '+/', '-_'), '=');
    
    return $signatureInput . '.' . $base64UrlSignature;
}

/**
 * Send FCM Notification using FCM v1 API
 */
function sendFCMNotificationV1($token, $title, $body, $cert_id, $cert_no, $sender_empno, $projectId, $accessToken) {
    // FCM v1 endpoint
    $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";
    
    // Notification payload - ✅ CORRECT STRUCTURE
    $data = [
        'message' => [
            'token' => $token,
            'notification' => [
                'title' => $title,
                'body' => $body
            ],
            'data' => [
                'title' => $title,
                'body' => $body,
                'certId' => $cert_id,
                'certNo' => $cert_no,
                'senderEmpNo' => $sender_empno,
                'action' => 'OPEN_APPROVAL'
            ],
            'android' => [
                'priority' => 'HIGH'
            ]
        ]
    ];
    
    $jsonData = json_encode($data);
    
    // Log request for debugging
    error_log("📤 FCM v1 Request: " . $jsonData);
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken,
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    // Log response
    error_log("📥 FCM v1 Response: HTTP $httpCode - " . $response);
    
    if (!empty($curlError)) {
        error_log("❌ FCM CURL Error: " . $curlError);
    }
    
    // Parse response
    $success = false;
    $resultMessage = $response;
    
    if ($httpCode == 200) {
        $responseData = json_decode($response, true);
        if ($responseData && isset($responseData['name'])) {
            $success = true;
            $resultMessage = 'Notification sent successfully';
        } else {
            $resultMessage = 'FCM Error: ' . ($responseData['error']['message'] ?? 'Unknown error');
            error_log("❌ FCM Error: " . $resultMessage);
        }
    } else {
        // Parse error response
        $responseData = json_decode($response, true);
        if ($responseData && isset($responseData['error'])) {
            $errorMsg = $responseData['error']['message'] ?? 'Unknown error';
            $errorStatus = $responseData['error']['status'] ?? '';
            $resultMessage = "HTTP $httpCode - $errorStatus: $errorMsg";
        } else {
            $resultMessage = "HTTP Error: $httpCode - " . $response;
        }
        error_log("❌ FCM Error: " . $resultMessage);
    }
    
    return [
        'success' => $success,
        'response' => $resultMessage,
        'httpCode' => $httpCode,
        'curlError' => $curlError
    ];
}
?>

🔑 Important Notes

  1. Project ID: Replace YOUR_PROJECT_ID_HERE with your actual Firebase Project ID (found in Firebase Console → Project Settings)

  2. Service Account: Download the service account JSON from Firebase Console and place it at /service-account.json

  3. Permissions: Make sure the service account has the "Firebase Cloud Messaging Admin" role

  4. Testing: Test by calling the API with a valid employee number

The FCM v1 API is more reliable and will work even if the legacy endpoint is blocked!

Expected Response:

{

    "success": true,

    "message": "Notification sent to 1 device(s)",

    "target_empno": "063",

    "total_tokens": 1,

    "success_count": 1,

    "failed_count": 0,

    "results": [

        {

            "token_id": "1",

            "success": true,

            "response": "Notification sent successfully",

            "httpCode": 200

        }

    ]

}

Add FCM Admin Role to Service Account MOST IMPORTANT


🔧 Step 2: Add FCM Admin Role to Service Account MOST IMPORTANT

  1. Go to Google Cloud Console

  2. Select your Firebase project

  3. Go to IAM & AdminIAM also then Go to APIs & ServicesLibrary Then Enable Search for "Firebase Cloud Messaging API"

  4. Find your service account email (from service-account.json)

  5. Click the Edit (pencil) icon

  6. Click Add Another Role

  7. Search and add: Firebase Cloud Messaging Admin

  8. Click Save

This should now work perfectly! If you still get errors, check the PHP error logs for detailed debugging information.Part 2 To show inside the APP
Tags:

Post a Comment

0Comments

Post a Comment (0)