PHP:向 ios 发送推送通知

Posted

技术标签:

【中文标题】PHP:向 ios 发送推送通知【英文标题】:PHP: Sending Push notification to ios 【发布时间】:2017-09-20 07:21:56 【问题描述】:

我正在从 phpios 发送推送通知。它工作正常,这是我的代码:

$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);

现在我面临的问题是,我无法确定通知是否失败,因为$result 在每种情况下都包含一个整数,无论​​是成功还是失败。我传递了一个随机数字作为令牌,它返回整数,如 115 或 65,并且每次都会更改。所以!$result 不会工作。我如何知道通知是否失败?

【问题讨论】:

可能与此重复 ***.com/questions/25830597/… 【参考方案1】:

对 fwrite() 的调用将返回它成功发送的字节数,或者如果发送错误则返回 FALSE。您的 $result 正在发生变化,因为它会随着您发送的消息的大小而变化。因此,知道了这一点,您可以推测如果 $result===FALSE 则出现错误并且通知失败。如果 $result!==FALSE,则通知已成功发送。这仅验证消息是通过网络发送的。它不会验证消息的结构或令牌的有效性或类似的东西。

现在,如果您尝试确定推送通知消息本身是否有效并且苹果接受并正在处理它,那么您可能需要 CURL 和 HTTP/2 来执行此操作。做一个快速的谷歌搜索我遇到了这个网站,它展示了一个演示如何做到这一点。我没有测试过这个网站http://coding.tabasoft.it/ios/sending-push-notification-with-http2-and-php/所以不能告诉你演示是否正确。这只是一个快速搜索,但可能会让您走上正轨。

【讨论】:

什么意思?您的意思是您知道 fwrite 失败并且您说它没有返回 false 吗?唯一一次 $result ===false 是 fwrite 失败的时候。 php.net/manual/en/function.fwrite.php 好吧,我通过了这个设备令牌“ddd”,它肯定不是有效的设备令牌,但$result === false 失败了。 好的,我知道你是如何测试的,你想完成什么你做不到。当您执行 fwrite 时,您正在检查它是否为假,只是为了查看您的通知是否已传输到苹果。它无法检查消息本身的结构或标记的有效性。您使用的是单向通信技术,您无法通过这种方式从 Apple APN 获得任何响应。您可能希望使用 CURL 来执行此操作,而不是使用流套接字。快速搜索发现此coding.tabasoft.it/ios/… 非常感谢您的解释。我会调查并告诉你【参考方案2】:

使用fwrite 向APNS 发送内容后,您需要fread(或stream_get_contents ;))回复。最好的方法是使用非阻塞连接(stream_set_blocking($fp, 0);)并在简单的限时循环中等待响应:

$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);

在那之后,在$read 中,你要么拥有一些东西,要么什么都没有。有些东西(正好有 6 个字节)意味着错误($error = unpack('Ccommand/Cstatus/Nident', $read);)。没有任何内容(或短于/长于 6 个字节的内容)意味着成功发送消息。

【讨论】:

【参考方案3】:

我的两分钱来澄清一个重要的观点:正如 Apple 所说,推送以这种方式工作时“无法保证交付”。

因此,您当然可以按照其他人的建议测试网络错误,但您不能保证已收到通知。为此,唯一的(长..)方法是在 iOS 设备收到推送时触发 URL 请求。此 URL 请求将更新您的数据库。

【讨论】:

以上是关于PHP:向 ios 发送推送通知的主要内容,如果未能解决你的问题,请参考以下文章

使用 php 向 IOS 设备发送推送通知

从 PHP 推送通知向 iOS 发送变量?

从 php 服务器向 ios 设备发送多个推送通知

如何在不使用php循环的情况下同时向ios设备发送1000条推送通知

向 iOS 测试设备发送推送通知时出现 PHP 错误

PHP:如何向 Apple 设备发送推送通知