bhavya kothari
bhavya kothari

Reputation: 7474

Apple Push Notification with PHP script not working?

When i run below script on terminal it gives the error :

Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure in
/Applications/MAMP/htdocs/SimplePush/simplepush.php on line 21

Warning: stream_socket_client(): Failed to enable crypto in /Applications/MAMP/htdocs/SimplePush/
simplepush.php on line 21

Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195
(Unknown error) in /Applications/MAMP/htdocs/SimplePush/simplepush.php on line 21
Failed to connect: 0 

Here is the code:

<?php

// Put your device token here (without spaces):
$deviceToken = '*******';

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

// Put your alert message here:
$message = 'Want more credits!';


$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.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);

?>

Upvotes: 1

Views: 3020

Answers (4)

chispitaos
chispitaos

Reputation: 937

I've used your script just like that, and the solution I found was to invoke it from a CURL call, inside the php script:

This is the code that works for me. Remember to call it via HTTPS

script 1 (to invoke the one via CURL):

// set post fields
    $post = [
        'mensaje' => 'THE MESSAGE TO SEND',
        'device_id' => $device_id,
    ];

    $ch = curl_init('https://www.DOMAIN/push-curl-script.php');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    $response = curl_exec($ch);
    curl_close($ch);

push-curl-script.php:

    $certificado_push   = "*****.pem";

    // Put your device token here (without spaces):
    $deviceToken        = $_POST["device_id"];

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

    // Put your alert message here:
    $message            = $_POST["mensaje"];


    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', $certificado_push);
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

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

    if (!$fp) {
            echo "Failed to connect: $err $errstr" ;
    }else{    
            echo 'Connected to APNS'  ;

            // 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' ;
            }else{
                echo 'Message successfully delivered' ;
            }

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

Upvotes: 0

Praveen Matanam
Praveen Matanam

Reputation: 2803

Download cacert.pem from https://curl.haxx.se/ca/cacert.pem and keep it in the same folder where PHP script is available.

Include the statement stream_context_set_option($ctx, 'ssl', 'cafile', 'cacert.pem'); after the line $ctx = stream_context_create();

fyi:

Syntax: bool stream_context_set_option ( resource $stream_or_context , string $wrapper , string $option , mixed $value )

For additional options check http://php.net/manual/en/context.ssl.php

Upvotes: 0

sumon
sumon

Reputation: 742

Old Question, but I faced same problem. And I solved it by changing the following code:

stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');

to

stream_context_set_option($ctx, 'ssl', 'local_cert', '/Users/Ohemod/Desktop/ck.pem');

The script was looking for ck.pem file, but for not providing the actual directory I got the error message everytime. If anyone face the same problem please try with the second one. Remember the directory of your file and my codes directory will not same. Put the actual directory link of your ck.pem file.

Upvotes: 1

Joe
Joe

Reputation: 2987

Since it sounds like your are using the development cert you might want to try pointing to: gateway.sandbox.push.apple.com:2195. The URL gateway.push.apple.com:2195 is for production certs.

Upvotes: 1

Related Questions