Search code examples
c#jsonfirebase-cloud-messaginghttp-status-code-401400-bad-request

How to resolve 400 bad request error while trying to send message through the new FCM API V1?


I am trying to migrate from legacy FCM(Firebase Cloud Messaging) API to the new FCM API V1. For this I have done a few things on the FCM side as per the FCM documentation, I have created the service account, downloaded the JSON file for authenticating requests. My code is in C#, so on C# side, I have made the following changes:

  1. Used OAuth 2.0 for authentication.
  2. Used the downloaded JSON file to get the credentials and used those credentials to generate the access token.
  3. Updated the FCM endpoint and used the new endpoint https://fcm.googleapis.com/v1/yourprojectid/messages:send
  4. Updated the JSON payload structure.

Below is the code that I have written for achieving this:

            PersUser persUser = PersUser.GetPersUser();
            string pushToken = persUser.PushNotificationToken;                
            if (persUser != null && !String.IsNullOrEmpty(pushToken))
            {
                string senderId = string.Empty;
                                   
                // Load credentials from the JSON key file
                GoogleCredential credential;
                using (var stream = new FileStream(@"JSON_FILE_PATH", FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream)
                        .CreateScoped("https://www.googleapis.com/auth/firebase.messaging");
                }
                string accessToken = String.Empty;
                // Obtain an access token
                if (credential != null)
                {
                    var token = await credential.UnderlyingCredential.GetAccessTokenForRequestAsync();
                    accessToken = Convert.ToString(token);                      
                }
                
                senderId = ConfigurationManager.AppSettings["FIREBASESENDERID"];
                
                var httpWebRequest = (HttpWebRequest)System.Net.WebRequest.Create("https://fcm.googleapis.com/v1/projects/myproject-id/messages:send");
                httpWebRequest.ContentType = "application/json";
                httpWebRequest.Headers.Add(string.Format("Authorization: Bearer {0}", accessToken));
                httpWebRequest.Method = "POST";

                var body = new object();

                body = new
                {
                    token = pushToken,
                    notification = new
                    {
                        title = "Patient Flow",
                        body = message,
                        sound = soundFileName
                    },
                    data = new
                    {
                        type = notificationType
                    }
                };
               
                string jsonPayload = String.Empty;
                var serializer = new JavaScriptSerializer();
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    string json = jsonPayload = serializer.Serialize(body);
                    streamWriter.Write(json);
                    streamWriter.Flush();
                }
                
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    string httpResult = streamReader.ReadToEnd();

                    if (httpResponse.StatusCode != HttpStatusCode.OK)
                    {
                        Logger.Write(TraceTyp.DEBUG, String.Empty, "PushNotificationProcessor.SendNotification", string.Format("Push notification for {0} was not successfully delivered.", httpResponse), String.Empty);
                    }
                }
                return true;
            }
            return false;

When I debug this, I see a 400 Bad request error at:

    var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();

I have also tried the solution suggested in Firebase Cloud Messaging Device Group Management via HTTP v1 auth, but that hasn't helped.

Please suggest what I may be missing here. Where am I possibly going wrong?


Solution

  • The 400 bad request error as we know it mostly has to do with the syntax, which means that the request might be malformed. The reason why I was getting the 400 bad request error was that I was trying to migrate to the new FCM API V1 and the new FCM API accepts a slightly different json payload as opposed to what the legacy FCM API used to accept. The only change that I have done to my code is at the place where I am forming the payload.

    This is the payload that I earlier had

    body = new {
    token = pushToken,
    notification = new
    {
     title = "Patient Flow",
     body = message,
     sound = soundFileName,
    };
    data = new
    {
     type = notificationType
    }
    };
    

    The updated payload:

    body = new {
    message = new 
    {
    token = pushToken,
    data = new
    {
      title = "Patient Flow",
      body = NotificationMessage,
      sound = soundFileName,
      notificationType = notificationType
    }
    }
    };
    

    It has basically required me to add the new key called 'message' within body and that has fixed the issue for me.