如何正确发送推送通知

时间:2013-06-14 15:34:47

标签: php ios push-notification apple-push-notifications

这不是我发送推送通知的第一个应用,但它是我的第一个应用,我同时向所有用户发送通知。

我遇到的是,并非我的所有用户都收到通知,只有其中一些,即使他们的设置正确(即启用了我的应用的通知),代码也是正确的,因为它被发送到其中一些,所以我的猜测是代码“错过”了一些执行,因为与APNS的连接是异步的,所以不知何故(你告诉我,如果我错了)它会混淆发送通知的队列。

以下是代码:

function sendNotification(){

$sql = "SELECT * FROM users WHERE phone = 'iPhone' AND pushID != ''";
try {
    $db = getConnection();
    $stmt = $db->prepare($sql);  
    $stmt->execute();
    $users = $stmt->fetchAll(PDO::FETCH_OBJ);

    $request = Slim::getInstance()->request();
    $content = json_decode($request->getBody());
    $message = $content->message;

    foreach($users as $user){

            // Put your device token here (without spaces):
            $deviceToken = $user->pushID;


            // Put your private key's passphrase here:
            $passphrase = 'xxxxxxx';

            ////////////////////////////////////////////////////////////////////////////////

            $ctx = stream_context_create();
            stream_context_set_option($ctx, 'ssl', 'local_cert', 'xxxxx.pem');
            stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

            // Open a connection to the APNS server
            $fp = stream_socket_client(
                'ssl://gateway.push.apple.com:2195', $err,
                $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

            if (!$fp)
                exit("Failed to connect: $err $errstr" . PHP_EOL);

            echo 'Connected to APNS' . PHP_EOL;

            // 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) . pack('n', strlen($payload)) . $payload;

            // Send it to the server
            $result = fwrite($fp, $msg, strlen($msg));

            if (!$result)
                echo 'Message not delivered' . PHP_EOL;
            else
                echo 'Message successfully delivered' . PHP_EOL;

            // Close the connection to the server
            fclose($fp);

    }
    $db = null;
} catch(PDOException $e) {
    echo '{"error":{"text":'. $e->getMessage() .'}}'; 
}
}

正如您所看到的,我使用iPhone获取所有用户,然后向他们发送通知。我的手机是该列表中的最后一个用户而我没有得到它,我认识的另一个用户是最早的用户之一,而且她得到了它。 它要么错过了阵列中的一些用户,要么只是前半部分,没有显示错误。

我正在使用Slim。

希望你能帮助我,谢谢!

2 个答案:

答案 0 :(得分:2)

您发送的某些设备令牌可能无效。即使是一个无效设备也可以解释您遇到的问题。当您发送带有无效设备令牌的通知时,Apple会返回错误响应并关闭套接字。

当您的代码检测到套接字关闭时,您可能已经发送了许多无效通知(甚至可能在检测到套接字关闭之前发送了所有通知),这会导致所有通知在被丢弃的无效之后发送。创建新套接字后,必须向Apple重新发送此类通知。

我建议您阅读this document中的Push Notification Throughput and Error Checking部分,了解更多详情。

确保您的数据库不包含生产设备令牌和沙盒设备令牌的混合,因为生产令牌在沙箱环境中无效,反之亦然。

答案 1 :(得分:1)

您可以使用以下方法使用此方法向多个用户发送通知。以下代码可帮助您发送Firebase push notification android。您需要将服务器密钥和消息传递给此功能。

<?php
$target = ["TARGET_ID"];

$notificationBody['data'] = [
    'type' => 1,
    'url' => "https://trinitytuts.com/wp-content/uploads/2018/07/macaw.png",
    'title' => "title",
    "msg" => "Message"
];

$response = sendMessage($notificationBody, $target, $_POST['serverKey']);

function sendMessage($data, $target, $serverKey){
    //FCM api URL
    $rsp = [];
    $url = 'https://fcm.googleapis.com/fcm/send';
    //api_key available in Firebase Console -> Project Settings -> CLOUD MESSAGING -> Server key
    $server_key = $serverKey;
    $fields = array();
    $fields['data'] = $data;
    if(is_array($target)){
            $fields['registration_ids'] = $target;
        }else{
            $fields['to'] = $target;
    }
    //header with content_type api key
    $headers = array(
        'Content-Type:application/json',
        'Authorization:key='.$server_key
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    $result = curl_exec($ch);
    if ($result === FALSE) {
        //die('FCM Send Error: ' . curl_error($ch));
    }
    curl_close($ch);

    //print_r($result);
    return $result;
}