EDIT - Sử dụng định dạng nhị phân tăng cườngAPNS SSL hoạt động thất bại với mã 1
Hóa ra tôi đã không sử dụng các định dạng nhị phân tăng cường vì vậy tôi đã thay đổi mã của tôi.
<?php
$message = $_POST['message'];
$passphrase = $_POST['pass'];
//Connect to db
if ($db_found) {
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', 'x.pem');
stream_context_set_option($streamContext, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $error, $errorString, 15, STREAM_CLIENT_CONNECT, $streamContext);
stream_set_blocking ($fp, 0);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS for Push Notification' . PHP_EOL;
// Keep push alive (waiting for delivery) for 90 days
$apple_expiry = time() + (90 * 24 * 60 * 60);
$tokenResult = //SQL QUERY TO GET TOKENS
while($row = mysql_fetch_array($tokenResult)) {
$apple_identifier = $row["id"];
$deviceToken = $row['device_id'];
$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.
// 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
usleep(500000);
checkAppleErrorResponse($fp);
echo 'Completed';
fclose($fp);
// SIMPLE BINARY FORMAT
/*for($i = 0; $i<count($deviceToken); $i++) {
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken[$i]) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
$bodyError .= 'result: '.$result.', devicetoken: '.$deviceToken[$i].'';
if (!$result) {
$errCounter = $errCounter + 1;
echo 'Message not delivered' . PHP_EOL;
}
else
echo 'Message successfully delivered' . PHP_EOL;
}*/
// Close the connection to the server
//fclose($fp);
//Insert message into database
mysql_close($db_handle);
}
else {
print "Database niet gevonden ";
mysql_close($db_handle);
}
// 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.
//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.
$apple_error_response = fread($fp, 6);
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;
}
?>
Trong khi sử dụng mã mới này, tôi vẫn không thể gửi nhiều hơn 300 thông điệp vì lỗi này:
Warning: fwrite() [function.fwrite]: SSL operation failed with code 1. OpenSSL Error messages: error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry in PATH_TO_SCRIPT.php on line NUMBER
mã này hoạt động tốt khi gửi chỉ là một vài báo đẩy.
CÂU HỎI THƯỜNG GẶP với định dạng nhị phân đơn giản Vì vậy, tôi đã tích hợp Thông báo đẩy một thời gian dài trước đây và nó hoạt động tốt cho các thư được gửi tới dưới 500 người. Bây giờ tôi đang cố gắng để gửi một thông báo push to hơn 1000 người nhưng sau đó tôi nhận được lỗi bị hỏng
Warning: fwrite() [function.fwrite]: SSL: Broken pipe in PATH_TO.PHP on line x
Tôi đã đọc các tài liệu táo và tôi biết rằng thẻ không hợp lệ có thể gây ra các ổ cắm để ngắt kết nối. Một số giải pháp trực tuyến giới thiệu về ngắt kết nối và kết nối lại phát hiện như thế này:
Your server needs to detect disconnections and reconnect if necessary. Nothing is
"instant" when networking is involved; there's always some latency and code needs to take
that into account. Also, consider using the enhanced binary interface so you can check the
return response and know why the connection was dropped. The connection can also be
dropped as a result of TCP keep-alive, which is outside of Apple's control.
Tôi cũng đang chạy một dịch vụ Phản hồi đó phát hiện thẻ không hợp lệ (Người dùng muốn Đẩy Notifications nhưng xóa ứng dụng) và chỉ hoạt động tốt. Tập lệnh php đó lặp lại ID đã xóa và tôi có thể xác nhận rằng các mã thông báo đó đã bị xóa khỏi cơ sở dữ liệu MySQL của chúng tôi.
Làm cách nào để có thể phát hiện thấy ngắt kết nối hoặc đường ống bị hỏng và phản ứng với điều đó để thông báo đẩy của tôi có thể tiếp cận hơn 1000 người?
Hiện tại tôi đang sử dụng tập lệnh push.php đơn giản này.
<?php
$message = $_POST['message'];
$passphrase = $_POST['pass'];
//Connect to database stuff
if ($db_found) {
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', 'x.pem');
stream_context_set_option($streamContext, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $error, $errorString, 15, STREAM_CLIENT_CONNECT, $streamContext);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS for Push Notification' . PHP_EOL;
$deviceToken[] = //GET ALL TOKENS FROM DATABASE AND STORE IN ARRAY
for($i = 0; $i<count($deviceToken); $i++) {
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken[$i]) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
$bodyError .= 'result: '.$result.', devicetoken: '.$deviceToken[$i].'';
if (!$result) {
$errCounter = $errCounter + 1;
echo 'Message not delivered' . PHP_EOL;
}
else
echo 'Message successfully delivered' . PHP_EOL;
}
echo $bodyError;
// Close the connection to the server
fclose($fp);
//CODE TO SAVE MESSAGE TO DATABSE HERE
if (!mysql_query($SQL,$db_handle)) {
die('Error: ' . mysql_error());
}
}
else {
print "Database niet gevonden ";
mysql_close($db_handle);
}
?>
Cũng trả về fwrite 0 byte bằng văn bản khi xảy ra lỗi ống SLL bị hỏng.
Tôi cũng phải đề cập rằng tôi không có PHP hoặc nhà phát triển web nhưng là nhà phát triển ứng dụng nên kỹ năng php của tôi không tốt.
Bạn đang sử dụng định dạng nhị phân đơn giản, mà không trả lại câu trả lời. Bạn nên sử dụng định dạng nâng cao để nhận phản hồi lỗi. Xem [câu trả lời này] (http://stackoverflow.com/questions/17724614/using-push-notification-usingf-api/17726433#17726433) để biết thêm chi tiết. – Eran
Cảm ơn vì điều đó. Tôi đang sử dụng định dạng enchanced ngay bây giờ và nó trả về lỗi này khi gửi một lượng lớn thư (không phải trong khi gửi chỉ một vài thư): Cảnh báo: fwrite() [function.fwrite]: Thao tác SSL không thành công với mã 1. OpenSSL Thông báo lỗi: lỗi: 1409F07F: Thường trình SSL: SSL3_WRITE_PENDING: viết xấu thử lại trong PATH_TO_PHP_FILE_ON_LINE –
Nhìn vào [câu hỏi này] (http://stackoverflow.com/questions/2997218/why-am-i-getting-error1409f07fssl-routinesssl3- write-pending-bad-write-retr), nó có giúp ích gì không? – LombaX