Search code examples
node.jsflutterfirebase-cloud-messagingsuperagent

Should A Successfully Sent FCM Payload Receive a Confirmation ID? [HTTP V1 API]


I am trying to trigger push notifications using the Firebase HTTP V1 API, and I have overcome some errors in order for FCMs to be sent to Firebase successfully.

I have become confused about my progress as I have read that when FCMs are sent to Firebase successfully, that each is assigned an ID to confirm that it has been received successfully.

I have not received an ID from Firebase despite being informed that my FCMs were sent successfully with 200 codes.

Please see the image which originates here: https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-specific-devices

enter image description here

Does the information presented pertain to the Firebase HTTP V1 API?

If the information does not pertain to the Firebase HTTP V1 API, could/should a success message be confirmed where an FCM payload is successfully sent across to Firebase-Messaging?

How could it be tested/verified whether or not the FCMs have been received by Firebase-Messaging?


With respect to Frank's comment, please see the code I have ran and received success confirmations from:

const correspond = require('superagent');

exports.sendCloudMessageSO = functions.https.onRequest(async (req, res) => {
  const deviceOS = 'Android';
  const receivedToken = req.body.token;

  try {
    await getAccessToken().then((accessToken) => { console.log('Next Token:', accessToken); })
    .catch((error) => { console.error('Error:', error); });

    const fcmMessage = {
      notification: {
        title: 'Sparky says hello!'
      },
      android: {
        notification: {
          imageUrl: 'https://foo.bar.pizza-monster.png'
        }
      },
      apns: {
        payload: {
          aps: {
            'mutable-content': 1
          }
        },
        fcm_options: {
          image: 'https://foo.bar.pizza-monster.png'
        }
      },
      webpush: {
        headers: {
          image: 'https://foo.bar.pizza-monster.png'
        }
      },
      token: receivedToken,
    };

    const feedback = correspond
        .post('https://fcm.googleapis.com/v1/projects/${PROJECT_ID}/messages:send')
        .set('Content-Type', 'application/json')
        .set('Authorization', 'Bearer ${accessToken}')
        .send(fcmMessage);

   // Convert the response body to JSON
    const jsonResponse = JSON.stringify(feedback.body);

    // Log the JSON response
    console.log(jsonResponse);

    res.status(200).send('Message sent to Firebase successfully');
  } catch (error) {
    console.error('Error sending cloud message:', error);
    res.status(500).send('Error sending cloud message');
  }
});

Examples of the feedback are:

I/flutter (26453): isIOS? = false
I/flutter (26453): Message sent to Firebase successfully
I/flutter (26453): Message sent successfully

200 code confirmation

token generated confirmation

From the view of someone who is expected to stop using the Firebase Legacy API in favour of the Firebase V1 API, Firebase has made a lot of information on the Legacy API available through its documentation, but the equivalent information pertaining to the Firebase V1 API has not been made available. It has actually been confusing and wastefully time-consuming how Firebase has presented information which has seemed to pertain to its V1 API but which actually pertains to its Legacy API. A clear differentiation between the two is missing.

The examples of code I have produced were not learned from Firebase documentation but from third parties instead.

The use case I have in mind for Firebase Cloud Messaging is for push notifications to be generated to confirm data/content within a Flutter application, and not prepared notifications or prepared campaigns. I have seen no Firebase examples of this use case and how to develop towards it. At times I have wondered whether my use case is possible for Firebase Messaging.

Generally, there's a lot of need-to-know information for people interested in the V1 API which Firebase has either made hard to find or has not made available at all. Approaching the V1 route for the first time, the person slowly comes to realise that it would have been more helpful for more information to have been offered or accessible.


Solution

  • It took some time and persistence but I finally sent my first cloud message using the V1 API today.

    During my confusion I went back to the migrate to V1 documents just to check that I had done all that I had been directed to, I checked the logs to understand the differences my changes were making, and I enquired with AI for the meaning of error messages.

    My perfected code is in two parts: (1) the server side, and (2) the UI side (a call from Flutter)

    Server side:

    const correspond = require('superagent');
    
    exports.sendMessage = functions.https.onRequest(async (req, res) => {
        const receivedToken = req.body.token;
        const deviceSystem = req.body.deviceSystem;
        let v1Token;
    
        if (receivedToken !== null)  {
    
            try {
    
                v1Token = await getAccessToken();
                console.log('Next Token:', v1Token);
    
                if (v1Token !== null) {
    
                    const PATH = `https://fcm.googleapis.com/v1/projects/${PROJECT_ID}/messages:send`;
                    const header = { 'Content-Type': 'application/json', 'Authorization': `Bearer  ${v1Token}` };
                    const fcmMessage = {
                                         "message":{
                                           "token": receivedToken,
                                           "notification":{
                                             "title":"Portugal vs. Denmark",
                                             "body":"great match!"
                                           }
                                         }
                                       }
    
                    const options = { header: header, body: fcmMessage };
    
                    correspond
                    .post(PATH)
                    .set(header)
                    .send(fcmMessage)
                    .end((err, res) => {
                        if (err) { console.error('Error:', err); return; }
    
                        console.log('Response:', res.text);
                        // Handle the response as needed
                                 });
    
                  } else {
                    console.log('Access Token value was null.');
                  }
    
              } catch (error) {
                console.log('Error:', error);
              }
          } else { console.log('receivedToken value was null.'); }
    
        });

    The call from Flutter:

    Future<void> sendToCloud(context) async {
        final uri = Uri.parse('https://us-central1-my-app.cloudfunctions.net/sendMessage');
        Map<String, dynamic> request = {
          'token': fcmToken2,
          'deviceSystem': 'Android',
        };
    
        if (fcmToken2 == null) {
          fcmToken2 = await _messaging.getToken();
        }
    
        try {
          if (fcmToken2 != null) {
            print('Current fcm-token: $fcmToken2');
            final callV1 = await http.post(uri, body: request);
    
              final response = await callV1.body;
              final jsonData = jsonDecode(response);
              print('Decoded JSON response: $jsonData');
    
              print('Response Status Code = ${callV1.statusCode}');
    
          } else {
            print('FCM Token = null!');
          }
        } catch (e) {
          print('Error: $e');
        }
      }

    This article by Ms. Jen Person was very helpful. My getAccessToken code originates here.

    At Flutter, I have a Stateful widget with an initState call requesting an fcm-token and the user's permission to receive push notifications.

    Notice the fcmMessage payload in my question and in my answer. Simply, the Firebase documentation misled me.

    Well, it's good to know that this stuff actually works! I trust that these examples are able to help others save time.

    The final challenge is to create V1 compatible payloads specific to the devices and mediums.

    I forgot to mention, that the response from the successfully sent payload is visible within the same logs where error messages can be noticed. A success confirmation is returned regarding each successfully sent Firebase Cloud Message.

    Happy Coding.