skip to Main Content

I utilized FCM to send notifications in my web app. I can send and receive notifications in my localhost, so everything is working perfectly on localhost. However, I can only receive notifications (sent from firebase console, postman, etc.) but not send them on my deployed version in production.

I am using Vercel to host my server and am using Vercel’s API routes. I have the same environment variables on both local and in Vercel. On the browser, I am also getting the same responses from the API route (both success 200) when I logged them. The only difference is that notifications do not appear when I send it from the production version. Also, for whatever reason, Vercel is not displaying any server-side logs so I can’t even debug.

Does anyone have any idea why this is happening and how I can fix it?

My API/send route in the API folder of my Next.js application

import { NextResponse } from 'next/server'
import { getFirestore } from 'firebase-admin/firestore'
import { initAdmin } from '@/db/firebaseAdmin'
import { getMessaging } from 'firebase-admin/messaging';

export async function GET (req: Request, res: Response) {

    // Initialize Firebase Admin
    const app = await initAdmin();

    // get current time
    const currentTime = new Date();

    try {
        const registrationTokens = [
            'f3QNNQiLrpA4n1ayL46sz6:APA91bE-Zy9ypgl6R9nmBKYc_KgrhZs6sD3NqzEG6pLIsaGEQF2wrPSZpO-MWwanAnP0eHUGmCy2PqesD7ZR3IWNO1uumO3-KAvcjMqFWZ3aFpzaoUGa9UKSUtSP3Zgj0LpePuPluf4T', // mobile
            'fWRzguAj87BidFhkNCRdUP:APA91bEfsz8d8XSPW3SOG862V968wvn3vOhu_eJiIG2pGp4a_MrwzUUapzNg8BKvoMuF2FXqFo1f0-YlKjJSqnyf7Y_YfhbTFB8X-PsxcHJ2oOHtUAa-aQHsZg9AK5LcQqOrir9k4X56', // localhost
            'faggSiQojS1TTnljfWE1R7:APA91bHTSLOpEykD75JB_0pyqAautPijFyeLXebor8nVguBHxmvj-eMJzYe6PW51sOoPK4KzAJJlHPc9x-jcFyRurggvXhSFzF8jPtJYfog4RCQSMC1Mi12bRgamCBhSdGz5Rcmhkya9' // deployed desktop
          ];

        const message = {
            notification: {
              title: currentTime.toString(),
              body: "message"
            }
        };

        // Initialize Messaging
        const messaging = getMessaging(app);

        // Send a message to the devices corresponding to the provided registration tokens.
        const sendPromises = registrationTokens.map(token => {
            return messaging.send({ ...message, token: token });
        });

        // Use Promise.all to wait for all messages to be sent
        const responses = await Promise.all(sendPromises);

        console.log('Successfully sent messages:', responses);

        return NextResponse.json({
            message: "Notifications sent",
            responses: responses
        });
    } catch (error: any) {
        console.error('An error occurred while sending notifications:', error);
        return NextResponse.json(
            { message: error.message || 'Internal Server Error' },
            { status: 500 }
        );
    }
}

2

Answers


  1. My dear fellow developer Tom, I have the same problem with Vercel. But I found a workaround, for now -> avoid using "firebase-admin".
    For me it works but randomly on Vercel, and on localhost zero problem.

    Here is my current setup, which works like a charm, I hope it helps you:

    //generate token

    const {JWT} = require('google-auth-library');
    const firebaseEmail = process.env.FIREBASE_EMAIL;
    const firebasePrivateKey = process.env.FIREBASE_PRIVATE_KEY.replace(/\n/g, 'n');
    
    async function generateAccessToken() {
        const client = new JWT(
            firebaseEmail,
            null,
            firebasePrivateKey,
            ['https://www.googleapis.com/auth/cloud-platform'],
            null
        );
        await client.authorize();
        return client.getAccessToken();
    }
    

    //use FCM HTTP v1 API call

    const url = "https://fcm.googleapis.com/v1/projects/your-project-from-fcm/messages:send";
        const GetFirebaseToken = await generateAccessToken();
        const headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + GetFirebaseToken.token
        }
    
        const data = {
            "message": {
                "topic": 'your-topic', //you can replace with device token if you want, but cannot use token and topic together
                "android": {
                    "priority": "high"
                },
                "webpush": {
                    "headers": {
                        "Urgency": "high"
                    },
                    "data": {
                        "body": message,
                        "title": `New Title`,
                        "requireInteraction": "true",
                    },
                    "fcm_options": {
                        "link": "you url"
                    }
                }
            }
        }
    

    //finally send request, and your push notification will popup

    const response = await fetch(url, {
                method: 'POST',
                headers: headers,
                body: JSON.stringify(data)
            });
    
    Login or Signup to reply.
  2. I am using FCM HTTP v1 API with below code, Its working fine on localhost. But after deployment, it doesn’t works on server, getting timeout issue (Error: socket hang up on postman from server url). Could you please help out in this. Is there any internal FCM APIs that need to whitelist on our server?

    const { GoogleAuth } = require("google-auth-library");
    
    const auth = new GoogleAuth({
          credentials: {
            client_email: CLIENT_EMAIL,
            private_key: PRIVATE_KEY,
          },
          scopes: ["https://www.googleapis.com/auth/firebase.messaging"],
    });
    
    const client = await auth.getClient();
    const accessToken = await client.getAccessToken();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search