查询 APNs 反馈服务器的 PHP 技术

发布于 2024-08-02 02:48:53 字数 862 浏览 8 评论 0原文

有人可以澄清 APNs(Apple 推送通知)想要什么以及如何查询它吗?

文档说,一旦建立连接,它就会开始发送。 这是否意味着我不对它执行 fread()

这是我当前的代码,请尝试阅读它。 我没有将 fread() 放入循环中,因为我不知道什么响应表明“没有更多记录可供读取”,并且我不希望服务器上出现无限循环。

<?php
$apnsCert = 'HOHRO-prod.pem';

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'verify_peer', false);

$apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);

echo 'error=' . $error;
echo 'errorString=' . $errorString;


$result = fread($apns, 38);
echo 'result=' . $result;


fclose($apns);
?>

到目前为止,我得到的只是一个空回复。 没有错误,因此正在连接。

我不知道空回复是否意味着没有数据,或者我的 fread() 是错误的方法。

谢谢

Can someone clarify what the APNs (Apple Push Notification) wants as far as how you query it?

The docs say it starts sending as soon as the connection is made. Does this mean that I don't do an fread() on it?

Here's my current code to try and read it. I did NOT put the fread() in a loop as I do not know what response indicates "no more records to read" and I didn't want an infinite loop on my server.

<?php
$apnsCert = 'HOHRO-prod.pem';

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'verify_peer', false);

$apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);

echo 'error=' . $error;
echo 'errorString=' . $errorString;


$result = fread($apns, 38);
echo 'result=' . $result;


fclose($apns);
?>

So far all I am getting is a null reply. There are no errors so it is connecting.

I don't know if the null reply means no data is there, or my fread() is the wrong way to do it.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我不会写诗 2024-08-09 02:48:53

当我第一次尝试连接时,有一个让我困惑的大问题:APNS 反馈服务器仅返回自您上次反馈请求以来“过期”的设备令牌。 这意味着大多数时候您会得到 NULL 响应,除非您已经在处理应用程序的大量用户。

因此,请确保将过期的设备令牌存储到磁盘或数据库中,因为在您的反馈查询之后,它们将永远消失。 至少可以说,这使得测试变得很痛苦!

这是一个从 APNS 反馈服务器获取设备令牌的完整函数(非常感谢上面的答案帮助我将它们放在一起):

function send_feedback_request() {
    //connect to the APNS feedback servers
    //make sure you're using the right dev/production server & cert combo!
    $stream_context = stream_context_create();
    stream_context_set_option($stream_context, 'ssl', 'local_cert', '/path/to/my/cert.pem');
    $apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context);
    if(!$apns) {
        echo "ERROR $errcode: $errstr\n";
        return;
    }


    $feedback_tokens = array();
    //and read the data on the connection:
    while(!feof($apns)) {
        $data = fread($apns, 38);
        if(strlen($data)) {
            $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
        }
    }
    fclose($apns);
    return $feedback_tokens;
}

如果一切顺利,该函数的返回值将如下所示(通过 print_r( )):

Array
(
    Array
    (
        [timestamp] => 1266604759
        [length] => 32
        [devtoken] => abc1234..............etcetc
    ),
    Array
    (
        [timestamp] => 1266604922
        [length] => 32
        [devtoken] => def56789..............etcetc
    ),
)

Here's a big gotcha which confused me when I first tried connecting: the APNS feedback servers only return the device tokens that have "expired" since your last feedback request. Which means most of the time you'll get a NULL response unless you're already dealing with a high volume of users of your app.

So make sure you store the expired device tokens to disk or db, because after your feedback query they're gone for good. This makes testing a pain to say the least!

Here's a complete function to fetch the device tokens from the APNS feedback servers (many thanks to the answers above for helping me put it all together):

