push notification on capacitor ios app with firebase or apnotic

Hi,

I'm working on an IOS app using capacitor. I'm trying to receive push notifications on my downloaded app from testflight. I tried with FCM and it's working on my android app but not on ios and the logs show no error.

This is how I retreive the FCM token:

const fcmToken = await FCM.getToken()
      sendSubscriptionToBackEnd({
        fcm_token: fcmToken.token,
        device: platform
      })

Then I have a job on my backend to send the push notifications:

def perform
    fcm = FCM.new(
      StringIO.new(Rails.application.credentials.google_application_credentials),
      Rails.application.credentials.firebase_project_id
    )

    NotificationSubscription.find_each(batch_size: 100) do |subscription|
        begin
          response = fcm.send_v1({
            token: subscription.fcm_token,
            notification: {
              title: 'Un nouveau signal a été publié',
              body: 'Un nouveau signal a été publié, cliquez ici pour le voir'
            },
            android: {
              priority: 'high'
            },
            apns: {
              payload: {
                aps: {
                  # alert: {
                  #   title: 'Un nouveau signal a été publié',
                  #   body: 'Un nouveau signal a été publié, cliquez ici pour le voir'
                  # },
                  sound: 'default'
                }
              },
              headers: {
                "apns-priority": "10",
                "apns-push-type": "alert"
              }
            }
          })
          if response[:status_code] == 200
            Rails.logger.info "Notification sent successfully to #{subscription.id} on device #{subscription.device}"
          else
            Rails.logger.error "Failed to send notification to #{subscription.id} body: #{response[:body]}"
            # subscription.destroy
          end
        rescue StandardError => e
          Rails.logger.error "Error while sending notification to #{subscription.device}: #{e.message}"
          subscription.destroy
        end
    end
  end

and the logs show that it's successful but i dont receive the notification. When I test from firebase console I receive the push notification on both ios and android capacitor apps. I also added this in the apple delegate:

      Messaging.messaging().apnsToken = deviceToken
      Messaging.messaging().token(completion: { (token, error) in
        if let error = error {
            NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
        } else if let token = token {
            NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: token)
        }
      })
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
      NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
    }

I also tried using apns tokens and ther apnotic gem:

      console.log('APNs Token:', token.value)
      if (platform === 'ios') {
        sendSubscriptionToBackEnd({
          apns_token: token.value,
          device: platform
        }).then(() => {
          displaySnackbar(`APNs token: ${token.value}`, 'success')
        })
      }
    })
    # Create the APNs connection outside the loop
    connection = Apnotic::Connection.new(
      auth_method: :token,
      cert_path: StringIO.new(Rails.application.credentials.apns_key_path),
      key_id: Rails.application.credentials.apn_key_id,
      team_id: Rails.application.credentials.apple_team_id
    )

    NotificationSubscription.find_each(batch_size: 100) do |subscription|
      if subscription.device == 'ios'
        begin
          # Create the notification for the current device token
          notification = Apnotic::Notification.new(subscription.apns_token)
          notification.alert = "Un nouveau signal a été publié"
          notification.topic = Rails.application.credentials.apple_bundle_id

          # Prepare and send the push
          push = connection.prepare_push(notification)
          push.on(:response) do |response|
            if response.ok?
              Rails.logger.info "Notification sent successfully to #{subscription.id} on device #{subscription.device}"
            else
              Rails.logger.error "Failed to send notification to #{subscription.id} body: #{response.status} - #{response.body}"
            end
          end

          connection.push_async(push)

        rescue StandardError => e
          Rails.logger.error "Error while sending notification to #{subscription.device}: #{e.message}"
          subscription.destroy
        end
      end
    end

    connection.join(timeout: 5)
    connection.close
  end

but i have a bad token error:

Failed to send notification to 223 body: 400 - {"reason"=>"BadDeviceToken"}
I, [2025-01-23T02:23:59.013407 #104]  INFO -- : [ActiveJob] [ApnsNotificationJob]

I checked my aps entitlement env and its production, have all the certificates, keys.. so I dont understand why i can receive push notifications from firebase console but not from my app

Answered by BilalBST in 822412022

I updated my method:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
      }

and my token is serialized into a hex. The logs of my job are sayimg that it was executed with no issue:

2025-01-24T01:45:16.343Z pid=104 tid=11a4 class=ApnsNotificationJob jid=93d701749b07ec517c5af0dc INFO: start

I, [2025-01-24T01:45:16.343727 #104]  INFO -- : [ActiveJob] [ApnsNotificationJob] [bd0856b9-b4a6-4a64-bf56-2e630903b66a] Performing ApnsNotificationJob (Job ID: bd0856b9-b4a6-4a64-bf56-2e630903b66a) from Sidekiq(default) enqueued at 2025-01-24T01:45:15.648814696Z

I, [2025-01-24T01:45:16.682414 #104]  INFO -- : Notification sent successfully to 227 on device ios

I, [2025-01-24T01:45:16.720211 #104]  INFO -- : [ActiveJob] [ApnsNotificationJob] [bd0856b9-b4a6-4a64-bf56-2e630903b66a] Performed ApnsNotificationJob (Job ID: bd0856b9-b4a6-4a64-bf56-2e630903b66a) from Sidekiq(default) in 376.5ms

2025-01-24T01:45:16.720Z pid=104 tid=11a4 class=ApnsNotificationJob jid=93d701749b07ec517c5af0dc elapsed=0.377 INFO: done

I checked and I use the aps prod cert, in xcode i enabled push notifications and i set the aps env to prod. I also enabled push notification for the app on testflight

Have you checked what the token.value is? The native didRegisterForRemoteNotifications() returns the token as binary data which needs to be serialized into a hex string before it can be used.

Also, is all this returning the actual APNs token or the FCM token? They are different, and cannot be used interchangeably on APNs.

The common reasons you will get this error are either the token is simply invalid/badly constructed or you are mixing and matching sandbox and production environments/tokens.

Accepted Answer

I updated my method:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
      }

and my token is serialized into a hex. The logs of my job are sayimg that it was executed with no issue:

2025-01-24T01:45:16.343Z pid=104 tid=11a4 class=ApnsNotificationJob jid=93d701749b07ec517c5af0dc INFO: start

I, [2025-01-24T01:45:16.343727 #104]  INFO -- : [ActiveJob] [ApnsNotificationJob] [bd0856b9-b4a6-4a64-bf56-2e630903b66a] Performing ApnsNotificationJob (Job ID: bd0856b9-b4a6-4a64-bf56-2e630903b66a) from Sidekiq(default) enqueued at 2025-01-24T01:45:15.648814696Z

I, [2025-01-24T01:45:16.682414 #104]  INFO -- : Notification sent successfully to 227 on device ios

I, [2025-01-24T01:45:16.720211 #104]  INFO -- : [ActiveJob] [ApnsNotificationJob] [bd0856b9-b4a6-4a64-bf56-2e630903b66a] Performed ApnsNotificationJob (Job ID: bd0856b9-b4a6-4a64-bf56-2e630903b66a) from Sidekiq(default) in 376.5ms

2025-01-24T01:45:16.720Z pid=104 tid=11a4 class=ApnsNotificationJob jid=93d701749b07ec517c5af0dc elapsed=0.377 INFO: done

I checked and I use the aps prod cert, in xcode i enabled push notifications and i set the aps env to prod. I also enabled push notification for the app on testflight

push notification on capacitor ios app with firebase or apnotic
 
 
Q