Push notifications from linux for iOS apps via SSL with PHP

Do you know how to sent push notifications to IOS app from php?
It's best answer for somebody http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
But it doesn't work:


        $production = 0;
        $passphrase = "kaka";
        $deviceToken = "bf38e156 29adac02 6b9b2ec6 35aa4381 df90df65 8238a13c d7f55261 798c3923";
        $message = "Hello people! What are you doing?";
        $deviceToken = str_replace(" ", "", $deviceToken);

        // Create a Stream
        $ctx = stream_context_create();
        // Define the certificate to use
        stream_context_set_option($ctx, "ssl", "local_cert", "CerAndKey.pem");
        // Passphrase to the certificate
        //stream_context_set_option($ctx, "ssl", "passphrase", $passphrase);
        stream_context_set_option($ctx, "ssl", "verify_peer", true);
        // load certificate
        stream_context_set_option($ctx, "ssl", "cafile", "CerAndKey.pem");

        if ($production) {
            $gateway = "gateway.push.apple.com:2195";
         } else {
            $gateway = "gateway.sandbox.push.apple.com:2195";
         }

        $fp = stream_socket_client($gateway,
            $err,
            $errstr,
            60,
            STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,
            $ctx);

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

        echo "Connected to APNS" . PHP_EOL;

        // Create the payload body
        $body["aps"] = array(
            "badge" => +1,
            "alert" => $message,
            "sound" => "default"
        );

        $payload = json_encode($body);

        // Build the binary notification
        $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

        // Ensure that blocking is disabled
        //stream_set_blocking($fp, 0);

        // Send it to the server
        $result = fwrite($fp, $msg, strlen($msg));
        print_r($result);
        if (!$result)
            echo 'Message not delivered' . PHP_EOL;
        else
            echo 'Message successfully delivered amar '.$message. PHP_EOL;

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




Many people don't know how is right. PHP can diferent work in linux-systems. If you want I tell you howto easy use it.
Step by step:
1. Generate ssl keys:

#!/bin/bash

## From
# http://stackoverflow.com/questions/24344325/how-to-use-linux-openssl-to-generate-csr-for-ios

openssl genrsa -out ios-dev.key 2048
openssl req -new -key ios-dev.key -out ios-dev.csr

# You must upload to Apple -> Identifiers -> App IDs -> <project> -> edit -> Push Notifications -> Create Certificate ->
# then download -> aps_development.cer
# and put file here


2. Prepare key whith certificate for server script.

#!/bin/bash
## from
# https://gist.github.com/stevenhaddox/1501893
# http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1

openssl x509 -in aps_development.cer -inform der -out CertAndKeyDevCert.pem
##cp CertAndKeyDevCert.pem /etc/ssl/certs/

openssl rsa -in ios-dev.key -out CertAndKeyDevKey.pem -outform PEM
cat CertAndKeyDevCert.pem CertAndKeyDevKey.pem > CertAndKey.pem


3. Connect to Apple server for test

#!/bin/bash
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert CertAndKey.pem -key CertAndKey.pem -CAfile CertAndKey.pem


Result in console:

CONNECTED(00000003)
depth=2 /O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)
verify return:1
depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
verify return:1
depth=0 /C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.sandbox.push.apple.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.sandbox.push.apple.com
   i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
 1 s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
   i:/O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFMzCCBBugAwIBAgIETCMmsDANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC
VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
Lm5ldC9ycGEgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
KGMpIDIwMDkgRW50cnVzdCwgSW5jLjEuMCwGA1UEAxMlRW50cnVzdCBDZXJ0aWZp
Y2F0aW9uIEF1dGhvcml0eSAtIEwxQzAeFw0xNDA1MjMxNzQyNDJaFw0xNjA1MjQw
NzA1MTNaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYD
VQQHEwlDdXBlcnRpbm8xEzARBgNVBAoTCkFwcGxlIEluYy4xJzAlBgNVBAMTHmdh
dGV3YXkuc2FuZGJveC5wdXNoLmFwcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAOQpUlXpU3+LJ2XR01QdVooN7S9OFOINp3/tomPaenQAwFGo
qIakKFcN7AotWLFXFcR0QXKJkn4PL/zPKDBucyRFkc79S5+ZraGRISWfi7G8XeaG
G3GzgeVQ977Qrn0IdCswnbwLsJoErnmq4AveQajUbYueR9SxhkWBwMimSxXzXoOS
XUOPzRvzObCxVZrvBBDSRJCeNVnVxtCmb17DM3+z5GZatBwWnvw0jgvSQsgof+uC
idXgqcN4msv3tVH54ipmuD9kbbwvtnDCHBZRXMMmhUfFXZRuE8GBEbPfVkqB16ad
JV4TVrVxwFENwdnsX9CXavHCgFJhtHRWKOoCH48CAwEAAaOCAY0wggGJMAsGA1Ud
DwQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwMwYDVR0fBCww
KjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9sZXZlbDFjLmNybDBkBggr
BgEFBQcBAQRYMFYwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0
MC8GCCsGAQUFBzAChiNodHRwOi8vYWlhLmVudHJ1c3QubmV0LzIwNDgtbDFjLmNl
cjBKBgNVHSAEQzBBMDUGCSqGSIb2fQdLAjAoMCYGCCsGAQUFBwIBFhpodHRwOi8v
d3d3LmVudHJ1c3QubmV0L3JwYTAIBgZngQwBAgIwKQYDVR0RBCIwIIIeZ2F0ZXdh
eS5zYW5kYm94LnB1c2guYXBwbGUuY29tMB8GA1UdIwQYMBaAFB7xq4kG+EkPATN3
7hR67hl8kyhNMB0GA1UdDgQWBBSSGfpGPmr9+FPcqRiStH0iKRBL7DAJBgNVHRME
AjAAMA0GCSqGSIb3DQEBBQUAA4IBAQAkj6+okMFVl7NHqQoii4e4iPDFiia+LmHX
BCc+2UEOOjilYWYoZ61oeqRXQ2b4Um3dT/LPmzMkKmgEt9epKNBLA6lSkL+IzEnF
wLQCHkL3BgvV20n5D8syzREV+8RKmSqiYmrF8dFq8cDcstu2joEKd173EfrymWW1
fMeaYTbjrn+vNkgM94+M4c/JnIDOhiPPbeAx9TESQZH+/6S98hrbuPIIlmaOJsOT
GMOUWeOTHXTCfGb1EM4SPVcyCW28TlWUBl8miqnsEO8g95jZZ25wFANlVxhfxBnP
fwUYU5NTM3h0xi3rIlXwAKD6zLKipcQ/YXRx7oMYnAm53tfU2MxV
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.sandbox.push.apple.com
issuer=/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
---
Acceptable client certificate CA names
/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA
/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Application Integration Certification Authority
---
SSL handshake has read 3160 bytes and written 2176 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID:
    Session-ID-ctx:
    Master-Key: 5602BDD396ED4E8E9FE2BDFAD5A0226DEBB53C568EB34E57DE69E0024041F1F9F242A551E88758F5B0D4A2CDBEACBCB2
    Key-Arg   : None
    Start Time: 1456218193
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---


Right responce:
1. verify return:1
2. Verify return code: 0 (ok)

Your certivicate and key are OK! Next step is php-script:

$production = 0;
        $keyFile = "CertAndKey.pem";
        $deviceToken = "bf38e156 29adac02 6b9b2ec6 35aa4381 df90df65 8238a13c d7f55261 798c3923";
        $message = "Ещё одно ...";

        $deviceToken = str_replace(" ", "", $deviceToken);

        if ($production) {
            $gateway = 'gateway.push.apple.com:2195';
         } else {
            $gateway = 'gateway.sandbox.push.apple.com:2195';
         }

        // Create the payload body
        $body['aps'] = array(
            'badge' => +1,
            'alert' => $message,
            'sound' => 'default',
        );

        $payload = json_encode($body);

        // Build the binary notification
        $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
        $filepath = "/tmp/sentPush.dat";
        file_put_contents($filepath,$msg);
        $command = "cat ".$filepath." | openssl s_client -connect ".$gateway." -cert ".$keyFile." -key ".$keyFile." -CAfile ".$keyFile." 2>&1";
        exec($command, $tmp);
        $last = end($tmp);
        unlink($filepath);
if ($last=="DONE"){
            $result = "Message successfully!";
         }else{
            $result = "ERROR:Message not send" . PHP_EOL;
         }


This solution will work somewhere, because I use only openssl.


+1 is not allowed for badge

Store the badge number where you store the device tokens and update it with every push notification.


There are some points that should be kept in mind:

  • This problem might be occur due to $production = 0; . It should be $production = true;
  • Try to use the full path for .pem file .=> stream_context_set_option($ctx, "ssl", "local_cert", "CerAndKey.pem"); use __FILE__ to get full path like: stream_context_set_option($ctx, "ssl", "local_cert", "(full-path-to-file)/CerAndKey.pem");
  • Double check the device token used to send notifications.
  • And in last try chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $item[0])) . chr(0) . chr(strlen($payload)) . $payload; chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $item[0])) . chr(0) . chr(strlen($payload)) . $payload;
    instead of
  • $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

    May be it helps to you or someone else. Should try once.

    链接地址: http://www.djcxy.com/p/57434.html

    上一篇: 枚举值:NSInteger或int?

    下一篇: 使用PHP通过SSL从Linux推送iOS应用通知