How to send push notifications with PHP

Sending push notifications to an iOS/Android Application can enhance the user experience exponentially, while allowing you to deliver key information easily. However, sending the push notification to users can be a bit tedious at times, and at times confusing. You need to ensure that you pack your integers, and times correctly - failing to do this and you'll probably get an unhelpful status from Apple or Google.

I've came across some online PHP Scripts for either iOS or Android implementation however not for both. This PHP script includes implementation for both mobile operating systems.

PHP Script (For a description, scroll below the script):

function send_mobile_notification_request($user_mobile_info, $payload_info)
{
    //Default result
    $result = -1;
    //Change depending on where to send notifications
    $pem_preference = "production";
    $user_device_type = $user_mobile_info['user_device_type'];
    $user_device_key = $user_mobile_info['user_mobile_token'];
    if ($user_device_type == "iOS") {
        $apns_url = NULL;
        $apns_cert = NULL;
        //Apple server listening port
        $apns_port = 2195;
        if ($pem_preference == "production") {
            $apns_url = 'gateway.push.apple.com';
            $apns_cert = __DIR__.'/cert-prod.pem';
        }
        //develop .pem
        else {
            $apns_url = 'gateway.sandbox.push.apple.com';
            $apns_cert = __DIR__.'/cert-dev.pem';
        }
        $stream_context = stream_context_create();
        stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
        $apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 2, STREAM_CLIENT_CONNECT,                                   $stream_context);
        $apns_message = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $user_device_key)) . chr(0) . chr(strlen($payload_info)) .                               $payload_info;
        if ($apns) {
            $result = fwrite($apns, $apns_message);
        }
        @socket_close($apns);
        @fclose($apns);
    }
    else if ($user_device_type == "Android") {
        // API access key from Google API's Console
        define('API_ACCESS_KEY', ADD_YOUR_API_KEY_HERE);
        // prep the bundle
        $msg = array
        (
            'message' => json_decode($payload_info)->aps->alert,
            'title' => 'This is a title. title',
            'subtitle' => 'This is a subtitle. subtitle',
            'tickerText' => 'Ticker text here...Ticker text here...',
            'vibrate' => 1,
            'sound' => 1,
            'largeIcon' => 'large_icon',
            'smallIcon' => 'small_icon'
        );
        $fields = array
        (
            'registration_ids' => array($user_device_key),
            'data' => $msg
        );
        $headers = array
        (
            'Authorization: key=' . API_ACCESS_KEY,
            'Content-Type: application/json'
        );
        $ch = curl_init();
        curl_setopt( $ch,CURLOPT_URL,                     'https://android.googleapis.com/gcm/send' );
        curl_setopt( $ch,CURLOPT_POST, true );
        curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
        curl_setopt( $ch,CURLOPT_RETURNTRANSFER, false );
        curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
        curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
        $result = curl_exec($ch);
        curl_close($ch);
    }
    return $result > 0;
}

function create_payload_json($message) {
    //Badge icon to show at users ios app icon after receiving notification
    $badge = "0";
    $sound = 'default';
    $payload = array();
    $payload['aps'] = array('alert' => $message, 'badge' => intval($badge),'sound' => $sound);
    return json_encode($payload);
}

Description

Let's start. The first method builds the body of the notification request depending on the users operating system and sends accordingly. The flow process for sending push notifications is first to Apple/Google servers, and only then to the end user. Therefore, each end user holds on his mobile device, a unique token. Learn more about how to retrieve the user device key in Android or iOS.

Personally, I wrote the main method such that the input contains $user_mobile_info - An array containing the user's device and unique device key, and $payload_info - A JSON which contains the body message for sending the push notification request (Found in the second method). The $pem_preference variable inside the method is also hard coded, however can be changed to your preference. Apple offers two servers for development - sandbox for QA (gateway.sandbox.push.apple.com) and regular for production (gateway.push.apple.com). If you're in the testing phase of your development, just change the url or the variable itself.

The second method builds the message body. I've hard coded some variables such as the sound and badge. Sound can be changed to various options, and badge describes the badge to be shown when the user receives the notification. I've modified it to "0", meaning there will be no badge icon when receiving notifications.

Usage Example

The main part of the push notification is the message itself. Let's say the notification we want to send is "I know how to send push notifications!". We'll first create the payload JSON using the second method:

$payload = create_payload_json("I know how to send push notifications!");

Let's say the user has an iOS (This info can be kept on a server, database etc... for each user) and the array is as follows:

$user_mobile_info = ['user_device_type'=>"iOS", 'user_mobile_token'=>'1234ABCD'];

Now we can send the notification itself using the first method: 

send_mobile_notification_request($user_mobile_info, $payload);

They're many minor sections which have not been covered by this blog post. Feel free to leave me comments if you have any further questions.