Critical outcome when sending push notification fr

2019-08-02 09:05发布

We have an app on appstore, and with registered push notifications. They have successfully worked all the time, but we now tried to send a 'global' push, and something weird happened. This is what we have in our server-side .php file:

//Loop through tokens in tokenArray
$i = 0;
$t = 0;
foreach($tokenArray as $token)
{
    $t++;
    // Make notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;

    // Send
    $result;
    if($message != null)
    {
        $result = fwrite($fp, $msg, strlen($msg));
    }

if ($result)
    $i++;
}
// Close the connection to the server
fclose($fp);

if($i == 0)
{
    echo 'The message was not delivered to anyone out of '.$t.'.';
}
else
{
    echo 'The message was delivered to '.$i.' out of '.$t.'.';
}

The code before this has always worked, and it kind of still does. The tokenArray contains the table with tokens, as in SELECT Token FROM Tokens; from our SQL. This works.

During development, when only our own tokens were registered, it always said "The message was delivered to 4 out of 4", even though we had deleted our apps from our phones. Now we tried to send to all ≈1100 registered tokens with this code. The message was sent, and the output was "The message was delivered to 588 out of 1194." And we did not receive the notification ourselves! What does that mean?

After about 5 minutes, I switched out the tokenArray with an array only containing my own tokens and sent a new push, and I received that one on my phone. I also know for a fact that the 'working' token exist in the previous 'tokenArray' which failed(I checked).

Is push notification a game of chance!? What does it mean when if($result) fails? And why did it fail over 500 times?

The certificates and .pem and .p12 etc are all working, the only thing I did different from push1 to push2 was to use another table which is a clone from the original table in my SQL-server. Table2 only have my tokens, and it worked. No other changes was made. Only SELECT Token FROM Tokens2, and later I proved that all the tokens in Tokens2 exist in Tokens I have no idea if anyone got the push at all, or if the 'lucky' 588 of the 1200 that still has the app installed received it.

What causes this? We don't dare send another one in case half of them already received it.. Is there some limit to how fast I can send pushes at once? Or what are we doing wrong?! Please help, thanks.

2条回答
劳资没心,怎么记你
2楼-- · 2019-08-02 09:32

Well, I don't know php, so your code doesn't help me. However, based on your description it's likely some of the device tokens in your DB are invalid. When Apple's server gets a notification with an invalid device token it closes the socket. If you already wrote more messages after the one with the bad token, they won't reach Apple. Only after you detect that the socket was closed and open a new one your messages will reach Apple. If you don't use the enhanced notification format, it would be a good idea to start using it - this way you can get from Apple the id of the invalid message and clean your DB from invalid tokens. However, even using the enhanced format doesn't guarantee that you'll detect all the errors (unless you are willing to send the messages really slowly, and check for error responses from Apple after each message you send).

查看更多
做自己的国王
3楼-- · 2019-08-02 09:40

Your main loop does not take into account cases in which Apple will close socket connections. As mentioned by Eran, if you send an invalid token, Apple closes the connection at which point, any further writes using fwrite will fail. So if your 589th token is invalid, no other push will be sent to Apple.

Here's a simple fix for that that fits into your logic; this part replaces the if statement in the main loop:

if ($result) {
    $i++;
} else {
    fclose($fp);
    // Add code here to re-open socket-connection with Apple.
}

Besides the enhanced notification format mentioned by Eran, you can also use the APNS Feedback API to query Apple for invalid tokens and purge them from your database. You can find more infomation on that here: http://bit.ly/14RPux4

There is no limit to how many push notifications you can send at once. I've sent thousands in a few seconds. The only real limitation is the connection between you and the APNS servers.

查看更多
登录 后发表回答