Sending a push notification in yii

2019-04-15 18:37发布

问题:

I want to send a push notification to an ios device by getting the device token, so far i have done this in yii:

public function actionPushtest(){

    $token=$_REQUEST['token'];

        $message = 'Hello';
        $badge = 1;
        $sound = 'default';
        $development = true;
        $passphrase='pass';

        $payload = array();
        $payload['aps'] = array('alert' => $message, 'badge' => intval($badge), 'sound' => $sound);
        $payload = json_encode($payload);

        $apns_url = NULL;
        $apns_cert = NULL;
        $apns_port = 2195;

        if($development)
        {
            $apns_url = 'gateway.sandbox.push.apple.com';
            $apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
        }
        else
        {
            $apns_url = 'gateway.push.apple.com';
            $apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
        }
        $stream_context = stream_context_create();
        stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
        stream_context_set_option($stream_context, 'ssl', 'passphrase', $passphrase);

        $apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 2, STREAM_CLIENT_CONNECT, $stream_context);



        $device_tokens=  str_replace("<","",$token);
        $device_tokens1=  str_replace(">","",$device_tokens);
        $device_tokens2= str_replace(' ', '', $device_tokens1);


            $apns_message = chr(0) . chr(0) . chr(32) . pack('H*', $device_tokens2 /*str_replace(' ', '', $device_tokens1)*/) . chr(0) . chr(strlen($payload)) . $payload;

            $msg=fwrite($apns, $apns_message);
            if (!$msg){
                echo 'Message not delivered' . PHP_EOL;
            }else{
                echo 'Message successfully delivered' . PHP_EOL;
            }


        @socket_close($apns);
        @fclose($apns);
}

..i am not getting any errors but the notification is not being received. what am i doing wrong?

回答1:

I discovered what my error was finally, the issue was with the pem file, though no error was being displayed for this and also no push notification is generated while the app is on, you need to minimize it or something. For others who run into this problem, make sure that your pem file is 100% OK. And thanks to others who spared some time and helped me solve it. Here is the code:

public function actionPushtest(){

    $token=$_REQUEST['token'];

        $message = 'Hello';
        $badge = 1;
        $sound = 'default';
        $development = true;//make it false if it is not in development mode
        $passphrase='pass';//your passphrase

        $payload = array();
        $payload['aps'] = array('alert' => $message, 'badge' => intval($badge), 'sound' => $sound);
        $payload = json_encode($payload);

        $apns_url = NULL;
        $apns_cert = NULL;
        $apns_port = 2195;

        if($development)
        {
            $apns_url = 'gateway.sandbox.push.apple.com';
            $apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
        }
        else
        {
            $apns_url = 'gateway.push.apple.com';
            $apns_cert = dirname(Yii::app()->request->scriptFile).'/file.pem';
        }
        $stream_context = stream_context_create();
        stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
        stream_context_set_option($stream_context, 'ssl', 'passphrase', $passphrase);

        $apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 2, STREAM_CLIENT_CONNECT, $stream_context);



        $device_tokens=  str_replace("<","",$token);
        $device_tokens1=  str_replace(">","",$device_tokens);
        $device_tokens2= str_replace(' ', '', $device_tokens1);


            $apns_message = chr(0) . chr(0) . chr(32) . pack('H*', $device_tokens2) . chr(0) . chr(strlen($payload)) . $payload;

            $msg=fwrite($apns, $apns_message);
            if (!$msg){
                echo 'Message not delivered' . PHP_EOL;
            }else{
                echo 'Message successfully delivered' . PHP_EOL;
            }


        @socket_close($apns);
        @fclose($apns);
}


回答2:

Before you fwrite you message, check if $apns isn't false. If it is false check $error_string for any errors. That's where the errors would be if you get any errors.

If the stream was not created you would be doing fwrite on false, which only returns into an warning and not an error:

http://codepad.org/lSYeUMwH

I would propose this changes:

    if (!apns) {
        Yii::app()->user->setFlash('error', "Apple Push failed!");
        Yii::log($error_string, 'error', 'myController.actionPushtest');
    } else {
        $device_tokens = str_replace("<", "", $token);
        $device_tokens1 = str_replace(">", "", $device_tokens);
        $device_tokens2 = str_replace(' ', '', $device_tokens1);


        $apns_message = chr(0) . chr(0) . chr(32) . pack(
                'H*',
                $device_tokens2 /*str_replace(' ', '', $device_tokens1)*/
            ) . chr(0) . chr(strlen($payload)) . $payload;

        $msg = fwrite($apns, $apns_message);
        if (!$msg) {
            echo 'Message not delivered' . PHP_EOL;
        } else {
            echo 'Message successfully delivered' . PHP_EOL;
        }


        @socket_close($apns);
        @fclose($apns);
    }