function send_feedback_request() {
    //connect to the APNS feedback servers
    //make sure you're using the right dev/production server & cert combo!
    $stream_context = stream_context_create();
    stream_context_set_option($stream_context, 'ssl', 'local_cert', '/path/to/my/cert.pem');
    $apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context);
    if(!$apns) {
        echo "ERROR $errcode: $errstr\n";
        return;
    }


    $feedback_tokens = array();
    //and read the data on the connection:
    while(!feof($apns)) {
        $data = fread($apns, 38);
        if(strlen($data)) {
            $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
        }
    }
    fclose($apns);
    return $feedback_tokens;
}

If all is well, the return values from this function will look something like this (via print_r()):

Array
(
    Array
    (
        [timestamp] => 1266604759
        [length] => 32
        [devtoken] => abc1234..............etcetc
    ),
    Array
    (
        [timestamp] => 1266604922
        [length] => 32
        [devtoken] => def56789..............etcetc
    ),
)
三生池水覆流年 2024-08-09 02:48:53

该代码看起来正确,但是您需要循环并检查流结尾才能读取所有设备代码。

 while (!feof($apns)) {
        $devcon = fread($apns, 38);
 }

然而我的问题是数据的实际解包。 有谁知道如何解压您刚刚读取的二进制数据以获取实际的设备 ID(作为字符串)以及时间戳等?

That code looks right however you need to loop and check for end of stream in order to read all the device codes.

 while (!feof($apns)) {
        $devcon = fread($apns, 38);
 }

However my problem is the actual unpacking of the data. Does anyone know how to unpack the binary data which you've just read to get the actual device ID (as string) along with the timestamp etc?

瞄了个咪的 2024-08-09 02:48:53

我从苹果论坛得到了解决方案,它是用于开发的。 也可以尝试在生产中使用此方法。

“好吧,虽然听起来很愚蠢,但我找到了一个解决方案:

在程序门户中创建一个虚拟应用程序 ID,在其上启用开发推送通知
创建并下载关联的配置文件
创建一个新的 xcode 项目,并在启动时调用 registerForRemoteNotificationTypes 方法。
在您的设备上安装虚拟应用程序。 此时,您的设备上应该运行两个 DEVELOPMENT 应用程序:原始应用程序和虚拟应用程序。 两者都应该注册才能接收推送通知。
卸载原始应用程序,然后尝试向该应用程序发送推送通知。
调用反馈服务,您应该会收到返回的数据。”

I got the solution from apple forum and it is for development. Try this for production also.

"Well, as dumb as it sounds, I found a solution:

Create a dummy app id in the program portal, enable development push notifications on it
Create and download the associated provisioning profile
Create a new xcode project, and invoke the registerForRemoteNotificationTypes method on start.
Install the dummy app on your device. At this point, you should have two DEVELOPMENT apps running on your device: the original app and the dummy app. Both should be registered to receive push notifications.
Uninstall the original app, and try to send a push notification to that app.
Invoke the feedback service, and you should receive data back."

摘星┃星的人 2024-08-09 02:48:53

这终于对我有用了。

$arr = unpack("H*", $devconts); 
$rawhex = trim(implode("", $arr));

$feedbackTime = hexdec(substr($rawhex, 0, 8)); 
$feedbackDate = date('Y-m-d H:i', $feedbackTime); 
$feedbackLen = hexdec(substr($rawhex, 8, 4)); 
$feedbackDeviceToken = substr($rawhex, 12, 64);

然后您只需根据时间戳检查设备令牌即可!

This finally worked for me.

$arr = unpack("H*", $devconts); 
$rawhex = trim(implode("", $arr));

$feedbackTime = hexdec(substr($rawhex, 0, 8)); 
$feedbackDate = date('Y-m-d H:i', $feedbackTime); 
$feedbackLen = hexdec(substr($rawhex, 8, 4)); 
$feedbackDeviceToken = substr($rawhex, 12, 64);

And then you simply check for the device token against the timestamp!

深白境迁sunset 2024-08-09 02:48:53

刚刚开始使用这个库 - 对我来说非常有用!

https://github.com/mac-cain13/notificato

Just started using this library - works great for me!

https://github.com/mac-cain13/notificato

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文