Which certificate should be used on app Server for waking iOS app using Pushkit and APNS?
Asked Answered
K

1

1

I am using Websocket in my iOS app for data transfer. But, since sometimes when the app is suspended in the background, the socket breaks. In that case, I use Voip push to iOS app to wake app up.

//called on appDidFinishLaunching
//register for voip notifications

PKPushRegistry *voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];

voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
voipRegistry.delegate = self;


//delegate methods for `PushKit`
#pragma mark - PushKit Delegate Methods

    - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)pushCredentials forType:(PKPushType)type {
        self.myDeviceToken = [[[[pushCredentials token] description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
        NSLog(@"voip token: %@", self.myDeviceToken);
    }

    - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type {

        if (![self socketIsConnected]) {
            [self reconnectSocket];
        }
    }

I send the token received from didUpdatePushCredentials in my Login API request to my app server.

I have the following doubts in my mind and seeking answers for them.

  1. Does PushKit require both the APNS certificate and Voip certificate? or just one of them and which one and why?
  2. If it requires both the certificates, do I need to keep both the certificates on the app server for sending success pushes to my app?
  3. Which certificate should be used on the server side to push notification which would invoke "didReceiveIncomingPushWithPayload" from server side?

Please find below the code on server side :

private ApnsService getService(String appId) {

    synchronized (APP_ID_2_SERVICE_MAP) {

        ApnsService service = APP_ID_2_SERVICE_MAP.get(appId);

        if (service == null) {

            InputStream certificate = getCertificateInputStream(appId);

            if (certificate == null) {

                String errorMessage = "APNS appId unsupported: " + appId;

                LOGGER.error(errorMessage);

                throw new ATRuntimeException(errorMessage);

            }

            boolean useProd = useAPNSProductionDestination();

            if (useProd) {

                LOGGER.info("Using APNS production environment for app " + appId);

                service = APNS.newService().withCert(certificate, CERTIFICATE_PASSWORD).withProductionDestination()

                        .build();

            } else {

                LOGGER.info("Using APNS sandbox environment for app " + appId);

                service = APNS.newService().withCert(certificate, CERTIFICATE_PASSWORD).withSandboxDestination()

                        .build();

            }

            APP_ID_2_SERVICE_MAP.put(appId, service);

        }

        return service;

    }

}

I did following implementation and it failed : 1. Created APNS SSL Service Certificate Sandbox + Production. 2. Sent token received in didUpdatePushCredentials to server. 3. Server used APNS Certificate to send the push. But failed since it could not find any corresponding certificate.

So I am failing at the combination of token to be sent to server and the certificate that would be used on the server to send the push.

Kun answered 15/4, 2020 at 10:50 Comment(0)
L
1

It seems like, You're confused about APNS and PushKit

You need to refer the below image first.

enter image description here.

It clearly states:

Establish connectivity between your notification server, the Apple Push Notification service sandbox, and production environments to deliver remote notifications to your app. When utilizing HTTP/2, the same certificate can be used to deliver app notifications, update ClockKit complication data, and alert background VoIP apps of incoming activity. A separate certificate is required for each app you distribute.

That's means single certificate worked for both.

Question: 1

Does PushKit require both the APNS certificate and VOIP certificate? or just one of them and which one and why?

  • The common certificate worked for both.

Question: 2

If it requires both the certificates, do I need to keep both the certificates on the app server for sending success pushes to my app?

  • Now, No meaning of this question.

Update: 1

It seems like an issue related to the certificate path. Leave it as of now, You can use below php script use to trigger notification

Push.php

<?php

// Put your device token here (without spaces):


$deviceToken = '1234567890123456789';
//


// Put your private key's passphrase here:
$passphrase = 'ProjectName';

// Put your alert message here:
$message = 'My first silent push notification!';



$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'PemFileName.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client(
//  'ssl://gateway.push.apple.com:2195', $err,
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;

// Create the payload body

$body['aps'] = array(
'content-available'=> 1,
'alert' => $message,
'sound' => 'default',
'badge' => 0,
);



// Encode the payload as JSON

$payload = json_encode($body);

// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));

if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);

You can trigger push by using php push.php command

Lundell answered 15/4, 2020 at 13:33 Comment(5)
Since APNS SSL Sandbox & Production certificate works for both. Then, which token should I send to backend so that they can send my device a push? Would it be APNS Token or token received in delegate method "didUpdatePushCredentials" of pushkit.?Kun
You need to store both tokens on server side. Use the respective token when it required.Lundell
I am not using push notifications in my app. I use pushkit and APNS SSL Certificate (that is also used to alert background VOIP apps of incoming activity. So, In this case wouldnt sending APNS token on server side be enough? Or pushkit token what do you suggest? Can you also ellaborate a bit on "Use respective token when it is required" in context of my application as i explained above.?Kun
If your app does not have push notification then no need to store APNS token on the server-side. In your case, you just need to store PushKit token to the server. If your app doesn't have APNS then there is no meaning of "Use respective token when it is required"Lundell
I don't understand how will server detect if it needs to send VOIP notification or regular notification if universal certificate/ key is being used? Just adding ".voip" in front of bundle id wont work. Is there a difference in their server url too?Druci

© 2022 - 2024 — McMap. All rights reserved.