6

I have implemented Push-Notifications into my Project and everything works fine so far. I've tried sending Notifications through Pusher and this worked out just fine. But I have to send them through PHP, which isn't working yet. I found many old explanations on how to make this happen, but none of them seem to work for me.

This is what I'm trying to work with:

    // APNs Push testen auf Token
$deviceToken = $_GET['key']; // Device-Token

// Payload erstellen und JSON codieren
$payload['aps'] = array('alert' => 'TitleText', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);

$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'certificate.pem';

// Stream erstellen
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'certificate.cer', $apnsCert);

$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if ($apns)
{
  // Nachricht erstellen und senden
  $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
  fwrite($apns, $apnsMessage);

  // Verbindung schliessen
  fclose($apns);
}
else
{
  echo "Fehler!";
  var_dump($error);
  var_dump($errorString);
}
Cristik
  • 30,989
  • 25
  • 91
  • 127
Nils
  • 1,755
  • 3
  • 13
  • 25
  • How can i add more Params/Data to the Notification, for example some Action-id so when the user open the notification the App will get that Action-id to perform some function related to it. – Ahmad Gulzar Aug 27 '22 at 17:35

4 Answers4

9

Try using this php script , make sure that the .pem certificate exits in same path as that php script when you run it , also get a correct device token

 <?php
        /* We are using the sandbox version of the APNS for development. For production
        environments, change this to ssl://gateway.push.apple.com:2195 */
        $apnsServer = 'ssl://gateway.sandbox.push.apple.com:2195';
        /* Make sure this is set to the password that you set for your private key
        when you exported it to the .pem file using openssl on your OS X */
        $privateKeyPassword = '1234';
        /* Put your own message here if you want to */
        $message = 'Welcome to iOS 7 Push Notifications';
        /* Pur your device token here */
        $deviceToken =
        '05924634A8EB6B84437A1E8CE02E6BE6683DEC83FB38680A7DFD6A04C6CC586E';
        /* Replace this with the name of the file that you have placed by your PHP
        script file, containing your private key and certificate that you generated
        earlier */
        $pushCertAndKeyPemFile = 'PushCertificateAndKey.pem';
        $stream = stream_context_create();
        stream_context_set_option($stream,
        'ssl',
        'passphrase',
        $privateKeyPassword);
        stream_context_set_option($stream,
        'ssl',
        'local_cert',
        $pushCertAndKeyPemFile);

        $connectionTimeout = 20;
        $connectionType = STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT;
        $connection = stream_socket_client($apnsServer,
        $errorNumber,
        $errorString,
        $connectionTimeout,
        $connectionType,
        $stream);
        if (!$connection){
        echo "Failed to connect to the APNS server. Error no = $errorNumber<br/>";
        exit;
        } else {
        echo "Successfully connected to the APNS. Processing...</br>";
        }
        $messageBody['aps'] = array('alert' => $message,
        'sound' => 'default',
        'badge' => 2,
        );
        $payload = json_encode($messageBody);
        $notification = chr(0) .
        pack('n', 32) .
        pack('H*', $deviceToken) .
        pack('n', strlen($payload)) .
        $payload;
        $wroteSuccessfully = fwrite($connection, $notification, strlen($notification));
        if (!$wroteSuccessfully){
        echo "Could not send the message<br/>";
        }
        else {
        echo "Successfully sent the message<br/>";
        }
        fclose($connection);

  ?>
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • Hey Khan, thanks for the help. It doesn't seem to be working though :/ I get an error with number 0. I have also tried this: ´stream_context_set_option($stream, 'ssl', 'cafile', 'entrust_2048_ca.cer'); ´ which doesnt help either. – Nils Jan 06 '18 at 19:36
  • Development or distribution ? – Shehata Gamal Jan 06 '18 at 19:38
  • I used distribution – Nils Jan 06 '18 at 19:38
  • $apnsServer = 'ssl://gateway.push.apple.com:2195'; – Shehata Gamal Jan 06 '18 at 19:39
  • replace the password with yours $privateKeyPassword – Shehata Gamal Jan 06 '18 at 19:41
  • 2
    After doing everything from scratch again it worked. Thank you! – Nils Jan 06 '18 at 22:35
  • where can i get the appi key? – Alberto Acuña Nov 15 '18 at 18:46
  • @Sh_Khan I'm trying to get this script to work, here's the things that I've done: run the script with https:// and http://, opened ports 2195 and 2196 to outbound traffic on the server, tested the certificate, password and token with pushtry.com (it works as expected there). What are the other possible missing links that I'm not thinking about? The error that I keep getting is "Failed to connect to the APNS server. Error no = 0". – Circle B Jan 23 '19 at 17:52
  • This is a very useful answer, though the code could perhaps be a little better organised. Also, you should change the line `pack('n', 32)`; Apple warns that device identifiers are not a fixed length, what I did was `$deviceToken = pack('H*', $deviceToken)` then later `pack('n', strlen($deviceToken)) . $deviceToken` to build the message with a potentially variable-length token. – Haravikk Jun 29 '20 at 11:40
3

Here is new updates on script, As Apple changed notification url:

<?php
    if ( defined("CURL_VERSION_HTTP2") && (curl_version()["features"] & CURL_VERSION_HTTP2) !== 0) {
        $ch = curl_init();
        $body ['aps'] = array (
            "alert" => array (
                "title"  => "hii",
            ),
            "sound"  => "default"
        );
        $curlconfig = array(
            CURLOPT_URL => "https://api.development.push.apple.com/3/device/device_token",
            CURLOPT_RETURNTRANSFER =>true,
            CURLOPT_POSTFIELDS => json_encode($body),
            CURLOPT_SSLCERT =>"apns.pem",
            CURLOPT_SSLCERTPASSWD => "123456",
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
            CURLOPT_VERBOSE => true
        );
        curl_setopt_array($ch, $curlconfig);
        $res = curl_exec($ch);
        if ($res === FALSE) {
                echo('Curl failed: ' . curl_error($ch));
        }
        curl_close($ch);
    }else{
        echo "No HTTP/2 support on client.";
    }
       
    ?>
Cristik
  • 30,989
  • 25
  • 91
  • 127
Arun sharma
  • 642
  • 1
  • 7
  • 17
2
<?php

    function sendFCM($body, $title, $id, $StudentAdmissionId, $activitytype) {
        $url = "https://fcm.googleapis.com/fcm/send";
        $token = $id;
        $serverKey = 'AAAA8XYL2Y8:APA91bF1fsddfgffdssdsdfsdsdsda8zyWJTgs0OSeiRlk9WQqLwKn51VkMH_XSbpRuiCTU-Fdi2hoV8JY8ST7gCBQe4dlMFASDbr5Oci1bLmg9tyl5dlxyFDauWWCMItUNdFGWO_CWhpHwSIbvbqYwlCnoRd7ucB';
        $notification = array(
            'title' => $title,
            'text' => $body,
            'sound' => 'default',
            'badge' => 1,
            'category' => $activitytype,
            'content-available' => 1
        );
        $arrayToSend = array(
            'to' => $token,
            'notification' => $notification,
            'priority' => 'high'
        );
        $json = json_encode($arrayToSend);
        $headers = array();
        $headers[] = 'Content-Type: application/json';
        $headers[] = 'Authorization: key=' . $serverKey;
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        //Send the request
        echo $response = curl_exec($ch);
        //Close request
        if ($response === FALSE) {
            die('FCM Send Error: ' . curl_error($ch));
        }
        curl_close($ch);
        mysql_query("INSERT INTO `tbl_notifications`(`n_activity_name`,`n_user_id`,`n_device_id`, `n_notification`) VALUES ('$activitytype','$StudentAdmissionId','$id','$response')");
        // #Echo Result Of FireBase Server
        return $response;
    }

?>
  • Use this for php & mysql backend for pusihing notification on android and ios on the same time

  • Here token of apns server is stored in db and pass to send fcm

Partho63
  • 3,117
  • 2
  • 21
  • 39
1

My solution:

$token = 'your device token';
$apns_topic = 'your bundle id';
$apns_pem = 'your location and name of your pem file';
$apns_pass = 'your password' // empty string if nopass
$body = array(
    'aps' => array(
        'alert' => $text,
        'sound' => 'default'
     )
); // Or the other bodies mentioned above

$ch = curl_init("https://api.development.push.apple.com/3/device/$token");
// https://api.push.apple.com/3/device/ in production
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("apns-topic: " . $apns_topic));
curl_setopt($ch, CURLOPT_SSLCERT, _FRW_CONFIG_DIR_ . $apns_pem);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $apns_pass);
$result = curl_exec($ch);