PHP Apple增强推送通知读取错误响应
在PHP中,如何在发送增强的推送通知时使用fread()来检查是否有错误响应?
我已经阅读了苹果的文档,通过谷歌几个模糊的post,和一些问题/答案在这里,但这仍然是非常混乱。
下面是我看到的: http : //developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html 从苹果增强推送通知读取错误与 iPhone iPhone推送通知 – 错误响应问题
我将在下面回答我自己的问题,基于以下事实:(1)我发现这是一个令人困惑的话题,(2)我必须将信息连同大量的反复试验结合起来, (3)这个博客文章说,这是鼓励: http : //blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/
当您发送推送通知时,有几个问题:
-
如果出现问题,苹果会断开你的连接,但你不知道。 当你使用基本的通知,没有办法知道他们是否全部发送。 解决scheme:这是使用增强型通知然后检查错误响应的关键。 请注意,我们将在数据库查询中使用“ORDER BY ID”,然后使用该ID作为我们在通知中发送的标识符。 这样,如果出现问题,我们知道数据库中的哪一行导致了问题(因此我们知道苹果何时断开连接并停止发送通知)。 然后,我们可以继续将推送通知发送到造成问题的行之后的所有行,而不必重新发送到我们已经发送到的行。
-
如果一切正常,苹果公司不会发回任何回应,所以这可能会导致脚本暂停并等待,而fread()正在等待未到的数据。 解决方法:需要将stream_set_blocking设置为0,以便fread总是立即返回。 请注意,这会导致fread在接收到错误响应之前返回的另一个小问题,但请在代码中查看解决方法,只需暂停1/2秒后,您的所有发送完成,然后再次检查fread 。
-
您可以发送多个推送通知,比发送错误响应要快得多。 解决方法:再次,这是上面提到的相同的解决方法…暂停1/2秒后,所有的发送完成,然后再次检查fread一次。
这里是我使用PHP的解决scheme,它解决了我遇到的所有问题。 它非常基本,但完成工作。 我已经testing了一次发送几个通知,同时发送了12万个。
<?php /* * Read Error Response when sending Apple Enhanced Push Notification * * This assumes your iOS devices have the proper code to add their device tokens * to the db and also the proper code to receive push notifications when sent. * */ //database $host = "localhost"; $user = "my_db_username"; $pass = "my_db_password"; $dbname = "my_db_name"; $con = mysql_connect($host, $user, $pass); if (!$con) { die('Could not connect to database: ' . mysql_error()); } else { mysql_select_db($dbname, $con); } // IMPORTANT: make sure you ORDER BY id column $result = mysql_query("SELECT id,token FROM `device_tokens` ORDER BY id"); //Setup notification message $body = array(); $body['aps'] = array('alert' => 'My push notification message!'); $body['aps']['notifurl'] = 'http://www.myexampledomain.com'; $body['aps']['badge'] = 1; //Setup stream (connect to Apple Push Server) $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'passphrase', 'password_for_apns.pem_file'); stream_context_set_option($ctx, 'ssl', 'local_cert', 'apns.pem'); $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); stream_set_blocking ($fp, 0); //This allows fread() to return right away when there are no errors. But it can also miss errors during last seconds of sending, as there is a delay before error is returned. Workaround is to pause briefly AFTER sending last notification, and then do one more fread() to see if anything else is there. if (!$fp) { //ERROR echo "Failed to connect (stream_socket_client): $err $errstrn"; } else { $apple_expiry = time() + (90 * 24 * 60 * 60); //Keep push alive (waiting for delivery) for 90 days //Loop thru tokens from database while($row = mysql_fetch_array($result)) { $apple_identifier = $row["id"]; $deviceToken = $row["token"]; $payload = json_encode($body); //Enhanced Notification $msg = pack("C", 1) . pack("N", $apple_identifier) . pack("N", $apple_expiry) . pack("n", 32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n", strlen($payload)) . $payload; //SEND PUSH fwrite($fp, $msg); //We can check if an error has been returned while we are sending, but we also need to check once more after we are done sending in case there was a delay with error response. checkAppleErrorResponse($fp); } //Workaround to check if there were any errors during the last seconds of sending. usleep(500000); //Pause for half a second. Note I tested this with up to a 5 minute pause, and the error message was still available to be retrieved checkAppleErrorResponse($fp); echo 'DONE!'; mysql_close($con); fclose($fp); } //FUNCTION to check if there is an error response from Apple // Returns TRUE if there was and FALSE if there was not function checkAppleErrorResponse($fp) { //byte1=always 8, byte2=StatusCode, bytes3,4,5,6=identifier(rowID). Should return nothing if OK. $apple_error_response = fread($fp, 6); //NOTE: Make sure you set stream_set_blocking($fp, 0) or else fread will pause your script and wait forever when there is no response to be sent. if ($apple_error_response) { //unpack the error response (first byte 'command" should always be 8) $error_response = unpack('Ccommand/Cstatus_code/Nidentifier', $apple_error_response); if ($error_response['status_code'] == '0') { $error_response['status_code'] = '0-No errors encountered'; } else if ($error_response['status_code'] == '1') { $error_response['status_code'] = '1-Processing error'; } else if ($error_response['status_code'] == '2') { $error_response['status_code'] = '2-Missing device token'; } else if ($error_response['status_code'] == '3') { $error_response['status_code'] = '3-Missing topic'; } else if ($error_response['status_code'] == '4') { $error_response['status_code'] = '4-Missing payload'; } else if ($error_response['status_code'] == '5') { $error_response['status_code'] = '5-Invalid token size'; } else if ($error_response['status_code'] == '6') { $error_response['status_code'] = '6-Invalid topic size'; } else if ($error_response['status_code'] == '7') { $error_response['status_code'] = '7-Invalid payload size'; } else if ($error_response['status_code'] == '8') { $error_response['status_code'] = '8-Invalid token'; } else if ($error_response['status_code'] == '255') { $error_response['status_code'] = '255-None (unknown)'; } else { $error_response['status_code'] = $error_response['status_code'] . '-Not listed'; } echo '<br><b>+ + + + + + ERROR</b> Response Command:<b>' . $error_response['command'] . '</b> Identifier:<b>' . $error_response['identifier'] . '</b> Status:<b>' . $error_response['status_code'] . '</b><br>'; echo 'Identifier is the rowID (index) in the database that caused the problem, and Apple will disconnect you from server. To continue sending Push Notifications, just start at the next rowID after this Identifier.<br>'; return true; } return false; } ?>
我不确定你的代码的内容,但你应该尝试ApnsPHP它是经过充分testing的作品完美无瑕 ,它能够为您处理所有可能的exception和错误。
其他select
https://github.com/sebastianborggrewe/PHP-Apple-Push-Notification-Server https://github.com/bortuzar/PHP-Mysql—Apple-Push-Notification-Server
已经testing了3个例子中的2个,没有实现和错误pipe理的问题。
谢谢
🙂