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

查询APNs反馈服务器的PHP技术,php,push-notification,stream,apple-push-notifications,fread,Php,Push Notification,Stream,Apple Push Notifications,Fread,有人能澄清APNs(苹果推送通知)想要什么吗 文件说,一旦建立连接,它就开始发送。这是否意味着我没有对其执行fread() 这是我当前的代码,可以尝试阅读它。我没有将fread()放入循环中,因为我不知道什么响应指示“没有更多记录可读取”,并且我不希望在我的服务器上出现无限循环 <?php $apnsCert = 'HOHRO-prod.pem'; $streamContext = stream_context_create(); stream_context_set_option($s

有人能澄清APNs(苹果推送通知)想要什么吗

文件说,一旦建立连接,它就开始发送。这是否意味着我没有对其执行
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()
是错误的方法


谢谢

我从苹果论坛获得了解决方案,它是用于开发的。在生产中也可以试试这个

“嗯,尽管听起来很愚蠢,我还是找到了一个解决办法:

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

该代码看起来不错,但是您需要循环并检查流的结尾,以便读取所有设备代码

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

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

这终于对我起作用了

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

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

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

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

这里有一个从APNS反馈服务器获取设备令牌的完整功能(非常感谢上面的答案,帮助我将其整合在一起):

如果一切正常,此函数的返回值将如下所示(通过print_r()):


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


我认为这是正确的想法-$array=unpack(“NnH32”,$result)$反馈时间=$行[0]$feedbackLen=$row[1]$feedbackUDID=$row[2];这将解压缩反馈服务器发送的38个字节。但是,32位的日期值是按网络顺序或big-endian排列的。如果有人能提供一个PHP函数,将这4个字节翻转为英特尔(little endian)顺序,我认为我们有了解决方案。注意:实际的UDID是一个字符串,不需要颠倒顺序。这有什么用?-----------/*将浮点数从主机订单转换为网络订单/函数FToN($val){$a=unpack(“I”,pack(“f”),pack(“f”),return pack(“N”,“a[1]);}/将浮点数从网络订单转换为主机订单*/函数NToF($val){$a=unpack(“N”,“val”);$b=unpack(“f”,pack(“I”,“a[1]);返回$b[1];}这非常有效,gw1921。现在,我将$feedbackDate存储在SQL列中。列应该是什么类型的数据?我把它设为整数,这就是“2009”。其他两列,长度和标记,效果很好!!感谢您提供这一优雅的解决方案。现在,我只需要知道如何将上述反馈代码返回的时间戳与我保存在数据库中的时间戳进行比较,这当然表示设备向我发送令牌的最新时间。我只是做一个整数比较吗?或者我必须把时间戳转换成正确的尾数还是什么?这个答案应该是公认的解决方案,依我看。这基本上就是我正在做的,而且它工作得非常完美。如果使用此方法仍看不到反馈数据,请验证设备上是否有另一个应用程序启用了推送功能,并与卸载的应用程序报告到相同的aps环境。Johnny-关于时间戳,一旦你像Nick的帖子那样解包,你就可以做一个整数比较了。在这种情况下,我不会从反馈服务器得到响应吗?我的通知通过良好(正如我可以说,从日志),但由于某些原因,我从来没有收到任何通知的设备!APNS反馈服务器只返回自您上次反馈请求以来“过期”的设备令牌。“哎哟,我想我真的应该阅读文档;(我尝试使用此功能。我确实确定我使用的是正确的证书/服务器组合。我始终使用.sandbox。我向开发设备发送两个推送通知,一个设备收到消息,反馈数组为空。即使我有一个类似的代码,我也从fread获得null。不确定我的代码是否真的有效,APNS是否正在发送ou。)没有空回复或只是缺少一些内容。我确信我与APNS的连接成功。我已在一些5-10台设备上安装了我的应用程序,并发送了几个警报,然后从少数设备上卸载了应用程序,并再次开始发送警报,以便APNS反馈服务器会让我们知道它在少数设备上无法交付。我没有收到任何通知在fread()中除了blank之外的任何内容:-(如果您做了一些不同的事情并使其工作,请务必让我知道。您使用过“pushutil”吗?一旦你弄明白了,这是检查反馈服务器的一种更快的方法。这是一个Mac OS X实用程序,你可以编译,然后从Unix命令行运行。Google Erica Sadun-它在她的网站上,正在推送中。仍然没有从反馈服务器得到响应
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;
}
Array
(
    Array
    (
        [timestamp] => 1266604759
        [length] => 32
        [devtoken] => abc1234..............etcetc
    ),
    Array
    (
        [timestamp] => 1266604922
        [length] => 32
        [devtoken] => def56789..............etcetc
    ),
)