0
votes

I need to send thousands (actually 10 000) push notifications at the same time, to do this, I checked StackOverflow and found those two questions:

And I implemented my push system using php:

    // Create the payload body
    $body['aps'] = [
        'alert' => $notification->getMessage(),//$notification is just a notification model, where getMessage() returns the message I want to send as string
        'sound' => 'default'
    ];

    // Encode the payload as JSON
    $payload = json_encode($body);

    $fp = self::createSocket();
    foreach($devices as $device) {
        $token = $device->getToken();
        $msg = chr(0) . pack('n', 32) . pack('H*', str_replace(' ', '', $token)) . pack('n', strlen($payload)) . $payload;
        if(!self::sendSSLMessage($fp, $msg)){
        //$msg is a parameter of the method, it's the message as string
            fclose($fp);
            $fp = self::createSocket();
        }else{
           //Here I log "n notification sent" every 100 notifications
        }
     }
     fclose($fp);

Here is the createSocket() method:

private static function createSocket(){
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', PUSH_IOS_CERTIFICAT_LOCATION);
    stream_context_set_option($ctx, 'ssl', 'passphrase', PUSH_IOS_PARAPHRASE);
    // Open a connection to the APNS server
    $fp = stream_socket_client(
        'ssl://gateway.push.apple.com:2195', $err,
        $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
    stream_set_blocking ($fp, 0);
    if (!$fp) {
        FileLog::log("Ios failed to connect: $err $errstr");
    }
    return $fp;
}

And the sendSSLMessage() method:

private static function sendSSLMessage($fp, $msg, $tries = 0){
        if($tries >= 10){
            return false;
        }

        return fwrite($fp, $msg, strlen($msg)) ? self::sendSSLMessage($fp, $msg, $tries++) : true;
    }

I'm not getting any error message from apple, everything looks fine except nobody is receiving the notification.

Before this, I was using a method creating one socket connection per message and closing it after sending the message, but it was way too slow so we decided to change it, so I know that it's not a client related issue.

1

1 Answers

0
votes

You have to first crate $fp socket then pass it to sendSSLMessage

// initally create Socket here
$fp = self::createSocket();

foreach($devices as $device) {
    $token = $device->getToken();
    $msg = chr(0) . pack('n', 32) . pack('H*', str_replace(' ', '', $token)) . pack('n', strlen($payload)) . $payload;

    if(!self::sendSSLMessage($fp, $msg)){
        fclose($fp);
        $fp = self::createSocket();
    }
}
fclose($fp);

UPDATE

// define in $body['aps'] message with sub array like this
$message = $notification->getMessage();
$body['aps'] = array(
            'alert' => array(
                      'body' => $message,
            ),
            'sound' => 'default',
);