简体   繁体   中英

PHP: Sending Push notification to ios

I am sending push notifications from php to ios. It is working fine and here is my code:

$passphrase = '';
$badge = 1;
$path = base_path('path/to/certificate.pem');
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $path);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client(
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx
);

if (!$fp) {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "pending", "normal", null);
}

//echo 'Connected to APNS' . PHP_EOL;
$body['aps'] = array(
    'alert' => $message,
    'badge' => $badge,
    'sound' => 'default'
);
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $device_token) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));

//print_r($result);exit;

if (!$result) {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "pending", "normal", null, $result);
} else {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "sent", "normal", null, $result);
}

fclose($fp);

Now the problem that I am facing is, I cannot determine if a notification fails as the $result contains an integer in every case, either, success or failure. I have passed a random digit as token and it returns integer like 115 or 65 and it changes, every time. So !$result wont work. How do I know if notification fails?

A call to fwrite() will return the number of bytes it successfully sent, or it will return FALSE if there was an error sending. Your $result is changing because it changes with the size of the message you are sending. So knowing that, you can surmise that if $result===FALSE then there was an error and the notification failed. If $result!==FALSE, then the notification was successfully sent. This only verifies that the message was sent over the network. It does not verify that the structure of the message or the validity of the tokens or anything like that.

Now, if you trying to find out if the push notification message itself is valid and that apple accepted and is processing it, then you probably want to CURL and HTTP/2 to do this. Doing a quick google search I came across this site that shows a demo how to do it. I have not tested this site http://coding.tabasoft.it/ios/sending-push-notification-with-http2-and-php/ so cannot tell you if the demo is correct or not. It was just a quick search but might get you on the right track.

After you send something to APNS with fwrite , you'll need to fread (or stream_get_contents ;)) response. Best way is to use non-blocking connection ( stream_set_blocking($fp, 0); ) and wait for response in simple time-limited loop:

$read = '';
$to = time() + 2;  // max 2 seconds wait...
while (!feof($fp)) // ...or end of connection
{
    $r = stream_get_contents($fp);
    if (strlen($r) > 0)
        $read .= $r;
    if (time() >= $to)
        break;
    usleep(100000);
}

After that, in $read you'll have either something or nothing. Something (exactly with 6 bytes) means error ( $error = unpack('Ccommand/Cstatus/Nident', $read); ). Nothing (or content shorter/longer than 6 bytes) means successfully sent message.

my two cents to clear an important point: as Apple states, there is "no guarantee of delivery" as push works in this way.

So You can certainly test for network errors, as other guys have suggested but you have no guarantee notification has been received. To obtain so, the only (long..) way is to trigger an URL request in iOS device when it receives a push. This URL request will update your DB.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM