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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1278834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:51:01  来源:igfitidea点击:

PHP technique to query the APNs Feedback Server

phppush-notificationstreamapple-push-notificationsfread

提问by Nick Baicoianu

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

就您查询的方式而言,有人可以澄清 APNs(Apple 推送通知)想要什么吗?

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?

文档说它在建立连接后立即开始发送。这是否意味着我不这样做fread()

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.

这是我当前尝试阅读的代码。我没有将它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);
?>

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.

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

Thanks

谢谢

回答by Nick Baicoianu

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.

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

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):

这是一个从 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;
}

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

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

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

回答by strange

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?

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

回答by strange

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."

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

回答by strange

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!

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

回答by Steven M

Just started using this library - works great for me!

刚开始使用这个库 - 对我很有用!

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

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